Implement basic CFI iteration (with 32-bit and 64-bit length support).
This commit is contained in:
Родитель
03f3d68965
Коммит
f7a81d11ac
|
@ -1,10 +1,34 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* Mock entry */
|
||||
typedef union cfi_entry {
|
||||
/* 32-bit and 64-bit size headers */
|
||||
struct {
|
||||
uint32_t size;
|
||||
} hdr_32;
|
||||
|
||||
struct {
|
||||
uint32_t flag64; /* Must be set to 0xffffffff */
|
||||
uint64_t size;
|
||||
} hdr_64;
|
||||
} cfi_entry;
|
||||
|
||||
// TODO
|
||||
uint32_t ef __attribute__((section("__PL_DWARF,__eh_frame"))) = {
|
||||
0
|
||||
cfi_entry ef[] __attribute__((section("__PL_DWARF,__eh_frame"))) = {
|
||||
{.hdr_64 = {
|
||||
.flag64 = 0xffffffff,
|
||||
.size = 24,
|
||||
}},
|
||||
|
||||
/* Terminator */
|
||||
{.hdr_32 = {
|
||||
.size = 0x0
|
||||
}}
|
||||
|
||||
/* Additional entries after terminator -- used to test offset handling */
|
||||
// TODO
|
||||
};
|
||||
|
||||
uint32_t df __attribute__((section("__PL_DWARF,__debug_frame"))) = {
|
||||
uint32_t df[] __attribute__((section("__PL_DWARF,__debug_frame"))) = {
|
||||
0
|
||||
};
|
||||
|
|
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.ios
Двоичный файл не отображается.
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.macosx
Двоичный файл не отображается.
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim
Двоичные данные
Resources/Tests/PLCrashAsyncDwarfEncodingTests/test.sim
Двоичный файл не отображается.
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "PLCrashAsyncDwarfEncoding.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
@ -43,27 +44,80 @@
|
|||
* @param reader The reader instance to initialize.
|
||||
* @param mobj The memory object containing frame data (eh_frame or debug_frame) at the start address. This instance must
|
||||
* survive for the lifetime of the reader.
|
||||
* @param cpu_type The target architecture of the CFE data, encoded as a Mach-O CPU type. Interpreting CFE data is
|
||||
* architecture-specific, and Apple has not defined encodings for all supported architectures.
|
||||
* @param byteoder The byte order of the data referenced by @a mobj.
|
||||
*/
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_init (plcrash_async_dwarf_frame_reader_t *reader, plcrash_async_mobject_t *mobj, cpu_type_t cputype) {
|
||||
// TODO
|
||||
return PLCRASH_EUNKNOWN;
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_init (plcrash_async_dwarf_frame_reader_t *reader, plcrash_async_mobject_t *mobj, const plcrash_async_byteorder_t *byteorder) {
|
||||
reader->mobj = mobj;
|
||||
reader->byteorder = byteorder;
|
||||
|
||||
return PLCRASH_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the frame descriptor entry for @a pc, if available.
|
||||
*
|
||||
* @param reader The initialized frame reader which will be searched for the entry.
|
||||
* @param offset A section-relative offset at which the FDE search will be initiated. This is primarily useful in combination with the compact unwind
|
||||
* encoding, in cases where the unwind instructions can not be expressed, and instead a FDE offset is provided by the encoding. Pass an offset of 0
|
||||
* to begin searching at the beginning of the unwind data.
|
||||
* @param pc The PC value to search for within the frame data. Note that this value must be relative to
|
||||
* the target Mach-O image's __TEXT vmaddr.
|
||||
*
|
||||
* @return Returns PLFRAME_ESUCCCESS on success, or one of the remaining error codes if a DWARF parsing error occurs. If
|
||||
* the entry can not be found, PLFRAME_ENOTFOUND will be returned.
|
||||
*/
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_find_fde (plcrash_async_dwarf_frame_reader_t *reader, pl_vm_address_t pc) {
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_find_fde (plcrash_async_dwarf_frame_reader_t *reader, pl_vm_size_t offset, pl_vm_address_t pc) {
|
||||
//const plcrash_async_byteorder_t *byteorder = reader->byteorder;
|
||||
const pl_vm_address_t base_addr = plcrash_async_mobject_base_address(reader->mobj);
|
||||
const pl_vm_address_t end_addr = base_addr + plcrash_async_mobject_length(reader->mobj);
|
||||
|
||||
/* Apply the FDE offset */
|
||||
pl_vm_address_t cfi_entry = base_addr;
|
||||
if (!plcrash_async_address_apply_offset(base_addr, offset, &cfi_entry)) {
|
||||
PLCF_DEBUG("FDE offset hint overflows the mobject's base address");
|
||||
return PLCRASH_EINVAL;
|
||||
}
|
||||
|
||||
if (cfi_entry >= end_addr) {
|
||||
PLCF_DEBUG("FDE base address + offset falls outside the mapped range");
|
||||
return PLCRASH_EINVAL;
|
||||
}
|
||||
|
||||
/* Iterate over table entries */
|
||||
while (cfi_entry < end_addr) {
|
||||
/* Fetch the entry length */
|
||||
uint64_t length;
|
||||
uint32_t *length32 = plcrash_async_mobject_remap_address(reader->mobj, cfi_entry, 0x0, sizeof(uint32_t));
|
||||
if (length32 == NULL) {
|
||||
PLCF_DEBUG("The current CFI entry 0x%" PRIx64 " header lies outside the mapped range", (uint64_t) cfi_entry);
|
||||
return PLCRASH_EINVAL;
|
||||
}
|
||||
|
||||
if (*length32 == 0xffffffff) {
|
||||
uint64_t *length64 = plcrash_async_mobject_remap_address(reader->mobj, cfi_entry, 4, sizeof(uint64_t));
|
||||
if (length64 == NULL) {
|
||||
PLCF_DEBUG("The current CFI entry 0x%" PRIx64 " header lies outside the mapped range", (uint64_t) cfi_entry);
|
||||
return PLCRASH_EINVAL;
|
||||
}
|
||||
|
||||
length = *length64;
|
||||
} else {
|
||||
length = *length32;
|
||||
}
|
||||
|
||||
/* Check for end marker */
|
||||
if (length == 0x0)
|
||||
return PLCRASH_ENOTFOUND;
|
||||
|
||||
/* Skip over entry */
|
||||
if (!plcrash_async_address_apply_offset(cfi_entry, length, &cfi_entry)) {
|
||||
PLCF_DEBUG("Entry length overflows the CFI address");
|
||||
return PLCRASH_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
return PLCRASH_EUNKNOWN;
|
||||
return PLCRASH_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,10 +43,7 @@
|
|||
typedef struct plcrash_async_dwarf_frame_reader {
|
||||
/** A memory object containing the DWARF data at the starting address. */
|
||||
plcrash_async_mobject_t *mobj;
|
||||
|
||||
/** The target CPU type. */
|
||||
cpu_type_t cpu_type;
|
||||
|
||||
|
||||
/** The byte order of the encoded data. */
|
||||
const plcrash_async_byteorder_t *byteorder;
|
||||
} plcrash_async_dwarf_frame_reader_t;
|
||||
|
@ -59,9 +56,9 @@ typedef struct plcrash_async_dwarf_fde {
|
|||
} plcrash_async_dwarf_fde_t;
|
||||
|
||||
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_init (plcrash_async_dwarf_frame_reader_t *reader, plcrash_async_mobject_t *mobj, cpu_type_t cputype);
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_init (plcrash_async_dwarf_frame_reader_t *reader, plcrash_async_mobject_t *mobj, const plcrash_async_byteorder_t *byteorder);
|
||||
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_find_fde (plcrash_async_dwarf_frame_reader_t *reader, pl_vm_address_t pc);
|
||||
plcrash_error_t plcrash_async_dwarf_frame_reader_find_fde (plcrash_async_dwarf_frame_reader_t *reader, pl_vm_size_t offset, pl_vm_address_t pc);
|
||||
|
||||
void plcrash_async_dwarf_frame_reader_free (plcrash_async_dwarf_frame_reader_t *reader);
|
||||
|
||||
|
|
|
@ -92,10 +92,10 @@
|
|||
STAssertEquals(err, PLCRASH_ESUCCESS, @"Failed to map __debug_frame section");
|
||||
|
||||
/* Initialize eh/debug readers */
|
||||
err = plcrash_async_dwarf_frame_reader_init(&_eh_reader, &_eh_frame, plcrash_async_macho_cpu_type(&_image));
|
||||
err = plcrash_async_dwarf_frame_reader_init(&_eh_reader, &_eh_frame, plcrash_async_macho_byteorder(&_image));
|
||||
STAssertEquals(PLCRASH_ESUCCESS, err, @"Failed to initialize reader");
|
||||
|
||||
err = plcrash_async_dwarf_frame_reader_init(&_debug_reader, &_debug_frame, plcrash_async_macho_cpu_type(&_image));
|
||||
err = plcrash_async_dwarf_frame_reader_init(&_debug_reader, &_debug_frame, plcrash_async_macho_byteorder(&_image));
|
||||
STAssertEquals(PLCRASH_ESUCCESS, err, @"Failed to initialize reader");
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@
|
|||
- (void) testFindEHFrameDescriptorEntry {
|
||||
plcrash_error_t err;
|
||||
|
||||
err = plcrash_async_dwarf_frame_reader_find_fde(&_eh_reader, 0x0 /* TODO */);
|
||||
err = plcrash_async_dwarf_frame_reader_find_fde(&_eh_reader, 0x0, 0x0 /* TODO */);
|
||||
STAssertEquals(PLCRASH_ESUCCESS, err, @"FDE search failed");
|
||||
}
|
||||
|
||||
|
@ -161,11 +161,10 @@
|
|||
}
|
||||
|
||||
/* Smoke test the FDE parser */
|
||||
cpu_type_t cpu_type = plcrash_async_macho_cpu_type(&image);
|
||||
// TODO
|
||||
if (has_eh_frame) {
|
||||
plcrash_async_dwarf_frame_reader_t reader;
|
||||
plcrash_async_dwarf_frame_reader_init(&reader, &eh_frame, cpu_type);
|
||||
plcrash_async_dwarf_frame_reader_init(&reader, &eh_frame, plcrash_async_macho_byteorder(&_image));
|
||||
}
|
||||
|
||||
if (has_debug_frame) {
|
||||
|
|
|
@ -76,7 +76,22 @@
|
|||
|
||||
/* Clean up */
|
||||
plcrash_async_mobject_free(&mobj);
|
||||
}
|
||||
|
||||
- (void) testLength {
|
||||
size_t size = vm_page_size+1;
|
||||
uint8_t template[size];
|
||||
|
||||
/* Map the memory */
|
||||
plcrash_async_mobject_t mobj;
|
||||
STAssertEquals(PLCRASH_ESUCCESS, plcrash_async_mobject_init(&mobj, mach_task_self(), (pl_vm_address_t)template, size, true), @"Failed to initialize mapping");
|
||||
STAssertEquals((pl_vm_address_t)template, (pl_vm_address_t) (mobj.address + mobj.vm_slide), @"Incorrect slide value!");
|
||||
|
||||
/* Test length accessor; this must be the user-requested length, not the page length. */
|
||||
STAssertEquals((pl_vm_size_t)size, plcrash_async_mobject_length(&mobj), @"Incorrect mapping length");
|
||||
|
||||
/* Clean up */
|
||||
plcrash_async_mobject_free(&mobj);
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче