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>
* readelf.c (get_symbol_type): Add ELFOSABI_FREEBSD to the

View File

@ -29,6 +29,7 @@
#include "bfdlink.h"
#include "mach-o.h"
#include "mach-o/external.h"
#include "mach-o/codesign.h"
/* Index of the options in the options[] array. */
#define OPT_HEADER 0
@ -36,6 +37,7 @@
#define OPT_MAP 2
#define OPT_LOAD 3
#define OPT_DYSYMTAB 4
#define OPT_CODESIGN 5
/* List of actions. */
static struct objdump_private_option options[] =
@ -45,6 +47,7 @@ static struct objdump_private_option options[] =
{ "map", 0 },
{ "load", 0 },
{ "dysymtab", 0 },
{ "codesign", 0 },
{ NULL, 0 }
};
@ -60,6 +63,7 @@ For Mach-O files:\n\
map Display the section map\n\
load Display the load commands\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);
printf (_(" magic : %08lx\n"), h->magic);
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 (_(" filetype : %08lx (%s)\n"),
h->filetype,
bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
h->filetype,
bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
printf (_(" flags : %08lx ("), h->flags);
@ -627,16 +631,226 @@ dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
{
char *buf = xmalloc (flavour->size);
if (buf
&& bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
&& (bfd_bread (buf, flavour->size, abfd)
== flavour->size))
if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
&& bfd_bread (buf, flavour->size, abfd) == flavour->size)
(*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, 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
dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
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",
linkedit->dataoff, linkedit->datasize,
linkedit->dataoff + linkedit->datasize);
if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
dump_code_signature (abfd, linkedit);
break;
}
case BFD_MACH_O_LC_SUB_FRAMEWORK:
@ -785,6 +1002,8 @@ mach_o_dump (bfd *abfd)
dump_load_commands (abfd, 0, 0);
if (options[OPT_DYSYMTAB].selected)
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. */

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>
* 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 */