binutils/

2011-12-16  Tristan Gingold  <gingold@adacore.com>

	* od-macho.c: Include mach-o/codesign.h
	(OPT_CODESIGN): Define.
	(options): Add an entry for codesign.
	(mach_o_help): Likewise.
	(dump_header): Fix indentation.
	(dump_thread): Do not test result of xmalloc.
	(bfd_mach_o_cs_magic, bfd_mach_o_cs_hash_type): New.
	(dump_code_signature_superblob): New function.
	(swap_code_codedirectory_v1_in): Likewise.
	(hexdump): Likewise.
	(dump_code_signature_codedirectory): Likewise.
	(dump_code_signature_blob, dump_code_signature): Likewise.
	(dump_load_command): Dump code signature.
	(mach_o_dump): Likewise.

include/mach-o/
2011-12-16  Tristan Gingold  <gingold@adacore.com>

	* codesign.h: New file.
This commit is contained in:
Tristan Gingold 2011-12-16 10:23:01 +00:00
parent fb35d3d8fa
commit 2634e8c8ff
4 changed files with 332 additions and 7 deletions

View File

@ -1,3 +1,20 @@
2011-12-16 Tristan Gingold <gingold@adacore.com>
* od-macho.c: Include mach-o/codesign.h
(OPT_CODESIGN): Define.
(options): Add an entry for codesign.
(mach_o_help): Likewise.
(dump_header): Fix indentation.
(dump_thread): Do not test result of xmalloc.
(bfd_mach_o_cs_magic, bfd_mach_o_cs_hash_type): New.
(dump_code_signature_superblob): New function.
(swap_code_codedirectory_v1_in): Likewise.
(hexdump): Likewise.
(dump_code_signature_codedirectory): Likewise.
(dump_code_signature_blob, dump_code_signature): Likewise.
(dump_load_command): Dump code signature.
(mach_o_dump): Likewise.
2011-12-15 Andreas Tobler <andreast@fgznet.ch> 2011-12-15 Andreas Tobler <andreast@fgznet.ch>
* readelf.c (get_symbol_type): Add ELFOSABI_FREEBSD to the * readelf.c (get_symbol_type): Add ELFOSABI_FREEBSD to the

View File

