From 5ee9dd0b2433c20bdf3ee921025baad8488ff02f Mon Sep 17 00:00:00 2001 From: Landon Fuller Date: Fri, 28 Jun 2013 15:07:18 -0400 Subject: [PATCH] Fix calculation of the CIE offset in eh_frame FDE records. Our initial implementation assumed that the offset was applied to the address of the FDE record's length field. In implementing integration tests against live DWARF data, it was demonstrated that this offset is actually calculated from the address of the FDE record *after* the initial length field. --- .../dwarf_encoding_test.h | 8 ++++++-- .../PLCrashAsyncDwarfEncodingTests/test.c | 10 +++++----- .../PLCrashAsyncDwarfEncodingTests/test.ios | Bin 33232 -> 33232 bytes .../test.macosx | Bin 24996 -> 24996 bytes .../PLCrashAsyncDwarfEncodingTests/test.sim | Bin 8608 -> 8608 bytes Source/PLCrashAsyncDwarfEncodingTests.m | 4 ++-- Source/PLCrashAsyncDwarfFDE.c | 6 ++---- Source/PLCrashAsyncDwarfFDETests.m | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h index 2eb575e..851d929 100644 --- a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h +++ b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h @@ -47,9 +47,13 @@ typedef struct pl_cfi_entry { }; } pl_cfi_entry; +/* Initial length field size */ +#define PL_CFI_LEN_SIZE_64 (sizeof(uint32_t) + sizeof(uint64_t)) +#define PL_CFI_LEN_SIZE_32 (sizeof(uint32_t)) + /* CFE lengths, minus the initial length field. */ -#define PL_CFI_LEN_64 (sizeof(pl_cfi_entry) - sizeof(uint32_t) - sizeof(uint64_t)) -#define PL_CFI_LEN_32 (sizeof(pl_cfi_entry) - sizeof(uint32_t)) +#define PL_CFI_SIZE_64 (sizeof(pl_cfi_entry) - sizeof(uint32_t) - sizeof(uint64_t)) +#define PL_CFI_SIZE_32 (sizeof(pl_cfi_entry) - sizeof(uint32_t)) /* PC values to be used when searching for FDE entries. */ #define PL_CFI_EH_FRAME_PC 0x60 diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c index c43867e..ed513e4 100644 --- a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c +++ b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c @@ -8,7 +8,7 @@ pl_cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = { { .hdr_64 = { .flag64 = UINT32_MAX, - .length = PL_CFI_LEN_64, + .length = PL_CFI_SIZE_64, .cie_id = 0, }, @@ -31,8 +31,8 @@ pl_cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = { { .hdr_64 = { .flag64 = UINT32_MAX, - .length = PL_CFI_LEN_64, - .cie_id = sizeof(ef[0]), // Offset to the first CIE entry + .length = PL_CFI_SIZE_64, + .cie_id = sizeof(ef[0]) + PL_CFI_LEN_SIZE_64, // Offset to the first CIE entry }, .fde_64 = { .initial_location = PL_CFI_EH_FRAME_PC, @@ -55,7 +55,7 @@ pl_cfi_entry df[] __attribute__((section("__PL_DWARF,__debug_frame"))) = { { .hdr_64 = { .flag64 = UINT32_MAX, - .length = PL_CFI_LEN_64, + .length = PL_CFI_SIZE_64, .cie_id = UINT64_MAX, }, @@ -78,7 +78,7 @@ pl_cfi_entry df[] __attribute__((section("__PL_DWARF,__debug_frame"))) = { { .hdr_64 = { .flag64 = UINT32_MAX, - .length = PL_CFI_LEN_64, + .length = PL_CFI_SIZE_64, .cie_id = 0, // Offset to the first CIE entry }, .fde_64 = { diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios index e3a52ae5de09537b6321fc33275b916e3d215900..64e89d5e09ef10f1098643af711bca48431e360e 100755 GIT binary patch delta 85 zcmcc6%ygldX~PpCf$A~~JH8_(EDO$fY(4t1NNe*KAzN8S!_7tpzxbIe?w#GN@32)! d;A2Ri()39tN2W~Q^kG#-#x}UB0=TM$i~vXrC9ePg delta 85 zcmcc6%ygldX~PpCfvST$`y~`DQa15@5sP4a{b}U1gZ|Ko~4~=tg>*I*vHj@la)6g5Gv$lG~8^YASb|FaqsNrU;{=W zfr439b|0;bU1a9<{mfNNoGIix_QCQ#Pk+u1NP$4g)>SiMaIRR#gl}9!Q8!!q9 zSkM0^+iGn*e}bE9)5os1Z<7xQiEOTL+6h(}z$d^7R2le%fq_9`a-xCo=9mNzMgWCd BBz*t? diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim index 259bd8b121ce348d72050026240d8acf00e81d2a..19a69d4db6cb7889b87ff170e68bce1372a42611 100755 GIT binary patch delta 45 zcmV+|0Mh@UL!d*jR00r~=nyS5>OPr<6nFA4OOL~|WCG0%0Wq^O5DpLnc;3ykLm*uN Dp*|5Y delta 45 zcmV+|0Mh@UL!d*jR00rewQ&1kU^NA^+N<=yjmhD&WCG0%0VT6C5DpLn7^%dwLm*uN D)ov26 diff --git a/Source/PLCrashAsyncDwarfEncodingTests.m b/Source/PLCrashAsyncDwarfEncodingTests.m index 487cf5a..5f0d19a 100644 --- a/Source/PLCrashAsyncDwarfEncodingTests.m +++ b/Source/PLCrashAsyncDwarfEncodingTests.m @@ -128,7 +128,7 @@ /* Should be the second entry in the table, plus the 12 byte length initial length field. */ STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + 12, @"Incorrect offset"); - STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_LEN_64, @"Incorrect length"); + STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_64, @"Incorrect length"); //STAssertEquals(fde_info.fde_instruction_offset, (pl_vm_address_t)0x0, @"Incorrect instruction offset (should be the first entry)"); plcrash_async_dwarf_fde_info_free(&fde_info); @@ -148,7 +148,7 @@ /* Should be the second entry in the table, plus the 12 byte length initial length field. */ STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + 12, @"Incorrect offset"); - STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_LEN_64, @"Incorrect length"); + STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_64, @"Incorrect length"); //STAssertEquals(fde_info.fde_instruction_offset, (pl_vm_address_t)0x0, @"Incorrect instruction offset (should be the first entry)"); plcrash_async_dwarf_fde_info_free(&fde_info); diff --git a/Source/PLCrashAsyncDwarfFDE.c b/Source/PLCrashAsyncDwarfFDE.c index 2db57c3..d3c4b70 100644 --- a/Source/PLCrashAsyncDwarfFDE.c +++ b/Source/PLCrashAsyncDwarfFDE.c @@ -119,12 +119,12 @@ plcrash_error_t plcrash_async_dwarf_fde_info_init (plcrash_async_dwarf_fde_info_ } } else { /* First, verify that the below subtraction won't overflow */ - if (raw_offset > fde_address) { + if (raw_offset > (fde_address+length_size)) { PLCF_DEBUG("CIE offset 0x%" PRIx64 " would place the CIE value outside of the .eh_frame section", raw_offset); return PLCRASH_EINVAL; } - cie_target_address = fde_address - raw_offset; + cie_target_address = (fde_address+length_size) - raw_offset; info->cie_offset = cie_target_address - sect_addr; } @@ -134,8 +134,6 @@ plcrash_error_t plcrash_async_dwarf_fde_info_init (plcrash_async_dwarf_fde_info_ * Set up default pointer state. TODO: Mac OS X and iOS do not currently use any relative-based encodings other * than pcrel. This matches libunwind-35.1, but we should ammend our API to support supplying the remainder of * the supported base addresses. - * - * We use the base of the eh_frame/debug_frame as the PC-relative base address (why?). */ plcrash_async_dwarf_gnueh_ptr_state_t ptr_state; plcrash_async_dwarf_gnueh_ptr_state_init(&ptr_state, address_size); diff --git a/Source/PLCrashAsyncDwarfFDETests.m b/Source/PLCrashAsyncDwarfFDETests.m index c7a7afa..fda0289 100644 --- a/Source/PLCrashAsyncDwarfFDETests.m +++ b/Source/PLCrashAsyncDwarfFDETests.m @@ -186,7 +186,7 @@ struct __attribute__((packed)) fde_data { plcrash_error_t err; /* Set up test data; we enable indirect encoding as to verify that the specified encoding is used. */ - _data.fde.cie_ptr = (uintptr_t)&_data.fde - (uintptr_t)&_data; // use an eh_frame-style offset. + _data.fde.cie_ptr = (uintptr_t)&_data.fde.cie_ptr - (uintptr_t)&_data; // use an eh_frame-style offset. err = plcrash_async_mobject_init(&mobj, mach_task_self(), &_data, sizeof(_data), false); STAssertEquals(err, PLCRASH_ESUCCESS, @"Failed to initialize memory mapping");