From b9c4ad20bf368493901a30298ad3f0278596e614 Mon Sep 17 00:00:00 2001 From: Wolfgang Pieb Date: Wed, 21 Jun 2017 19:37:44 +0000 Subject: [PATCH] [DWARF] Support for DW_FORM_strx3 and complete support for DW_FORM_strx{1,2,4} (consumer). Reviewer: aprantl Differential Revision: https://reviews.llvm.org/D34418 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305944 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/DataExtractor.h | 41 ++++++++++++ lib/DebugInfo/DWARF/DWARFFormValue.cpp | 18 +++++- lib/Support/DataExtractor.cpp | 7 +++ test/DebugInfo/Inputs/dwarfdump-str-offsets.s | 59 +++++++++++++++++- .../Inputs/dwarfdump-str-offsets.x86_64.o | Bin 4000 -> 4344 bytes test/DebugInfo/dwarfdump-str-offsets.test | 36 ++++++++--- 6 files changed, 148 insertions(+), 13 deletions(-) diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 380b628fd95..31447882a91 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -14,6 +14,30 @@ #include "llvm/Support/DataTypes.h" namespace llvm { + +/// An auxiliary type to facilitate extraction of 3-byte entities. +struct Uint24 { + uint8_t Bytes[3]; + Uint24(uint8_t U) { + Bytes[0] = Bytes[1] = Bytes[2] = U; + } + Uint24(uint8_t U0, uint8_t U1, uint8_t U2) { + Bytes[0] = U0; Bytes[1] = U1; Bytes[2] = U2; + } + uint32_t getAsUint32(bool IsLittleEndian) const { + int LoIx = IsLittleEndian ? 0 : 2; + return Bytes[LoIx] + (Bytes[1] << 8) + (Bytes[2-LoIx] << 16); + } +}; + +using uint24_t = Uint24; +static_assert(sizeof(uint24_t) == 3, "sizeof(uint24_t) != 3"); + +/// Needed by swapByteOrder(). +inline uint24_t getSwappedBytes(uint24_t C) { + return uint24_t(C.Bytes[2], C.Bytes[1], C.Bytes[0]); +} + class DataExtractor { StringRef Data; uint8_t IsLittleEndian; @@ -236,6 +260,23 @@ public: /// NULL otherise. uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const; + /// Extract a 24-bit unsigned value from \a *offset_ptr and return it + /// in a uint32_t. + /// + /// Extract 3 bytes from the binary data at the offset pointed to by + /// \a offset_ptr, construct a uint32_t from them and update the offset + /// on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the 3 bytes if the value is extracted correctly. If the offset + /// is out of bounds or there are not enough bytes to extract this value, + /// the offset will be left unmodified. + /// + /// @return + /// The extracted 24-bit value represented in a uint32_t. + uint32_t getU24(uint32_t *offset_ptr) const; + /// Extract a uint32_t value from \a *offset_ptr. /// /// Extract a single uint32_t from the binary data at the offset diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index ed1f5f46dcf..39c1f5fd5c5 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -138,6 +138,9 @@ static Optional getFixedByteSize(dwarf::Form Form, const T *U) { case DW_FORM_addrx2: return 2; + case DW_FORM_strx3: + return 3; + case DW_FORM_data4: case DW_FORM_ref4: case DW_FORM_ref_sup4: @@ -302,6 +305,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: case DW_FORM_strx: + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: return (FC == FC_String); case DW_FORM_implicit_const: return (FC == FC_Constant); @@ -368,6 +375,9 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data, case DW_FORM_addrx2: Value.uval = Data.getU16(OffsetPtr); break; + case DW_FORM_strx3: + Value.uval = Data.getU24(OffsetPtr); + break; case DW_FORM_data4: case DW_FORM_ref4: case DW_FORM_ref_sup4: @@ -545,6 +555,10 @@ void DWARFFormValue::dump(raw_ostream &OS) const { dumpString(OS); break; case DW_FORM_strx: + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: case DW_FORM_GNU_str_index: OS << format(" indexed (%8.8x) string = ", (uint32_t)UValue); dumpString(OS); @@ -623,7 +637,9 @@ Optional DWARFFormValue::getAsCString() const { if (Form == DW_FORM_GNU_strp_alt || U == nullptr) return None; uint32_t Offset = Value.uval; - if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx) { + if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx || + Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || + Form == DW_FORM_strx4) { uint64_t StrOffset; if (!U->getStringOffsetSectionItem(Offset, StrOffset)) return None; diff --git a/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp index 53c10bcc562..0199b300ba7 100644 --- a/lib/Support/DataExtractor.cpp +++ b/lib/Support/DataExtractor.cpp @@ -68,6 +68,13 @@ uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst, Data.data()); } +uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const { + uint24_t ExtractedVal = + getU(offset_ptr, this, IsLittleEndian, Data.data()); + // The 3 bytes are in the correct byte order for the host. + return ExtractedVal.getAsUint32(sys::IsLittleEndianHost); +} + uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const { return getU(offset_ptr, this, IsLittleEndian, Data.data()); } diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s index f395f4b872c..9ae59ec609c 100644 --- a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s +++ b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s @@ -20,6 +20,14 @@ str_TU: .asciz "Type_Unit" str_TU_type: .asciz "MyStruct" +str_Subprogram: + .asciz "MyFunc" +str_Variable1: + .asciz "MyVar1" +str_Variable2: + .asciz "MyVar2" +str_Variable3: + .asciz "MyVar3" # Every unit contributes to the string_offsets table. .section .debug_str_offsets,"",@progbits @@ -31,6 +39,10 @@ str_TU_type: .long str_producer .long str_CU1 .long str_CU1_dir + .long str_Subprogram + .long str_Variable1 + .long str_Variable2 + .long str_Variable3 .debug_str_offsets_segment0_end: # CU2's contribution .long .debug_str_offsets_segment1_end-.debug_str_offsets_base1 @@ -85,7 +97,7 @@ dwo_str_TU_5_type: .section .debug_abbrev,"",@progbits .byte 0x01 # Abbrev code .byte 0x11 # DW_TAG_compile_unit - .byte 0x00 # DW_CHILDREN_no + .byte 0x01 # DW_CHILDREN_yes .byte 0x25 # DW_AT_producer .byte 0x1a # DW_FORM_strx .byte 0x03 # DW_AT_name @@ -112,9 +124,37 @@ dwo_str_TU_5_type: .byte 0x1a # DW_FORM_strx .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) + .byte 0x04 # Abbrev code + .byte 0x2e # DW_TAG_subprogram + .byte 0x01 # DW_CHILDREN_yes + .byte 0x03 # DW_AT_name + .byte 0x25 # DW_FORM_strx1 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x05 # Abbrev code + .byte 0x34 # DW_TAG_variable + .byte 0x00 # DW_CHILDREN_no + .byte 0x03 # DW_AT_name + .byte 0x26 # DW_FORM_strx2 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x06 # Abbrev code + .byte 0x34 # DW_TAG_variable + .byte 0x00 # DW_CHILDREN_no + .byte 0x03 # DW_AT_name + .byte 0x27 # DW_FORM_strx3 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x07 # Abbrev code + .byte 0x34 # DW_TAG_variable + .byte 0x00 # DW_CHILDREN_no + .byte 0x03 # DW_AT_name + .byte 0x28 # DW_FORM_strx4 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) .byte 0x00 # EOM(3) -# And a .dwo copy for the .dwo sections. +# And a .dwo copy of a subset for the .dwo sections. .section .debug_abbrev.dwo,"",@progbits .byte 0x01 # Abbrev code .byte 0x11 # DW_TAG_compile_unit @@ -163,6 +203,21 @@ CU1_5_version: .byte 1 # The index of the CU name string .long .debug_str_offsets_base0 .byte 2 # The index of the comp dir string +# A subprogram DIE with DW_AT_name, using DW_FORM_strx1. + .byte 4 # Abbreviation code + .byte 3 # Subprogram name string (DW_FORM_strx1) +# A variable DIE with DW_AT_name, using DW_FORM_strx2. + .byte 5 # Abbreviation code + .short 0x0004 # Subprogram name string (DW_FORM_strx2) +# A variable DIE with DW_AT_name, using DW_FORM_strx3. + .byte 6 # Abbreviation code + .byte 5 # Subprogram name string (DW_FORM_strx3) + .short 0 # Subprogram name string (DW_FORM_strx3) +# A variable DIE with DW_AT_name, using DW_FORM_strx4. + .byte 7 # Abbreviation code + .quad 0x00000006 # Subprogram name string (DW_FORM_strx4) + .byte 0 # NULL + .byte 0 # NULL .byte 0 # NULL CU1_5_end: diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets.x86_64.o b/test/DebugInfo/Inputs/dwarfdump-str-offsets.x86_64.o index e15ac1c1542f7f7bac6310a7d7bc6a7d627f1dca..14753d82e10a0d4114d5e7023c087d8b6004bbb7 100644 GIT binary patch delta 1203 zcmZXTO=uHA6vyA&uXHy_gS4rzNsodDZ9#BmGb775hkb8;|Np$1-F@?@^>@75 zrDa34?v?o1;_>prIT%|!T`Z;Rp|2kL;Q#=b^wnvty?Kd9RgA@qUewze9RR%pz+#~j zAizQw&0`$fX%m~84c#=rGMQkp3iUznutIswI60|v5P$|D$PgBsZ|Wa&8lMHA*$-LX zMm5b{z3#0t{;Sq4cv4yQ#j9pOUg38HZ&P?d@T|g(I*&m?5%!P+2NE=*ciKP1EJs&# zcVCa<{Y>}u6n>)}_Iyse?72e;BZc>9(l~*y=rPN;=%e9ApLlgFIHOb;Cp1%PfaQ$r$mSWHll<&JTc z^@lg)|MOHvo@^HXxbV5mp^oF;WLT{UHhpx>0KHL zuHtRl3});tv2}qklySDjWj%;=Bs8c6k(NR^yg{!+!}bHOc>sn8!x{WUhr`46Pr-7u z7S3qj1GEv&X=#o2SSU2mP-9M;&}fN;n+>$ln8P{RZ5-CBOp0{i3o1t3uBz8e09m7c O6kd|w68TwWbNmJF(~U3y delta 910 zcmZWoO=uHA6n-=Nmrb&p#27Y-4O+0xHU|?yn|LresECMQp-AIF@Z?dCf|MeNn1hh? z13{rh528>!NWCZs_Ta%|dx~ECxrzr5Vm*k?OlD!(zGdgV`M&SHc{?+^JN@|JFyvp- zqsFq8B_eAye$NQ&tZEV~sGvjzNf1j3M@&4zI1cc^xkHAG9a4-8wSD6!{hq+no>U{E7szQYAjPKT2jG6 zytM-sZmy*UZ1Z^f6vIv?z((dY{$_63v?eyo7;P8bd(I^N5*}t(*fmtVw);$1?4a+p z(