diff options
author | David Srbecky <dsrbecky@google.com> | 2015-04-17 21:14:10 +0100 |
---|---|---|
committer | David Srbecky <dsrbecky@google.com> | 2015-04-21 19:47:42 +0100 |
commit | 527c9c71f0c6e2f9943ac028e7c050500699a44b (patch) | |
tree | 09e6794e5b184ce33ca468c972a8ef2faff7f174 /compiler/dwarf | |
parent | e7bee3b7d307508243f4a00b5cf8a8867fcaaff5 (diff) | |
download | art-527c9c71f0c6e2f9943ac028e7c050500699a44b.zip art-527c9c71f0c6e2f9943ac028e7c050500699a44b.tar.gz art-527c9c71f0c6e2f9943ac028e7c050500699a44b.tar.bz2 |
Generate .eh_frame_hdr section and PT_GNU_EH_FRAME segment.
Fixes issue 20125400 - ART: Need .eh_frame_hdr and PT_GNU_EH_FRAME
for libunwind.
.eh_frame_hdr serves two purposes. Firstly, it can optionally contain
binary search table for fast eh_frame lookup. This is important for
C++ exception handling, but we do not need it so we omit it.
Secondly, it contains a relative .eh_frame pointer which makes it
easier for run-time code to locate the .eh_frame section.
libunwind seems to rely on this relative pointer.
Bug: 20125400
Change-Id: I7c1e3f68d914f70781404c508395831a3296a7da
Diffstat (limited to 'compiler/dwarf')
-rw-r--r-- | compiler/dwarf/dwarf_constants.h | 22 | ||||
-rw-r--r-- | compiler/dwarf/dwarf_test.cc | 10 | ||||
-rw-r--r-- | compiler/dwarf/dwarf_test.h | 20 | ||||
-rw-r--r-- | compiler/dwarf/headers.h | 9 |
4 files changed, 45 insertions, 16 deletions
diff --git a/compiler/dwarf/dwarf_constants.h b/compiler/dwarf/dwarf_constants.h index 8e39ca7..61a44cd 100644 --- a/compiler/dwarf/dwarf_constants.h +++ b/compiler/dwarf/dwarf_constants.h @@ -658,6 +658,28 @@ enum CallFrameInstruction : uint8_t { DW_CFA_hi_user = 0x3f }; +enum ExceptionHeaderValueFormat : uint8_t { + DW_EH_PE_native = 0x00, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_omit = 0xFF, +}; + +enum ExceptionHeaderValueApplication : uint8_t { + DW_EH_PE_absptr = 0x00, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, +}; + } // namespace dwarf } // namespace art diff --git a/compiler/dwarf/dwarf_test.cc b/compiler/dwarf/dwarf_test.cc index 98f691a..edba00a 100644 --- a/compiler/dwarf/dwarf_test.cc +++ b/compiler/dwarf/dwarf_test.cc @@ -16,6 +16,7 @@ #include "dwarf_test.h" +#include "dwarf/dwarf_constants.h" #include "dwarf/debug_frame_opcode_writer.h" #include "dwarf/debug_info_entry_writer.h" #include "dwarf/debug_line_opcode_writer.h" @@ -119,7 +120,8 @@ TEST_F(DwarfTest, DebugFrame) { DW_CHECK_NEXT("DW_CFA_restore: r5 (ebp)"); DebugFrameOpCodeWriter<> initial_opcodes; - WriteEhFrameCIE(is64bit, Reg(is64bit ? 16 : 8), initial_opcodes, &eh_frame_data_); + WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(is64bit ? 16 : 8), + initial_opcodes, &eh_frame_data_); std::vector<uintptr_t> eh_frame_patches; std::vector<uintptr_t> expected_patches { 28 }; // NOLINT WriteEhFrameFDE(is64bit, 0, 0x01000000, 0x01000000, opcodes.data(), @@ -132,7 +134,8 @@ TEST_F(DwarfTest, DebugFrame) { TEST_F(DwarfTest, DebugFrame64) { constexpr bool is64bit = true; DebugFrameOpCodeWriter<> initial_opcodes; - WriteEhFrameCIE(is64bit, Reg(16), initial_opcodes, &eh_frame_data_); + WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16), + initial_opcodes, &eh_frame_data_); DebugFrameOpCodeWriter<> opcodes; std::vector<uintptr_t> eh_frame_patches; std::vector<uintptr_t> expected_patches { 32 }; // NOLINT @@ -170,7 +173,8 @@ TEST_F(DwarfTest, x86_64_RegisterMapping) { DW_CHECK_NEXT("DW_CFA_offset: r14 (r14)"); DW_CHECK_NEXT("DW_CFA_offset: r15 (r15)"); DebugFrameOpCodeWriter<> initial_opcodes; - WriteEhFrameCIE(is64bit, Reg(16), initial_opcodes, &eh_frame_data_); + WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16), + initial_opcodes, &eh_frame_data_); std::vector<uintptr_t> eh_frame_patches; WriteEhFrameFDE(is64bit, 0, 0x0100000000000000, 0x0200000000000000, opcodes.data(), &eh_frame_data_, &eh_frame_patches); diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h index dd5e0c2..cbe700a 100644 --- a/compiler/dwarf/dwarf_test.h +++ b/compiler/dwarf/dwarf_test.h @@ -100,30 +100,30 @@ class DwarfTest : public CommonRuntimeTest { Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> builder( &code, file.GetFile(), isa, 0, 0, 0, 0, 0, 0, false, false); typedef ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> Section; + Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); + Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); + Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); + Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0); + Section eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); if (!debug_info_data_.empty()) { - Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); debug_info.SetBuffer(debug_info_data_); - builder.RegisterRawSection(debug_info); + builder.RegisterRawSection(&debug_info); } if (!debug_abbrev_data_.empty()) { - Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); debug_abbrev.SetBuffer(debug_abbrev_data_); - builder.RegisterRawSection(debug_abbrev); + builder.RegisterRawSection(&debug_abbrev); } if (!debug_str_data_.empty()) { - Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); debug_str.SetBuffer(debug_str_data_); - builder.RegisterRawSection(debug_str); + builder.RegisterRawSection(&debug_str); } if (!debug_line_data_.empty()) { - Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0); debug_line.SetBuffer(debug_line_data_); - builder.RegisterRawSection(debug_line); + builder.RegisterRawSection(&debug_line); } if (!eh_frame_data_.empty()) { - Section eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); eh_frame.SetBuffer(eh_frame_data_); - builder.RegisterRawSection(eh_frame); + builder.RegisterRawSection(&eh_frame); } builder.Init(); builder.Write(); diff --git a/compiler/dwarf/headers.h b/compiler/dwarf/headers.h index 760f53c..9f64766 100644 --- a/compiler/dwarf/headers.h +++ b/compiler/dwarf/headers.h @@ -22,6 +22,7 @@ #include "dwarf/debug_frame_opcode_writer.h" #include "dwarf/debug_info_entry_writer.h" #include "dwarf/debug_line_opcode_writer.h" +#include "dwarf/dwarf_constants.h" #include "dwarf/register.h" #include "dwarf/writer.h" @@ -36,7 +37,9 @@ namespace dwarf { // Write common information entry (CIE) to .eh_frame section. template<typename Allocator> -void WriteEhFrameCIE(bool is64bit, Reg return_address_register, +void WriteEhFrameCIE(bool is64bit, + ExceptionHeaderValueApplication address_type, + Reg return_address_register, const DebugFrameOpCodeWriter<Allocator>& opcodes, std::vector<uint8_t>* eh_frame) { Writer<> writer(eh_frame); @@ -50,9 +53,9 @@ void WriteEhFrameCIE(bool is64bit, Reg return_address_register, writer.PushUleb128(return_address_register.num()); // ubyte in DWARF2. writer.PushUleb128(1); // z: Augmentation data size. if (is64bit) { - writer.PushUint8(0x04); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8). + writer.PushUint8(address_type | DW_EH_PE_udata8); // R: Pointer encoding. } else { - writer.PushUint8(0x03); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4). + writer.PushUint8(address_type | DW_EH_PE_udata4); // R: Pointer encoding. } writer.PushData(opcodes.data()); writer.Pad(is64bit ? 8 : 4); |