1. Fix CFI for quick compiled code in x86 & x86_64;
2. Emit CFI in .eh_frame instead of .debug_frame.
With CFI, we can correctly unwind past quick generated code.
Now gdb should unwind to main() for both x86 & x86_64 host-side ART.
Note that it does not work with relocation yet.
Testing:
1. art/test/run-test --host --gdb [--64] --no-relocate 005
2. In gdb, run 'b art_quick_invoke_stub', then 'r', then 'c' a few times
3. In gdb, run 'bt'. You should see stack frames down to main()
Change-Id: I5350d4097dc3d360a60cb17c94f1d02b99bc58bb
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index e5402e1..594c65f 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1033,18 +1033,13 @@
}
static bool IsFDE(FDE* frame) {
- // TODO This seems to be the constant everyone uses (for the .debug_frame
- // section at least), however we should investigate this further.
- const uint32_t kDwarfCIE_id = 0xffffffff;
- const uint32_t kReservedLengths[] = {0xffffffff, 0xfffffff0};
- return frame->CIE_pointer != kDwarfCIE_id &&
- frame->raw_length_ != kReservedLengths[0] && frame->raw_length_ != kReservedLengths[1];
+ return frame->CIE_pointer != 0;
}
// TODO This only works for 32-bit Elf Files.
-static bool FixupDebugFrame(uintptr_t text_start, byte* dbg_frame, size_t dbg_frame_size) {
- FDE* last_frame = reinterpret_cast<FDE*>(dbg_frame + dbg_frame_size);
- FDE* frame = NextFDE(reinterpret_cast<FDE*>(dbg_frame));
+static bool FixupEHFrame(uintptr_t text_start, byte* eh_frame, size_t eh_frame_size) {
+ FDE* last_frame = reinterpret_cast<FDE*>(eh_frame + eh_frame_size);
+ FDE* frame = NextFDE(reinterpret_cast<FDE*>(eh_frame));
for (; frame < last_frame; frame = NextFDE(frame)) {
if (!IsFDE(frame)) {
return false;
@@ -1301,7 +1296,7 @@
static bool FixupDebugSections(const byte* dbg_abbrev, size_t dbg_abbrev_size,
uintptr_t text_start,
byte* dbg_info, size_t dbg_info_size,
- byte* dbg_frame, size_t dbg_frame_size) {
+ byte* eh_frame, size_t eh_frame_size) {
std::unique_ptr<DebugAbbrev> abbrev(DebugAbbrev::Create(dbg_abbrev, dbg_abbrev_size));
if (abbrev.get() == nullptr) {
return false;
@@ -1313,7 +1308,7 @@
return false;
}
return FixupDebugInfo(text_start, iter.get())
- && FixupDebugFrame(text_start, dbg_frame, dbg_frame_size);
+ && FixupEHFrame(text_start, eh_frame, eh_frame_size);
}
void ElfFile::GdbJITSupport() {
@@ -1334,20 +1329,15 @@
// Do we have interesting sections?
const Elf32_Shdr* debug_info = all.FindSectionByName(".debug_info");
const Elf32_Shdr* debug_abbrev = all.FindSectionByName(".debug_abbrev");
- const Elf32_Shdr* debug_frame = all.FindSectionByName(".debug_frame");
+ const Elf32_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
const Elf32_Shdr* debug_str = all.FindSectionByName(".debug_str");
const Elf32_Shdr* strtab_sec = all.FindSectionByName(".strtab");
const Elf32_Shdr* symtab_sec = all.FindSectionByName(".symtab");
Elf32_Shdr* text_sec = all.FindSectionByName(".text");
- if (debug_info == nullptr || debug_abbrev == nullptr || debug_frame == nullptr ||
+ if (debug_info == nullptr || debug_abbrev == nullptr || eh_frame == nullptr ||
debug_str == nullptr || text_sec == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
return;
}
-#ifdef __LP64__
- if (true) {
- return; // No ELF debug support in 64bit.
- }
-#endif
// We need to add in a strtab and symtab to the image.
// all is MAP_PRIVATE so it can be written to freely.
// We also already have strtab and symtab so we are fine there.
@@ -1364,7 +1354,7 @@
if (!FixupDebugSections(
all.Begin() + debug_abbrev->sh_offset, debug_abbrev->sh_size, text_sec->sh_addr,
all.Begin() + debug_info->sh_offset, debug_info->sh_size,
- all.Begin() + debug_frame->sh_offset, debug_frame->sh_size)) {
+ all.Begin() + eh_frame->sh_offset, eh_frame->sh_size)) {
LOG(ERROR) << "Failed to load GDB data";
return;
}