llvm.org GIT mirror llvm / 4ca606f
[DWARF parser] Add basic support for DWZ DWARF multifile extensions. This change implements basic support for DWARF alternate sections proposal: http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open LLVM tools now understand new forms: DW_FORM_GNU_ref_alt and DW_FORM_GNU_strp_alt, which are used as references to .debug_info and .debug_str sections respectively, stored in a separate file, and possibly shared between different executables / shared objects. llvm-dwarfdump and llvm-symbolizer don't yet know how to access this alternate debug file (usually pointed by .gnu_debugaltlink section), but they can at lease properly parse and dump regular files, which refer to it. This change should fix crashes of llvm-dwarfdump and llvm-symbolizer on files produced by running "dwz" tool. Such files are already installed on some modern Linux distributions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237721 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 4 years ago
9 changed file(s) with 82 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
8686
8787 static ArrayRef getFixedFormSizes(uint8_t AddrSize,
8888 uint16_t Version);
89 private:
90 void dumpString(raw_ostream &OS, const DWARFUnit *U) const;
8991 };
9092
9193 }
284284
285285 // Extensions for Fission proposal
286286 DW_FORM_GNU_addr_index = 0x1f01,
287 DW_FORM_GNU_str_index = 0x1f02
287 DW_FORM_GNU_str_index = 0x1f02,
288
289 // Alternate debug sections proposal (output of "dwz" tool).
290 DW_FORM_GNU_ref_alt = 0x1f20,
291 DW_FORM_GNU_strp_alt = 0x1f21
288292 };
289293
290294 enum LocationAtom {
160160 // We have dumped the attribute raw value. For some attributes
161161 // having both the raw value and the pretty-printed value is
162162 // interesting. These attributes are handled below.
163 if ((attr == DW_AT_specification || attr == DW_AT_abstract_origin) &&
164 // The signature references aren't handled.
165 formValue.getForm() != DW_FORM_ref_sig8) {
166 uint32_t Ref = formValue.getAsReference(u).getValue();
167 DWARFDebugInfoEntryMinimal DIE;
168 if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref))
169 if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName))
170 OS << " \"" << Ref << '\"';
163 if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
164 Optional Ref = formValue.getAsReference(u);
165 if (Ref.hasValue()) {
166 uint32_t RefOffset = Ref.getValue();
167 DWARFDebugInfoEntryMinimal DIE;
168 if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset))
169 if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName))
170 OS << " \"" << Name << '\"';
171 }
171172 } else if (attr == DW_AT_APPLE_property_attribute) {
172173 if (Optional OptVal = formValue.getAsUnsignedConstant())
173174 dumpApplePropertyAttribute(OS, *OptVal);
112112 if (Form < ArrayRef(DWARF4FormClasses).size() &&
113113 DWARF4FormClasses[Form] == FC)
114114 return true;
115 // Check DW_FORM_ref_sig8 from DWARF4.
116 if (Form == DW_FORM_ref_sig8)
115 // Check more forms from DWARF4 and DWARF5 proposals.
116 switch (Form) {
117 case DW_FORM_ref_sig8:
118 case DW_FORM_GNU_ref_alt:
117119 return (FC == FC_Reference);
118 // Check for some DWARF5 forms.
119 if (Form == DW_FORM_GNU_addr_index)
120 case DW_FORM_GNU_addr_index:
120121 return (FC == FC_Address);
121 if (Form == DW_FORM_GNU_str_index)
122 case DW_FORM_GNU_str_index:
123 case DW_FORM_GNU_strp_alt:
122124 return (FC == FC_String);
125 }
123126 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
124127 // Don't check for DWARF version here, as some producers may still do this
125128 // by mistake.
198201 case DW_FORM_sdata:
199202 Value.sval = data.getSLEB128(offset_ptr);
200203 break;
201 case DW_FORM_strp: {
202 Value.uval = data.getU32(offset_ptr);
203 if (!cu)
204 break;
205 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
206 if (AI != cu->getRelocMap()->end())
207 Value.uval += AI->second.second;
208 break;
209 }
210204 case DW_FORM_udata:
211205 case DW_FORM_ref_udata:
212206 Value.uval = data.getULEB128(offset_ptr);
218212 Form = data.getULEB128(offset_ptr);
219213 indirect = true;
220214 break;
221 case DW_FORM_sec_offset: {
215 case DW_FORM_sec_offset:
216 case DW_FORM_strp:
217 case DW_FORM_GNU_ref_alt:
218 case DW_FORM_GNU_strp_alt: {
222219 // FIXME: This is 64-bit for DWARF64.
223220 Value.uval = data.getU32(offset_ptr);
224221 if (!cu)
225222 break;
226 RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
223 RelocAddrMap::const_iterator AI =
224 cu->getRelocMap()->find(*offset_ptr - 4);
227225 if (AI != cu->getRelocMap()->end())
228 Value.uval += AI->second.second;
226 Value.uval += AI->second.second;
229227 break;
230228 }
231229 case DW_FORM_flag_present:
322320 return true;
323321
324322 // 4 byte values
325 case DW_FORM_strp:
326323 case DW_FORM_data4:
327324 case DW_FORM_ref4:
328325 *offset_ptr += 4;
352349
353350 // FIXME: 4 for DWARF32, 8 for DWARF64.
354351 case DW_FORM_sec_offset:
352 case DW_FORM_strp:
353 case DW_FORM_GNU_ref_alt:
354 case DW_FORM_GNU_strp_alt:
355355 *offset_ptr += 4;
356356 return true;
357357
423423 case DW_FORM_udata: OS << Value.uval; break;
424424 case DW_FORM_strp: {
425425 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
426 Optional DbgStr = getAsCString(cu);
427 if (DbgStr.hasValue()) {
428 raw_ostream &COS = WithColor(OS, syntax::String);
429 COS << '"';
430 COS.write_escaped(DbgStr.getValue());
431 COS << '"';
432 }
426 dumpString(OS, cu);
433427 break;
434428 }
435429 case DW_FORM_GNU_str_index: {
436430 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
437 Optional DbgStr = getAsCString(cu);
438 if (DbgStr.hasValue()) {
439 raw_ostream &COS = WithColor(OS, syntax::String);
440 COS << '"';
441 COS.write_escaped(DbgStr.getValue());
442 COS << '"';
443 }
431 dumpString(OS, cu);
432 break;
433 }
434 case DW_FORM_GNU_strp_alt: {
435 OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue);
436 dumpString(OS, cu);
444437 break;
445438 }
446439 case DW_FORM_ref_addr:
465458 case DW_FORM_ref_udata:
466459 cu_relative_offset = true;
467460 OS << format("cu + 0x%" PRIx64, uvalue);
461 break;
462 case DW_FORM_GNU_ref_alt:
463 OS << format("", uvalue);
468464 break;
469465
470466 // All DW_FORM_indirect attributes should be resolved prior to calling
491487 }
492488 }
493489
490 void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
491 Optional DbgStr = getAsCString(U);
492 if (DbgStr.hasValue()) {
493 raw_ostream &COS = WithColor(OS, syntax::String);
494 COS << '"';
495 COS.write_escaped(DbgStr.getValue());
496 COS << '"';
497 }
498 }
499
494500 Optional DWARFFormValue::getAsCString(const DWARFUnit *U) const {
495501 if (!isFormClass(FC_String))
496502 return None;
497503 if (Form == DW_FORM_string)
498504 return Value.cstr;
499 if (!U)
505 // FIXME: Add support for DW_FORM_GNU_strp_alt
506 if (Form == DW_FORM_GNU_strp_alt || U == nullptr)
500507 return None;
501508 uint32_t Offset = Value.uval;
502509 if (Form == DW_FORM_GNU_str_index) {
538545 return Value.uval + U->getOffset();
539546 case DW_FORM_ref_addr:
540547 return Value.uval;
541 // FIXME: Add proper support for DW_FORM_ref_sig8
548 // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt.
542549 default:
543 return Value.uval;
550 return None;
544551 }
545552 }
546553
232232 // DWARF5 Fission Extension Forms
233233 case DW_FORM_GNU_addr_index: return "DW_FORM_GNU_addr_index";
234234 case DW_FORM_GNU_str_index: return "DW_FORM_GNU_str_index";
235
236 // Alternate debug sections proposal (output of "dwz" tool).
237 case DW_FORM_GNU_ref_alt: return "DW_FORM_GNU_ref_alt";
238 case DW_FORM_GNU_strp_alt: return "DW_FORM_GNU_strp_alt";
235239 }
236240 return nullptr;
237241 }
2020 // $ cp dwarfdump-test.cc /tmp/dbginfo
2121 // $ cd /tmp/dbginfo
2222 // $ clang++ -g dwarfdump-test.cc -o
23
24 // The result is also used as an input to .dwz tool:
25 // $ cp output1.dwz
26 // $ cp output2.dwz
27 // $ dwz -m output.dwz -r output1.dwz output2.dwz
28 // $ rm output2.dwz
0 ; RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-dwz.elf-x86-64 -debug-dump=info | FileCheck %s -check-prefix DUMP_INFO
1
2 ; DUMP_INFO: .debug_info
3 ; DUMP_INFO: DW_TAG_compile_unit [2] *
4 ; DUMP_INFO-NEXT: DW_AT_producer [DW_FORM_GNU_strp_alt] (alt indirect string, offset: 0x0)
5 ; DUMP_INFO-NEXT: DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
6 ; DUMP_INFO-NEXT: DW_AT_name [DW_FORM_GNU_strp_alt] (alt indirect string, offset: 0x31)
7 ; DUMP_INFO-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
8 ; DUMP_INFO-NEXT: DW_AT_stmt_list [DW_FORM_data4] (0x00000000)
9 ; DUMP_INFO-NEXT: DW_AT_comp_dir [DW_FORM_GNU_strp_alt] (alt indirect string, offset: 0x6b)
10
11 ; DUMP_INFO: DW_TAG_imported_unit [4]
12 ; DUMP_INFO-NEXT: DW_AT_import [DW_FORM_GNU_ref_alt] ()
13