@ -29,6 +29,7 @@
#include "bfdlink.h" #include "bfdlink.h"
#include "mach-o.h" #include "mach-o.h"
#include "mach-o/external.h" #include "mach-o/external.h"
#include "mach-o/codesign.h"
/* Index of the options in the options[] array. */ /* Index of the options in the options[] array. */
#define OPT_HEADER 0 #define OPT_HEADER 0
@ -36,6 +37,7 @@
#define OPT_MAP 2 #define OPT_MAP 2
#define OPT_LOAD 3 #define OPT_LOAD 3
#define OPT_DYSYMTAB 4 #define OPT_DYSYMTAB 4
#define OPT_CODESIGN 5
/* List of actions. */ /* List of actions. */
static struct objdump_private_option options[] = static struct objdump_private_option options[] =
@ -45,6 +47,7 @@ static struct objdump_private_option options[] =
{ "map", 0 }, { "map", 0 },
{ "load", 0 }, { "load", 0 },
{ "dysymtab", 0 }, { "dysymtab", 0 },
{ "codesign", 0 },
{ NULL, 0 } { NULL, 0 }
}; };
@ -60,6 +63,7 @@ For Mach-O files:\n\
map Display the section map\n\ map Display the section map\n\
load Display the load commands\n\ load Display the load commands\n\
dysymtab Display the dynamic symbol table\n\ dysymtab Display the dynamic symbol table\n\
codesign Display code signature section\n\
")); "));
} }
@ -253,11 +257,11 @@ dump_header (bfd *abfd)
fputs (_("Mach-O header:\n"), stdout); fputs (_("Mach-O header:\n"), stdout);
printf (_(" magic : %08lx\n"), h->magic); printf (_(" magic : %08lx\n"), h->magic);
printf (_(" cputype : %08lx (%s)\n"), h->cputype, printf (_(" cputype : %08lx (%s)\n"), h->cputype,
bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype)); bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
printf (_(" cpusubtype: %08lx\n"), h->cpusubtype); printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
printf (_(" filetype : %08lx (%s)\n"), printf (_(" filetype : %08lx (%s)\n"),
h->filetype, h->filetype,
bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype)); bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds); printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds); printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
printf (_(" flags : %08lx ("), h->flags); printf (_(" flags : %08lx ("), h->flags);
@ -627,16 +631,226 @@ dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
{ {
char *buf = xmalloc (flavour->size); char *buf = xmalloc (flavour->size);
if (buf if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
&& bfd_seek (abfd, flavour->offset, SEEK_SET) == 0 && bfd_bread (buf, flavour->size, abfd) == flavour->size)
&& (bfd_bread (buf, flavour->size, abfd)
== flavour->size))
(*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf); (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
free (buf); free (buf);
} }
} }
} }
static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
{
{ "embedded signature", BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE },
{ "requirement", BFD_MACH_O_CS_MAGIC_REQUIREMENT },
{ "requirements", BFD_MACH_O_CS_MAGIC_REQUIREMENTS },
{ "code directory", BFD_MACH_O_CS_MAGIC_CODEDIRECTORY },
{ "embedded entitlements", BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS },
{ "blob wrapper", BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER },
{ NULL, 0 }
};
static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
{
{ "no-hash", BFD_MACH_O_CS_NO_HASH },
{ "sha1", BFD_MACH_O_CS_HASH_SHA1 },
{ "sha256", BFD_MACH_O_CS_HASH_SHA256 },
{ "skein 160", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 },
{ "skein 256", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 },
{ NULL, 0 }
};
static unsigned int
dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
static void
dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
const unsigned char *buf, unsigned int len)
{
unsigned int count;
unsigned int i;
if (len < 12)
{
printf (_(" [bad block length]\n"));
return;
}
count = bfd_getb32 (buf + 8);
printf (_(" %u index entries:\n"), count);
if (len < 12 + 8 * count)
{
printf (_(" [bad block length]\n"));
return;
}
for (i = 0; i < count; i++)
{
unsigned int type;
unsigned int off;
type = bfd_getb32 (buf + 12 + 8 * i);
off = bfd_getb32 (buf + 12 + 8 * i + 4);
printf (_(" index entry %u: type: %08x, offset: %08x\n"),
i, type, off);
dump_code_signature_blob (abfd, buf + off, len - off);
}
}
static void
swap_code_codedirectory_v1_in
(const struct mach_o_codesign_codedirectory_external_v1 *src,
struct mach_o_codesign_codedirectory_v1 *dst)
{
dst->version = bfd_getb32 (src->version);
dst->flags = bfd_getb32 (src->flags);
dst->hash_offset = bfd_getb32 (src->hash_offset);
dst->ident_offset = bfd_getb32 (src->ident_offset);
dst->nbr_special_slots = bfd_getb32 (src->nbr_special_slots);
dst->nbr_code_slots = bfd_getb32 (src->nbr_code_slots);
dst->code_limit = bfd_getb32 (src->code_limit);
dst->hash_size = src->hash_size[0];
dst->hash_type = src->hash_type[0];
dst->spare1 = src->spare1[0];
dst->page_size = src->page_size[0];
dst->spare2 = bfd_getb32 (src->spare2);
}
static void
hexdump (unsigned int start, unsigned int len,
const unsigned char *buf)
{
unsigned int i, j;
for (i = 0; i < len; i += 16)
{
printf ("%08x:", start + i);
for (j = 0; j < 16; j++)
{
fputc (j == 8 ? '-' : ' ', stdout);
if (i + j < len)
printf ("%02x", buf[i + j]);
else
fputs (" ", stdout);
}
fputc (' ', stdout);
for (j = 0; j < 16; j++)
{
if (i + j < len)
fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
else
fputc (' ', stdout);
}
fputc ('\n', stdout);
}
}
static void
dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
const unsigned char *buf, unsigned int len)
{
struct mach_o_codesign_codedirectory_v1 cd;
const char *id;
if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
{
printf (_(" [bad block length]\n"));
return;
}
swap_code_codedirectory_v1_in
((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
printf (_(" version: %08x\n"), cd.version);
printf (_(" flags: %08x\n"), cd.flags);
printf (_(" hash offset: %08x\n"), cd.hash_offset);
id = (const char *) buf + cd.ident_offset;
printf (_(" ident offset: %08x (- %08x)\n"),
cd.ident_offset, cd.ident_offset + (unsigned) strlen (id) + 1);
printf (_(" identity: %s\n"), id);
printf (_(" nbr special slots: %08x (at offset %08x)\n"),
cd.nbr_special_slots,
cd.hash_offset - cd.nbr_special_slots * cd.hash_size);
printf (_(" nbr code slots: %08x\n"), cd.nbr_code_slots);
printf (_(" code limit: %08x\n"), cd.code_limit);
printf (_(" hash size: %02x\n"), cd.hash_size);
printf (_(" hash type: %02x (%s)\n"),
cd.hash_type,
bfd_mach_o_get_name (bfd_mach_o_cs_hash_type, cd.hash_type));
printf (_(" spare1: %02x\n"), cd.spare1);
printf (_(" page size: %02x\n"), cd.page_size);
printf (_(" spare2: %08x\n"), cd.spare2);
if (cd.version >= 0x20100)
printf (_(" scatter offset: %08x\n"),
(unsigned) bfd_getb32 (buf + 44));
}
static unsigned int
dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
{
unsigned int magic;
unsigned int length;
if (len < 8)
{
printf (_(" [truncated block]\n"));
return 0;
}
magic = bfd_getb32 (buf);
length = bfd_getb32 (buf + 4);
if (magic == 0 || length == 0)
return 0;
printf (_(" magic : %08x (%s)\n"), magic,
bfd_mach_o_get_name (bfd_mach_o_cs_magic, magic));
printf (_(" length: %08x\n"), length);
if (length > len)
{
printf (_(" [bad block length]\n"));
return 0;
}
switch (magic)
{
case BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE:
dump_code_signature_superblob (abfd, buf, length);
break;
case BFD_MACH_O_CS_MAGIC_CODEDIRECTORY:
dump_code_signature_codedirectory (abfd, buf, length);
break;
default:
hexdump (0, length - 8, buf + 8);
break;
}
return length;
}
static void
dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
{
unsigned char *buf = xmalloc (cmd->datasize);
unsigned int off;
if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
|| bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
{
non_fatal (_("cannot read code signature data"));
free (buf);
return;
}
for (off = 0; off < cmd->datasize;)
{
unsigned int len;
len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
if (len == 0)
break;
off += len;
}
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)
@ -716,6 +930,9 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
" dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n", " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
linkedit->dataoff, linkedit->datasize, linkedit->dataoff, linkedit->datasize,
linkedit->dataoff + linkedit->datasize); linkedit->dataoff + linkedit->datasize);
if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
dump_code_signature (abfd, linkedit);
break; break;
} }
case BFD_MACH_O_LC_SUB_FRAMEWORK: case BFD_MACH_O_LC_SUB_FRAMEWORK:
@ -785,6 +1002,8 @@ mach_o_dump (bfd *abfd)
dump_load_commands (abfd, 0, 0); dump_load_commands (abfd, 0, 0);
if (options[OPT_DYSYMTAB].selected) if (options[OPT_DYSYMTAB].selected)
dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0); dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
if (options[OPT_CODESIGN].selected)
dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
} }
/* Vector for Mach-O. */ /* Vector for Mach-O. */

