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,12 @@
2014-03-27 Tristan Gingold <gingold@adacore.com>
* 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.
2014-03-26 Nick Clifton <nickc@redhat.com>
* cofflink.c (_bfd_coff_generic_relocate_section): Skip

View file

@ -2018,7 +2018,8 @@ bfd_mach_o_write_contents (bfd *abfd)
case BFD_MACH_O_LC_SUB_FRAMEWORK:
break;
default:
(*_bfd_error_handler) (_("unable to write unknown load command 0x%lx"),
(*_bfd_error_handler)
(_("unable to write unknown load command 0x%lx"),
(unsigned long) cur->type);
return FALSE;
}
@ -2042,7 +2043,8 @@ bfd_mach_o_append_section_to_segment (bfd_mach_o_segment_command *seg,
/* Create section Mach-O flags from BFD flags. */
static void
bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec)
{
flagword bfd_flags;
bfd_mach_o_section *s = bfd_mach_o_get_mach_o_section (sec);
@ -2173,7 +2175,8 @@ bfd_mach_o_build_seg_command (const char *segment,
mdata->filelen += s->size;
}
/* Now pass through again, for zerofill, only now we just update the vmsize. */
/* Now pass through again, for zerofill, only now we just update the
vmsize. */
for (i = 0; i < mdata->nsects; ++i)
{
bfd_mach_o_section *s = mdata->sections[i];
@ -4274,6 +4277,35 @@ bfd_mach_o_gen_core_p (bfd *abfd)
return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0);
}
/* Return the base address of ABFD, ie the address at which the image is
mapped. The possible initial pagezero is ignored. */
bfd_vma
bfd_mach_o_get_base_address (bfd *abfd)
{
bfd_mach_o_data_struct *mdata;
unsigned int i;
/* Check for Mach-O. */
if (!bfd_mach_o_valid (abfd))
return 0;
mdata = bfd_mach_o_get_data (abfd);
for (i = 0; i < mdata->header.ncmds; i++)
{
bfd_mach_o_load_command *cmd = &mdata->commands[i];
if ((cmd->type == BFD_MACH_O_LC_SEGMENT
|| cmd->type == BFD_MACH_O_LC_SEGMENT_64))
{
struct bfd_mach_o_segment_command *segcmd = &cmd->command.segment;
if (segcmd->initprot != 0)
return segcmd->vmaddr;
}
}
return 0;
}
typedef struct mach_o_fat_archentry
{
unsigned long cputype;

View file

@ -656,6 +656,8 @@ unsigned int bfd_mach_o_section_get_entry_size (bfd *, bfd_mach_o_section *);
bfd_boolean bfd_mach_o_read_symtab_symbols (bfd *);
bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd);
bfd_vma bfd_mach_o_get_base_address (bfd *);
/* A placeholder in case we need to suppress emitting the dysymtab for some
reason (e.g. compatibility with older system versions). */
#define bfd_mach_o_should_emit_dysymtab(x) TRUE

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 }
};
@ -72,6 +74,7 @@ For Mach-O files:\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)
@ -394,7 +403,12 @@ dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
printf ("\n");
printf (" nsects: %lu", seg->nsects);
printf (" flags: %lx\n", seg->flags);
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",