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:
parent
b5bee91426
commit
3cc27770cf
5 changed files with 142 additions and 20 deletions
|
@ -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
|
||||
|
|
42
bfd/mach-o.c
42
bfd/mach-o.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue