diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h index 851d929..7080b3a 100644 --- a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h +++ b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/dwarf_encoding_test.h @@ -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 diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c index ed513e4..e3d69dc 100644 --- a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c +++ b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.c @@ -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 }} }; diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios index 64e89d5..c1bc20d 100755 Binary files a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios and b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios differ diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx index 18b0278..5b5bc45 100755 Binary files a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx and b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx differ diff --git a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim index 19a69d4..aebffa6 100755 Binary files a/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim and b/Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim differ diff --git a/Source/PLCrashAsyncDwarfCIE.c b/Source/PLCrashAsyncDwarfCIE.c index 451ce12..69f6fb5 100644 --- a/Source/PLCrashAsyncDwarfCIE.c +++ b/Source/PLCrashAsyncDwarfCIE.c @@ -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; } diff --git a/Source/PLCrashAsyncDwarfEncoding.c b/Source/PLCrashAsyncDwarfEncoding.c index c799ec5..820d834 100644 --- a/Source/PLCrashAsyncDwarfEncoding.c +++ b/Source/PLCrashAsyncDwarfEncoding.c @@ -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; diff --git a/Source/PLCrashAsyncDwarfEncodingTests.m b/Source/PLCrashAsyncDwarfEncodingTests.m index 5f0d19a..e0e2c82 100644 --- a/Source/PLCrashAsyncDwarfEncodingTests.m +++ b/Source/PLCrashAsyncDwarfEncodingTests.m @@ -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);