diff options
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 12 | ||||
-rw-r--r-- | binutils/od-macho.c | 97 |
2 files changed, 94 insertions, 15 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index b9fa77d..975979d 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,15 @@ +2014-03-27 Tristan Gingold <gingold@adacore.com> + + * od-macho.c (OPT_FUNCTION_STARTS): New macro. + (options): Add entry for function_starts. + (mach_o_help): Ditto. + (disp_segment_prot): New function. + (dump_section_map): Call disp_segment_prot. + (dump_function_starts): New function. + (dump_obj_compact_unwind): Fix ouput indentation. + (dump_exe_compact_unwind): Fix ouput indentation. + (mach_o_dump): Handle function_starts. + 2014-03-26 Tristan Gingold <gingold@adacore.com> * od-macho.c (bfd_mach_o_cpu_name): Add BFD_MACH_O_CPU_TYPE_ARM64. diff --git a/binutils/od-macho.c b/binutils/od-macho.c index 6f88112..4733e87 100644 --- a/binutils/od-macho.c +++ b/binutils/od-macho.c @@ -42,6 +42,7 @@ #define OPT_CODESIGN 5 #define OPT_SEG_SPLIT_INFO 6 #define OPT_COMPACT_UNWIND 7 +#define OPT_FUNCTION_STARTS 8 /* List of actions. */ static struct objdump_private_option options[] = @@ -54,6 +55,7 @@ static struct objdump_private_option options[] = { "codesign", 0 }, { "seg_split_info", 0 }, { "compact_unwind", 0 }, + { "function_starts", 0 }, { NULL, 0 } }; @@ -64,14 +66,15 @@ mach_o_help (FILE *stream) { fprintf (stream, _("\ For Mach-O files:\n\ - header Display the file header\n\ - section Display the segments and sections commands\n\ - map Display the section map\n\ - load Display the load commands\n\ - dysymtab Display the dynamic symbol table\n\ - codesign Display code signature\n\ - seg_split_info Display segment split info\n\ - compact_unwind Display compact unwinding info\n\ + header Display the file header\n\ + section Display the segments and sections commands\n\ + map Display the section map\n\ + load Display the load commands\n\ + dysymtab Display the dynamic symbol table\n\ + codesign Display code signature\n\ + seg_split_info Display segment split info\n\ + compact_unwind Display compact unwinding info\n\ + function_starts Display start address of functions\n\ ")); } @@ -284,6 +287,14 @@ dump_header (bfd *abfd) } static void +disp_segment_prot (unsigned int prot) +{ + putchar (prot & BFD_MACH_O_PROT_READ ? 'r' : '-'); + putchar (prot & BFD_MACH_O_PROT_WRITE ? 'w' : '-'); + putchar (prot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-'); +} + +static void dump_section_map (bfd *abfd) { bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); @@ -309,9 +320,7 @@ dump_section_map (bfd *abfd) putchar ('-'); printf_vma (seg->vmaddr + seg->vmsize - 1); putchar (' '); - putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-'); - putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-'); - putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-'); + disp_segment_prot (seg->initprot); printf ("]\n"); for (sec = seg->sect_head; sec != NULL; sec = sec->next) @@ -393,8 +402,13 @@ dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd) printf (" endoff: "); printf_vma ((bfd_vma)(seg->fileoff + seg->filesize)); printf ("\n"); - printf (" nsects: %lu ", seg->nsects); - printf (" flags: %lx\n", seg->flags); + printf (" nsects: %lu", seg->nsects); + printf (" flags: %lx", seg->flags); + printf (" initprot: "); + disp_segment_prot (seg->initprot); + printf (" maxprot: "); + disp_segment_prot (seg->maxprot); + printf ("\n"); for (sec = seg->sect_head; sec != NULL; sec = sec->next) dump_section_header (abfd, sec); } @@ -912,6 +926,55 @@ dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd) } static void +dump_function_starts (bfd *abfd, bfd_mach_o_linkedit_command *cmd) +{ + unsigned char *buf = xmalloc (cmd->datasize); + unsigned char *end_buf = buf + cmd->datasize; + unsigned char *p; + bfd_vma addr; + + if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0 + || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize) + { + non_fatal (_("cannot read function starts")); + free (buf); + return; + } + + /* Function starts are delta encoded, starting from the base address. */ + addr = bfd_mach_o_get_base_address (abfd); + + for (p = buf; ;) + { + bfd_vma delta = 0; + unsigned int shift = 0; + + if (*p == 0 || p == end_buf) + break; + while (1) + { + unsigned char b = *p++; + + delta |= (b & 0x7f) << shift; + if ((b & 0x80) == 0) + break; + if (p == end_buf) + { + fputs (" [truncated]\n", stdout); + break; + } + shift += 7; + } + + addr += delta; + fputs (" ", stdout); + bfd_printf_vma (abfd, addr); + putchar ('\n'); + } + free (buf); +} + +static void dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose) { @@ -1005,6 +1068,8 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd, dump_code_signature (abfd, linkedit); else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO) dump_segment_split_info (abfd, linkedit); + else if (verbose && cmd->type == BFD_MACH_O_LC_FUNCTION_STARTS) + dump_function_starts (abfd, linkedit); break; } case BFD_MACH_O_LC_SUB_FRAMEWORK: @@ -1260,7 +1325,7 @@ dump_obj_compact_unwind (bfd *abfd, int is_64 = mdata->header.version == 2; const unsigned char *p; - printf (" compact unwind info:\n"); + printf ("Compact unwind info:\n"); printf (" start length personality lsda\n"); if (is_64) @@ -1309,7 +1374,7 @@ dump_exe_compact_unwind (bfd *abfd, unsigned int i; /* The header. */ - printf (" compact unwind info:\n"); + printf ("Compact unwind info:\n"); hdr = (struct mach_o_unwind_info_header *) content; if (size < sizeof (*hdr)) @@ -1544,6 +1609,8 @@ mach_o_dump (bfd *abfd) dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0); if (options[OPT_SEG_SPLIT_INFO].selected) dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0); + if (options[OPT_FUNCTION_STARTS].selected) + dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0); if (options[OPT_COMPACT_UNWIND].selected) { dump_section_content (abfd, "__LD", "__compact_unwind", |