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.
This commit is contained in:
Tristan Gingold
2014-03-25 15:51:54 +01:00
parent b5bee91426
commit 3cc27770cf
5 changed files with 142 additions and 20 deletions

View File

@ -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.

View File

@ -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\
"));
}
@ -283,6 +286,14 @@ dump_header (bfd *abfd)
printf (_(" reserved : %08x\n"), h->reserved);
}
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)
{
@ -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);
}
@ -911,6 +925,55 @@ dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
free (buf);
}
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",