View File

@ -1,3 +1,7 @@
2011-12-16 Tristan Gingold <gingold@adacore.com>
* codesign.h: New file.
2011-08-08 Tristan Gingold <gingold@adacore.com> 2011-08-08 Tristan Gingold <gingold@adacore.com>
* loader.h (bfd_mach_o_load_command_type): Add * loader.h (bfd_mach_o_load_command_type): Add

85
include/mach-o/codesign.h Normal file
View File

@ -0,0 +1,85 @@
/* Mach-O support for BFD.
Copyright 2011
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#ifndef _MACH_O_CODESIGN_H
#define _MACH_O_CODESIGN_H
/* Codesign blob magics. */
/* Superblob containing all the components. */
#define BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE 0xfade0cc0
/* Individual code requirement. */
#define BFD_MACH_O_CS_MAGIC_REQUIREMENT 0xfade0c00
/* Collection of code requirements, indexed by type. */
#define BFD_MACH_O_CS_MAGIC_REQUIREMENTS 0xfade0c01
/* Directory. */
#define BFD_MACH_O_CS_MAGIC_CODEDIRECTORY 0xfade0c02
/* Entitlements blob. */
#define BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS 0xfade7171
/* Blob container. */
#define BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER 0xfade0b01
struct mach_o_codesign_codedirectory_external_v1
{
/* All the fields are in network byte order (big endian). */
unsigned char version[4];
unsigned char flags[4];
unsigned char hash_offset[4];
unsigned char ident_offset[4];
unsigned char nbr_special_slots[4];
unsigned char nbr_code_slots[4];
unsigned char code_limit[4];
unsigned char hash_size[1];
unsigned char hash_type[1];
unsigned char spare1[1];
unsigned char page_size[1];
unsigned char spare2[4];
};
struct mach_o_codesign_codedirectory_v1
{
unsigned int version;
unsigned int flags;
unsigned int hash_offset;
unsigned int ident_offset;
unsigned int nbr_special_slots;
unsigned int nbr_code_slots;
unsigned int code_limit;
unsigned char hash_size;
unsigned char hash_type;
unsigned char spare1;
unsigned char page_size;
unsigned int spare2;
};
/* Value for hash_type. */
#define BFD_MACH_O_CS_NO_HASH 0
#define BFD_MACH_O_CS_HASH_SHA1 1
#define BFD_MACH_O_CS_HASH_SHA256 2
#define BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 32 /* Skein, 160 bits */
#define BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 33 /* Skein, 256 bits */
#endif /* _MACH_O_CODESIGN_H */