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
diff --git a/compiler/debug/dwarf/dwarf_test.cc b/compiler/debug/dwarf/dwarf_test.cc
index 8897e45..8fdc7ca 100644
--- a/compiler/debug/dwarf/dwarf_test.cc
+++ b/compiler/debug/dwarf/dwarf_test.cc
@@ -131,7 +131,7 @@
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 @@
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 @@
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 765a81d..d0ca6db 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -215,8 +215,8 @@
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 @@
}
}, [&](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 d77012f..b48d089 100644
--- a/libelffile/dwarf/headers.h
+++ b/libelffile/dwarf/headers.h
@@ -46,22 +46,26 @@
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.
- if (is64bit) {
- writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata8); // R: Pointer encoding.
- } else {
- writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata4); // R: Pointer encoding.
- }
writer.PushData(opcodes.data());
writer.Pad(is64bit ? 8 : 4);
- writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4);
+ if (is64bit) {
+ writer.UpdateUint64(cie_header_start_ + 4, writer.data()->size() - cie_header_start_ - 12);
+ } else {
+ 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 @@
/*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 266c638..54aade7 100644
--- a/libelffile/elf/elf_debug_reader.h
+++ b/libelffile/elf/elf_debug_reader.h
@@ -43,11 +43,41 @@
// 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 @@
// 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 @@
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 506661a..14cd6a8 100644
--- a/tools/create_minidebuginfo/create_minidebuginfo.cc
+++ b/tools/create_minidebuginfo/create_minidebuginfo.cc
@@ -122,7 +122,7 @@
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));
}