Fix GNU EH pointer reads; these should use the native platform pointer size, rather than the DWARF entry's 32/64 word size.

This commit is contained in:
Landon Fuller 2013-07-01 14:53:18 -04:00
Родитель 2161b2a159
Коммит f4c680ef57
8 изменённых файлов: 127 добавлений и 34 удалений

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

@ -2,7 +2,7 @@
/* Constants and structures used to generate the CFI test binaries. See also: Resources/Tests/PLCrashAsyncDwarfEncodingTests */
struct __attribute__((packed)) pl_cie_data_64 {
struct __attribute__((packed)) pl_cie_data {
uint8_t version; /* Must be set to 1 or 3 -- 1=eh_frame, 3=DWARF3, 4=DWARF4 */
uint8_t augmentation[7];
@ -22,6 +22,13 @@ struct __attribute__((packed)) pl_fde_data_64 {
uint8_t instructions[];
};
struct __attribute__((packed)) pl_fde_data_32 {
uint32_t initial_location;
uint32_t address_range;
uint8_t instructions[];
};
/* 32-bit and 64-bit length headers */
struct pl_cfi_header_32 {
uint32_t length;
@ -35,16 +42,21 @@ struct pl_cfi_header_64 {
} __attribute__((packed));
/* Mock entry */
typedef struct pl_cfi_entry {
union {
struct pl_cfi_header_32 hdr_32;
struct pl_cfi_header_64 hdr_64;
};
union {
struct pl_cie_data_64 cie_64;
struct pl_fde_data_64 fde_64;
};
typedef union pl_cfi_entry {
struct {
struct pl_cfi_header_64 hdr;
union {
struct pl_cie_data cie;
struct pl_fde_data_64 fde;
};
} e64;
struct {
struct pl_cfi_header_32 hdr;
union {
struct pl_cie_data cie;
struct pl_fde_data_32 fde;
};
} e32;
} pl_cfi_entry;
/* Initial length field size */
@ -52,8 +64,8 @@ typedef struct pl_cfi_entry {
#define PL_CFI_LEN_SIZE_32 (sizeof(uint32_t))
/* CFE lengths, minus the initial length field. */
#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))
#define PL_CFI_SIZE_64 (sizeof(pl_cfi_entry) - PL_CFI_LEN_SIZE_64)
#define PL_CFI_SIZE_32 (sizeof(pl_cfi_entry) - PL_CFI_LEN_SIZE_32)
/* PC values to be used when searching for FDE entries. */
#define PL_CFI_EH_FRAME_PC 0x60

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

@ -4,15 +4,16 @@
// TODO
pl_cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = {
#ifdef __LP64__
/* Common CIE entry */
{
.hdr_64 = {
.e64.hdr = {
.flag64 = UINT32_MAX,
.length = PL_CFI_SIZE_64,
.cie_id = 0,
},
.cie_64 = {
.e64.cie = {
.version = 1, // eh_frame
.augmentation[0] = 'z', // Enable GNU EH augmentation handling
.augmentation[1] = 'R', // Pointer encoding is included in the augmentation data.
@ -22,26 +23,61 @@ pl_cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = {
.data_alignment_factor = 0,
.return_address_register = 0,
.augmentation_data[0] = sizeof(ef[0].cie_64.augmentation_data), // augmentation data length; uleb128, must fit in 7 bits.
.augmentation_data[0] = sizeof(ef[0].e64.cie.augmentation_data), // augmentation data length; uleb128, must fit in 7 bits.
.augmentation_data[1] = 0x04, // DW_EH_PE_udata8 FDE pointer size
}
},
/* A FDE entry */
{
.hdr_64 = {
.e64.hdr = {
.flag64 = UINT32_MAX,
.length = PL_CFI_SIZE_64,
.cie_id = sizeof(ef[0]) + PL_CFI_LEN_SIZE_64, // Offset to the first CIE entry
},
.fde_64 = {
.e64.fde = {
.initial_location = PL_CFI_EH_FRAME_PC,
.address_range = PL_CFI_EH_FRAME_PC_RANGE
}
},
#else
/* Common CIE entry */
{
.e32.hdr = {
.length = PL_CFI_SIZE_32,
.cie_id = 0,
},
.e32.cie = {
.version = 1, // eh_frame
.augmentation[0] = 'z', // Enable GNU EH augmentation handling
.augmentation[1] = 'R', // Pointer encoding is included in the augmentation data.
.augmentation[2] = '\0',
.code_alignment_factor = 0,
.data_alignment_factor = 0,
.return_address_register = 0,
.augmentation_data[0] = sizeof(ef[0].e32.cie.augmentation_data), // augmentation data length; uleb128, must fit in 7 bits.
.augmentation_data[1] = 0x04, // DW_EH_PE_udata8 FDE pointer size
}
},
/* A FDE entry */
{
.e32.hdr = {
.length = PL_CFI_SIZE_32,
.cie_id = sizeof(ef[0]) + PL_CFI_LEN_SIZE_32, // Offset to the first CIE entry
},
.e32.fde = {
.initial_location = PL_CFI_EH_FRAME_PC,
.address_range = PL_CFI_EH_FRAME_PC_RANGE
}
},
#endif
/* Terminator */
{.hdr_32 = {
{.e32.hdr = {
.length = 0x0
}}
@ -51,15 +87,16 @@ pl_cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = {
pl_cfi_entry df[] __attribute__((section("__PL_DWARF,__debug_frame"))) = {
#ifdef __LP64__
/* Common CIE entry */
{
.hdr_64 = {
.e64.hdr = {
.flag64 = UINT32_MAX,
.length = PL_CFI_SIZE_64,
.cie_id = UINT64_MAX,
},
.cie_64 = {
.e64.cie = {
.version = 1, // eh_frame
.augmentation[0] = 'z',
.augmentation[1] = 'R',
@ -69,26 +106,61 @@ pl_cfi_entry df[] __attribute__((section("__PL_DWARF,__debug_frame"))) = {
.data_alignment_factor = 0,
.return_address_register = 0,
.augmentation_data[0] = sizeof(ef[0].cie_64.augmentation_data), // uleb128, must fit in 7 bits.
.augmentation_data[0] = sizeof(ef[0].e64.cie.augmentation_data), // uleb128, must fit in 7 bits.
.augmentation_data[1] = 0x04, // DW_EH_PE_udata8 FDE pointer size
}
},
/* A FDE entry */
{
.hdr_64 = {
.e64.hdr = {
.flag64 = UINT32_MAX,
.length = PL_CFI_SIZE_64,
.cie_id = 0, // Offset to the first CIE entry
},
.fde_64 = {
.e64.fde = {
.initial_location = PL_CFI_DEBUG_FRAME_PC,
.address_range = PL_CFI_DEBUG_FRAME_PC_RANGE
}
},
#else
/* Common CIE entry */
{
.e32.hdr = {
.length = PL_CFI_SIZE_32,
.cie_id = UINT32_MAX,
},
.e32.cie = {
.version = 1, // eh_frame
.augmentation[0] = 'z',
.augmentation[1] = 'R',
.augmentation[2] = '\0',
.code_alignment_factor = 0,
.data_alignment_factor = 0,
.return_address_register = 0,
.augmentation_data[0] = sizeof(ef[0].e32.cie.augmentation_data), // uleb128, must fit in 7 bits.
.augmentation_data[1] = 0x04, // DW_EH_PE_udata8 FDE pointer size
}
},
/* A FDE entry */
{
.e32.hdr = {
.length = PL_CFI_SIZE_32,
.cie_id = 0, // Offset to the first CIE entry
},
.e32.fde = {
.initial_location = PL_CFI_DEBUG_FRAME_PC,
.address_range = PL_CFI_DEBUG_FRAME_PC_RANGE
}
},
#endif
/* Terminator */
{.hdr_32 = {
{.e32.hdr = {
.length = 0x0
}}
};

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

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

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

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

@ -122,7 +122,7 @@ plcrash_error_t plcrash_async_dwarf_cie_info_init (plcrash_async_dwarf_cie_info_
}
if (info->cie_version != 1 && info->cie_version != 3 && info->cie_version != 4) {
PLCF_DEBUG("CIE id is not one of 1 (eh_frame) or 3 (DWARF3) or 4 (DWARF4): %" PRIu8, info->cie_version);
PLCF_DEBUG("CIE version is not one of 1 (eh_frame) or 3 (DWARF3) or 4 (DWARF4): %" PRIu8, info->cie_version);
return PLCRASH_EINVAL;
}

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

@ -182,7 +182,7 @@ plcrash_error_t plcrash_async_dwarf_frame_reader_find_fde (plcrash_async_dwarf_f
}
/* Decode the FDE */
err = plcrash_async_dwarf_fde_info_init(fde_info, reader->mobj, byteorder, dwarf_word_size, cfi_entry, reader->debug_frame);
err = plcrash_async_dwarf_fde_info_init(fde_info, reader->mobj, byteorder, reader->address_size, cfi_entry, reader->debug_frame);
if (err != PLCRASH_ESUCCESS)
return err;

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

@ -125,10 +125,14 @@
err = plcrash_async_dwarf_frame_reader_find_fde(&_eh_reader, 0x0, PL_CFI_EH_FRAME_PC+PL_CFI_EH_FRAME_PC_RANGE-1, &fde_info);
STAssertEquals(PLCRASH_ESUCCESS, err, @"FDE search failed");
/* 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_SIZE_64, @"Incorrect length");
/* Should be the second entry in the table, plus the initial length field. */
if (_eh_reader.address_size == 8) {
STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + PL_CFI_LEN_SIZE_64, @"Incorrect offset");
STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_64, @"Incorrect length");
} else {
STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + PL_CFI_LEN_SIZE_32, @"Incorrect offset");
STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_32, @"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);
@ -145,10 +149,15 @@
err = plcrash_async_dwarf_frame_reader_find_fde(&_debug_reader, 0x0, PL_CFI_DEBUG_FRAME_PC+PL_CFI_DEBUG_FRAME_PC_RANGE-1, &fde_info);
STAssertEquals(PLCRASH_ESUCCESS, err, @"FDE search failed");
/* 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");
/* Should be the second entry in the table, plus the initial length field. */
if (_eh_reader.address_size == 8) {
STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + PL_CFI_LEN_SIZE_64, @"Incorrect offset");
STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_64, @"Incorrect length");
} else {
STAssertEquals(fde_info.fde_offset, (pl_vm_address_t) (sizeof(pl_cfi_entry)) + PL_CFI_LEN_SIZE_32, @"Incorrect offset");
STAssertEquals(fde_info.fde_length, (uint64_t)PL_CFI_SIZE_32, @"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);