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.
This commit is contained in:
Landon Fuller 2013-06-28 15:07:18 -04:00
Родитель 31f67bd0d8
Коммит 5ee9dd0b24
8 изменённых файлов: 16 добавлений и 14 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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 = {

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);

Просмотреть файл

@ -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");