Implementation and tests for compressed encoding tables, using a private (rather than common) encoding reference.

This commit is contained in:
Landon Fuller 2013-03-14 15:47:17 -04:00
Родитель 92b0e45319
Коммит cd3eee3570
6 изменённых файлов: 62 добавлений и 9 удалений

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

@ -3,13 +3,19 @@
// Keep in sync with PLCrashAsyncCompactUnwindEncodingTests
#define BASE_PC 0
#define PC_COMPACT_COMMON (BASE_PC+1)
#define PC_COMPACT_BASE (BASE_PC+1)
#define PC_COMPACT_COMMON (PC_COMPACT_BASE+0)
#define PC_COMPACT_COMMON_ENCODING (UNWIND_X86_64_MODE_DWARF | 0xFF)
#define PC_COMPACT_PRIVATE (PC_COMPACT_BASE+1)
#define PC_COMPACT_PRIVATE_ENCODING (UNWIND_X86_64_MODE_DWARF | 0xFE)
struct unwind_sect_compressed_page {
struct unwind_info_compressed_second_level_page_header header;
uint32_t entries[1];
uint32_t entries[2];
uint32_t encodings[1];
};
struct unwind_sect_regular_page {
@ -65,18 +71,27 @@ struct unwind_sect data __attribute__((section("__TEXT,__unwind_info"))) = {
}
},
#define COMPRESSED(foff, enc_index) ((foff & 0x00FFFFFF) | (enc_index << 24))
.compressed_page_1 = {
.header = {
.kind = UNWIND_SECOND_LEVEL_COMPRESSED,
.entryPageOffset = offsetof(struct unwind_sect_compressed_page, entries),
.entryCount = 1
.entryCount = 2,
.encodingsPageOffset = offsetof(struct unwind_sect_compressed_page, encodings),
.encodingsCount = 1
},
.entries = {
#define COMPRESSED(foff, enc_index) ((foff & 0x00FFFFFF) | (enc_index << 24))
/* Note that these are offsets from the first-level functionOffset */
COMPRESSED(0, 0)
COMPRESSED(0, 0),
COMPRESSED(1, 1)
#undef COMPRESSED
},
.encodings = {
PC_COMPACT_PRIVATE_ENCODING
}
},
};

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

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

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

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

@ -279,9 +279,31 @@ plcrash_error_t plcrash_async_cfe_reader_find_pc (plcrash_async_cfe_reader_t *re
return PLCRASH_ESUCCESS;
}
// TODO
__builtin_trap();
PLCF_DEBUG("FOUND func_offset=%" PRIx32 " idx = %" PRIx32, base_foffset + UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(c_entry), UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(c_entry));
/* Map in the encodings table */
uint32_t encodings_offset = byteorder->swap16(header->encodingsPageOffset);
uint32_t encodings_count = byteorder->swap16(header->encodingsCount);
if (VERIFY_SIZE_T(sizeof(uint32_t), encodings_count)) {
PLCF_DEBUG("CFE second level entry count extends beyond the range of size_t");
return PLCRASH_EINVAL;
}
if (!plcrash_async_mobject_verify_local_pointer(reader->mobj, header, encodings_offset, encodings_count * sizeof(uint32_t))) {
PLCF_DEBUG("CFE compressed encodings table lies outside the mapped CFE range");
return PLCRASH_EINVAL;
}
uint32_t *encodings = (uint32_t *) (((uintptr_t)header) + encodings_offset);
/* Verify that the entry is within range */
c_encoding_idx -= common_enc_count;
if (c_encoding_idx >= encodings_count) {
PLCF_DEBUG("Encoding index lies outside the second level encoding table");
return PLCRASH_EINVAL;
}
/* Extract the encoding */
*encoding = encodings[c_encoding_idx];
return PLCRASH_ESUCCESS;
}

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

@ -53,6 +53,10 @@
#define PC_COMPACT_COMMON (BASE_PC+1)
#define PC_COMPACT_COMMON_ENCODING (UNWIND_X86_64_MODE_DWARF | 0xFF)
/** PC to use for the compact-private test */
#define PC_COMPACT_PRIVATE (BASE_PC+2)
#define PC_COMPACT_PRIVATE_ENCODING (UNWIND_X86_64_MODE_DWARF | 0xFE)
/**
* @internal
*
@ -216,4 +220,16 @@
STAssertEquals(encoding, (uint32_t)PC_COMPACT_COMMON_ENCODING, @"Incorrect encoding returned");
}
/**
* Test reading of a PC, compressed, private encoding.
*/
- (void) testReadCompressedEncoding {
plcrash_error_t err;
uint32_t encoding;
err = plcrash_async_cfe_reader_find_pc(&_reader, PC_COMPACT_PRIVATE, &encoding);
STAssertEquals(PLCRASH_ESUCCESS, err, @"Failed to locate CFE entry");
STAssertEquals(encoding, (uint32_t)PC_COMPACT_PRIVATE_ENCODING, @"Incorrect encoding returned");
}
@end