aboutsummaryrefslogtreecommitdiff
path: root/binutils/od-macho.c
diff options
context:
space:
mode:
authorTristan Gingold <tristan.gingold@adacore.com>2014-03-25 15:51:54 +0100
committerTristan Gingold <tristan.gingold@adacore.com>2014-03-27 10:23:22 +0100
commit3cc27770cfa2080f70d44659de9d62adc80489fc (patch)
treebc8a143d3941d458aa0224b3293675bf6217af88 /binutils/od-macho.c
parentb5bee914261ea82683b7da4245790465b9373131 (diff)
downloadgdb-3cc27770cfa2080f70d44659de9d62adc80489fc.zip
gdb-3cc27770cfa2080f70d44659de9d62adc80489fc.tar.gz
gdb-3cc27770cfa2080f70d44659de9d62adc80489fc.tar.bz2
Mach-O: add objdump -P function_starts to display function starts.
bfd/ * mach-o.h (bfd_mach_o_get_base_address): New prototype. * mach-o.c (bfd_mach_o_write_symtab) (bfd_mach_o_write_contents) (bfd_mach_o_set_section_flags_from_bfd) (bfd_mach_o_build_seg_command): Fix indentation. (bfd_mach_o_get_base_address): New function. binutils/ * 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.
Diffstat (limited to 'binutils/od-macho.c')
-rw-r--r--binutils/od-macho.c97
1 files changed, 82 insertions, 15 deletions
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",