diff options
author | 2021-06-25 17:37:32 -0700 | |
---|---|---|
committer | 2021-07-01 00:37:35 +0000 | |
commit | 546243375d7e129aa02ca7ea9663ed7c40b4880e (patch) | |
tree | adc158db1f6d6d6c482ac88462ad687a63d8267d | |
parent | 7ffab8106445905d30fdef6291ebd18765c961f0 (diff) |
libelffile: move to DWARF3 when writing .debug_frame.
zR augmentation in .debug_frame isn't recognized by llvm-dwarfdump.
This leads to below test failure after compiler update:
DwarfTest.DebugFrame
DwarfTest.x86_64_RegisterMapping
So switch to DWARF3, which supports 64-bit format without using zR
augmentation.
Bug: 192012848
Test: run art-test
Change-Id: Ib37c0bba7a293ae7b04c8cc0e9e09c045bcc0287
-rw-r--r-- | compiler/debug/dwarf/dwarf_test.cc | 6 | ||||
-rw-r--r-- | compiler/debug/elf_debug_writer.cc | 8 | ||||
-rw-r--r-- | libelffile/dwarf/headers.h | 37 | ||||
-rw-r--r-- | libelffile/elf/elf_debug_reader.h | 59 | ||||
-rw-r--r-- | tools/create_minidebuginfo/create_minidebuginfo.cc | 2 |
5 files changed, 83 insertions, 29 deletions
diff --git a/compiler/debug/dwarf/dwarf_test.cc b/compiler/debug/dwarf/dwarf_test.cc index 8897e45584..8fdc7ca63a 100644 --- a/compiler/debug/dwarf/dwarf_test.cc +++ b/compiler/debug/dwarf/dwarf_test.cc @@ -131,7 +131,7 @@ TEST_F(DwarfTest, DebugFrame) { CheckObjdumpOutput(is64bit, "-debug-frame"); } -TEST_F(DwarfTest, DISABLED_DebugFrame64) { +TEST_F(DwarfTest, DebugFrame64) { constexpr bool is64bit = true; DebugFrameOpCodeWriter<> initial_opcodes; WriteCIE(is64bit, Reg(16), initial_opcodes, &debug_frame_data_); @@ -143,7 +143,7 @@ TEST_F(DwarfTest, DISABLED_DebugFrame64) { 0x0200000000000000, ArrayRef<const uint8_t>(*opcodes.data()), &debug_frame_data_); - DW_CHECK("FDE cie=00000000 pc=100000000000000..300000000000000"); + DW_CHECK("FDE cie=00000000 pc=100000000000000...300000000000000"); CheckObjdumpOutput(is64bit, "-debug-frame"); } @@ -158,7 +158,7 @@ TEST_F(DwarfTest, x86_64_RegisterMapping) { opcodes.RelOffset(Reg::X86_64Core(i), 0); } DW_CHECK("FDE"); - DW_CHECK_NEXT("DWARF32"); + DW_CHECK_NEXT("DWARF64"); DW_CHECK_NEXT("DW_CFA_nop:"); // TODO: Why is a nop here. DW_CHECK_NEXT("DW_CFA_offset: RAX 0"); DW_CHECK_NEXT("DW_CFA_offset: RCX 0"); diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index 765a81d4f8..d0ca6db005 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -215,8 +215,8 @@ std::vector<uint8_t> MakeElfFileForJIT( reader.VisitDebugFrame([&](const Reader::CIE* cie ATTRIBUTE_UNUSED) { num_cies++; }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) { - DCHECK_EQ(fde->sym_addr, method_info.code_address); - DCHECK_EQ(fde->sym_size, method_info.code_size); + DCHECK_EQ(fde->sym_addr(), method_info.code_address); + DCHECK_EQ(fde->sym_size(), method_info.code_size); num_fdes++; }); DCHECK_EQ(num_syms, 1u); @@ -308,8 +308,8 @@ std::vector<uint8_t> PackElfFileForJIT( } }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) { DCHECK(copied_cie); - DCHECK_EQ(fde->cie_pointer, 0); - if (!is_removed_symbol(fde->sym_addr)) { + DCHECK_EQ(fde->cie_pointer(), 0); + if (!is_removed_symbol(fde->sym_addr())) { debug_frame->WriteFully(fde->data(), fde->size()); } }); diff --git a/libelffile/dwarf/headers.h b/libelffile/dwarf/headers.h index d77012ffe3..b48d089bc4 100644 --- a/libelffile/dwarf/headers.h +++ b/libelffile/dwarf/headers.h @@ -46,22 +46,26 @@ void WriteCIE(bool is64bit, Writer<> writer(buffer); size_t cie_header_start_ = writer.data()->size(); - writer.PushUint32(0); // Length placeholder. - writer.PushUint32(0xFFFFFFFF); // CIE id. - writer.PushUint8(1); // Version. - writer.PushString("zR"); + if (is64bit) { + writer.PushUint32(0xFFFFFFFF); + writer.PushUint64(0); // Length placeholder. + writer.PushUint64(0xFFFFFFFFFFFFFFFFull); // CIE id. + } else { + writer.PushUint32(0); // Length placeholder. + writer.PushUint32(0xFFFFFFFF); // CIE id. + } + writer.PushUint8(3); // Version. + writer.PushString(""); // Augmentation. writer.PushUleb128(DebugFrameOpCodeWriter<Vector>::kCodeAlignmentFactor); writer.PushSleb128(DebugFrameOpCodeWriter<Vector>::kDataAlignmentFactor); writer.PushUleb128(return_address_register.num()); // ubyte in DWARF2. - writer.PushUleb128(1); // z: Augmentation data size. + writer.PushData(opcodes.data()); + writer.Pad(is64bit ? 8 : 4); if (is64bit) { - writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata8); // R: Pointer encoding. + writer.UpdateUint64(cie_header_start_ + 4, writer.data()->size() - cie_header_start_ - 12); } else { - writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata4); // R: Pointer encoding. + writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4); } - writer.PushData(opcodes.data()); - writer.Pad(is64bit ? 8 : 4); - writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4); } // Write frame description entry (FDE) to .debug_frame or .eh_frame section. @@ -74,20 +78,27 @@ void WriteFDE(bool is64bit, /*inout*/ std::vector<uint8_t>* buffer) { Writer<> writer(buffer); size_t fde_header_start = writer.data()->size(); - writer.PushUint32(0); // Length placeholder. - writer.PushUint32(cie_pointer); // Relocate code_address if it has absolute value. if (is64bit) { + writer.PushUint32(0xFFFFFFFF); + writer.PushUint64(0); // Length placeholder. + writer.PushUint64(cie_pointer); writer.PushUint64(code_address); writer.PushUint64(code_size); } else { + writer.PushUint32(0); // Length placeholder. + writer.PushUint32(cie_pointer); writer.PushUint32(code_address); writer.PushUint32(code_size); } writer.PushUleb128(0); // Augmentation data size. writer.PushData(opcodes.data(), opcodes.size()); writer.Pad(is64bit ? 8 : 4); - writer.UpdateUint32(fde_header_start, writer.data()->size() - fde_header_start - 4); + if (is64bit) { + writer.UpdateUint64(fde_header_start + 4, writer.data()->size() - fde_header_start - 12); + } else { + writer.UpdateUint32(fde_header_start, writer.data()->size() - fde_header_start - 4); + } } // Write compilation unit (CU) to .debug_info section. diff --git a/libelffile/elf/elf_debug_reader.h b/libelffile/elf/elf_debug_reader.h index 266c638473..54aade7fe7 100644 --- a/libelffile/elf/elf_debug_reader.h +++ b/libelffile/elf/elf_debug_reader.h @@ -43,11 +43,41 @@ class ElfDebugReader { // Call Frame Information. struct CFI { - uint32_t length; // Length excluding the size of this field. - int32_t cie_pointer; // Offset in the section or -1 for CIE. - const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(this); } - size_t size() const { return sizeof(uint32_t) + length; } + const uint32_t* data_u32() const { return reinterpret_cast<const uint32_t*>(this); } + uint32_t* data_u32() { return reinterpret_cast<uint32_t*>(this); } + + bool is_64bit() const { + return data_u32()[0] == 0xFFFFFFFF; + } + + size_t size() const { + const uint32_t* s = data_u32(); + if (is_64bit()) { + return 12 + (static_cast<uint64_t>(s[2]) << 32) + s[1]; + } + return 4 + s[0]; + } + + // Offset in the section or -1 for CIE. + int64_t cie_pointer() const { + const uint32_t* s = data_u32(); + if (is_64bit()) { + return static_cast<int64_t>((static_cast<uint64_t>(s[4]) << 32) + s[3]); + } + return static_cast<int32_t>(s[1]); + } + + void set_cie_pointer(uint64_t cie_pointer) { + uint32_t* s = data_u32(); + if (is_64bit()) { + s[3] = cie_pointer & 0xFFFFFFFF; + s[4] = cie_pointer >> 32; + } else { + s[1] = static_cast<uint32_t>(cie_pointer); + } + } + } PACKED(1); // Common Information Entry. @@ -56,8 +86,21 @@ class ElfDebugReader { // Frame Description Entry. struct FDE : public CFI { - Elf_Addr sym_addr; - Elf_Addr sym_size; + Elf_Addr sym_addr() const { + const uint32_t* s = this->data_u32(); + if (this->is_64bit()) { + return (static_cast<uint64_t>(s[6]) << 32) + s[5]; + } + return s[2]; + } + + Elf_Addr sym_size() const { + const uint32_t* s = this->data_u32(); + if (this->is_64bit()) { + return (static_cast<uint64_t>(s[8]) << 32) + s[7]; + } + return s[3]; + } } PACKED(1); explicit ElfDebugReader(ArrayRef<const uint8_t> file) : file_(file) { @@ -157,11 +200,11 @@ class ElfDebugReader { for (size_t offset = 0; offset < debug_frame->sh_size;) { const CFI* entry = Read<CFI>(debug_frame->sh_offset + offset); DCHECK_LE(entry->size(), debug_frame->sh_size - offset); - if (entry->cie_pointer == -1) { + if (entry->cie_pointer() == -1) { visit_cie(Read<CIE>(debug_frame->sh_offset + offset)); } else { const FDE* fde = Read<FDE>(debug_frame->sh_offset + offset); - visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer)); + visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer())); } offset += entry->size(); } diff --git a/tools/create_minidebuginfo/create_minidebuginfo.cc b/tools/create_minidebuginfo/create_minidebuginfo.cc index 506661a377..14cd6a8619 100644 --- a/tools/create_minidebuginfo/create_minidebuginfo.cc +++ b/tools/create_minidebuginfo/create_minidebuginfo.cc @@ -122,7 +122,7 @@ static void WriteMinidebugInfo(const std::vector<uint8_t>& input, std::vector<ui const FDE* fde = entry.first; const CIE* cie = entry.second; FDE new_header = *fde; - new_header.cie_pointer = new_cie_offset[cie]; + new_header.set_cie_pointer(new_cie_offset[cie]); debug_frame->WriteFully(&new_header, sizeof(FDE)); debug_frame->WriteFully(fde->data() + sizeof(FDE), fde->size() - sizeof(FDE)); } |