Skip to content

Commit 3cc2777

Browse files
author
Tristan Gingold
committed
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.
1 parent b5bee91 commit 3cc2777

5 files changed

Lines changed: 142 additions & 20 deletions

File tree

bfd/ChangeLog

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
2014-03-27 Tristan Gingold <[email protected]>
2+
3+
* mach-o.h (bfd_mach_o_get_base_address): New prototype.
4+
* mach-o.c (bfd_mach_o_write_symtab)
5+
(bfd_mach_o_write_contents)
6+
(bfd_mach_o_set_section_flags_from_bfd)
7+
(bfd_mach_o_build_seg_command): Fix indentation.
8+
(bfd_mach_o_get_base_address): New function.
9+
110
2014-03-26 Nick Clifton <[email protected]>
211

312
* cofflink.c (_bfd_coff_generic_relocate_section): Skip

bfd/mach-o.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
14781478
BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
14791479

14801480
/* Write the symbols first. */
1481-
mdata->filelen = FILE_ALIGN(mdata->filelen, wide ? 3 : 2);
1481+
mdata->filelen = FILE_ALIGN (mdata->filelen, wide ? 3 : 2);
14821482
sym->symoff = mdata->filelen;
14831483
if (bfd_seek (abfd, sym->symoff, SEEK_SET) != 0)
14841484
return FALSE;
@@ -2018,8 +2018,9 @@ bfd_mach_o_write_contents (bfd *abfd)
20182018
case BFD_MACH_O_LC_SUB_FRAMEWORK:
20192019
break;
20202020
default:
2021-
(*_bfd_error_handler) (_("unable to write unknown load command 0x%lx"),
2022-
(unsigned long) cur->type);
2021+
(*_bfd_error_handler)
2022+
(_("unable to write unknown load command 0x%lx"),
2023+
(unsigned long) cur->type);
20232024
return FALSE;
20242025
}
20252026
}
@@ -2042,7 +2043,8 @@ bfd_mach_o_append_section_to_segment (bfd_mach_o_segment_command *seg,
20422043
/* Create section Mach-O flags from BFD flags. */
20432044

20442045
static void
2045-
bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
2046+
bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED,
2047+
asection *sec)
20462048
{
20472049
flagword bfd_flags;
20482050
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,
21732175
mdata->filelen += s->size;
21742176
}
21752177

2176-
/* Now pass through again, for zerofill, only now we just update the vmsize. */
2178+
/* Now pass through again, for zerofill, only now we just update the
2179+
vmsize. */
21772180
for (i = 0; i < mdata->nsects; ++i)
21782181
{
21792182
bfd_mach_o_section *s = mdata->sections[i];
@@ -4274,6 +4277,35 @@ bfd_mach_o_gen_core_p (bfd *abfd)
42744277
return bfd_mach_o_header_p (abfd, BFD_MACH_O_MH_CORE, 0);
42754278
}
42764279

4280+
/* Return the base address of ABFD, ie the address at which the image is
4281+
mapped. The possible initial pagezero is ignored. */
4282+
4283+
bfd_vma
4284+
bfd_mach_o_get_base_address (bfd *abfd)
4285+
{
4286+
bfd_mach_o_data_struct *mdata;
4287+
unsigned int i;
4288+
4289+
/* Check for Mach-O. */
4290+
if (!bfd_mach_o_valid (abfd))
4291+
return 0;
4292+
mdata = bfd_mach_o_get_data (abfd);
4293+
4294+
for (i = 0; i < mdata->header.ncmds; i++)
4295+
{
4296+
bfd_mach_o_load_command *cmd = &mdata->commands[i];
4297+
if ((cmd->type == BFD_MACH_O_LC_SEGMENT
4298+
|| cmd->type == BFD_MACH_O_LC_SEGMENT_64))
4299+
{
4300+
struct bfd_mach_o_segment_command *segcmd = &cmd->command.segment;
4301+
4302+
if (segcmd->initprot != 0)
4303+
return segcmd->vmaddr;
4304+
}
4305+
}
4306+
return 0;
4307+
}
4308+
42774309
typedef struct mach_o_fat_archentry
42784310
{
42794311
unsigned long cputype;

bfd/mach-o.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,8 @@ unsigned int bfd_mach_o_section_get_entry_size (bfd *, bfd_mach_o_section *);
656656
bfd_boolean bfd_mach_o_read_symtab_symbols (bfd *);
657657
bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd);
658658

