Skip to content

Commit 639d0aa

Browse files
Fix .debug_aranges parsing. (#2019)
Code was added that used llvm error checking to parse .debug_aranges, but the error check after parsing the DWARFDebugArangesSet was reversed and was causing no error to be returned with no valid address ranges being actually used. This meant we always would fall back onto creating out own address ranges by parsing the compile unit's ranges. This was causing problems for cases where the DW_TAG_compile_unit had a single address range by using a DW_AT_low_pc and DW_AT_high_pc attribute pair (not using a DW_AT_ranges attribute), but the .debug_aranges had correct split ranges. In this case we would end up using the single range for the compile unit that encompassed all of the ranges from the .debug_aranges section and would cause address resolving issues in LLDB where address lookups would fail for certain addresses. Differential Revision: https://reviews.llvm.org/D87626 (cherry picked from commit 79f22b1) Co-authored-by: Greg Clayton <[email protected]>
1 parent 08dd9cc commit 639d0aa

File tree

2 files changed

+66
-27
lines changed

2 files changed

+66
-27
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
3939
Range range;
4040
while (debug_aranges_data.ValidOffset(offset)) {
4141
llvm::Error error = set.extract(debug_aranges_data, &offset);
42-
if (!error)
42+
if (error)
4343
return error;
4444

4545
const uint32_t num_descriptors = set.NumDescriptors();

lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h"
2020
#include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h"
2121
#include "Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h"
22+
#include "Plugins/SymbolFile/DWARF/DWARFDebugAranges.h"
2223
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
2324
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
2425
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -70,7 +71,7 @@ TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) {
7071
TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
7172
// Test that if we have a .debug_abbrev that contains ordered abbreviation
7273
// codes that start at 1, that we get O(1) access.
73-
74+
7475
const auto byte_order = eByteOrderLittle;
7576
const uint8_t addr_size = 4;
7677
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -81,17 +82,17 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
8182
encoder.PutULEB128(DW_FORM_strp);
8283
encoder.PutULEB128(0);
8384
encoder.PutULEB128(0);
84-
85+
8586
encoder.PutULEB128(2); // Abbrev code 2
8687
encoder.PutULEB128(DW_TAG_subprogram);
8788
encoder.PutHex8(DW_CHILDREN_no);
8889
encoder.PutULEB128(DW_AT_name);
8990
encoder.PutULEB128(DW_FORM_strp);
9091
encoder.PutULEB128(0);
9192
encoder.PutULEB128(0);
92-
93+
9394
encoder.PutULEB128(0); // Abbrev code 0 (termination)
94-
95+
9596
DWARFDataExtractor data;
9697
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
9798
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -101,7 +102,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
101102
// Make sure we have O(1) access to each abbreviation by making sure the
102103
// index offset is 1 and not UINT32_MAX
103104
EXPECT_EQ(abbrev_set.GetIndexOffset(), 1u);
104-
105+
105106
auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(1);
106107
EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
107108
EXPECT_TRUE(abbrev1->HasChildren());
@@ -115,7 +116,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start1) {
115116
TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
116117
// Test that if we have a .debug_abbrev that contains ordered abbreviation
117118
// codes that start at 5, that we get O(1) access.
118-
119+
119120
const auto byte_order = eByteOrderLittle;
120121
const uint8_t addr_size = 4;
121122
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -126,17 +127,17 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
126127
encoder.PutULEB128(DW_FORM_strp);
127128
encoder.PutULEB128(0);
128129
encoder.PutULEB128(0);
129-
130+
130131
encoder.PutULEB128(6); // Abbrev code 6
131132
encoder.PutULEB128(DW_TAG_subprogram);
132133
encoder.PutHex8(DW_CHILDREN_no);
133134
encoder.PutULEB128(DW_AT_name);
134135
encoder.PutULEB128(DW_FORM_strp);
135136
encoder.PutULEB128(0);
136137
encoder.PutULEB128(0);
137-
138+
138139
encoder.PutULEB128(0); // Abbrev code 0 (termination)
139-
140+
140141
DWARFDataExtractor data;
141142
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
142143
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -146,7 +147,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
146147
// Make sure we have O(1) access to each abbreviation by making sure the
147148
// index offset is 5 and not UINT32_MAX
148149
EXPECT_EQ(abbrev_set.GetIndexOffset(), 5u);
149-
150+
150151
auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(5);
151152
EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
152153
EXPECT_TRUE(abbrev1->HasChildren());
@@ -160,7 +161,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOrder1Start5) {
160161
TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
161162
// Test that if we have a .debug_abbrev that contains unordered abbreviation
162163
// codes, that we can access the information correctly.
163-
164+
164165
const auto byte_order = eByteOrderLittle;
165166
const uint8_t addr_size = 4;
166167
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -171,17 +172,17 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
171172
encoder.PutULEB128(DW_FORM_strp);
172173
encoder.PutULEB128(0);
173174
encoder.PutULEB128(0);
174-
175+
175176
encoder.PutULEB128(1); // Abbrev code 1
176177
encoder.PutULEB128(DW_TAG_subprogram);
177178
encoder.PutHex8(DW_CHILDREN_no);
178179
encoder.PutULEB128(DW_AT_name);
179180
encoder.PutULEB128(DW_FORM_strp);
180181
encoder.PutULEB128(0);
181182
encoder.PutULEB128(0);
182-
183+
183184
encoder.PutULEB128(0); // Abbrev code 0 (termination)
184-
185+
185186
DWARFDataExtractor data;
186187
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
187188
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -191,7 +192,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
191192
// Make sure we don't have O(1) access to each abbreviation by making sure
192193
// the index offset is UINT32_MAX
193194
EXPECT_EQ(abbrev_set.GetIndexOffset(), UINT32_MAX);
194-
195+
195196
auto abbrev1 = abbrev_set.GetAbbreviationDeclaration(2);
196197
EXPECT_EQ(abbrev1->Tag(), DW_TAG_compile_unit);
197198
EXPECT_TRUE(abbrev1->HasChildren());
@@ -205,7 +206,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevOutOfOrder) {
205206
TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) {
206207
// Test that we detect when an abbreviation has a NULL tag and that we get
207208
// an error when decoding.
208-
209+
209210
const auto byte_order = eByteOrderLittle;
210211
const uint8_t addr_size = 4;
211212
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -214,9 +215,9 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) {
214215
encoder.PutHex8(DW_CHILDREN_no);
215216
encoder.PutULEB128(0);
216217
encoder.PutULEB128(0);
217-
218+
218219
encoder.PutULEB128(0); // Abbrev code 0 (termination)
219-
220+
220221
DWARFDataExtractor data;
221222
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
222223
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -232,7 +233,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevInvalidNULLTag) {
232233
TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) {
233234
// Test that we detect when an abbreviation has a NULL attribute and a non
234235
// NULL form and that we get an error when decoding.
235-
236+
236237
const auto byte_order = eByteOrderLittle;
237238
const uint8_t addr_size = 4;
238239
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -245,7 +246,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) {
245246
encoder.PutULEB128(0);
246247

247248
encoder.PutULEB128(0); // Abbrev code 0 (termination)
248-
249+
249250
DWARFDataExtractor data;
250251
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
251252
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -255,13 +256,12 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevNullAttrValidForm) {
255256
EXPECT_TRUE(bool(error));
256257
EXPECT_EQ("malformed abbreviation declaration attribute",
257258
llvm::toString(std::move(error)));
258-
259259
}
260260

261261
TEST_F(SymbolFileDWARFTests, TestAbbrevValidAttrNullForm) {
262262
// Test that we detect when an abbreviation has a valid attribute and a
263263
// NULL form and that we get an error when decoding.
264-
264+
265265
const auto byte_order = eByteOrderLittle;
266266
const uint8_t addr_size = 4;
267267
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -272,9 +272,9 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevValidAttrNullForm) {
272272
encoder.PutULEB128(0); // NULL form
273273
encoder.PutULEB128(0);
274274
encoder.PutULEB128(0);
275-
275+
276276
encoder.PutULEB128(0); // Abbrev code 0 (termination)
277-
277+
278278
DWARFDataExtractor data;
279279
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
280280
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -290,7 +290,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevMissingTerminator) {
290290
// Test that we detect when an abbreviation has a valid attribute and a
291291
// form, but is missing the NULL attribute and form that terminates an
292292
// abbreviation
293-
293+
294294
const auto byte_order = eByteOrderLittle;
295295
const uint8_t addr_size = 4;
296296
StreamString encoder(Stream::eBinary, addr_size, byte_order);
@@ -300,7 +300,7 @@ TEST_F(SymbolFileDWARFTests, TestAbbrevMissingTerminator) {
300300
encoder.PutULEB128(DW_AT_name);
301301
encoder.PutULEB128(DW_FORM_strp);
302302
// Don't add the NULL DW_AT and NULL DW_FORM terminator
303-
303+
304304
DWARFDataExtractor data;
305305
data.SetData(encoder.GetData(), encoder.GetSize(), byte_order);
306306
DWARFAbbreviationDeclarationSet abbrev_set;
@@ -346,3 +346,42 @@ TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) {
346346
llvm::toString(std::move(error)));
347347
EXPECT_EQ(off, 12U); // Parser should read no further than the segment size
348348
}
349+
350+
TEST_F(SymbolFileDWARFTests, ParseAranges) {
351+
// Test we can successfully parse a DWARFDebugAranges. The initial error
352+
// checking code had a bug where it would always return an empty address
353+
// ranges for everything in .debug_aranges and no error.
354+
const unsigned char binary_data[] = {
355+
60, 0, 0, 0, // unit_length
356+
2, 0, // DWARF version number
357+
255, 0, 0, 0, // offset into the .debug_info_table
358+
8, // address size
359+
0, // segment size
360+
0, 0, 0, 0, // pad bytes
361+
// BEGIN TUPLES
362+
// First tuple: [0x1000-0x1100)
363+
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000
364+
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
365+
// Second tuple: [0x2000-0x2100)
366+
0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000
367+
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size 0x0100
368+
// Terminating tuple
369+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator
370+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Terminator
371+
};
372+
DWARFDataExtractor data;
373+
data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,
374+
lldb::ByteOrder::eByteOrderLittle);
375+
DWARFDebugAranges debug_aranges;
376+
llvm::Error error = debug_aranges.extract(data);
377+
ASSERT_FALSE(bool(error));
378+
EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);
379+
EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);
380+
EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);
381+
EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);
382+
EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);
383+
EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);
384+
EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);
385+
EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u);
386+
EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);
387+
}

0 commit comments

Comments
 (0)