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>
|
2014-03-26 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* cofflink.c (_bfd_coff_generic_relocate_section): Skip
|
* cofflink.c (_bfd_coff_generic_relocate_section): Skip
|
||||||
|
|
40
bfd/mach-o.c
40
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);
|
BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
|
||||||
|
|
||||||
/* Write the symbols first. */
|
/* 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;
|
sym->symoff = mdata->filelen;
|
||||||
if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
|
if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2018,7 +2018,8 @@ bfd_mach_o_write_contents (bfd *abfd)
|
||||||
case BFD_MACH_O_LC_SUB_FRAMEWORK:
|
case BFD_MACH_O_LC_SUB_FRAMEWORK:
|
||||||
break;
|
break;
|
||||||
default:
|
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);
|
(unsigned long) cur->type);
|
||||||
return FALSE;
|
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. */
|
/* Create section Mach-O flags from BFD flags. */
|
||||||
|
|
||||||
static void
|
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;
|
flagword bfd_flags;
|
||||||
bfd_mach_o_section *s = bfd_mach_o_get_mach_o_section (sec);
|
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;
|
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)
|
for (i = 0; i < mdata->nsects; ++i)
|
||||||
{
|
{
|
||||||
bfd_mach_o_section *s = mdata->sections[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 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
|
typedef struct mach_o_fat_archentry
|
||||||
{
|
{
|
||||||
unsigned long cputype;
|
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_symbols (bfd *);
|
||||||
bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd);
|
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
|
/* A placeholder in case we need to suppress emitting the dysymtab for some
|
||||||
reason (e.g. compatibility with older system versions). */
|
reason (e.g. compatibility with older system versions). */
|
||||||
#define bfd_mach_o_should_emit_dysymtab(x) TRUE
|
#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>
|
2014-03-26 Tristan Gingold <gingold@adacore.com>
|
||||||
|
|
||||||
* od-macho.c (bfd_mach_o_cpu_name): Add BFD_MACH_O_CPU_TYPE_ARM64.
|
* 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_CODESIGN 5
|
||||||
#define OPT_SEG_SPLIT_INFO 6
|
#define OPT_SEG_SPLIT_INFO 6
|
||||||
#define OPT_COMPACT_UNWIND 7
|
#define OPT_COMPACT_UNWIND 7
|
||||||
|
#define OPT_FUNCTION_STARTS 8
|
||||||
|
|
||||||
/* List of actions. */
|
/* List of actions. */
|
||||||
static struct objdump_private_option options[] =
|
static struct objdump_private_option options[] =
|
||||||
|
@ -54,6 +55,7 @@ static struct objdump_private_option options[] =
|
||||||
{ "codesign", 0 },
|
{ "codesign", 0 },
|
||||||
{ "seg_split_info", 0 },
|
{ "seg_split_info", 0 },
|
||||||
{ "compact_unwind", 0 },
|
{ "compact_unwind", 0 },
|
||||||
|
{ "function_starts", 0 },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,6 +74,7 @@ For Mach-O files:\n\
|
||||||
codesign Display code signature\n\
|
codesign Display code signature\n\
|
||||||
seg_split_info Display segment split info\n\
|
seg_split_info Display segment split info\n\
|
||||||
compact_unwind Display compact unwinding 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);
|
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
|
static void
|
||||||
dump_section_map (bfd *abfd)
|
dump_section_map (bfd *abfd)
|
||||||
{
|
{
|
||||||
|
@ -309,9 +320,7 @@ dump_section_map (bfd *abfd)
|
||||||
putchar ('-');
|
putchar ('-');
|
||||||
printf_vma (seg->vmaddr + seg->vmsize - 1);
|
printf_vma (seg->vmaddr + seg->vmsize - 1);
|
||||||
putchar (' ');
|
putchar (' ');
|
||||||
putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-');
|
disp_segment_prot (seg->initprot);
|
||||||
putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
|
|
||||||
putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
|
|
||||||
printf ("]\n");
|
printf ("]\n");
|
||||||
|
|
||||||
for (sec = seg->sect_head; sec != NULL; sec = sec->next)
|
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 (" endoff: ");
|
||||||
printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
|
printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf (" nsects: %lu ", seg->nsects);
|
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)
|
for (sec = seg->sect_head; sec != NULL; sec = sec->next)
|
||||||
dump_section_header (abfd, sec);
|
dump_section_header (abfd, sec);
|
||||||
}
|
}
|
||||||
|
@ -911,6 +925,55 @@ dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
|
||||||
free (buf);
|
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
|
static void
|
||||||
dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
|
dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
|
||||||
bfd_boolean verbose)
|
bfd_boolean verbose)
|
||||||
|
@ -1005,6 +1068,8 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
|
||||||
dump_code_signature (abfd, linkedit);
|
dump_code_signature (abfd, linkedit);
|
||||||
else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO)
|
else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO)
|
||||||
dump_segment_split_info (abfd, linkedit);
|
dump_segment_split_info (abfd, linkedit);
|
||||||
|
else if (verbose && cmd->type == BFD_MACH_O_LC_FUNCTION_STARTS)
|
||||||
|
dump_function_starts (abfd, linkedit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BFD_MACH_O_LC_SUB_FRAMEWORK:
|
case BFD_MACH_O_LC_SUB_FRAMEWORK:
|
||||||
|
@ -1260,7 +1325,7 @@ dump_obj_compact_unwind (bfd *abfd,
|
||||||
int is_64 = mdata->header.version == 2;
|
int is_64 = mdata->header.version == 2;
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
|
|
||||||
printf (" compact unwind info:\n");
|
printf ("Compact unwind info:\n");
|
||||||
printf (" start length personality lsda\n");
|
printf (" start length personality lsda\n");
|
||||||
|
|
||||||
if (is_64)
|
if (is_64)
|
||||||
|
@ -1309,7 +1374,7 @@ dump_exe_compact_unwind (bfd *abfd,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* The header. */
|
/* The header. */
|
||||||
printf (" compact unwind info:\n");
|
printf ("Compact unwind info:\n");
|
||||||
|
|
||||||
hdr = (struct mach_o_unwind_info_header *) content;
|
hdr = (struct mach_o_unwind_info_header *) content;
|
||||||
if (size < sizeof (*hdr))
|
if (size < sizeof (*hdr))
|
||||||
|
@ -1544,6 +1609,8 @@ mach_o_dump (bfd *abfd)
|
||||||
dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
|
dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
|
||||||
if (options[OPT_SEG_SPLIT_INFO].selected)
|
if (options[OPT_SEG_SPLIT_INFO].selected)
|
||||||
dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0);
|
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)
|
if (options[OPT_COMPACT_UNWIND].selected)
|
||||||
{
|
{
|
||||||
dump_section_content (abfd, "__LD", "__compact_unwind",
|
dump_section_content (abfd, "__LD", "__compact_unwind",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue