[Lldb-commits] [lldb] r222884 - A little more work on the compact unwind dumper.
Jason Molenda
jmolenda at apple.com
Thu Nov 27 05:21:38 PST 2014
Author: jmolenda
Date: Thu Nov 27 07:21:38 2014
New Revision: 222884
URL: http://llvm.org/viewvc/llvm-project?rev=222884&view=rev
Log:
A little more work on the compact unwind dumper.
UNWIND_X86_64_MODE_STACK_IND mode is almost correct; extra stack
space allocated before the reg saves isn't handled right. Still a
little wobbily on the file addresses of functions. Finally understand
how the 6 registers that may be saved are ordered in just 10 its
of space -- the Lehmer code for the registers is derived and then
the sequence is encoded in a variable base number. Added some
comments with references to what the code is doing so it'll be
easier for others to track down.
Modified:
lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c
Modified: lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c?rev=222884&r1=222883&r2=222884&view=diff
==============================================================================
--- lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c (original)
+++ lldb/trunk/tools/compact-unwind/compact-unwind-dumper.c Thu Nov 27 07:21:38 2014
@@ -1,4 +1,3 @@
-#include <stdio.h>
#include <stdint.h>
#include <mach-o/loader.h>
#include <mach-o/compact_unwind_encoding.h>
@@ -12,6 +11,7 @@
#include <sys/errno.h>
#include <sys/stat.h>
#include <inttypes.h>
+#include <stdio.h>
// A quick sketch of a program which can parse the compact unwind info
@@ -29,7 +29,9 @@ struct baton
int addr_size; // 4 or 8 bytes, the size of addresses in this file
- uint64_t text_segment_vmaddr;
+ uint64_t text_segment_vmaddr; // __TEXT segment vmaddr
+ uint64_t text_section_vmaddr; // __TEXT,__text section vmaddr
+
uint64_t eh_section_file_address; // the file address of the __TEXT,__eh_frame section
uint8_t *lsda_array_start; // for the currently-being-processed first-level index
@@ -117,7 +119,8 @@ scan_macho_load_commands (struct baton *
offset += sizeof (struct segment_command);
}
- if (nsects != 0 && segment_name[0] != '\0' && strcmp (segment_name, "__TEXT") == 0)
+ if ((*lc_cmd == LC_SEGMENT || *lc_cmd == LC_SEGMENT_64)
+ && nsects != 0 && segment_name[0] != '\0' && strcmp (segment_name, "__TEXT") == 0)
{
baton->text_segment_vmaddr = segment_vmaddr;
@@ -157,6 +160,21 @@ scan_macho_load_commands (struct baton *
baton->eh_section_file_address = sect.addr;
}
}
+ if (strcmp (sect_name, "__text") == 0)
+ {
+ if (is_64bit)
+ {
+ struct section_64 sect;
+ memcpy (§, offset, sizeof (struct section_64));
+ baton->text_section_vmaddr = sect.addr;
+ }
+ else
+ {
+ struct section sect;
+ memcpy (§, offset, sizeof (struct section));
+ baton->text_section_vmaddr = sect.addr;
+ }
+ }
if (is_64bit)
{
@@ -228,17 +246,12 @@ print_encoding_x86_64 (struct baton bato
}
case UNWIND_X86_64_MODE_STACK_IMMD:
{
- printf (" UNWIND_X86_64_MODE_STACK_IND not yet supported\n");
- break;
-
- // FIXME not getting the rbp register saves out of the register permutation yet
-
uint32_t stack_size = (encoding & UNWIND_X86_64_FRAMELESS_STACK_SIZE) >> (__builtin_ctz (UNWIND_X86_64_FRAMELESS_STACK_SIZE));
- uint32_t stack_adjust = (encoding & UNWIND_X86_FRAMELESS_STACK_ADJUST) >> (__builtin_ctz (UNWIND_X86_FRAMELESS_STACK_ADJUST));
+ uint32_t stack_adjust = (encoding & UNWIND_X86_64_FRAMELESS_STACK_ADJUST) >> (__builtin_ctz (UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
uint32_t register_count = (encoding & UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT) >> (__builtin_ctz (UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
- uint32_t permutation = (encoding & UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION) >> (__builtin_ctz (UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
+ uint32_t permutation = (encoding & UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION) >> (__builtin_ctz (UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
-// printf (" frameless function: stack size %d, stack adjust %d, register count %d ", stack_size * 8, stack_adjust * 8, register_count);
+ printf (" frameless function: stack size %d, stack adjust %d, register count %d ", stack_size * 8, stack_adjust * 8, register_count);
if ((encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_STACK_IND)
{
printf (" UNWIND_X86_64_MODE_STACK_IND not handled ");
@@ -255,6 +268,10 @@ print_encoding_x86_64 (struct baton bato
else
{
int permunreg[6];
+
+ // Decode the variable base number that's used to encode
+ // the Lehmer code for this permutation.
+ // v. http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
switch (register_count)
{
case 6:
@@ -306,12 +323,15 @@ print_encoding_x86_64 (struct baton bato
break;
}
+ // Decode the Lehmer code for this permutation of
+ // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
+
int registers[6];
bool used[7] = { false, false, false, false, false, false, false };
for (int i = 0; i < register_count; i++)
{
int renum = 0;
- for (int j = 0; j < 7; j++)
+ for (int j = 1; j < 7; j++)
{
if (used[j] == false)
{
@@ -327,7 +347,7 @@ print_encoding_x86_64 (struct baton bato
}
- printf ("CFA is rsp+%d ", stack_size * 8);
+ printf (" CFA is rsp+%d ", stack_size * 8);
uint32_t saved_registers_offset = 1;
printf (" rip=[CFA-%d]", saved_registers_offset * 8);
@@ -369,11 +389,16 @@ print_encoding_x86_64 (struct baton bato
case UNWIND_X86_64_MODE_DWARF:
{
uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET;
- printf (" use DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")\n",
+ printf (" use DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")",
dwarf_offset, dwarf_offset + baton.eh_section_file_address);
}
break;
+ case 0:
+ {
+ printf (" no unwind information");
+ }
+ break;
}
}
@@ -405,7 +430,10 @@ print_function_encoding (struct baton ba
}
printf (" func [%d] offset %d (file addr 0x%" PRIx64 ")%s - 0x%x",
idx, entry_func_offset,
- entry_func_offset + baton.first_level_index_entry.functionOffset + baton.text_segment_vmaddr,
+ entry_func_offset + baton.text_segment_vmaddr, // FIXME
+#if 0
+ entry_func_offset + baton.first_level_index_entry.functionOffset + baton.text_segment_vmaddr, // FIXME
+#endif
entry_encoding_index_str,
encoding);
@@ -466,16 +494,18 @@ void
print_second_level_index_regular (struct baton baton)
{
uint8_t *page_entries = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset + baton.regular_second_level_page_header.entryPageOffset;
- uint8_t entries_count = baton.regular_second_level_page_header.entryCount;
+ uint32_t entries_count = baton.regular_second_level_page_header.entryCount;
uint8_t *offset = page_entries;
- uint8_t idx = 0;
- for (uint32_t idx = 0; idx < entries_count; idx++, offset += 8)
+ uint32_t idx = 0;
+ while (idx < entries_count)
{
uint32_t func_offset = *((uint32_t *) (offset));
uint32_t encoding = *((uint32_t *) (offset + 4));
print_function_encoding (baton, idx, encoding, (uint32_t) -1, func_offset);
+ idx++;
+ offset += 8;
}
}
@@ -512,7 +542,7 @@ print_second_level_index_compressed (str
}
void
-print_second_level_index (struct baton baton)
+print_second_level_index (struct baton baton, uint32_t second_level_index_count)
{
uint8_t *index_start = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset;
@@ -520,7 +550,7 @@ print_second_level_index (struct baton b
{
struct unwind_info_regular_second_level_page_header header;
memcpy (&header, index_start, sizeof (struct unwind_info_regular_second_level_page_header));
- printf (" UNWIND_SECOND_LEVEL_REGULAR entryPageOffset %d, entryCount %d\n", header.entryPageOffset, header.entryCount);
+ printf (" UNWIND_SECOND_LEVEL_REGULAR #%d entryPageOffset %d, entryCount %d\n", second_level_index_count, header.entryPageOffset, header.entryCount);
baton.regular_second_level_page_header = header;
print_second_level_index_regular (baton);
}
@@ -529,7 +559,7 @@ print_second_level_index (struct baton b
{
struct unwind_info_compressed_second_level_page_header header;
memcpy (&header, index_start, sizeof (struct unwind_info_compressed_second_level_page_header));
- printf (" UNWIND_SECOND_LEVEL_COMPRESSED entryPageOffset %d, entryCount %d, encodingsPageOffset %d, encodingsCount %d\n", header.entryPageOffset, header.entryCount, header.encodingsPageOffset, header.encodingsCount);
+ printf (" UNWIND_SECOND_LEVEL_COMPRESSED #%d entryPageOffset %d, entryCount %d, encodingsPageOffset %d, encodingsCount %d\n", second_level_index_count, header.entryPageOffset, header.entryCount, header.encodingsPageOffset, header.encodingsCount);
baton.compressed_second_level_page_header = header;
print_second_level_index_compressed (baton);
}
@@ -569,8 +599,8 @@ print_index_sections (struct baton baton
printf (" LSDA [%d] functionOffset %d (%d) (file address 0x%" PRIx64 "), lsdaOffset %d (file address 0x%" PRIx64 ")\n",
lsda_count, lsda_entry.functionOffset,
lsda_entry.functionOffset - index_entry.functionOffset,
- lsda_entry.functionOffset + baton.text_segment_vmaddr,
- lsda_entry.lsdaOffset, lsda_entry.lsdaOffset + baton.text_segment_vmaddr);
+ lsda_entry.functionOffset - index_entry.functionOffset + baton.text_section_vmaddr,
+ lsda_entry.lsdaOffset, lsda_entry.lsdaOffset + baton.text_section_vmaddr);
lsda_count++;
lsda_entry_offset += sizeof (struct unwind_info_section_header_lsda_index_entry);
}
@@ -578,7 +608,7 @@ print_index_sections (struct baton baton
printf ("\n");
baton.first_level_index_entry = index_entry;
- print_second_level_index (baton);
+ print_second_level_index (baton, cur_idx);
}
printf ("\n");
@@ -648,7 +678,7 @@ int main (int argc, char **argv)
while (pers_idx < header.personalityArrayCount)
{
int32_t pers_delta = *((int32_t*) (baton.compact_unwind_start + header.personalityArraySectionOffset + (pers_idx * sizeof (uint32_t))));
- printf (" Personality [%d]: offset to personality function address ptr %d (file address 0x%" PRIx64 ")\n", pers_idx, pers_delta, baton.text_segment_vmaddr + pers_delta);
+ printf (" Personality [%d]: offset to personality function address ptr %d (file address 0x%" PRIx64 ")\n", pers_idx, pers_delta, baton.text_section_vmaddr + pers_delta);
pers_idx++;
pers_arr += sizeof (uint32_t);
}
More information about the lldb-commits
mailing list