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

@ -1478,7 +1478,7 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
/* Write the symbols first. */
mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
mdata->filelen = FILE_ALIGN (mdata->filelen, wide ? 3 : 2);
sym->symoff = mdata->filelen;
if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
return FALSE;
@ -2018,8 +2018,9 @@ 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"),
(unsigned long) cur->type);
(*_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 }
};
@ -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",