+2014-04-02 Tristan Gingold <gingold@adacore.com>
+
+ * mach-o.h (bfd_mach_o_twolevel_hints_command)
+ (bfd_mach_o_prebind_cksum_command): New types.
+ (bfd_mach_o_prebound_dylib_command): Rewrite.
+ (bfd_mach_o_load_command): Add prebind_cksum and twolevel_hints
+ fields.
+ * mach-o.c (bfd_mach_o_read_prebound_dylib): Read and decode the
+ command.
+ (bfd_mach_o_read_prebind_cksum): New function.
+ (bfd_mach_o_read_twolevel_hints): Ditto.
+ (bfd_mach_o_read_command): Handle prebind cksum and twolevel hints
+ commands.
+
2014-04-02 Alan Modra <amodra@gmail.com>
* elfcode.h (bfd_from_remote_memory): Add "size" parameter.
}
static int
-bfd_mach_o_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
- bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
+bfd_mach_o_read_prebound_dylib (bfd *abfd,
+ bfd_mach_o_load_command *command)
{
- /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
+ bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib;
+ struct mach_o_prebound_dylib_command_external raw;
+ unsigned int nameoff;
+ unsigned int modoff;
+ unsigned int str_len;
+ unsigned char *str;
+
+ if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+ || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+ return -1;
+
+ nameoff = bfd_h_get_32 (abfd, raw.name);
+ modoff = bfd_h_get_32 (abfd, raw.linked_modules);
+ if (nameoff > command->len || modoff > command->len)
+ return -1;
+
+ str_len = command->len - sizeof (raw);
+ str = bfd_alloc (abfd, str_len);
+ if (str == NULL)
+ return -1;
+ if (bfd_bread (str, str_len, abfd) != str_len)
+ return -1;
+
+ cmd->name_offset = command->offset + nameoff;
+ cmd->nmodules = bfd_h_get_32 (abfd, raw.nmodules);
+ cmd->linked_modules_offset = command->offset + modoff;
+
+ cmd->name_str = (char *)str + nameoff - (sizeof (raw) + BFD_MACH_O_LC_SIZE);
+ cmd->linked_modules = str + modoff - (sizeof (raw) + BFD_MACH_O_LC_SIZE);
+ return 0;
+}
+
+static int
+bfd_mach_o_read_prebind_cksum (bfd *abfd,
+ bfd_mach_o_load_command *command)
+{
+ bfd_mach_o_prebind_cksum_command *cmd = &command->command.prebind_cksum;
+ struct mach_o_prebind_cksum_command_external raw;
- BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
+ if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+ || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+ return -1;
+
+ cmd->cksum = bfd_get_32 (abfd, raw.cksum);
+ return 0;
+}
+
+static int
+bfd_mach_o_read_twolevel_hints (bfd *abfd,
+ bfd_mach_o_load_command *command)
+{
+ bfd_mach_o_twolevel_hints_command *cmd = &command->command.twolevel_hints;
+ struct mach_o_twolevel_hints_command_external raw;
+
+ if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+ || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+ return -1;
+
+ cmd->offset = bfd_get_32 (abfd, raw.offset);
+ cmd->nhints = bfd_get_32 (abfd, raw.nhints);
return 0;
}
if (bfd_mach_o_read_dysymtab (abfd, command) != 0)
return -1;
break;
- case BFD_MACH_O_LC_TWOLEVEL_HINTS:
case BFD_MACH_O_LC_PREBIND_CKSUM:
+ if (bfd_mach_o_read_prebind_cksum (abfd, command) != 0)
+ return -1;
+ break;
+ case BFD_MACH_O_LC_TWOLEVEL_HINTS:
+ if (bfd_mach_o_read_twolevel_hints (abfd, command) != 0)
+ return -1;
break;
case BFD_MACH_O_LC_UUID:
if (bfd_mach_o_read_uuid (abfd, command) != 0)
#define BFD_MACH_O_INDIRECT_SYMBOL_ABS 0x40000000
#define BFD_MACH_O_INDIRECT_SYMBOL_SIZE 4
+/* For LC_TWOLEVEL_HINTS. */
+
+typedef struct bfd_mach_o_twolevel_hints_command
+{
+ /* Offset to the hint table. */
+ unsigned int offset;
+
+ /* Number of entries in the table. */
+ unsigned int nhints;
+}
+bfd_mach_o_twolevel_hints_command;
+
+/* For LC_PREBIND_CKSUM. */
+
+typedef struct bfd_mach_o_prebind_cksum_command
+{
+ /* Checksum or zero. */
+ unsigned int cksum;
+}
+bfd_mach_o_prebind_cksum_command;
+
/* For LC_THREAD or LC_UNIXTHREAD. */
typedef struct bfd_mach_o_thread_flavour
typedef struct bfd_mach_o_prebound_dylib_command
{
- unsigned long name; /* Library's path name. */
- unsigned long nmodules; /* Number of modules in library. */
- unsigned long linked_modules; /* Bit vector of linked modules. */
+ unsigned int name_offset; /* Library's path name. */
+ unsigned int nmodules; /* Number of modules in library. */
+ unsigned int linked_modules_offset; /* Bit vector of linked modules. */
+
+ char *name_str;
+ unsigned char *linked_modules;
}
bfd_mach_o_prebound_dylib_command;
bfd_mach_o_dylib_command dylib;
bfd_mach_o_dylinker_command dylinker;
bfd_mach_o_prebound_dylib_command prebound_dylib;
+ bfd_mach_o_prebind_cksum_command prebind_cksum;
+ bfd_mach_o_twolevel_hints_command twolevel_hints;
bfd_mach_o_uuid_command uuid;
bfd_mach_o_linkedit_command linkedit;
bfd_mach_o_str_command str;
+2014-04-02 Tristan Gingold <gingold@adacore.com>
+
+ * od-macho.c (OPT_TWOLEVEL_HINTS): New macro.
+ (options): Add entry for twolevel_hints.
+ (dump_data_in_code): Fix error message.
+ (dump_twolevel_hints): New function.
+ (dump_load_command): Handle prebound dylib, prebind cksum
+ and twolevel hints.
+ (mach_o_dump): Handle twolevel hints.
+
2014-04-01 Tristan Gingold <gingold@adacore.com>
* od-macho.c (OPT_DATA_IN_CODE): New macro.
#define OPT_COMPACT_UNWIND 7
#define OPT_FUNCTION_STARTS 8
#define OPT_DATA_IN_CODE 9
+#define OPT_TWOLEVEL_HINTS 10
/* List of actions. */
static struct objdump_private_option options[] =
{ "compact_unwind", 0 },
{ "function_starts", 0 },
{ "data_in_code", 0 },
+ { "twolevel_hints", 0 },
{ NULL, 0 }
};
compact_unwind Display compact unwinding info\n\
function_starts Display start address of functions\n\
data_in_code Display data in code entries\n\
+ twolevel_hints Display the two-level namespace lookup hints table\n\
"));
}
if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
|| bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
{
- non_fatal (_("cannot read function starts"));
+ non_fatal (_("cannot read data_in_code"));
free (buf);
return;
}
}
static void
+dump_twolevel_hints (bfd *abfd, bfd_mach_o_twolevel_hints_command *cmd)
+{
+ size_t sz = 4 * cmd->nhints;
+ unsigned char *buf;
+ unsigned char *p;
+
+ buf = xmalloc (sz);
+ if (bfd_seek (abfd, cmd->offset, SEEK_SET) != 0
+ || bfd_bread (buf, sz, abfd) != sz)
+ {
+ non_fatal (_("cannot read twolevel hints"));
+ free (buf);
+ return;
+ }
+
+ for (p = buf; p < buf + sz; p += 4)
+ {
+ unsigned int v;
+ unsigned int isub_image;
+ unsigned int itoc;
+
+ v = bfd_get_32 (abfd, p);
+ if (bfd_big_endian (abfd))
+ {
+ isub_image = (v >> 24) & 0xff;
+ itoc = v & 0xffffff;
+ }
+ else
+ {
+ isub_image = v & 0xff;
+ itoc = (v >> 8) & 0xffffff;
+ }
+
+ printf (" %3u %8u\n", isub_image, itoc);
+ }
+ free (buf);
+}
+
+static void
dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
bfd_boolean verbose)
{
version->a, version->b, version->c, version->d, version->e);
break;
}
+ case BFD_MACH_O_LC_PREBOUND_DYLIB:
+ {
+ bfd_mach_o_prebound_dylib_command *pbdy = &cmd->command.prebound_dylib;
+ unsigned char *lm = pbdy->linked_modules;
+ unsigned int j;
+ unsigned int last;
+
+ printf (" %s\n", pbdy->name_str);
+ printf (" nmodules: %u\n", pbdy->nmodules);
+ printf (" linked modules (at %u): ",
+ pbdy->linked_modules_offset - cmd->offset);
+ last = pbdy->nmodules > 32 ? 32 : pbdy->nmodules;
+ for (j = 0; j < last; j++)
+ printf ("%u", (lm[j >> 3] >> (j & 7)) & 1);
+ if (last < pbdy->nmodules)
+ printf ("...");
+ putchar ('\n');
+ break;
+ }
+ case BFD_MACH_O_LC_PREBIND_CKSUM:
+ {
+ bfd_mach_o_prebind_cksum_command *cksum = &cmd->command.prebind_cksum;
+ printf (" 0x%08x\n", cksum->cksum);
+ break;
+ }
+ case BFD_MACH_O_LC_TWOLEVEL_HINTS:
+ {
+ bfd_mach_o_twolevel_hints_command *hints =
+ &cmd->command.twolevel_hints;
+
+ printf ("\n"
+ " table offset: 0x%08x nbr hints: %u\n",
+ hints->offset, hints->nhints);
+ if (verbose)
+ dump_twolevel_hints (abfd, hints);
+ break;
+ }
case BFD_MACH_O_LC_MAIN:
{
bfd_mach_o_main_command *entry = &cmd->command.main;
dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0);
if (options[OPT_DATA_IN_CODE].selected)
dump_load_commands (abfd, BFD_MACH_O_LC_DATA_IN_CODE, 0);
+ if (options[OPT_TWOLEVEL_HINTS].selected)
+ dump_load_commands (abfd, BFD_MACH_O_LC_TWOLEVEL_HINTS, 0);
if (options[OPT_COMPACT_UNWIND].selected)
{
dump_section_content (abfd, "__LD", "__compact_unwind",
+2014-04-02 Tristan Gingold <gingold@adacore.com>
+
+ * external.h (mach_o_prebound_dylib_command_external)
+ (mach_o_prebind_cksum_command_external)
+ (mach_o_twolevel_hints_command_external): New types.
+
2014-03-26 Tristan Gingold <gingold@adacore.com>
* loader.h (bfd_mach_o_cpu_type): Add BFD_MACH_O_CPU_TYPE_ARM64.
unsigned char export_size[4];
};
+struct mach_o_prebound_dylib_command_external
+{
+ unsigned char name[4];
+ unsigned char nmodules[4];
+ unsigned char linked_modules[4];
+};
+
+struct mach_o_prebind_cksum_command_external
+{
+ unsigned char cksum[4];
+};
+
+struct mach_o_twolevel_hints_command_external
+{
+ unsigned char offset[4];
+ unsigned char nhints[4];
+};
+
struct mach_o_version_min_command_external
{
unsigned char version[4];