659+
bfd_vma bfd_mach_o_get_base_address (bfd *);
660+
659661
/* A placeholder in case we need to suppress emitting the dysymtab for some
660662
reason (e.g. compatibility with older system versions). */
661663
#define bfd_mach_o_should_emit_dysymtab(x) TRUE

binutils/ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2014-03-27 Tristan Gingold <[email protected]>
2+
3+
* od-macho.c (OPT_FUNCTION_STARTS): New macro.
4+
(options): Add entry for function_starts.
5+
(mach_o_help): Ditto.
6+
(disp_segment_prot): New function.
7+
(dump_section_map): Call disp_segment_prot.
8+
(dump_function_starts): New function.
9+
(dump_obj_compact_unwind): Fix ouput indentation.
10+
(dump_exe_compact_unwind): Fix ouput indentation.
11+
(mach_o_dump): Handle function_starts.
12+
113
2014-03-26 Tristan Gingold <[email protected]>
214

315
* od-macho.c (bfd_mach_o_cpu_name): Add BFD_MACH_O_CPU_TYPE_ARM64.

binutils/od-macho.c

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define OPT_CODESIGN 5
4343
#define OPT_SEG_SPLIT_INFO 6
4444
#define OPT_COMPACT_UNWIND 7
45+
#define OPT_FUNCTION_STARTS 8
4546

4647
/* List of actions. */
4748
static struct objdump_private_option options[] =
@@ -54,6 +55,7 @@ static struct objdump_private_option options[] =
5455
{ "codesign", 0 },
5556
{ "seg_split_info", 0 },
5657
{ "compact_unwind", 0 },
58+
{ "function_starts", 0 },
5759
{ NULL, 0 }
5860
};
5961

@@ -64,14 +66,15 @@ mach_o_help (FILE *stream)
6466
{
6567
fprintf (stream, _("\
6668
For Mach-O files:\n\
67-
header Display the file header\n\
68-
section Display the segments and sections commands\n\
69-
map Display the section map\n\
70-
load Display the load commands\n\
71-
dysymtab Display the dynamic symbol table\n\
72-
codesign Display code signature\n\
73-
seg_split_info Display segment split info\n\
74-
compact_unwind Display compact unwinding info\n\
69+
header Display the file header\n\
70+
section Display the segments and sections commands\n\
71+
map Display the section map\n\
72+
load Display the load commands\n\
73+
dysymtab Display the dynamic symbol table\n\
74+
codesign Display code signature\n\
75+
seg_split_info Display segment split info\n\
76+
compact_unwind Display compact unwinding info\n\
77+
function_starts Display start address of functions\n\
7578
"));
7679
}
7780

@@ -283,6 +286,14 @@ dump_header (bfd *abfd)
283286
printf (_(" reserved : %08x\n"), h->reserved);
284287
}
285288

289+
static void
290+
disp_segment_prot (unsigned int prot)
291+
{
292+
putchar (prot & BFD_MACH_O_PROT_READ ? 'r' : '-');
293+
putchar (prot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
294+
putchar (prot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
295+
}
296+
286297
static void
287298
dump_section_map (bfd *abfd)
288299
{
@@ -309,9 +320,7 @@ dump_section_map (bfd *abfd)
309320
putchar ('-');
310321
printf_vma (seg->vmaddr + seg->vmsize - 1);
311322
putchar (' ');
312-
putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-');
313-
putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
314-
putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
323+
disp_segment_prot (seg->initprot);
315324
printf ("]\n");
316325

317326
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)
393402
printf (" endoff: ");
394403
printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
395404
printf ("\n");
396-
printf (" nsects: %lu ", seg->nsects);
397-
printf (" flags: %lx\n", seg->flags);
405+
printf (" nsects: %lu", seg->nsects);
406+
printf (" flags: %lx", seg->flags);
407+
printf (" initprot: ");
408+
disp_segment_prot (seg->initprot);
409+
printf (" maxprot: ");
410+
disp_segment_prot (seg->maxprot);
411+
printf ("\n");
398412
for (sec = seg->sect_head; sec != NULL; sec = sec->next)
399413
dump_section_header (abfd, sec);
400414
}
@@ -911,6 +925,55 @@ dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
911925
free (buf);
912926
}
913927

928+
static void
929+
dump_function_starts (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
930+
{
931+
unsigned char *buf = xmalloc (cmd->datasize);
932+
unsigned char *end_buf = buf + cmd->datasize;
933+
unsigned char *p;
934+
bfd_vma addr;
935+
936+
if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
937+
|| bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
938+
{
939+
non_fatal (_("cannot read function starts"));
940+
free (buf);
941+
return;
942+
}
943+
944+
/* Function starts are delta encoded, starting from the base address. */
945+
addr = bfd_mach_o_get_base_address (abfd);
946+
947+
for (p = buf; ;)
948+
{
949+
bfd_vma delta = 0;
950+
unsigned int shift = 0;
951+
952+
if (*p == 0 || p == end_buf)
953+
break;
954+
while (1)
955+
{
956+
unsigned char b = *p++;
957+
958+
delta |= (b & 0x7f) << shift;
959+
if ((b & 0x80) == 0)
960+
break;
961+
if (p == end_buf)
962+
{
963+
fputs (" [truncated]\n", stdout);
964+
break;
965+
}
966+
shift += 7;
967+
}
968+
969+
addr += delta;
970+
fputs (" ", stdout);
971+
bfd_printf_vma (abfd, addr);
972+
putchar ('\n');
973+
}
974+
free (buf);
975+
}
976+
914977
static void
915978
dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
916979
bfd_boolean verbose)
@@ -1005,6 +1068,8 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
10051068
dump_code_signature (abfd, linkedit);
10061069
else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO)
10071070
dump_segment_split_info (abfd, linkedit);
1071+
else if (verbose && cmd->type == BFD_MACH_O_LC_FUNCTION_STARTS)
1072+
dump_function_starts (abfd, linkedit);
10081073
break;
10091074
}
10101075
case BFD_MACH_O_LC_SUB_FRAMEWORK:
@@ -1260,7 +1325,7 @@ dump_obj_compact_unwind (bfd *abfd,
12601325
int is_64 = mdata->header.version == 2;
12611326
const unsigned char *p;
12621327

1263-
printf (" compact unwind info:\n");
1328+
printf ("Compact unwind info:\n");
12641329
printf (" start length personality lsda\n");
12651330

12661331
if (is_64)
@@ -1309,7 +1374,7 @@ dump_exe_compact_unwind (bfd *abfd,
13091374
unsigned int i;
13101375

13111376
/* The header. */
1312-
printf (" compact unwind info:\n");
1377+
printf ("Compact unwind info:\n");
13131378

13141379
hdr = (struct mach_o_unwind_info_header *) content;
13151380
if (size < sizeof (*hdr))
@@ -1544,6 +1609,8 @@ mach_o_dump (bfd *abfd)
15441609
dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
15451610
if (options[OPT_SEG_SPLIT_INFO].selected)
15461611
dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0);
1612+
if (options[OPT_FUNCTION_STARTS].selected)
1613+
dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0);
15471614
if (options[OPT_COMPACT_UNWIND].selected)
15481615
{
15491616
dump_section_content (abfd, "__LD", "__compact_unwind",

0 commit comments

Comments
 (0)