Exemplo n.º 1
0
/*
 * get_toc_byte_sex() guesses the byte sex of the table of contents of the
 * library mapped in at the address, addr, of size, size based on the first
 * object file's bytesex.  If it can't figure it out, because the library has
 * no object file members or is malformed it will return UNKNOWN_BYTE_SEX.
 */
__private_extern__
enum byte_sex
get_toc_byte_sex(
char *addr,
uint32_t size)
{
     uint32_t magic;
     uint32_t ar_name_size;
     struct ar_hdr *ar_hdr;
     char *p;

	ar_hdr = (struct ar_hdr *)(addr + SARMAG);

	p = addr + SARMAG + sizeof(struct ar_hdr) +
	    rnd(strtoul(ar_hdr->ar_size, NULL, 10), sizeof(short));
	while(p + sizeof(struct ar_hdr) + sizeof(uint32_t) < addr + size){
	    ar_hdr = (struct ar_hdr *)p;
	    if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0)
		ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,
				       NULL, 10);
	    else
		ar_name_size = 0;
	    p += sizeof(struct ar_hdr);
	    memcpy(&magic, p + ar_name_size, sizeof(uint32_t));
	    if(magic == MH_MAGIC || magic == MH_MAGIC_64)
		return(get_host_byte_sex());
	    else if(magic == SWAP_INT(MH_MAGIC) ||
		    magic == SWAP_INT(MH_MAGIC_64))
		return(get_host_byte_sex() == BIG_ENDIAN_BYTE_SEX ?
		       LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX);
	    p += rnd(strtoul(ar_hdr->ar_size, NULL, 10), sizeof(short));
	}
	return(UNKNOWN_BYTE_SEX);
}
Exemplo n.º 2
0
/*
 * ofile_get_word() gets a 32 bit word for the address in the object file.
 */
__private_extern__
long
ofile_get_word(
unsigned long addr,
unsigned long *word,
void *get_word_data /* struct mach_object_file *ofile */ )
{
    unsigned long i, j;
    struct load_command *lc;
    struct segment_command *sg;
    struct section *s;
    struct ofile *ofile;

	ofile = (struct ofile *)get_word_data;
	for(i = 0, lc = ofile->load_commands; i < ofile->mh->ncmds; i++){
	    if(lc->cmd == LC_SEGMENT){
		sg = (struct segment_command *)lc;
		s = (struct section *)
		    ((char *)sg + sizeof(struct segment_command));
		for(j = 0 ; j < sg->nsects ; j++){
		    if(addr >= s->addr && addr < s->addr + s->size){
			if(s->flags == S_ZEROFILL)
			    *word = 0;
			else {
			    if(s->offset > ofile->object_size ||
			       s->offset + s->size > ofile->object_size ||
			       s->offset % sizeof(long) != 0 ||
			       (addr - s->addr) % sizeof(long) != 0)
				return(-1);
			    else{
				memcpy(word, (ofile->object_addr +
					       (s->offset + addr - s->addr)),
					sizeof(unsigned long));
				if(ofile->object_byte_sex !=get_host_byte_sex())
				    *word = SWAP_LONG(*word);
			    }
			}
			return(0);
		    }
		    s++;
		}
	    }
	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
	}
	return(-1);
}
Exemplo n.º 3
0
/*
 * The program cmpdylib.  This compares an old and an new dynamic shared library
 * for compatiblity.  Usage:
 *
 *	cmpdylib old_dylib new_dylib
 * 
 * It exits non-zero for incompatible libraries and prints why the libraries are
 * incompatible.  It exit zero and prints nothing for compatible libraries.
 */
int
main(
int argc,
char *argv[],
char *envp[])
{
	progname = argv[0];
	host_byte_sex = get_host_byte_sex();

	if(argc != 3){
	    fprintf(stderr, "Usage: %s old_dylib new_dylib\n", progname);
	    exit(EXIT_FAILURE);
	}
	old_dylib = argv[1];
	new_dylib = argv[2];

	ofile_process(old_dylib, NULL, 0, TRUE, TRUE, TRUE, FALSE, process_old, 
		      NULL);

	if(compatible == TRUE)
	    return(EXIT_SUCCESS);
	else
	    return(EXIT_FAILURE);
}
Exemplo n.º 4
0
/*
 * print_symbols() prints out the value of the data symbols
 * in the specified format.
 */
static
void
print_symbols(
struct ofile *ofile,
struct nlist *symbols,
unsigned long nsymbols,
char *strings,
unsigned long strsize,
struct cmd_flags *cmd_flags,
struct process_flags *process_flags,
char *arch_name)
{
    unsigned long i;
    unsigned char c;
    unsigned long value;

    char *sect, *addr;
    unsigned long sect_size, sect_addr, sect_nrelocs, sect_flags, size;
    struct relocation_info *sect_relocs;
    enum bool swapped;
    

	if(ofile->file_type == OFILE_FAT){
	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
	    size = ofile->fat_archs[ofile->narch].size;
	}
	else{
	    addr = ofile->file_addr;
	    size = ofile->file_size;
	}
	if(addr + size > ofile->file_addr + ofile->file_size)
	    size = (ofile->file_addr + ofile->file_size) - addr;

	swapped = ofile->object_byte_sex != get_host_byte_sex();

	if(get_sect_info(SEG_DATA, SECT_DATA, ofile->mh,
	    ofile->load_commands, ofile->object_byte_sex,
	    addr, size, &sect, &sect_size, &sect_addr,
	    &sect_relocs, &sect_nrelocs, &sect_flags) != TRUE) {
	    error("No data section information\n");
	    return;
	}

	for(i = 0; i < nsymbols; i++){
	    c = symbols[i].n_type;
	    if(c & N_STAB){
		continue;
	    }
	    switch(c & N_TYPE){
	    case N_UNDF:
		c = 'u';
		if(symbols[i].n_value != 0)
		    c = 'c';
		break;
	    case N_ABS:
		c = 'a';
		break;
	    case N_SECT:
		if(symbols[i].n_sect == process_flags->text_nsect)
		    c = 't';
		else if(symbols[i].n_sect == process_flags->data_nsect)
		    c = 'd';
		else if(symbols[i].n_sect == process_flags->bss_nsect)
		    c = 'b';
		else
		    c = 's';
		break;
	    case N_INDR:
		c = 'i';
		break;
	    default:
		c = '?';
		break;
	    }
	    if((symbols[i].n_type & N_EXT) && c != '?')
		c = toupper(c);

		if(c == 'u' || c == 'U' || c == 'i' || c == 'I')
		    fprintf(output, "        ");
		else {
		    if (c == 'D') {
			unsigned long offset;

			if (cmd_flags->c == TRUE)
			    fprintf(output, "#define ");
			/* skip leading underscore of names */
			fprintf(output, "%s\t", (symbols[i].n_un.n_name + 1));
			/* Subtract section offset */
			offset = sect_addr + symbols[i].n_value;
			/* Check range */
			if (offset > (sect_size - sizeof(unsigned long))) {
			    error("value for symbol '%s' located "
			          "outside data section\n",
				  (symbols[i].n_un.n_name + 1));
			    continue;
			}
			bcopy(sect + offset, &value, sizeof(value));
			if (swapped)
			    value = SWAP_LONG(value);
			/* SWAP_LONG */
			if (cmd_flags->x == TRUE)
			    fprintf(output, "0x%08lx\n", value);
			else
			    fprintf(output, "%ld\n", value);
		    }
		}
	}
}
Exemplo n.º 5
0
/*
 * select_symbols returns an allocated array of nlist structs as the symbols
 * that are to be printed based on the flags.  The number of symbols in the
 * array returned in returned indirectly through nsymbols.
 */
static
struct nlist *
select_symbols(
struct ofile *ofile,
struct symtab_command *st,
struct dysymtab_command *dyst,
struct cmd_flags *cmd_flags,
struct process_flags *process_flags,
unsigned long *nsymbols)
{
    unsigned long i, flags;
    struct nlist *all_symbols, *selected_symbols, undefined;
    struct dylib_module m;
    struct dylib_reference *refs;

	all_symbols = (struct nlist *)(ofile->object_addr + st->symoff);
	selected_symbols = allocate(sizeof(struct nlist) * st->nsyms);
	*nsymbols = 0;

	if(ofile->object_byte_sex != get_host_byte_sex())
	    swap_nlist(all_symbols, st->nsyms, get_host_byte_sex());

	if(ofile->dylib_module != NULL){
	    m = *ofile->dylib_module;
	    refs = (struct dylib_reference *)(ofile->object_addr +
					      dyst->extrefsymoff);
	    if(ofile->object_byte_sex != get_host_byte_sex()){
		swap_dylib_module(&m, 1, get_host_byte_sex());
		swap_dylib_reference(refs + m.irefsym, m.nrefsym,
				     get_host_byte_sex());
	    }
	    for(i = 0; i < m.nrefsym; i++){
		flags = refs[i + m.irefsym].flags;
		if(flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY ||
		   flags == REFERENCE_FLAG_UNDEFINED_LAZY ||
		   flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY ||
		   flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY){
		    undefined = all_symbols[refs[i + m.irefsym].isym];
		    if(flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY ||
		       flags == REFERENCE_FLAG_UNDEFINED_LAZY)
			undefined.n_type = N_UNDF | N_EXT;
		    else
			undefined.n_type = N_UNDF;
		    undefined.n_desc = (undefined.n_desc &~ REFERENCE_TYPE) |
				       flags;
		    undefined.n_value = 0;
		    
		    selected_symbols[(*nsymbols)++] = undefined;
		}
	    }
	    for(i = 0; i < m.nextdefsym; i++){
		selected_symbols[(*nsymbols)++] =
			all_symbols[m.iextdefsym + i];
	    }
	    for(i = 0; i < m.nlocalsym; i++){
		selected_symbols[(*nsymbols)++] =
			all_symbols[m.ilocalsym + i];
	    }
	}
	else{
	    for(i = 0; i < st->nsyms; i++){
		selected_symbols[(*nsymbols)++] = all_symbols[i];
	    }
	}
	if(ofile->object_byte_sex != get_host_byte_sex())
	    swap_nlist(all_symbols, st->nsyms, ofile->object_byte_sex);
	/*
	 * Could reallocate selected symbols to the exact size but it is more
	 * of a time waste than a memory savings.
	 */
	return(selected_symbols);
}
Exemplo n.º 6
0
enum bool
get_sect_info(
char *segname,				/* input */
char *sectname,
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
char **sect_pointer,			/* output */
unsigned long *sect_size,
unsigned long *sect_addr,
struct relocation_info **sect_relocs,
unsigned long *sect_nrelocs,
unsigned long *sect_flags)
{
    enum byte_sex host_byte_sex;
    enum bool found;
    unsigned long i, j, left, size;
    struct load_command *lc, l;
    struct segment_command sg;
    struct section s;
    char *p;

	*sect_pointer = NULL;
	*sect_size = 0;
	*sect_addr = 0;
	*sect_relocs = NULL;
	*sect_nrelocs = 0;
	*sect_flags = 0;

	found = FALSE;
	host_byte_sex = get_host_byte_sex();

	lc = load_commands;
	for(i = 0 ; found == FALSE && i < mh->ncmds; i++){
	    memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
	    if(l.cmdsize % sizeof(long) != 0)
		error("load command %lu size not a multiple of "
		       "sizeof(long)\n", i);
	    if((char *)lc + l.cmdsize >
	       (char *)load_commands + mh->sizeofcmds)
		error("load command %lu extends past end of load "
		       "commands\n", i);
	    left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);

	    switch(l.cmd){
	    case LC_SEGMENT:
		memset((char *)&sg, '\0', sizeof(struct segment_command));
		size = left < sizeof(struct segment_command) ?
		       left : sizeof(struct segment_command);
		memcpy((char *)&sg, (char *)lc, size);

		if((mh->filetype == MH_OBJECT && sg.segname[0] == '\0') ||
		   strncmp(sg.segname, segname, sizeof(sg.segname)) == 0){

		    p = (char *)lc + sizeof(struct segment_command);
		    for(j = 0 ; found == FALSE && j < sg.nsects ; j++){
			if(p + sizeof(struct section) >
			   (char *)load_commands + mh->sizeofcmds){
			    error("section structure command extends past "
				   "end of load commands\n");
			}
			left = mh->sizeofcmds - (p - (char *)load_commands);
			memset((char *)&s, '\0', sizeof(struct section));
			size = left < sizeof(struct section) ?
			       left : sizeof(struct section);
			memcpy((char *)&s, p, size);

			if(strncmp(s.sectname, sectname,
				   sizeof(s.sectname)) == 0){
			    found = TRUE;
			    break;
			}

			if(p + sizeof(struct section) >
			   (char *)load_commands + mh->sizeofcmds)
			    return(FALSE);
			p += size;
		    }
		}
		break;
	    }
	    if(l.cmdsize == 0){
		error("load command %lu size zero (can't advance to other "
		       "load commands)\n", i);
		break;
	    }
	    lc = (struct load_command *)((char *)lc + l.cmdsize);
	    if((char *)lc > (char *)load_commands + mh->sizeofcmds)
		break;
	}
	if(found == FALSE)
	    return(FALSE);

	if((s.flags & SECTION_TYPE) == S_ZEROFILL){
	    *sect_pointer = NULL;
	    *sect_size = s.size;
	}
	else{
	    if(s.offset >= object_size){
		error("section offset for section (%.16s,%.16s) is past end "
		       "of file\n", s.segname, s.sectname);
	    }
	    else{
		*sect_pointer = object_addr + s.offset;
		if(s.offset + s.size > object_size){
		    error("section (%.16s,%.16s) extends past end of file\n",
			   s.segname, s.sectname);
		    *sect_size = object_size - s.offset;
		}
		else
		    *sect_size = s.size;
	    }
	}
	if(s.reloff >= object_size){
	    error("relocation entries offset for (%.16s,%.16s): is past end "
		   "of file\n", s.segname, s.sectname);
	}
	else{
	    *sect_relocs = (struct relocation_info *)(object_addr + s.reloff);
	    if(s.reloff + s.nreloc * sizeof(struct relocation_info) >
								object_size){
		error("relocation entries for section (%.16s,%.16s) extends "
		       "past end of file\n", s.segname, s.sectname);
		*sect_nrelocs = (object_size - s.reloff) /
				sizeof(struct relocation_info);
	    }
	    else
		*sect_nrelocs = s.nreloc;
	}
	*sect_addr = s.addr;
	*sect_flags = s.flags;
	return(TRUE);
}
Exemplo n.º 7
0
static
void
process(
struct arch *archs,
unsigned long narchs)
{
    unsigned long i, j, k, offset, size;
    struct object *object;
    struct load_command *lc;
    struct segment_command *sg;

	for(i = 0; i < narchs; i++){
	    if(archs[i].type == OFILE_ARCHIVE){
		for(j = 0; j < archs[i].nmembers; j++){
		    if(archs[i].members[j].type == OFILE_Mach_O){
			object = archs[i].members[j].object;
			lc = object->load_commands;
			for(k = 0; k < object->mh->ncmds; k++){
			    if(lc->cmd == LC_SYMTAB){
				object->st = (struct symtab_command *)lc;
			    }
			    else if(lc->cmd == LC_SEGMENT){
				sg = (struct segment_command *)lc;
				hack_seg(object, lc, sg);
			    }
			    else if(lc->cmd == LC_DYSYMTAB){
				error_arch(archs + i, archs[i].members + j,
				    "can't process -dynamic object: ");
				return;
			    }
			    lc = (struct load_command *)((char *)lc +
							 lc->cmdsize);
			}
			if(object->st != NULL && object->st->nsyms != 0){
			    object->output_symbols
				    = (struct nlist *)(object->object_addr +
						       object->st->symoff);
			    if(object->object_byte_sex != get_host_byte_sex())
				swap_nlist(object->output_symbols,
					   object->st->nsyms,
					   get_host_byte_sex());
			    object->output_nsymbols = object->st->nsyms;
			    object->output_strings =
				object->object_addr + object->st->stroff;
			    object->output_strings_size = object->st->strsize;
			    object->input_sym_info_size =
				object->st->nsyms * sizeof(struct nlist) +
				object->st->strsize;
			    object->output_sym_info_size =
				object->input_sym_info_size;
			}
		    }
		}
		/*
		 * Reset the library offsets and size.
		 */
		offset = 0;
		for(j = 0; j < archs[i].nmembers; j++){
		    archs[i].members[j].offset = offset;
		    size = 0;
		    if(archs[i].members[j].member_long_name == TRUE){
			size = round(archs[i].members[j].member_name_size,
				     sizeof(long));
			archs[i].toc_long_name = TRUE;
		    }
		    if(archs[i].members[j].object != NULL){
			size += archs[i].members[j].object->object_size
			   - archs[i].members[j].object->input_sym_info_size
			   + archs[i].members[j].object->output_sym_info_size;
			sprintf(archs[i].members[j].ar_hdr->ar_size, "%-*ld",
			       (int)sizeof(archs[i].members[j].ar_hdr->ar_size),
			       (long)(size));
			/*
			 * This has to be done by hand because sprintf puts a
			 * null at the end of the buffer.
			 */
			memcpy(archs[i].members[j].ar_hdr->ar_fmag, ARFMAG,
			      (int)sizeof(archs[i].members[j].ar_hdr->ar_fmag));
		    }
		    else{
			size += archs[i].members[j].unknown_size;
		    }
		    offset += sizeof(struct ar_hdr) + size;
		}
		archs[i].library_size = offset;
	    }
	    else if(archs[i].type == OFILE_Mach_O){
		object = archs[i].object;
		lc = object->load_commands;
		for(j = 0; j < object->mh->ncmds; j++){
		    if(lc->cmd == LC_SYMTAB){
			object->st = (struct symtab_command *)lc;
		    }
		    else if(lc->cmd == LC_SEGMENT){
			sg = (struct segment_command *)lc;
			hack_seg(object, lc, sg);
		    }
		    else if(lc->cmd == LC_DYSYMTAB){
			error_arch(archs + i, NULL, "can't process -dynamic "
			    "object: ");
			return;
		    }
		    lc = (struct load_command *)((char *)lc +
						 lc->cmdsize);
		}
		if(object->st != NULL && object->st->nsyms != 0){
		    object->output_symbols
			    = (struct nlist *)(object->object_addr +
					       object->st->symoff);
		    if(object->object_byte_sex != get_host_byte_sex()){
			swap_nlist(object->output_symbols, object->st->nsyms,
				   get_host_byte_sex());
		    }
		    object->output_nsymbols = object->st->nsyms;
		    object->output_strings =
			object->object_addr + object->st->stroff;
		    object->output_strings_size = object->st->strsize;
		    object->input_sym_info_size =
			object->st->nsyms * sizeof(struct nlist) +
			object->st->strsize;
		    object->output_sym_info_size =
			object->input_sym_info_size;
		}
		/*
		 * Always clear the prebind checksum if any when creating a new
		 * file.
		 */
		if(object->cs != NULL)
		    object->cs->cksum = 0;
	    }
	}
}
Exemplo n.º 8
0
unsigned long nsorted_symbols,
char *strings,
unsigned long strings_size,
enum bool verbose)
{
    enum byte_sex host_byte_sex;
    enum bool swapped;
    unsigned long opcode;
    unsigned int i, num, do_completers;
    char *format, c;
    int jbsr;
    unsigned long sect_offset;
    
	jbsr = 0;
	sect_offset = addr - sect_addr;
	host_byte_sex = get_host_byte_sex();
	swapped = host_byte_sex != object_byte_sex;

	if(left < sizeof(unsigned long)){
	   if(left != 0){
		memcpy(&opcode, sect, left);
		if(swapped)
		    opcode = SWAP_LONG(opcode);
		printf(".long\t0x%08x\n", (unsigned int)opcode);
	   }
	   printf("(end of section)\n");
	   return(left);
	}

	memcpy(&opcode, sect, sizeof(unsigned long));
	if(swapped)
Exemplo n.º 9
0
enum bool
swap_object_headers(
void *mach_header,
struct load_command *load_commands)
{
    unsigned long i;
    uint32_t magic, ncmds, sizeofcmds, cmd_multiple;
    cpu_type_t cputype;
    cpu_subtype_t cpusubtype;
    struct mach_header *mh;
    struct mach_header_64 *mh64;
    enum byte_sex target_byte_sex;
    struct load_command *lc, l;
    struct segment_command *sg;
    struct segment_command_64 *sg64;
    struct section *s;
    struct section_64 *s64;
    struct symtab_command *st;
    struct dysymtab_command *dyst;
    struct symseg_command *ss;
    struct fvmlib_command *fl;
    struct thread_command *ut;
    struct ident_command *id;
    struct dylib_command *dl;
    struct sub_framework_command *sub;
    struct sub_umbrella_command *usub;
    struct sub_library_command *lsub;
    struct sub_client_command *csub;
    struct prebound_dylib_command *pbdylib;
    struct dylinker_command *dyld;
    struct routines_command *rc;
    struct routines_command_64 *rc64;
    struct twolevel_hints_command *hints;
    struct prebind_cksum_command *cs;
    struct uuid_command *uuid;
    unsigned long flavor, count, nflavor;
    char *p, *state;

	magic = *((uint32_t *)mach_header);
	if(magic == MH_MAGIC){
	    mh = (struct mach_header *)mach_header;
	    ncmds = mh->ncmds;
	    sizeofcmds = mh->sizeofcmds;
	    cputype = mh->cputype;
	    cpusubtype = mh->cpusubtype;
	    cmd_multiple = 4;
	    mh64 = NULL;
	}
	else{
	    mh64 = (struct mach_header_64 *)mach_header;
	    ncmds = mh64->ncmds;
	    sizeofcmds = mh64->sizeofcmds;
	    cputype = mh64->cputype;
	    cpusubtype = mh64->cpusubtype;
	    cmd_multiple = 8;
	    mh = NULL;
	}
	/*
	 * Make a pass through the load commands checking them to the level
	 * that they can be parsed and then swapped.
	 */
	for(i = 0, lc = load_commands; i < ncmds; i++){
	    l = *lc;
	    /* check load command size for a correct multiple size */
	    if(lc->cmdsize % cmd_multiple != 0){
		error("in swap_object_headers(): malformed load command %lu "
		      "(cmdsize not a multiple of %u)", i, cmd_multiple);
		return(FALSE);
	    }
	    /* check that load command does not extends past end of commands */
	    if((char *)lc + lc->cmdsize >
	       (char *)load_commands + sizeofcmds){
		error("in swap_object_headers(): truncated or malformed load "
		      "command %lu (extends past the end of the all load "
		      "commands)", i);
		return(FALSE);
	    }
	    /* check that the load command size is not zero */
	    if(lc->cmdsize == 0){
		error("in swap_object_headers(): malformed load command %lu "
		      "(cmdsize is zero)", i);
		return(FALSE);
	    }
	    switch(lc->cmd){
	    case LC_SEGMENT:
		sg = (struct segment_command *)lc;
		if(sg->cmdsize != sizeof(struct segment_command) +
				     sg->nsects * sizeof(struct section)){
		    error("in swap_object_headers(): malformed load command "
			  "(inconsistent cmdsize in LC_SEGMENT command %lu for "
			  "the number of sections)", i);
		    return(FALSE);
		}
		break;

	    case LC_SEGMENT_64:
		sg64 = (struct segment_command_64 *)lc;
		if(sg64->cmdsize != sizeof(struct segment_command_64) +
				     sg64->nsects * sizeof(struct section_64)){
		    error("in swap_object_headers(): malformed load command "
			  "(inconsistent cmdsize in LC_SEGMENT_64 command %lu "
			  "for the number of sections)", i);
		    return(FALSE);
		}
		break;

	    case LC_SYMTAB:
		st = (struct symtab_command *)lc;
		if(st->cmdsize != sizeof(struct symtab_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_SYMTAB command %lu has incorrect cmdsize", i);
		    return(FALSE);
		}
		break;

	    case LC_DYSYMTAB:
		dyst = (struct dysymtab_command *)lc;
		if(dyst->cmdsize != sizeof(struct dysymtab_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_DYSYMTAB command %lu has incorrect cmdsize", i);
		    return(FALSE);
		}
		break;

	    case LC_SYMSEG:
		ss = (struct symseg_command *)lc;
		if(ss->cmdsize != sizeof(struct symseg_command)){
		    error("in swap_object_headers(): malformed load command "
			  "(LC_SYMSEG command %lu has incorrect cmdsize", i);
		    return(FALSE);
		}
		break;

	    case LC_IDFVMLIB:
	    case LC_LOADFVMLIB:
		fl = (struct fvmlib_command *)lc;
		if(fl->cmdsize < sizeof(struct fvmlib_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(%s command %lu has too small cmdsize field)",
			  fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" :
			  "LC_LOADFVMLIB", i);
		    return(FALSE);
		}
		if(fl->fvmlib.name.offset >= fl->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (name.offset field of %s command %lu "
			  "extends past the end of all load commands)",
			  fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" :
			  "LC_LOADFVMLIB", i);
		    return(FALSE);
		}
		break;

	    case LC_ID_DYLIB:
	    case LC_LOAD_DYLIB:
	    case LC_LOAD_WEAK_DYLIB:
		dl = (struct dylib_command *)lc;
		if(dl->cmdsize < sizeof(struct dylib_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(%s command %lu has too small cmdsize field)",
			  dl->cmd == LC_ID_DYLIB ? "LC_ID_DYLIB" :
			  (dl->cmd == LC_LOAD_DYLIB ? "LC_LOAD_DYLIB" :
			  "LC_LOAD_WEAK_DYLIB"), i);
		    return(FALSE);
		}
		if(dl->dylib.name.offset >= dl->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (name.offset field of %s command %lu "
			  "extends past the end of all load commands)",
			  dl->cmd == LC_ID_DYLIB ? "LC_ID_DYLIB" :
			  (dl->cmd == LC_LOAD_DYLIB ? "LC_LOAD_DYLIB" :
			  "LC_LOAD_WEAK_DYLIB"), i);
		    return(FALSE);
		}
		break;

	    case LC_SUB_FRAMEWORK:
		sub = (struct sub_framework_command *)lc;
		if(sub->cmdsize < sizeof(struct sub_framework_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_SUB_FRAMEWORK command %lu has too small cmdsize "
			  "field)", i);
		    return(FALSE);
		}
		if(sub->umbrella.offset >= sub->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (umbrella.offset field of "
			  "LC_SUB_FRAMEWORK command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_SUB_UMBRELLA:
		usub = (struct sub_umbrella_command *)lc;
		if(usub->cmdsize < sizeof(struct sub_umbrella_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_SUB_UMBRELLA command %lu has too small cmdsize "
			  "field)", i);
		    return(FALSE);
		}
		if(usub->sub_umbrella.offset >= usub->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (sub_umbrella.offset field of "
			  "LC_SUB_UMBRELLA command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_SUB_LIBRARY:
		lsub = (struct sub_library_command *)lc;
		if(lsub->cmdsize < sizeof(struct sub_library_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_SUB_LIBRARY command %lu has too small cmdsize "
			  "field)", i);
		    return(FALSE);
		}
		if(lsub->sub_library.offset >= lsub->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (sub_library.offset field of "
			  "LC_SUB_LIBRARY command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_SUB_CLIENT:
		csub = (struct sub_client_command *)lc;
		if(csub->cmdsize < sizeof(struct sub_client_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_SUB_CLIENT command %lu has too small cmdsize "
			  "field)", i);
		    return(FALSE);
		}
		if(csub->client.offset >= csub->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (client.offset field of "
			  "LC_SUB_CLIENT command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_PREBOUND_DYLIB:
		pbdylib = (struct prebound_dylib_command *)lc;
		if(pbdylib->cmdsize < sizeof(struct prebound_dylib_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_PREBOUND_DYLIB command %lu has too small "
			  "cmdsize field)", i);
		    return(FALSE);
		}
		if(pbdylib->name.offset >= pbdylib->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (name.offset field of "
			  "LC_PREBOUND_DYLIB command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (linked_modules.offset field of "
			  "LC_PREBOUND_DYLIB command %lu extends past the end "
			  "of all load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_ID_DYLINKER:
	    case LC_LOAD_DYLINKER:
		dyld = (struct dylinker_command *)lc;
		if(dyld->cmdsize < sizeof(struct dylinker_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(%s command %lu has too small cmdsize field)",
			  dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" :
			  "LC_LOAD_DYLINKER", i);
		    return(FALSE);
		}
		if(dyld->name.offset >= dyld->cmdsize){
		    error("in swap_object_headers(): truncated or malformed "
			  "load commands (name.offset field of %s command %lu "
			  "extends past the end of all load commands)",
			  dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" :
			  "LC_LOAD_DYLINKER", i);
		    return(FALSE);
		}
		break;

	    case LC_UNIXTHREAD:
	    case LC_THREAD:
		ut = (struct thread_command *)lc;
		state = (char *)ut + sizeof(struct thread_command);

	    	if(cputype == CPU_TYPE_MC680x0){
		    struct m68k_thread_state_regs *cpu;
		    struct m68k_thread_state_68882 *fpu;
		    struct m68k_thread_state_user_reg *user_reg;

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case M68K_THREAD_STATE_REGS:
			    if(count != M68K_THREAD_STATE_REGS_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M68K_THREAD_STATE_REGS_COUNT for "
				    "flavor number %lu which is a M68K_THREAD_"
				    "STATE_REGS flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (struct m68k_thread_state_regs *)state;
			    state += sizeof(struct m68k_thread_state_regs);
			    break;
			case M68K_THREAD_STATE_68882:
			    if(count != M68K_THREAD_STATE_68882_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M68K_THREAD_STATE_68882_COUNT for "
				    "flavor number %lu which is a M68K_THREAD_"
				    "STATE_68882 flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (struct m68k_thread_state_68882 *)state;
			    state += sizeof(struct m68k_thread_state_68882);
			    break;
			case M68K_THREAD_STATE_USER_REG:
			    if(count != M68K_THREAD_STATE_USER_REG_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M68K_THREAD_STATE_USER_REG_COUNT for "
				    "flavor number %lu which is a M68K_THREAD_"
				    "STATE_USER_REG flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    user_reg =
				(struct m68k_thread_state_user_reg *)state;
			    state += sizeof(struct m68k_thread_state_user_reg);
			    break;
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_POWERPC ||
	    	   cputype == CPU_TYPE_VEO ||
		   cputype == CPU_TYPE_POWERPC64){
		    ppc_thread_state_t *cpu;
		    ppc_float_state_t *fpu;
		    ppc_exception_state_t *except;
		    ppc_thread_state64_t *cpu64;

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case PPC_THREAD_STATE:
			    if(count != PPC_THREAD_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not PPC_THREAD_STATE_COUNT for "
				    "flavor number %lu which is a PPC_THREAD_"
				    "STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (ppc_thread_state_t *)state;
			    state += sizeof(ppc_thread_state_t);
			    break;
			case PPC_FLOAT_STATE:
			    if(count != PPC_FLOAT_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not PPC_FLOAT_STATE_COUNT for "
				    "flavor number %lu which is a PPC_FLOAT_"
				    "STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (ppc_float_state_t *)state;
			    state += sizeof(ppc_float_state_t);
			    break;
			case PPC_EXCEPTION_STATE:
			    if(count != PPC_EXCEPTION_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not PPC_EXCEPTION_STATE_COUNT for "
				    "flavor number %lu which is a PPC_EXCEPT"
				    "ION_STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    except = (ppc_exception_state_t *)state;
			    state += sizeof(ppc_exception_state_t);
			    break;
			case PPC_THREAD_STATE64:
			    if(count != PPC_THREAD_STATE64_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not PPC_THREAD_STATE64_COUNT for "
				    "flavor number %lu which is a PPC_THREAD_"
				    "STATE64 flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu64 = (ppc_thread_state64_t *)state;
			    state += sizeof(ppc_thread_state64_t);
			    break;
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_MC88000){
		    m88k_thread_state_grf_t *cpu;
		    m88k_thread_state_xrf_t *fpu;
		    m88k_thread_state_user_t *user;
		    m88110_thread_state_impl_t *spu;

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case M88K_THREAD_STATE_GRF:
			    if(count != M88K_THREAD_STATE_GRF_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M88K_THREAD_STATE_GRF_COUNT for "
				    "flavor number %lu which is a M88K_THREAD_"
				    "STATE_GRF flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (m88k_thread_state_grf_t *)state;
			    state += sizeof(m88k_thread_state_grf_t);
			    break;
			case M88K_THREAD_STATE_XRF:
			    if(count != M88K_THREAD_STATE_XRF_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M88K_THREAD_STATE_XRF_COUNT for "
				    "flavor number %lu which is a M88K_THREAD_"
				    "STATE_XRF flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (m88k_thread_state_xrf_t *)state;
			    state += sizeof(m88k_thread_state_xrf_t);
			    break;
			case M88K_THREAD_STATE_USER:
			    if(count != M88K_THREAD_STATE_USER_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M88K_THREAD_STATE_USER_COUNT for "
				    "flavor number %lu which is a M88K_THREAD_"
				    "STATE_USER flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    user = (m88k_thread_state_user_t *)state;
			    state += sizeof(m88k_thread_state_user_t);
			    break;
			case M88110_THREAD_STATE_IMPL:
			    if(count != M88110_THREAD_STATE_IMPL_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not M88110_THREAD_STATE_IMPL_COUNT for "
				    "flavor number %lu which is a M88110_THREAD"
				    "_STATE_IMPL flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    spu = (m88110_thread_state_impl_t *)state;
			    state += sizeof(m88110_thread_state_impl_t);
			    break;
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_I860){
		    struct i860_thread_state_regs *cpu;

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case I860_THREAD_STATE_REGS:
			    if(count != I860_THREAD_STATE_REGS_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not I860_THREAD_STATE_REGS_COUNT for "
				    "flavor number %lu which is a I860_THREAD_"
				    "STATE_REGS flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (struct i860_thread_state_regs *)state;
			    state += sizeof(struct i860_thread_state_regs);
			    break;
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_I386
#ifdef x86_THREAD_STATE64
		   || cputype == CPU_TYPE_X86_64
#endif /* x86_THREAD_STATE64 */
		   ){
		    i386_thread_state_t *cpu;
#ifdef x86_THREAD_STATE64
		    x86_thread_state64_t *cpu64;
#endif /* x86_THREAD_STATE64 */
/* current i386 thread states */
#if i386_THREAD_STATE == 1
		    struct i386_float_state *fpu;
		    i386_exception_state_t *exc;
#endif /* i386_THREAD_STATE == 1 */

/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
		    i386_thread_fpstate_t *fpu;
		    i386_thread_exceptstate_t *exc;
		    i386_thread_cthreadstate_t *user;
#endif /* i386_THREAD_STATE == -1 */

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case i386_THREAD_STATE:
/* current i386 thread states */
#if i386_THREAD_STATE == 1
			case -1:
#endif /* i386_THREAD_STATE == 1 */
/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
			case 1:
#endif /* i386_THREAD_STATE == -1 */
			    if(count != i386_THREAD_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not i386_THREAD_STATE_COUNT for flavor "
				    "number %lu which is a i386_THREAD_STATE "
				    "flavor in %s command %lu)", nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (i386_thread_state_t *)state;
			    state += sizeof(i386_thread_state_t);
			    break;
/* current i386 thread states */
#if i386_THREAD_STATE == 1
			case i386_FLOAT_STATE:
			    if(count != i386_FLOAT_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not i386_FLOAT_STATE_COUNT for flavor "
				    "number %lu which is a i386_FLOAT_STATE "
				    "flavor in %s command %lu)", nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (struct i386_float_state *)state;
			    state += sizeof(struct i386_float_state);
			    break;
			case i386_EXCEPTION_STATE:
			    if(count != I386_EXCEPTION_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not I386_EXCEPTION_STATE_COUNT for "
				    "flavor number %lu which is a i386_"
				    "EXCEPTION_STATE flavor in %s command %lu)",
				    nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    exc = (i386_exception_state_t *)state;
			    state += sizeof(i386_exception_state_t);
			    break;
#endif /* i386_THREAD_STATE == 1 */

/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
			case i386_THREAD_FPSTATE:
			    if(count != i386_THREAD_FPSTATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not i386_THREAD_FPSTATE_COUNT for flavor "
				    "number %lu which is a i386_THREAD_FPSTATE "
				    "flavor in %s command %lu)", nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (i386_thread_fpstate_t *)state;
			    state += sizeof(i386_thread_fpstate_t);
			    break;
			case i386_THREAD_EXCEPTSTATE:
			    if(count != i386_THREAD_EXCEPTSTATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not i386_THREAD_EXCEPTSTATE_COUNT for "
				    "flavor number %lu which is a i386_THREAD_"
				    "EXCEPTSTATE flavor in %s command %lu)",
				    nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    exc = (i386_thread_exceptstate_t *)state;
			    state += sizeof(i386_thread_fpstate_t);
			    break;
			case i386_THREAD_CTHREADSTATE:
			    if(count != i386_THREAD_CTHREADSTATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not i386_THREAD_CTHREADSTATE_COUNT for "
				    "flavor number %lu which is a i386_THREAD_"
				    "CTHREADSTATE flavor in %s command %lu)",
				    nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    user = (i386_thread_cthreadstate_t *)state;
			    state += sizeof(i386_thread_fpstate_t);
			    break;
#endif /* i386_THREAD_STATE == -1 */
#ifdef x86_THREAD_STATE64
			case x86_THREAD_STATE64:
			    if(count != x86_THREAD_STATE64_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not x86_THREAD_STATE64_COUNT for "
				    "flavor number %lu which is an x86_THREAD_"
				    "STATE64 flavor in %s command %lu)",
				    nflavor,
				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				    "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu64 = (x86_thread_state64_t *)state;
			    state += sizeof(x86_thread_state64_t);
			    break;
#endif /* x86_THREAD_STATE64 */
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
	        if(cputype == CPU_TYPE_HPPA){
		    struct hp_pa_integer_thread_state *cpu;
		    struct hp_pa_frame_thread_state *frame;
		    struct hp_pa_fp_thread_state *fpu;

		    nflavor = 0;
		    p = (char *)ut + ut->cmdsize;
		    while(state < p){
			flavor = *((unsigned long *)state);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			state += sizeof(unsigned long);
			switch(flavor){
			case HPPA_INTEGER_THREAD_STATE:
			    if(count != HPPA_INTEGER_THREAD_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not HPPA_INTEGER_THREAD_STATE_COUNT for "
				    "flavor number %lu which is a HPPA_INTEGER"
				    "_THREAD_STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    cpu = (struct hp_pa_integer_thread_state *)state;
			    state += sizeof(struct hp_pa_integer_thread_state);
			    break;
			case HPPA_FRAME_THREAD_STATE:
			    if(count != HPPA_FRAME_THREAD_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not HPPA_FRAME_THREAD_STATE_COUNT for "
				    "flavor number %lu which is a HPPA_FRAME"
				    "_THREAD_STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    frame = (struct hp_pa_frame_thread_state *)state;
			    state += sizeof(struct hp_pa_frame_thread_state);
			    break;
			case HPPA_FP_THREAD_STATE:
			    if(count != HPPA_FP_THREAD_STATE_COUNT){
				error("in swap_object_headers(): malformed "
				    "load commands (count "
				    "not HPPA_FP_THREAD_STATE_COUNT for "
				    "flavor number %lu which is a HPPA_FP"
				    "_THREAD_STATE flavor in %s command %lu)",
				    nflavor, ut->cmd == LC_UNIXTHREAD ? 
				    "LC_UNIXTHREAD" : "LC_THREAD", i);
				return(FALSE);
			    }
			    fpu = (struct hp_pa_fp_thread_state *)state;
			    state += sizeof(struct hp_pa_fp_thread_state);
			    break;
			default:
			    error("in swap_object_headers(): malformed "
				"load commands (unknown "
				"flavor %lu for flavor number %lu in %s command"
				" %lu can't byte swap it)", flavor, nflavor,
				ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
				"LC_THREAD", i);
			    return(FALSE);
			}
			nflavor++;
		    }
		    break;
		}
		if(cputype == CPU_TYPE_SPARC) {
		  struct sparc_thread_state_regs *cpu;
		  struct sparc_thread_state_fpu *fpu;

		  nflavor = 0;
		  p = (char *)ut + ut->cmdsize;
		  while (state < p) {
		    flavor = *((unsigned long *) state);
		    state += sizeof(unsigned long);
		    count = *((unsigned int *) state);
		    state += sizeof(unsigned long);
		    switch (flavor) {
		    case SPARC_THREAD_STATE_REGS:
		      if (count != SPARC_THREAD_STATE_REGS_COUNT) {
			error("in swap_object_headers(): malformed "
			      "load commands (count "
			      "not SPARC_THREAD_STATE_REGS_COUNT for "
			      "flavor number %lu which is a SPARC_THREAD_"
			      "STATE_REGS flavor in %s command %lu)",
			      nflavor, ut->cmd == LC_UNIXTHREAD ? 
			      "LC_UNIXTHREAD" : "LC_THREAD", i);
			return(FALSE);
		      }
		      cpu = (struct sparc_thread_state_regs *) state;
		      state += sizeof(struct sparc_thread_state_regs);
		      break;
		    case SPARC_THREAD_STATE_FPU:
		      if (count != SPARC_THREAD_STATE_FPU_COUNT) {
			error("in swap_object_headers(): malformed "
			      "load commands (count "
			      "not SPARC_THREAD_STATE_FPU_COUNT for "
			      "flavor number %lu which is a SPARC_THREAD_"
			      "STATE_FPU flavor in %s command %lu)",
			      nflavor, ut->cmd == LC_UNIXTHREAD ? 
			      "LC_UNIXTHREAD" : "LC_THREAD", i);
			return(FALSE);
		      }
		      fpu = (struct sparc_thread_state_fpu *) state;
		      state += sizeof(struct sparc_thread_state_fpu);
		      break;
		    }
		  }
		  break;
		}

        if (cputype == CPU_TYPE_ARM) {
            nflavor = 0;

            p = (char *)ut + ut->cmdsize;
            while (state < p) {
                state += 8 + sizeof(arm_thread_state_t);
                nflavor++; 
            }
            break;
        }
		    
		error("in swap_object_headers(): malformed load commands "
		    "(unknown cputype (%d) and cpusubtype (%d) of object and "
                    "can't byte swap %s command %lu)", cputype, 
		    cpusubtype, ut->cmd == LC_UNIXTHREAD ?
		    "LC_UNIXTHREAD" : "LC_THREAD", i);
		return(FALSE);
	    case LC_IDENT:
		id = (struct ident_command *)lc;
		if((char *)id + id->cmdsize >
		   (char *)load_commands + sizeofcmds){
		    error("in swap_object_headers(): truncated or malformed "
			"load commands (cmdsize field of LC_IDENT command %lu "
			"extends past the end of the load commands)", i);
		    return(FALSE);
		}
		break;

	    case LC_ROUTINES:
		rc = (struct routines_command *)lc;
		if(rc->cmdsize != sizeof(struct routines_command)){
		    error("in swap_object_headers(): malformed load commands ("
			  "LC_ROUTINES command %lu has incorrect cmdsize",
			  i);
		    return(FALSE);
		}
		break;

	    case LC_ROUTINES_64:
		rc64 = (struct routines_command_64 *)lc;
		if(rc64->cmdsize != sizeof(struct routines_command_64)){
		    error("in swap_object_headers(): malformed load commands ("
			  "LC_ROUTINES_64 command %lu has incorrect cmdsize",
			  i);
		    return(FALSE);
		}
		break;

	    case LC_TWOLEVEL_HINTS:
		hints = (struct twolevel_hints_command *)lc;
		if(hints->cmdsize != sizeof(struct twolevel_hints_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_TWOLEVEL_HINTS command %lu has incorrect "
			  "cmdsize", i);
		    return(FALSE);
		}
		break;

	    case LC_PREBIND_CKSUM:
		cs = (struct prebind_cksum_command *)lc;
		if(cs->cmdsize != sizeof(struct prebind_cksum_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_PREBIND_CKSUM command %lu has incorrect cmdsize",
			  i);
		    return(FALSE);
		}
		break;

	    case LC_UUID:
		uuid = (struct uuid_command *)lc;
		if(uuid->cmdsize != sizeof(struct uuid_command)){
		    error("in swap_object_headers(): malformed load commands "
			  "(LC_UUID command %lu has incorrect cmdsize", i);
		    return(FALSE);
		}
		break;

	    default:
		error("in swap_object_headers(): malformed load commands "
		      "(unknown load command %lu)", i);
		return(FALSE);
	    }

	    lc = (struct load_command *)((char *)lc + l.cmdsize);
	    /* check that next load command does not extends past the end */
	    if((char *)lc > (char *)load_commands + sizeofcmds){
		error("in swap_object_headers(): truncated or malformed load "
		      "commands (load command %lu extends past the end of all "
		      "load commands)", i + 1);
		return(FALSE);
	    }
	}
	/* check for an inconsistent size of the load commands */
	if((char *)load_commands + sizeofcmds != (char *)lc){
	    error("in swap_object_headers(): malformed load commands "
		  "(inconsistent sizeofcmds field in mach header)");
	    return(FALSE);
	}


	/*
	 * Now knowing the load commands can be parsed swap them.
	 */
	target_byte_sex = get_host_byte_sex() == BIG_ENDIAN_BYTE_SEX ?
			  LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
	for(i = 0, lc = load_commands; i < ncmds; i++){
	    l = *lc;
	    switch(lc->cmd){
	    case LC_SEGMENT:
		sg = (struct segment_command *)lc;
		s = (struct section *)
		    ((char *)sg + sizeof(struct segment_command));
		swap_section(s, sg->nsects, target_byte_sex);
		swap_segment_command(sg, target_byte_sex);
		break;

	    case LC_SEGMENT_64:
		sg64 = (struct segment_command_64 *)lc;
		s64 = (struct section_64 *)
		      ((char *)sg64 + sizeof(struct segment_command_64));
		swap_section_64(s64, sg64->nsects, target_byte_sex);
		swap_segment_command_64(sg64, target_byte_sex);
		break;

	    case LC_SYMTAB:
		st = (struct symtab_command *)lc;
		swap_symtab_command(st, target_byte_sex);
		break;

	    case LC_DYSYMTAB:
		dyst = (struct dysymtab_command *)lc;
		swap_dysymtab_command(dyst, target_byte_sex);
		break;

	    case LC_SYMSEG:
		ss = (struct symseg_command *)lc;
		swap_symseg_command(ss, target_byte_sex);
		break;

	    case LC_IDFVMLIB:
	    case LC_LOADFVMLIB:
		fl = (struct fvmlib_command *)lc;
		swap_fvmlib_command(fl, target_byte_sex);
		break;

	    case LC_ID_DYLIB:
	    case LC_LOAD_DYLIB:
	    case LC_LOAD_WEAK_DYLIB:
		dl = (struct dylib_command *)lc;
		swap_dylib_command(dl, target_byte_sex);
		break;

	    case LC_SUB_FRAMEWORK:
		sub = (struct sub_framework_command *)lc;
		swap_sub_framework_command(sub, target_byte_sex);
		break;

	    case LC_SUB_UMBRELLA:
		usub = (struct sub_umbrella_command *)lc;
		swap_sub_umbrella_command(usub, target_byte_sex);
		break;

	    case LC_SUB_LIBRARY:
		lsub = (struct sub_library_command *)lc;
		swap_sub_library_command(lsub, target_byte_sex);
		break;

	    case LC_SUB_CLIENT:
		csub = (struct sub_client_command *)lc;
		swap_sub_client_command(csub, target_byte_sex);
		break;

	    case LC_PREBOUND_DYLIB:
		pbdylib = (struct prebound_dylib_command *)lc;
		swap_prebound_dylib_command(pbdylib, target_byte_sex);
		break;

	    case LC_ID_DYLINKER:
	    case LC_LOAD_DYLINKER:
		dyld = (struct dylinker_command *)lc;
		swap_dylinker_command(dyld, target_byte_sex);
		break;

	    case LC_UNIXTHREAD:
	    case LC_THREAD:
		ut = (struct thread_command *)lc;
		state = (char *)ut + sizeof(struct thread_command);
		p = (char *)ut + ut->cmdsize;
		swap_thread_command(ut, target_byte_sex);

	    	if(cputype == CPU_TYPE_MC680x0){
		    struct m68k_thread_state_regs *cpu;
		    struct m68k_thread_state_68882 *fpu;
		    struct m68k_thread_state_user_reg *user_reg;

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case M68K_THREAD_STATE_REGS:
			    cpu = (struct m68k_thread_state_regs *)state;
			    swap_m68k_thread_state_regs(cpu, target_byte_sex);
			    state += sizeof(struct m68k_thread_state_regs);
			    break;
			case M68K_THREAD_STATE_68882:
			    fpu = (struct m68k_thread_state_68882 *)state;
			    swap_m68k_thread_state_68882(fpu, target_byte_sex);
			    state += sizeof(struct m68k_thread_state_68882);
			    break;
			case M68K_THREAD_STATE_USER_REG:
			    user_reg =
				(struct m68k_thread_state_user_reg *)state;
			    swap_m68k_thread_state_user_reg(user_reg,
							    target_byte_sex);
			    state += sizeof(struct m68k_thread_state_user_reg);
			    break;
			}
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_POWERPC ||
	    	   cputype == CPU_TYPE_VEO ||
		   cputype == CPU_TYPE_POWERPC64){
		    ppc_thread_state_t *cpu;
		    ppc_thread_state64_t *cpu64;
		    ppc_float_state_t *fpu;
		    ppc_exception_state_t *except;

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case PPC_THREAD_STATE:
			    cpu = (ppc_thread_state_t *)state;
			    swap_ppc_thread_state_t(cpu, target_byte_sex);
			    state += sizeof(ppc_thread_state_t);
			    break;
			case PPC_THREAD_STATE64:
			    cpu64 = (ppc_thread_state64_t *)state;
			    swap_ppc_thread_state64_t(cpu64, target_byte_sex);
			    state += sizeof(ppc_thread_state64_t);
			    break;
			case PPC_FLOAT_STATE:
			    fpu = (ppc_float_state_t *)state;
			    swap_ppc_float_state_t(fpu, target_byte_sex);
			    state += sizeof(ppc_float_state_t);
			case PPC_EXCEPTION_STATE:
			    except = (ppc_exception_state_t *)state;
			    swap_ppc_exception_state_t(except, target_byte_sex);
			    state += sizeof(ppc_exception_state_t);
			    break;
			}
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_MC88000){
		    m88k_thread_state_grf_t *cpu;
		    m88k_thread_state_xrf_t *fpu;
		    m88k_thread_state_user_t *user;
		    m88110_thread_state_impl_t *spu;

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case M88K_THREAD_STATE_GRF:
			    cpu = (m88k_thread_state_grf_t *)state;
			    swap_m88k_thread_state_grf_t(cpu,
							 target_byte_sex);
			    state += sizeof(m88k_thread_state_grf_t);
			    break;
			case M88K_THREAD_STATE_XRF:
			    fpu = (m88k_thread_state_xrf_t *)state;
			    swap_m88k_thread_state_xrf_t(fpu,
							 target_byte_sex);
			    state += sizeof(m88k_thread_state_xrf_t);
			    break;
			case M88K_THREAD_STATE_USER:
			    user = (m88k_thread_state_user_t *)state;
			    swap_m88k_thread_state_user_t(user,
							  target_byte_sex);
			    state += sizeof(m88k_thread_state_user_t);
			    break;
			case M88110_THREAD_STATE_IMPL:
			    spu = (m88110_thread_state_impl_t *)state;
			    swap_m88110_thread_state_impl_t(spu,
							  target_byte_sex);
			    state += sizeof(m88110_thread_state_impl_t);
			    break;
			}
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_I860){
		    struct i860_thread_state_regs *cpu;

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case I860_THREAD_STATE_REGS:
			    cpu = (struct i860_thread_state_regs *)state;
			    swap_i860_thread_state_regs(cpu, target_byte_sex);
			    state += sizeof(struct i860_thread_state_regs);
			    break;
			}
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_I386
#ifdef x86_THREAD_STATE64
		   || cputype == CPU_TYPE_X86_64
#endif /* x86_THREAD_STATE64 */
		   ){
		    i386_thread_state_t *cpu;
#ifdef x86_THREAD_STATE64
		    x86_thread_state64_t *cpu64;
#endif /* x86_THREAD_STATE64 */
/* current i386 thread states */
#if i386_THREAD_STATE == 1
		    struct i386_float_state *fpu;
		    i386_exception_state_t *exc;
#endif /* i386_THREAD_STATE == 1 */

/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
		    i386_thread_fpstate_t *fpu;
		    i386_thread_exceptstate_t *exc;
		    i386_thread_cthreadstate_t *user;
#endif /* i386_THREAD_STATE == -1 */

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case i386_THREAD_STATE:
/* current i386 thread states */
#if i386_THREAD_STATE == 1
			case -1:
#endif /* i386_THREAD_STATE == 1 */
/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
			case 1:
#endif /* i386_THREAD_STATE == -1 */
			    cpu = (i386_thread_state_t *)state;
			    swap_i386_thread_state(cpu, target_byte_sex);
			    state += sizeof(i386_thread_state_t);
			    break;
/* current i386 thread states */
#if i386_THREAD_STATE == 1
			case i386_FLOAT_STATE:
			    fpu = (struct i386_float_state *)state;
			    swap_i386_float_state(fpu, target_byte_sex);
			    state += sizeof(struct i386_float_state);
			    break;
			case i386_EXCEPTION_STATE:
			    exc = (i386_exception_state_t *)state;
			    swap_i386_exception_state(exc, target_byte_sex);
			    state += sizeof(i386_exception_state_t);
			    break;
#endif /* i386_THREAD_STATE == 1 */

/* i386 thread states on older releases */
#if i386_THREAD_STATE == -1
			case i386_THREAD_FPSTATE:
			    fpu = (i386_thread_fpstate_t *)state;
			    swap_i386_thread_fpstate(fpu, target_byte_sex);
			    state += sizeof(i386_thread_fpstate_t);
			    break;
			case i386_THREAD_EXCEPTSTATE:
			    exc = (i386_thread_exceptstate_t *)state;
			    swap_i386_thread_exceptstate(exc, target_byte_sex);
			    state += sizeof(i386_thread_exceptstate_t);
			    break;
			case i386_THREAD_CTHREADSTATE:
			    user = (i386_thread_cthreadstate_t *)state;
			    swap_i386_thread_cthreadstate(user,target_byte_sex);
			    state += sizeof(i386_thread_cthreadstate_t);
			    break;
#endif /* i386_THREAD_STATE == -1 */
#ifdef x86_THREAD_STATE64
			case x86_THREAD_STATE64:
			    cpu64 = (x86_thread_state64_t *)state;
			    swap_x86_thread_state64(cpu64, target_byte_sex);
			    state += sizeof(x86_thread_state64_t);
			    break;
#endif /* x86_THREAD_STATE64 */
			}
		    }
		    break;
		}
	    	if(cputype == CPU_TYPE_HPPA){
		    struct hp_pa_integer_thread_state *cpu;
		    struct hp_pa_frame_thread_state *frame;
		    struct hp_pa_fp_thread_state *fpu;

		    while(state < p){
			flavor = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(flavor);
			state += sizeof(unsigned long);
			count = *((unsigned long *)state);
			*((unsigned long *)state) = SWAP_LONG(count);
			state += sizeof(unsigned long);
			switch(flavor){
			case HPPA_INTEGER_THREAD_STATE:
			    cpu = (struct hp_pa_integer_thread_state *)state;
			    swap_hppa_integer_thread_state(cpu,
							 target_byte_sex);
			    state += sizeof(struct hp_pa_integer_thread_state);
			    break;
			case HPPA_FRAME_THREAD_STATE:
			    frame = (struct hp_pa_frame_thread_state *)state;
			    swap_hppa_frame_thread_state(frame,
							 target_byte_sex);
			    state += sizeof(struct hp_pa_frame_thread_state);
			    break;
			case HPPA_FP_THREAD_STATE:
			    fpu = (struct hp_pa_fp_thread_state *)state;
			    swap_hppa_fp_thread_state(fpu,
						     target_byte_sex);
			    state += sizeof(struct hp_pa_fp_thread_state);
			    break;
			}
		    }
		    break;
		}

		if(cputype == CPU_TYPE_SPARC) {
		  struct sparc_thread_state_regs *cpu;
		  struct sparc_thread_state_fpu *fpu;

		  while (state < p) {
		    flavor = *((unsigned long *) state);
		    *((unsigned long *) state) = SWAP_LONG(flavor);
		    state += sizeof(unsigned long);
		    count = *((unsigned int *) state);
		    *((unsigned int *) state) = SWAP_LONG(count);
		    state += sizeof(unsigned long);
		    switch (flavor) {
		    case SPARC_THREAD_STATE_REGS:
		      cpu = (struct sparc_thread_state_regs *) state;
		      swap_sparc_thread_state_regs(cpu, target_byte_sex);
		      state += sizeof(struct sparc_thread_state_regs);
		      break;
		    case SPARC_THREAD_STATE_FPU:
		      fpu = (struct sparc_thread_state_fpu *) state;
		      swap_sparc_thread_state_fpu(fpu, target_byte_sex);
		      state += sizeof(struct sparc_thread_state_fpu);
		      break;
		    }
		  }
		  break;
		}

        if (cputype == CPU_TYPE_ARM) {
            arm_thread_state_t *thread_state;
            while (state < p) {
                u_int32_t n;
                n = *((u_int32_t *)state); *((u_int32_t *)state) = SWAP_LONG(n);
                state += 4;
                n = *((u_int32_t *)state); *((u_int32_t *)state) = SWAP_LONG(n);
                state += 4;
                thread_state = (arm_thread_state_t *)state;
                swap_arm_thread_state(thread_state, target_byte_sex);
                state += sizeof(arm_thread_state_t);
            }
        }
        
		break;

	    case LC_IDENT:
		id = (struct ident_command *)lc;
		swap_ident_command(id, target_byte_sex);
		break;

	    case LC_ROUTINES:
		rc = (struct routines_command *)lc;
		swap_routines_command(rc, target_byte_sex);
		break;

	    case LC_ROUTINES_64:
		rc64 = (struct routines_command_64 *)lc;
		swap_routines_command_64(rc64, target_byte_sex);
		break;

	    case LC_TWOLEVEL_HINTS:
		hints = (struct twolevel_hints_command *)lc;
		swap_twolevel_hints_command(hints, target_byte_sex);
		break;

	    case LC_PREBIND_CKSUM:
		cs = (struct prebind_cksum_command *)lc;
		swap_prebind_cksum_command(cs, target_byte_sex);
		break;

	    case LC_UUID:
		uuid = (struct uuid_command *)lc;
		swap_uuid_command(uuid, target_byte_sex);
		break;
	    }

	    lc = (struct load_command *)((char *)lc + l.cmdsize);
	}
	if(mh != NULL)
	    swap_mach_header(mh, target_byte_sex);
	else
	    swap_mach_header_64(mh64, target_byte_sex);

	return(TRUE);
}
Exemplo n.º 10
0
static
void
setup_object_symbolic_info(
struct object *object)
{
	if(object->st != NULL && object->st->nsyms != 0){
	    object->output_symbols = (struct nlist *)
		(object->object_addr + object->st->symoff);
	    if(object->object_byte_sex != get_host_byte_sex())
		swap_nlist(object->output_symbols,
			   object->st->nsyms,
			   get_host_byte_sex());
	    object->output_nsymbols = object->st->nsyms;
	    object->output_strings =
		object->object_addr + object->st->stroff;
	    object->output_strings_size = object->st->strsize;
	    object->input_sym_info_size =
		object->st->nsyms * sizeof(struct nlist) +
		object->st->strsize;
	    object->output_sym_info_size =
		object->input_sym_info_size;
	}
	if(object->dyst != NULL){
	    object->output_ilocalsym = object->dyst->ilocalsym;
	    object->output_nlocalsym = object->dyst->nlocalsym;
	    object->output_iextdefsym = object->dyst->iextdefsym;
	    object->output_nextdefsym = object->dyst->nextdefsym;
	    object->output_iundefsym = object->dyst->iundefsym;
	    object->output_nundefsym = object->dyst->nundefsym;

	    object->output_loc_relocs = (struct relocation_info *)
		(object->object_addr + object->dyst->locreloff);
	    object->output_ext_relocs = (struct relocation_info *)
		(object->object_addr + object->dyst->extreloff);
	    object->output_indirect_symtab = (unsigned long *)
		(object->object_addr + object->dyst->indirectsymoff);
	    object->output_tocs =
		(struct dylib_table_of_contents *)
		(object->object_addr + object->dyst->tocoff);
	    object->output_ntoc = object->dyst->ntoc;
	    object->output_mods = (struct dylib_module *)
		(object->object_addr + object->dyst->modtaboff);
	    object->output_nmodtab = object->dyst->nmodtab;
	    object->output_refs = (struct dylib_reference *)
		(object->object_addr + object->dyst->extrefsymoff);
	    object->output_nextrefsyms = object->dyst->nextrefsyms;
	    object->input_sym_info_size +=
		object->dyst->nlocrel *
		    sizeof(struct relocation_info) +
		object->dyst->nextrel *
		    sizeof(struct relocation_info) +
		object->dyst->nindirectsyms *
		    sizeof(unsigned long) +
		object->dyst->ntoc *
		    sizeof(struct dylib_table_of_contents)+
		object->dyst->nmodtab *
		    sizeof(struct dylib_module) +
		object->dyst->nextrefsyms *
		    sizeof(struct dylib_reference);
	    object->output_sym_info_size +=
		object->dyst->nlocrel *
		    sizeof(struct relocation_info) +
		object->dyst->nextrel *
		    sizeof(struct relocation_info) +
		object->dyst->nindirectsyms *
		    sizeof(unsigned long) +
		object->dyst->ntoc *
		    sizeof(struct dylib_table_of_contents)+
		object->dyst->nmodtab *
		    sizeof(struct dylib_module) +
		object->dyst->nextrefsyms *
		    sizeof(struct dylib_reference);
	    if(object->hints_cmd != NULL){
		object->output_hints = (struct twolevel_hint *)
		    (object->object_addr +
		     object->hints_cmd->offset);
		object->input_sym_info_size +=
		    object->hints_cmd->nhints *
		    sizeof(struct twolevel_hint);
		object->output_sym_info_size +=
		    object->hints_cmd->nhints *
		    sizeof(struct twolevel_hint);
	    }
	}
}
Exemplo n.º 11
0
/*
 * setup_code_signature() does the work to add or update the needed
 * LC_CODE_SIGNATURE load command for the specified broken out ofile if it
 * is of one of the architecures specifed with a -a command line options.
 */
static
void
setup_code_signature(
    struct arch *arch,
    struct member *member,
    struct object *object)
{
    uint32_t i;
    cpu_type_t cputype;
    cpu_subtype_t cpusubtype;
    uint32_t flags, linkedit_end;
    uint32_t dyld_info_start;
    uint32_t dyld_info_end;
    uint32_t align_delta;

    linkedit_end = 0;
    /*
     * First set up all the pointers and sizes of the symbolic info.
     */
    if(object->st != NULL && object->st->nsyms != 0) {
        if(object->mh != NULL) {
            object->output_symbols = (struct nlist *)
                                     (object->object_addr + object->st->symoff);
            if(object->object_byte_sex != get_host_byte_sex())
                swap_nlist(object->output_symbols,
                           object->st->nsyms,
                           get_host_byte_sex());
            object->output_symbols64 = NULL;
        }
        else {
            object->output_symbols64 = (struct nlist_64 *)
                                       (object->object_addr + object->st->symoff);
            if(object->object_byte_sex != get_host_byte_sex())
                swap_nlist_64(object->output_symbols64,
                              object->st->nsyms,
                              get_host_byte_sex());
            object->output_symbols = NULL;
        }
        object->output_nsymbols = object->st->nsyms;
        object->output_strings =
            object->object_addr + object->st->stroff;
        object->output_strings_size = object->st->strsize;
        if(object->mh != NULL) {
            object->input_sym_info_size =
                object->st->nsyms * sizeof(struct nlist) +
                object->st->strsize;
        }
        else {
            object->input_sym_info_size =
                object->st->nsyms * sizeof(struct nlist_64) +
                object->st->strsize;
        }
    }
    if(object->dyld_info != NULL) {
        /* there are five parts to the dyld info, but
         codesign_allocate does not alter them, so copy as a block */
        dyld_info_start = 0;
        if (object->dyld_info->rebase_off != 0)
            dyld_info_start = object->dyld_info->rebase_off;
        else if (object->dyld_info->bind_off != 0)
            dyld_info_start = object->dyld_info->bind_off;
        else if (object->dyld_info->weak_bind_off != 0)
            dyld_info_start = object->dyld_info->weak_bind_off;
        else if (object->dyld_info->lazy_bind_off != 0)
            dyld_info_start = object->dyld_info->lazy_bind_off;
        else if (object->dyld_info->export_off != 0)
            dyld_info_start = object->dyld_info->export_off;
        dyld_info_end = 0;
        if (object->dyld_info->export_size != 0)
            dyld_info_end = object->dyld_info->export_off
                            + object->dyld_info->export_size;
        else if (object->dyld_info->lazy_bind_size != 0)
            dyld_info_end = object->dyld_info->lazy_bind_off
                            + object->dyld_info->lazy_bind_size;
        else if (object->dyld_info->weak_bind_size != 0)
            dyld_info_end = object->dyld_info->weak_bind_off
                            + object->dyld_info->weak_bind_size;
        else if (object->dyld_info->bind_size != 0)
            dyld_info_end = object->dyld_info->bind_off
                            + object->dyld_info->bind_size;
        else if (object->dyld_info->rebase_size != 0)
            dyld_info_end = object->dyld_info->rebase_off
                            + object->dyld_info->rebase_size;
        object->output_dyld_info = object->object_addr + dyld_info_start;
        object->output_dyld_info_size = dyld_info_end - dyld_info_start;
        object->output_sym_info_size += object->output_dyld_info_size;
    }
    if(object->dyst != NULL) {
        object->output_ilocalsym = object->dyst->ilocalsym;
        object->output_nlocalsym = object->dyst->nlocalsym;
        object->output_iextdefsym = object->dyst->iextdefsym;
        object->output_nextdefsym = object->dyst->nextdefsym;
        object->output_iundefsym = object->dyst->iundefsym;
        object->output_nundefsym = object->dyst->nundefsym;
        object->output_indirect_symtab = (uint32_t *)
                                         (object->object_addr + object->dyst->indirectsymoff);
        object->output_loc_relocs = (struct relocation_info *)
                                    (object->object_addr + object->dyst->locreloff);
        if(object->split_info_cmd != NULL) {
            object->output_split_info_data =
                (object->object_addr + object->split_info_cmd->dataoff);
            object->output_split_info_data_size =
                object->split_info_cmd->datasize;
        }
        if(object->func_starts_info_cmd != NULL) {
            object->output_func_start_info_data =
                (object->object_addr + object->func_starts_info_cmd->dataoff);
            object->output_func_start_info_data_size =
                object->func_starts_info_cmd->datasize;
        }
        if(object->data_in_code_cmd != NULL) {
            object->output_data_in_code_info_data =
                (object->object_addr + object->data_in_code_cmd->dataoff);
            object->output_data_in_code_info_data_size =
                object->data_in_code_cmd->datasize;
        }
        if(object->code_sign_drs_cmd != NULL) {
            object->output_code_sign_drs_info_data =
                (object->object_addr + object->code_sign_drs_cmd->dataoff);
            object->output_code_sign_drs_info_data_size =
                object->code_sign_drs_cmd->datasize;
        }
        if(object->link_opt_hint_cmd != NULL) {
            object->output_link_opt_hint_info_data =
                (object->object_addr + object->link_opt_hint_cmd->dataoff);
            object->output_link_opt_hint_info_data_size =
                object->link_opt_hint_cmd->datasize;
        }
        object->output_ext_relocs = (struct relocation_info *)
                                    (object->object_addr + object->dyst->extreloff);
        object->output_tocs =
            (struct dylib_table_of_contents *)
            (object->object_addr + object->dyst->tocoff);
        object->output_ntoc = object->dyst->ntoc;
        if(object->mh != NULL) {
            object->output_mods = (struct dylib_module *)
                                  (object->object_addr + object->dyst->modtaboff);
            object->output_mods64 = NULL;
        }
        else {
            object->output_mods64 = (struct dylib_module_64 *)
                                    (object->object_addr + object->dyst->modtaboff);
            object->output_mods = NULL;
        }
        object->output_nmodtab = object->dyst->nmodtab;
        object->output_refs = (struct dylib_reference *)
                              (object->object_addr + object->dyst->extrefsymoff);
        object->output_nextrefsyms = object->dyst->nextrefsyms;
        if(object->hints_cmd != NULL) {
            object->output_hints = (struct twolevel_hint *)
                                   (object->object_addr +
                                    object->hints_cmd->offset);
        }
        if(object->dyld_info != NULL) {
            object->input_sym_info_size += object->dyld_info->rebase_size
                                           + object->dyld_info->bind_size
                                           + object->dyld_info->weak_bind_size
                                           + object->dyld_info->lazy_bind_size
                                           + object->dyld_info->export_size;
        }
        object->input_sym_info_size +=
            object->dyst->nlocrel *
            sizeof(struct relocation_info) +
            object->dyst->nextrel *
            sizeof(struct relocation_info) +
            object->dyst->ntoc *
            sizeof(struct dylib_table_of_contents)+
            object->dyst->nextrefsyms *
            sizeof(struct dylib_reference);
        if(object->split_info_cmd != NULL)
            object->input_sym_info_size += object->split_info_cmd->datasize;
        if(object->func_starts_info_cmd != NULL)
            object->input_sym_info_size +=
                object->func_starts_info_cmd->datasize;
        if(object->data_in_code_cmd != NULL)
            object->input_sym_info_size +=
                object->data_in_code_cmd->datasize;
        if(object->code_sign_drs_cmd != NULL)
            object->input_sym_info_size +=
                object->code_sign_drs_cmd->datasize;
        if(object->link_opt_hint_cmd != NULL)
            object->input_sym_info_size +=
                object->link_opt_hint_cmd->datasize;
        if(object->mh != NULL) {
            object->input_sym_info_size +=
                object->dyst->nmodtab *
                sizeof(struct dylib_module) +
                object->dyst->nindirectsyms *
                sizeof(uint32_t);
        }
        else {
            object->input_sym_info_size +=
                object->dyst->nmodtab *
                sizeof(struct dylib_module_64) +
                object->dyst->nindirectsyms *
                sizeof(uint32_t) +
                object->input_indirectsym_pad;
        }
        if(object->hints_cmd != NULL) {
            object->input_sym_info_size +=
                object->hints_cmd->nhints *
                sizeof(struct twolevel_hint);
        }
    }
    object->output_sym_info_size = object->input_sym_info_size;
    if(object->code_sig_cmd != NULL) {
        object->input_sym_info_size = rnd(object->input_sym_info_size,
                                          16);
        object->input_sym_info_size += object->code_sig_cmd->datasize;
    }

    /*
     * Now see if one of the -a flags matches this object.
     */
    if(object->mh != NULL) {
        cputype = object->mh->cputype;
        cpusubtype = object->mh->cpusubtype & ~CPU_SUBTYPE_MASK;
        flags = object->mh->flags;
    }
    else {
        cputype = object->mh64->cputype;
        cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK;
        flags = object->mh64->flags;
    }
    for(i = 0; i < narch_signs; i++) {
        if(arch_signs[i].arch_flag.cputype == cputype &&
                arch_signs[i].arch_flag.cpusubtype == cpusubtype)
            break;
    }
    /*
     * If we didn't find a matching -a flag then just use the existing
     * code signature if any.
     */
    if(i >= narch_signs) {
        if(object->code_sig_cmd != NULL) {
            object->output_code_sig_data_size =
                object->code_sig_cmd->datasize;
        }
        object->output_sym_info_size = object->input_sym_info_size;
        return;
    }

    /*
     * We did find a matching -a flag for this object
     */
    arch_signs[i].found = TRUE;

    /*
     * We now allow statically linked objects as well as objects that are
     * input for the dynamic linker or an MH_OBJECT filetypes to have
     * code signatures.  So no checks are done here anymore based on the
     * flags or filetype in the mach_header.
     */

    /*
     * If this has a code signature load command reuse it and just change
     * the size of that data.  But do not use the old data.
     */
    if(object->code_sig_cmd != NULL) {
        if(object->seg_linkedit != NULL) {
            object->seg_linkedit->filesize +=
                arch_signs[i].datasize - object->code_sig_cmd->datasize;
            if(object->seg_linkedit->filesize >
                    object->seg_linkedit->vmsize)
                object->seg_linkedit->vmsize =
                    rnd(object->seg_linkedit->filesize,
                        get_segalign_from_flag(&arch_signs[i].arch_flag));
        }
        else if(object->seg_linkedit64 != NULL) {
            object->seg_linkedit64->filesize +=
                arch_signs[i].datasize;
            object->seg_linkedit64->filesize -=
                object->code_sig_cmd->datasize;
            if(object->seg_linkedit64->filesize >
                    object->seg_linkedit64->vmsize)
                object->seg_linkedit64->vmsize =
                    rnd(object->seg_linkedit64->filesize,
                        get_segalign_from_flag(&arch_signs[i].arch_flag));
        }

        object->code_sig_cmd->datasize = arch_signs[i].datasize;
        object->output_code_sig_data_size = arch_signs[i].datasize;
        object->output_code_sig_data = NULL;

        object->output_sym_info_size = rnd(object->output_sym_info_size,
                                           16);
        object->output_sym_info_size += object->code_sig_cmd->datasize;
    }
    /*
     * The object does not have a code signature load command we add one.
     * And if that does not fail we then set the new load command's size and
     * offset of the code signature data to allocate in the object.  We also
     * adjust the linkedit's segment size.
     */
    else {
        object->code_sig_cmd = add_code_sig_load_command(arch,
                               arch_signs[i].arch_flag.name);
        object->code_sig_cmd->datasize = arch_signs[i].datasize;
        if(object->seg_linkedit != NULL)
            linkedit_end = object->seg_linkedit->fileoff +
                           object->seg_linkedit->filesize;
        else if(object->seg_linkedit64 != NULL)
            linkedit_end = object->seg_linkedit64->fileoff +
                           object->seg_linkedit64->filesize;
        else if(object->mh_filetype == MH_OBJECT)
            linkedit_end = object->object_size;
        else
            fatal("can't allocate code signature data for: %s (for "
                  "architecture %s) because file does not have a "
                  SEG_LINKEDIT " segment", arch->file_name,
                  arch_signs[i].arch_flag.name);

        object->code_sig_cmd->dataoff = rnd(linkedit_end, 16);
        object->output_code_sig_data_size = arch_signs[i].datasize;
        object->output_code_sig_data = NULL;
        align_delta = object->code_sig_cmd->dataoff - linkedit_end;

        if(object->output_sym_info_size != 0)
            object->output_sym_info_size = rnd(object->output_sym_info_size,
                                               16);
        else
            object->output_sym_info_size = align_delta;
        object->output_sym_info_size += object->code_sig_cmd->datasize;

        if(object->seg_linkedit != NULL) {
            object->seg_linkedit->filesize =
                rnd(object->seg_linkedit->filesize, 16) +
                object->code_sig_cmd->datasize;
            if(object->seg_linkedit->filesize >
                    object->seg_linkedit->vmsize)
                object->seg_linkedit->vmsize =
                    rnd(object->seg_linkedit->filesize,
                        get_segalign_from_flag(&arch_signs[i].arch_flag));
        }
        else if(object->seg_linkedit64 != NULL) {
            object->seg_linkedit64->filesize =
                rnd(object->seg_linkedit64->filesize, 16) +
                object->code_sig_cmd->datasize;
            if(object->seg_linkedit64->filesize >
                    object->seg_linkedit64->vmsize)
                object->seg_linkedit64->vmsize =
                    rnd(object->seg_linkedit64->filesize,
                        get_segalign_from_flag(&arch_signs[i].arch_flag));
        }
    }
}
Exemplo n.º 12
0
static
void
setup_object_symbolic_info(
struct object *object)
{
    uint32_t output_indirectsym_pad_diff;

	if(object->st != NULL && object->st->nsyms != 0){
	    if(object->mh != NULL){
		object->output_symbols = (struct nlist *)
		    (object->object_addr + object->st->symoff);
		if(object->object_byte_sex != get_host_byte_sex())
		    swap_nlist(object->output_symbols,
			       object->st->nsyms,
			       get_host_byte_sex());
		object->output_symbols64 = NULL;
	    }
	    else{
		object->output_symbols64 = (struct nlist_64 *)
		    (object->object_addr + object->st->symoff);
		if(object->object_byte_sex != get_host_byte_sex())
		    swap_nlist_64(object->output_symbols64,
				  object->st->nsyms,
				  get_host_byte_sex());
		object->output_symbols = NULL;
	    }
	    object->output_nsymbols = object->st->nsyms;
	    object->output_strings =
		object->object_addr + object->st->stroff;
	    object->output_strings_size = object->st->strsize;
	    if(object->mh != NULL){
		object->input_sym_info_size =
		    object->st->nsyms * sizeof(struct nlist) +
		    object->st->strsize;
	    }
	    else{
		object->input_sym_info_size =
		    object->st->nsyms * sizeof(struct nlist_64) +
		    object->st->strsize;
	    }
	}
	output_indirectsym_pad_diff = 0;
	if(object->dyst != NULL){
	    object->output_ilocalsym = object->dyst->ilocalsym;
	    object->output_nlocalsym = object->dyst->nlocalsym;
	    object->output_iextdefsym = object->dyst->iextdefsym;
	    object->output_nextdefsym = object->dyst->nextdefsym;
	    object->output_iundefsym = object->dyst->iundefsym;
	    object->output_nundefsym = object->dyst->nundefsym;
	    object->output_indirect_symtab = (uint32_t *)
		(object->object_addr + object->dyst->indirectsymoff);
	    object->output_loc_relocs = (struct relocation_info *)
		(object->object_addr + object->dyst->locreloff);
	    if(object->split_info_cmd != NULL){
		object->output_split_info_data = 
		(object->object_addr + object->split_info_cmd->dataoff);
		object->output_split_info_data_size = 
		    object->split_info_cmd->datasize;
	    }
	    if(object->func_starts_info_cmd != NULL){
		object->output_func_start_info_data = 
		(object->object_addr + object->func_starts_info_cmd->dataoff);
		object->output_func_start_info_data_size = 
		    object->func_starts_info_cmd->datasize;
	    }
	    if(object->data_in_code_cmd != NULL){
		object->output_data_in_code_info_data = 
		(object->object_addr + object->data_in_code_cmd->dataoff);
		object->output_data_in_code_info_data_size = 
		    object->data_in_code_cmd->datasize;
	    }
	    if(object->code_sign_drs_cmd != NULL){
		object->output_code_sign_drs_info_data = 
		(object->object_addr + object->code_sign_drs_cmd->dataoff);
		object->output_code_sign_drs_info_data_size = 
		    object->code_sign_drs_cmd->datasize;
	    }
	    if(object->link_opt_hint_cmd != NULL){
		object->output_link_opt_hint_info_data = 
		(object->object_addr + object->link_opt_hint_cmd->dataoff);
		object->output_link_opt_hint_info_data_size = 
		    object->link_opt_hint_cmd->datasize;
	    }
	    object->output_ext_relocs = (struct relocation_info *)
		(object->object_addr + object->dyst->extreloff);
	    object->output_tocs =
		(struct dylib_table_of_contents *)
		(object->object_addr + object->dyst->tocoff);
	    object->output_ntoc = object->dyst->ntoc;
	    if(object->mh != NULL){
		object->output_mods = (struct dylib_module *)
		    (object->object_addr + object->dyst->modtaboff);
		object->output_mods64 = NULL;
	    }
	    else{
		object->output_mods64 = (struct dylib_module_64 *)
		    (object->object_addr + object->dyst->modtaboff);
		object->output_mods = NULL;
	    }
	    object->output_nmodtab = object->dyst->nmodtab;
	    object->output_refs = (struct dylib_reference *)
		(object->object_addr + object->dyst->extrefsymoff);
	    object->output_nextrefsyms = object->dyst->nextrefsyms;
	    if(object->hints_cmd != NULL){
		object->output_hints = (struct twolevel_hint *)
		    (object->object_addr +
		     object->hints_cmd->offset);
	    }
	    if(object->code_sig_cmd != NULL){
		object->output_code_sig_data = object->object_addr +
		    object->code_sig_cmd->dataoff;
		object->output_code_sig_data_size = 
		    object->code_sig_cmd->datasize;
	    }
	    object->input_sym_info_size +=
		object->dyst->nlocrel *
		    sizeof(struct relocation_info) +
		object->dyst->nextrel *
		    sizeof(struct relocation_info) +
		object->dyst->ntoc *
		    sizeof(struct dylib_table_of_contents)+
		object->dyst->nextrefsyms *
		    sizeof(struct dylib_reference);
	    if(object->split_info_cmd != NULL)
		object->input_sym_info_size += object->split_info_cmd->datasize;
	    if(object->func_starts_info_cmd != NULL)
		object->input_sym_info_size +=
		    object->func_starts_info_cmd->datasize;
	    if(object->data_in_code_cmd != NULL)
		object->input_sym_info_size +=
		    object->data_in_code_cmd->datasize;
	    if(object->code_sign_drs_cmd != NULL)
		object->input_sym_info_size +=
		    object->code_sign_drs_cmd->datasize;
	    if(object->link_opt_hint_cmd != NULL)
		object->input_sym_info_size +=
		    object->link_opt_hint_cmd->datasize;
	    if(object->mh != NULL){
		object->input_sym_info_size +=
		    object->dyst->nmodtab *
			sizeof(struct dylib_module) +
		    object->dyst->nindirectsyms *
			sizeof(uint32_t);
	    }
	    else{
		object->input_sym_info_size +=
		    object->dyst->nmodtab *
			sizeof(struct dylib_module_64)+
		    object->dyst->nindirectsyms *
			  sizeof(uint32_t) +
		    object->input_indirectsym_pad;
		    if(object->input_indirectsym_pad == 0 &&
		       (object->dyst->nindirectsyms % 2) != 0)
			output_indirectsym_pad_diff = 4;
	    }
	    if(object->hints_cmd != NULL){
		object->input_sym_info_size +=
		    object->hints_cmd->nhints *
		    sizeof(struct twolevel_hint);
	    }
	    if(object->code_sig_cmd != NULL){
		object->input_sym_info_size = rnd(object->input_sym_info_size,
						    16);
		object->input_sym_info_size += object->code_sig_cmd->datasize;
	    }
	    if(output_indirectsym_pad_diff != 0){
		if(object->output_ntoc != 0)
		    object->dyst->tocoff += output_indirectsym_pad_diff;
		if(object->output_nmodtab != 0)
		    object->dyst->modtaboff += output_indirectsym_pad_diff;
		if(object->output_nextrefsyms != 0)
		    object->dyst->extrefsymoff += output_indirectsym_pad_diff;
		if(object->output_strings_size != 0)
		    object->st->stroff += output_indirectsym_pad_diff;
		object->seg_linkedit64->filesize += output_indirectsym_pad_diff;
		if(object->seg_linkedit64->filesize >
		   object->seg_linkedit64->vmsize)
		    object->seg_linkedit64->vmsize +=
			output_indirectsym_pad_diff;
	    }
	}
	object->output_sym_info_size =
	    object->input_sym_info_size + output_indirectsym_pad_diff;
}
Exemplo n.º 13
0
/*
 * ctf_insert() does the work to add the ctf section in the specified broken
 * out ofile for the architecure specifed with a -arch command line option.
 */
static
void
ctf_insert(
struct arch *arch,
struct member *member,
struct object *object)
{
    uint32_t i, move_size;
    cpu_type_t cputype;
    cpu_subtype_t cpusubtype;
    uint32_t flags, offset;
    uint64_t addr;

	if(object->mh != NULL){
	    cputype = object->mh->cputype;
	    cpusubtype = object->mh->cpusubtype & ~CPU_SUBTYPE_MASK;
	    flags = object->mh->flags;
	    offset = object->seg_linkedit->fileoff;
	    addr = object->seg_linkedit->vmaddr;
	}
	else{
	    cputype = object->mh64->cputype;
	    cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK;
	    flags = object->mh64->flags;
	    offset = object->seg_linkedit64->fileoff;
	    addr = object->seg_linkedit64->vmaddr;
	}

	/*
	 * Make sure this object is valid to process.  Since the input should
	 * be a mach_kernel that is statically linked we should not see any
	 * dynamic symbol table info. Or a code signature at the point this
	 * program is called in the build process.
	 */
	if((flags & MH_DYLDLINK) == MH_DYLDLINK ||
	   object->dyld_info != NULL ||
	   object->split_info_cmd != NULL ||
	   object->hints_cmd != NULL)
	     fatal_arch(arch, member, "file is input for the dynamic linker so "
			"not a valid input for this program to process: ");
	/*
	 * Allow a dynamic symbol table load command where it only has an
	 * indirect symbol table and no other tables.
	 */
        if(object->dyst != NULL &&
	   (object->dyst->ntoc != 0 ||
	    object->dyst->nmodtab != 0 ||
	    object->dyst->nmodtab != 0 ||
	    object->dyst->nextrefsyms != 0 ||
	    object->dyst->nextrel != 0))
	     fatal_arch(arch, member, "file is input for the dynamic linker so "
			"not a valid input for this program to process: ");
	if(object->mh_filetype != MH_EXECUTE)
	     fatal_arch(arch, member, "file type is not MH_EXECUTE so "
			"not a valid input for this program to process: ");
	if(object->seg_linkedit == NULL && object->seg_linkedit64 == NULL)
	     fatal_arch(arch, member, "file type does not have a __LINKEDIT "
			"segment so not a valid input for this program to "
			"process: ");
	if(object->code_sig_cmd != NULL)
	     fatal_arch(arch, member, "file type has code signature "
			"so not a valid input for this program to process: ");

	/*
	 * Now see if one of the -arch flags matches this object.
	 */
	for(i = 0; i < narch_ctfs; i++){
	    if(arch_ctfs[i].arch_flag.cputype == cputype &&
	       arch_ctfs[i].arch_flag.cpusubtype == cpusubtype)
		break;
	}
	/*
	 * If we didn't find a matching -arch flag it is an error.
	 */
	if(i >= narch_ctfs){
	     fatal_arch(arch, member, "no matching -arch option for this slice "
			"of file: ");
	     return;
	}
	arch_ctfs[i].arch_found = TRUE;

	/*
	 * Add the section for the ctf data for this arch.  It is placed in
	 * the file where the linkedit info was and that info will then be
	 * moved.
	 */
	add_ctf_section(arch, arch_ctfs[i].arch_flag.name,
			offset, addr, arch_ctfs[i].size);

	/*
	 * Now set up all the pointers and sizes of the symbol and string table.
	 */
	if(object->st != NULL && object->st->nsyms != 0){
	    if(object->mh != NULL){
		object->output_symbols = (struct nlist *)
		    (object->object_addr + object->st->symoff);
		if(object->object_byte_sex != get_host_byte_sex())
		    swap_nlist(object->output_symbols,
			       object->st->nsyms,
			       get_host_byte_sex());
		object->output_symbols64 = NULL;
	    }
	    else{
		object->output_symbols64 = (struct nlist_64 *)
		    (object->object_addr + object->st->symoff);
		if(object->object_byte_sex != get_host_byte_sex())
		    swap_nlist_64(object->output_symbols64,
				  object->st->nsyms,
				  get_host_byte_sex());
		object->output_symbols = NULL;
	    }
	    object->output_nsymbols = object->st->nsyms;
	    object->output_strings =
		object->object_addr + object->st->stroff;
	    object->output_strings_size = object->st->strsize;
	    if(object->mh != NULL){
		object->input_sym_info_size =
		    object->st->nsyms * sizeof(struct nlist) +
		    object->st->strsize;
	    }
	    else{
		object->input_sym_info_size =
		    object->st->nsyms * sizeof(struct nlist_64) +
		    object->st->strsize;
	    }
	}
	if(object->dyst != NULL){
	    object->output_ilocalsym = object->dyst->ilocalsym;
	    object->output_nlocalsym = object->dyst->nlocalsym;
	    object->output_iextdefsym = object->dyst->iextdefsym;
	    object->output_nextdefsym = object->dyst->nextdefsym;
	    object->output_iundefsym = object->dyst->iundefsym;
	    object->output_nundefsym = object->dyst->nundefsym;
	    object->output_indirect_symtab = (uint32_t *)
		(object->object_addr + object->dyst->indirectsymoff);
	    object->output_loc_relocs = (struct relocation_info *)
		(object->object_addr + object->dyst->locreloff);
	    if(object->mh != NULL){
		object->input_sym_info_size +=
		    object->dyst->nindirectsyms *
			sizeof(uint32_t);
	    }
	    else{
		object->input_sym_info_size +=
		    object->dyst->nindirectsyms *
			sizeof(uint32_t) +
		    object->input_indirectsym_pad;
	    }
	    object->input_sym_info_size +=
		object->dyst->nlocrel *
		    sizeof(struct relocation_info);
	}
	if(object->func_starts_info_cmd != NULL){
	    object->output_func_start_info_data = object->object_addr +
		object->func_starts_info_cmd->dataoff;
	    object->output_func_start_info_data_size = 
		object->func_starts_info_cmd->datasize;
	    object->input_sym_info_size +=
		object->func_starts_info_cmd->datasize;
	}
	if(object->data_in_code_cmd != NULL){
	    object->output_data_in_code_info_data = object->object_addr +
		object->data_in_code_cmd->dataoff;
	    object->output_data_in_code_info_data_size = 
		object->data_in_code_cmd->datasize;
	    object->input_sym_info_size +=
		object->data_in_code_cmd->datasize;
	}
	if(object->code_sign_drs_cmd != NULL){
	    object->output_code_sign_drs_info_data = object->object_addr +
		object->code_sign_drs_cmd->dataoff;
	    object->output_code_sign_drs_info_data_size = 
		object->code_sign_drs_cmd->datasize;
	    object->input_sym_info_size +=
		object->code_sign_drs_cmd->datasize;
	}
	if(object->link_opt_hint_cmd != NULL){
	    object->output_link_opt_hint_info_data = object->object_addr +
		object->link_opt_hint_cmd->dataoff;
	    object->output_link_opt_hint_info_data_size = 
		object->link_opt_hint_cmd->datasize;
	    object->input_sym_info_size +=
		object->link_opt_hint_cmd->datasize;
	}
	object->output_sym_info_size = object->input_sym_info_size;

	/*
	 * Now move the link edit info by the size of the ctf for this arch
	 * rounded to the load command size for this arch.
	 */
	if(object->mh != NULL){
	    move_size = rnd(arch_ctfs[i].size, sizeof(uint32_t));
	    object->seg_linkedit->fileoff += move_size;
	}
	else{
	    move_size = rnd(arch_ctfs[i].size, sizeof(uint64_t));
	    object->seg_linkedit64->fileoff += move_size;
	}
	if(object->st != NULL && object->st->nsyms != 0){
	    object->st->symoff += move_size;
	    object->st->stroff += move_size;
	}
	if(object->dyst != NULL){
	    if(object->dyst->nindirectsyms != 0)
	        object->dyst->indirectsymoff += move_size;
	    if(object->dyst->nlocrel != 0)
		object->dyst->locreloff += move_size;
	}
	if(object->func_starts_info_cmd != NULL)
	    object->func_starts_info_cmd->dataoff += move_size;
	if(object->data_in_code_cmd != NULL)
	    object->data_in_code_cmd->dataoff += move_size;
	if(object->code_sign_drs_cmd != NULL)
	    object->code_sign_drs_cmd->dataoff += move_size;
	if(object->link_opt_hint_cmd != NULL)
	    object->link_opt_hint_cmd->dataoff += move_size;

	/*
	 * Record the new content for writeout() to put in to the output file.
	 */
	object->output_new_content = arch_ctfs[i].contents;
	object->output_new_content_size = move_size;
}
Exemplo n.º 14
0
/*
 * write_object() writes a Mach-O object file from the built up data structures.
 */
void
write_object(
char *out_file_name)
{
    /* The structures for Mach-O relocatables */
    mach_header_t		header;
    segment_command_t		reloc_segment;
    struct symtab_command	symbol_table;
    struct dysymtab_command	dynamic_symbol_table;
    uint32_t			section_type;
    uint32_t			*indirect_symbols;
    isymbolS			*isymbolP;
    uint32_t			i, j, nsects, nsyms, strsize, nindirectsyms;

    /* locals to fill in section struct fields */
    uint32_t offset, zero;

    /* The GAS data structures */
    struct frchain *frchainP, *p;
    struct symbol *symbolP;
    struct frag *fragP;
    struct fix *fixP;

    uint32_t output_size;
    char *output_addr;
    kern_return_t r;

    enum byte_sex host_byte_sex;
    uint32_t reloff, nrelocs;
    int32_t count;
    char *fill_literal;
    int32_t fill_size;
    int32_t num_bytes;
    char *symbol_name;
    int fd;
    uint32_t local;
    struct stat stat_buf;

#ifdef I860
	I860_tweeks();
#endif
	i = 0; /* to shut up a compiler "may be used uninitialized" warning */

	/*
	 * The first group of things to do is to set all the fields in the
	 * header structures which includes offsets and determining the final
	 * sizes of things.
	 */

	/* 
	 * Fill in the addr and size fields of each section structure and count
	 * the number of sections.
	 */
	nsects = 0;
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    frchainP->frch_section.addr = frchainP->frch_root->fr_address;
	    frchainP->frch_section.size = frchainP->frch_last->fr_address -
		   			  frchainP->frch_root->fr_address;
	    nsects++;
	}

	/*
	 * Setup the indirect symbol tables by looking up or creating symbol
	 * from the indirect symbol names and recording the symbol pointers.
	 */
	nindirectsyms = layout_indirect_symbols();

	/*
	 * Setup the symbol table to include only those symbols that will be in
	 * the object file, assign the string table offsets into the symbols
	 * and size the string table.
	 */
	nsyms = 0;
	strsize = 0;
	layout_symbols((int32_t *)&nsyms, (int32_t *)&strsize);

	/* fill in the Mach-O header */
	header.magic = MH_MAGIC_VALUE;
	header.cputype = md_cputype;
	if(archflag_cpusubtype != -1)
	    header.cpusubtype = archflag_cpusubtype;
	else
	    header.cpusubtype = md_cpusubtype;

	header.filetype = MH_OBJECT;
	header.ncmds = 0;
	header.sizeofcmds = 0;
	if(nsects != 0){
	    header.ncmds += 1;
	    header.sizeofcmds += sizeof(segment_command_t) +
				 nsects * sizeof(section_t);
	}
	if(nsyms != 0){
	    header.ncmds += 1;
	    header.sizeofcmds += sizeof(struct symtab_command);
	    if(flagseen['k']){
		header.ncmds += 1;
		header.sizeofcmds += sizeof(struct dysymtab_command);
	    }
	}
	else
	    strsize = 0;
	header.flags = 0;
	if(subsections_via_symbols == TRUE)
	    header.flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
#ifdef ARCH64
	header.reserved = 0;
#endif

	/* fill in the segment command */
	memset(&reloc_segment, '\0', sizeof(segment_command_t));
	reloc_segment.cmd = LC_SEGMENT_VALUE;
	reloc_segment.cmdsize = sizeof(segment_command_t) +
				nsects * sizeof(section_t);
	/* leave reloc_segment.segname full of zeros */
	reloc_segment.vmaddr = 0;
	reloc_segment.vmsize = 0;
	reloc_segment.filesize = 0;
	offset = header.sizeofcmds + sizeof(mach_header_t);
	reloc_segment.fileoff = offset;
	reloc_segment.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
	reloc_segment.initprot= VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
	reloc_segment.nsects = nsects;
	reloc_segment.flags = 0;
	/*
	 * Set the offsets to the contents of the sections (for non-zerofill
	 * sections) and set the filesize and vmsize of the segment.  This is
	 * complicated by the fact that all the zerofill sections have addresses
	 * after the non-zerofill sections and that the alignment of sections
	 * produces gaps that are not in any section.  For the vmsize we rely on
	 * the fact the the sections start at address 0 so it is just the last
	 * zerofill section or the last not-zerofill section.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL)
		continue;
	    for(p = frchainP->frch_next; p != NULL; p = p->frch_next)
		if((p->frch_section.flags & SECTION_TYPE) != S_ZEROFILL)
		    break;
	    if(p != NULL)
		i = p->frch_section.addr - frchainP->frch_section.addr;
	    else
		i = frchainP->frch_section.size;
	    reloc_segment.filesize += i;
	    frchainP->frch_section.offset = offset;
	    offset += i;
	    reloc_segment.vmsize = frchainP->frch_section.addr +
				   frchainP->frch_section.size;
	}
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if((frchainP->frch_section.flags & SECTION_TYPE) != S_ZEROFILL)
		continue;
	    reloc_segment.vmsize = frchainP->frch_section.addr +
				   frchainP->frch_section.size;
	}
	offset = round(offset, sizeof(int32_t));

	/*
	 * Count the number of relocation entries for each section.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    frchainP->frch_section.nreloc = 0;
	    for(fixP = frchainP->frch_fix_root; fixP; fixP = fixP->fx_next){
		frchainP->frch_section.nreloc += nrelocs_for_fix(fixP);
	    }
	}

	/*
	 * Fill in the offset to the relocation entries of the sections.
	 */
	offset = round(offset, sizeof(int32_t));
	reloff = offset;
	nrelocs = 0;
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    if(frchainP->frch_section.nreloc == 0)
		frchainP->frch_section.reloff = 0;
	    else
		frchainP->frch_section.reloff = offset;
	    offset += frchainP->frch_section.nreloc *
		      sizeof(struct relocation_info);
	    nrelocs += frchainP->frch_section.nreloc;
	}

	if(flagseen['k']){
	    /* fill in the fields of the dysymtab_command */
	    dynamic_symbol_table.cmd = LC_DYSYMTAB;
	    dynamic_symbol_table.cmdsize = sizeof(struct dysymtab_command);

	    dynamic_symbol_table.ilocalsym = ilocalsym;
	    dynamic_symbol_table.nlocalsym = nlocalsym;
	    dynamic_symbol_table.iextdefsym = iextdefsym;
	    dynamic_symbol_table.nextdefsym = nextdefsym;
	    dynamic_symbol_table.iundefsym = iundefsym;
	    dynamic_symbol_table.nundefsym = nundefsym;

	    if(nindirectsyms == 0){
		dynamic_symbol_table.nindirectsyms = 0;
		dynamic_symbol_table.indirectsymoff = 0;
	    }
	    else{
		dynamic_symbol_table.nindirectsyms = nindirectsyms;
		dynamic_symbol_table.indirectsymoff = offset;
		offset += nindirectsyms * sizeof(uint32_t);
	    }

	    dynamic_symbol_table.tocoff = 0;
	    dynamic_symbol_table.ntoc = 0;
	    dynamic_symbol_table.modtaboff = 0;
	    dynamic_symbol_table.nmodtab = 0;
	    dynamic_symbol_table.extrefsymoff = 0;
	    dynamic_symbol_table.nextrefsyms = 0;
	    dynamic_symbol_table.extreloff = 0;
	    dynamic_symbol_table.nextrel = 0;
	    dynamic_symbol_table.locreloff = 0;
	    dynamic_symbol_table.nlocrel = 0;
	}

	/* fill in the fields of the symtab_command (except the string table) */
	symbol_table.cmd = LC_SYMTAB;
	symbol_table.cmdsize = sizeof(struct symtab_command);
	if(nsyms == 0)
	    symbol_table.symoff = 0;
	else
	    symbol_table.symoff = offset;
	symbol_table.nsyms = nsyms;
	offset += symbol_table.nsyms * sizeof(nlist_t);

	/* fill in the string table fields of the symtab_command */
	if(strsize == 0)
	    symbol_table.stroff = 0;
	else
	    symbol_table.stroff = offset;
	symbol_table.strsize = round(strsize, sizeof(uint32_t));
	offset += round(strsize, sizeof(uint32_t));

	/*
	 * The second group of things to do is now with the size of everything
	 * known the object file and the offsets set in the various structures
	 * the contents of the object file can be created.
	 */

	/*
	 * Create the buffer to copy the parts of the output file into.
	 */
	output_size = offset;
	if((r = vm_allocate(mach_task_self(), (vm_address_t *)&output_addr,
			    output_size, TRUE)) != KERN_SUCCESS)
	    as_fatal("can't vm_allocate() buffer for output file of size %u",
		     output_size);

	/* put the headers in the output file's buffer */
	host_byte_sex = get_host_byte_sex();
	offset = 0;

	/* put the mach_header in the buffer */
	memcpy(output_addr + offset, &header, sizeof(mach_header_t));
	if(host_byte_sex != md_target_byte_sex)
	    swap_mach_header_t((mach_header_t *)(output_addr + offset),
			       md_target_byte_sex);
	offset += sizeof(mach_header_t);

	/* put the segment_command in the buffer */
	if(nsects != 0){
	    memcpy(output_addr + offset, &reloc_segment,
		   sizeof(segment_command_t));
	    if(host_byte_sex != md_target_byte_sex)
		swap_segment_command_t((segment_command_t *)
				       (output_addr + offset),
				       md_target_byte_sex);
	    offset += sizeof(segment_command_t);
	}

	/* put the segment_command's section structures in the buffer */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    memcpy(output_addr + offset, &(frchainP->frch_section),
		   sizeof(section_t));
	    if(host_byte_sex != md_target_byte_sex)
		swap_section_t((section_t *)(output_addr + offset), 1,
			       md_target_byte_sex);
	    offset += sizeof(section_t);
	}

	/* put the symbol_command in the buffer */
	if(nsyms != 0){
	    memcpy(output_addr + offset, &symbol_table,
		   sizeof(struct symtab_command));
	    if(host_byte_sex != md_target_byte_sex)
		swap_symtab_command((struct symtab_command *)
				     (output_addr + offset),
				     md_target_byte_sex);
	    offset += sizeof(struct symtab_command);
	}

	if(flagseen['k']){
	    /* put the dysymbol_command in the buffer */
	    if(nsyms != 0){
		memcpy(output_addr + offset, &dynamic_symbol_table,
		       sizeof(struct dysymtab_command));
		if(host_byte_sex != md_target_byte_sex)
		    swap_dysymtab_command((struct dysymtab_command *)
					  (output_addr + offset),
					  md_target_byte_sex);
		offset += sizeof(struct dysymtab_command);
	    }
	}

	/* put the section contents (frags) in the buffer */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    offset = frchainP->frch_section.offset;
	    for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){
		know(fragP->fr_type == rs_fill);
		/* put the fixed part of the frag in the buffer */
		memcpy(output_addr + offset, fragP->fr_literal, fragP->fr_fix);
		offset += fragP->fr_fix;

		/* put the variable repeated part of the frag in the buffer */
		fill_literal = fragP->fr_literal + fragP->fr_fix;
		fill_size = fragP->fr_var;
		num_bytes = fragP->fr_offset * fragP->fr_var;
		for(count = 0; count < num_bytes; count += fill_size){
		    memcpy(output_addr + offset, fill_literal, fill_size);
		    offset += fill_size;
		}
	    }
	}


	/* put the symbols in the output file's buffer */
	offset = symbol_table.symoff;
	for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
	    if((symbolP->sy_type & N_EXT) == 0){
		symbol_name = symbolP->sy_name;
		symbolP->sy_nlist.n_un.n_strx = symbolP->sy_name_offset;
		if(symbolP->expression != 0) {
		    expressionS *exp;

		    exp = (expressionS *)symbolP->expression;
		    if((exp->X_add_symbol->sy_type & N_TYPE) == N_UNDF)
	    		as_fatal("undefined symbol `%s' in operation setting "
				 "`%s'", exp->X_add_symbol->sy_name,
				 symbol_name);
		    if((exp->X_subtract_symbol->sy_type & N_TYPE) == N_UNDF)
	    		as_fatal("undefined symbol `%s' in operation setting "
				 "`%s'", exp->X_subtract_symbol->sy_name,
				 symbol_name);
		    if(exp->X_add_symbol->sy_other !=
		       exp->X_subtract_symbol->sy_other)
	    		as_fatal("invalid sections for operation on `%s' and "
				 "`%s' setting `%s'",exp->X_add_symbol->sy_name,
				 exp->X_subtract_symbol->sy_name, symbol_name);
		    symbolP->sy_nlist.n_value +=
			exp->X_add_symbol->sy_value -
			exp->X_subtract_symbol->sy_value;
		}
		memcpy(output_addr + offset, (char *)(&symbolP->sy_nlist),
		       sizeof(nlist_t));
		symbolP->sy_name = symbol_name;
		offset += sizeof(nlist_t);
	    }
	}
	for(i = 0; i < nextdefsym; i++){
	    symbol_name = extdefsyms[i]->sy_name;
	    extdefsyms[i]->sy_nlist.n_un.n_strx = extdefsyms[i]->sy_name_offset;
	    memcpy(output_addr + offset, (char *)(&extdefsyms[i]->sy_nlist),
	           sizeof(nlist_t));
	    extdefsyms[i]->sy_name = symbol_name;
	    offset += sizeof(nlist_t);
	}
	for(j = 0; j < nundefsym; j++){
	    symbol_name = undefsyms[j]->sy_name;
	    undefsyms[j]->sy_nlist.n_un.n_strx = undefsyms[j]->sy_name_offset;
	    memcpy(output_addr + offset, (char *)(&undefsyms[j]->sy_nlist),
	           sizeof(nlist_t));
	    undefsyms[j]->sy_name = symbol_name;
	    offset += sizeof(nlist_t);
	}
	if(host_byte_sex != md_target_byte_sex)
	    swap_nlist_t((nlist_t *)(output_addr + symbol_table.symoff),
		         symbol_table.nsyms, md_target_byte_sex);

	/*
	 * Put the relocation entries for each section in the buffer.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    offset = frchainP->frch_section.reloff;
	    for(fixP = frchainP->frch_fix_root; fixP; fixP = fixP->fx_next){
		offset += fix_to_relocation_entries(
					fixP,
					frchainP->frch_section.addr,
					(struct relocation_info *)(output_addr +
								   offset),
				        frchainP->frch_section.flags &
					  S_ATTR_DEBUG);
	    }
	}
	if(host_byte_sex != md_target_byte_sex)
	    swap_relocation_info((struct relocation_info *)
		(output_addr + reloff), nrelocs, md_target_byte_sex);

	if(flagseen['k']){
	    /* put the indirect symbol table in the buffer */
	    offset = dynamic_symbol_table.indirectsymoff;
	    for(frchainP = frchain_root;
		frchainP != NULL;
		frchainP = frchainP->frch_next){
		section_type = frchainP->frch_section.flags & SECTION_TYPE;
		if(section_type == S_NON_LAZY_SYMBOL_POINTERS ||
		   section_type == S_LAZY_SYMBOL_POINTERS ||
		   section_type == S_SYMBOL_STUBS){
		    /*
		     * For each indirect symbol put out the symbol number.
		     */
		    for(isymbolP = frchainP->frch_isym_root;
			isymbolP != NULL;
			isymbolP = isymbolP->isy_next){
			/*
			 * If this is a non-lazy pointer symbol section and
			 * if the symbol is a local symbol then put out
			 * INDIRECT_SYMBOL_LOCAL as the indirect symbol table
			 * entry.  This is used with code gen for fix-n-continue
			 * where the compiler generates indirection for static
			 * data references.  See the comments at the end of
			 * fixup_section() that explains the assembly code used.
			 */
			if(section_type == S_NON_LAZY_SYMBOL_POINTERS &&
			   (isymbolP->isy_symbol->sy_nlist.n_type & N_EXT) !=
			    N_EXT){
    			    local = INDIRECT_SYMBOL_LOCAL;
			    if((isymbolP->isy_symbol->sy_nlist.n_type &
				N_TYPE) == N_ABS)
				local |= INDIRECT_SYMBOL_ABS;
			    memcpy(output_addr + offset, (char *)(&local),
	   			   sizeof(uint32_t));
			}
			else{
			    memcpy(output_addr + offset,
				   (char *)(&isymbolP->isy_symbol->sy_number),
				   sizeof(uint32_t));
			}
			offset += sizeof(uint32_t);
		    }
		}
	    }
	    if(host_byte_sex != md_target_byte_sex){
		indirect_symbols = (uint32_t *)(output_addr +
				    dynamic_symbol_table.indirectsymoff);
		swap_indirect_symbols(indirect_symbols, nindirectsyms, 
				      md_target_byte_sex);
	    }
	}

	/* put the strings in the output file's buffer */
	offset = symbol_table.stroff;
	if(symbol_table.strsize != 0){
	    zero = 0;
	    memcpy(output_addr + offset, (char *)&zero, sizeof(char));
	    offset += sizeof(char);
	}
	for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
	    /* Ordinary case: not .stabd. */
	    if(symbolP->sy_name != NULL){
		if((symbolP->sy_type & N_EXT) != 0){
		    memcpy(output_addr + offset, symbolP->sy_name,
			   strlen(symbolP->sy_name) + 1);
		    offset += strlen(symbolP->sy_name) + 1;
		}
	    }
	}
	for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
	    /* Ordinary case: not .stabd. */
	    if(symbolP->sy_name != NULL){
		if((symbolP->sy_type & N_EXT) == 0){
		    memcpy(output_addr + offset, symbolP->sy_name,
			   strlen(symbolP->sy_name) + 1);
		    offset += strlen(symbolP->sy_name) + 1;
		}
	    }
	}
	/*
         * Create the output file.  The unlink() is done to handle the problem
         * when the out_file_name is not writable but the directory allows the
         * file to be removed (since the file may not be there the return code
         * of the unlink() is ignored).
         */
	if(bad_error != 0)
	    return;
	/*
	 * Avoid doing the unlink() on special files, just unlink regular files
	 * that exist.
	 */
	if(stat(out_file_name, &stat_buf) != -1){
	    if(stat_buf.st_mode & S_IFREG)
		(void)unlink(out_file_name);
	}
	if((fd = open(out_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
	    as_fatal("can't create output file: %s", out_file_name);
	if(write(fd, output_addr, output_size) != (int)output_size)
	    as_fatal("can't write output file");
	if(close(fd) == -1)
	    as_fatal("can't close output file");
}
Exemplo n.º 15
0
/*
 * checksyms() is the routine that gets called by ofile_process() to process
 * single object files.
 */
static
void
checksyms(
struct ofile *ofile,
char *arch_name,
void *cookie)
{
    struct cmd_flags *cmd_flags;
    unsigned long i;
    struct load_command *lc;
    struct symtab_command *st;
    struct nlist *symbols;
    unsigned long nsymbols;
    char *strings;
    unsigned long strsize;
    unsigned long nfiledefs, ncats, nlocal, nstabs, nfun;
    unsigned long filedef_strings, cat_strings, local_strings, stab_strings;
    enum bool debug;

	if(ofile->mh == NULL)
	    return;

	debug = FALSE;
	cmd_flags = (struct cmd_flags *)cookie;

	if(cmd_flags->check_dynamic_binary == TRUE)
	    if((ofile->mh->flags & MH_DYLDLINK) == MH_DYLDLINK)
		check_dynamic_binary(ofile, arch_name, cmd_flags->detail,
				     cmd_flags->verification);

	if(ofile->mh->filetype == MH_DYLIB ||
	   ofile->mh->filetype == MH_DYLIB_STUB)
	    check_dylib(ofile, arch_name, cmd_flags->detail,
			cmd_flags->verification, &debug);

	st = NULL;
	lc = ofile->load_commands;
	for(i = 0; i < ofile->mh->ncmds; i++){
	    if(st == NULL && lc->cmd == LC_SYMTAB){
		st = (struct symtab_command *)lc;
	    }
	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
	}
	if(st == NULL || st->nsyms == 0){
	    return;
	}

	if(cmd_flags->rldtype == FALSE &&
	   cmd_flags->trey == FALSE &&
	   (ofile->mh->flags & MH_DYLDLINK) == 0 &&
	    (ofile->file_type != OFILE_FAT ||
	     ofile->arch_type != OFILE_ARCHIVE) &&
	    ofile->file_type != OFILE_ARCHIVE &&
	    ofile->mh->filetype != MH_FVMLIB){
	    if(st->nsyms == 0)
		return;

	    if(cmd_flags->detail == TRUE){
		if(arch_name != NULL)
		    printf("(for architecture %s):", arch_name);
		if(ofile->member_ar_hdr != NULL){
		    printf("%s:%.*s:", ofile->file_name,
			   (int)ofile->member_name_size, ofile->member_name);
		}
		else
		    printf("%s:", ofile->file_name);
		printf(" has %u symbols and %u string bytes\n", st->nsyms,
		       st->strsize);
	    }
	    if(cmd_flags->verification == TRUE)
		printf("unstripped_binary\n");
	    exit_status = EXIT_FAILURE;
	    return;
	}

	symbols = (struct nlist *)(ofile->object_addr + st->symoff);
	nsymbols = st->nsyms;
	if(ofile->object_byte_sex != get_host_byte_sex())
	    swap_nlist(symbols, nsymbols, get_host_byte_sex());

	strings = ofile->object_addr + st->stroff;
	strsize = st->strsize;
	for(i = 0; i < nsymbols; i++){
	    if(symbols[i].n_un.n_strx == 0)
		symbols[i].n_un.n_name = "";
	    else if(symbols[i].n_un.n_strx < 0 ||
		    (unsigned long)symbols[i].n_un.n_strx > st->strsize)
		symbols[i].n_un.n_name = "bad string index";
	    else
		symbols[i].n_un.n_name = symbols[i].n_un.n_strx + strings;

	    if((symbols[i].n_type & N_TYPE) == N_INDR){
		if(symbols[i].n_value == 0)
		    symbols[i].n_value = (long)"";
		else if(symbols[i].n_value > st->strsize)
		    symbols[i].n_value = (long)"bad string index";
		else
		    symbols[i].n_value =
				(long)(symbols[i].n_value + strings);
	    }
	}

	nfiledefs = 0;
	ncats = 0;
	nlocal = 0;
	nstabs = 0;
	nfun = 0;
	filedef_strings = 0;
	cat_strings = 0;
	local_strings = 0;
	stab_strings = 0;
	for(i = 0; i < nsymbols; i++){
	    if(ofile->mh->filetype == MH_EXECUTE){
		if(symbols[i].n_type == (N_ABS | N_EXT) &&
		   symbols[i].n_value == 0){
		    if(strncmp(symbols[i].n_un.n_name, ".file_definition_",
			       sizeof(".file_definition_") - 1) == 0){
			nfiledefs++;
			filedef_strings += strlen(symbols[i].n_un.n_name);
		    }
		    if(strncmp(symbols[i].n_un.n_name, ".objc_category_name_",
			       sizeof(".objc_category_name_") - 1) == 0){
			ncats++;
			cat_strings += strlen(symbols[i].n_un.n_name);
		    }
		}
	    }
	    if((symbols[i].n_type & N_EXT) == 0){
		nlocal++;
		local_strings += strlen(symbols[i].n_un.n_name);
	    }
	    if(symbols[i].n_type & N_STAB){
		nstabs++;
		stab_strings += strlen(symbols[i].n_un.n_name);
		if(symbols[i].n_type == N_FUN)
		    nfun++;
	    }
	}

	if(nfiledefs == 0 && ncats == 0 && nlocal == 0 && nstabs == 0)
	    return;
	if(cmd_flags->rldtype == TRUE && nstabs == 0)
	    return;
	if((ofile->mh->flags & MH_DYLDLINK) == MH_DYLDLINK &&
	   (nstabs == 0 && nlocal == 0))
	    return;
	if(nstabs == 0 &&
	   ((ofile->file_type == OFILE_FAT &&
	     ofile->arch_type == OFILE_ARCHIVE) ||
	    ofile->file_type == OFILE_ARCHIVE ||
	    ofile->mh->filetype == MH_FVMLIB))
	    return;
	if((ofile->mh->filetype == MH_DYLIB ||
	    ofile->mh->filetype == MH_DYLIB_STUB ||
	    ofile->mh->filetype == MH_FVMLIB) &&
	    (nfun == 0 || debug == TRUE))
	    return;

	if(cmd_flags->detail == TRUE){
	    if(arch_name != NULL)
		printf("(for architecture %s):", arch_name);
	    if(ofile->member_ar_hdr != NULL){
		printf("%s:%.*s:", ofile->file_name,
		       (int)ofile->member_name_size, ofile->member_name);
	    }
	    else
		printf("%s:", ofile->file_name);
	    printf("\n");
	    if(nfiledefs != 0)
		printf(" has %lu .file_definition_ symbols and %lu string "
		       "bytes\n", nfiledefs, filedef_strings);
	    if(ncats != 0)
		printf(" has %lu .objc_category_name_ symbols and %lu string "
		       "bytes\n", ncats, cat_strings);
	    if(nlocal != 0)
		printf(" has %lu local symbols and %lu string "
		       "bytes\n", nlocal, local_strings);
	    if(nstabs != 0)
		printf(" has %lu debugging symbols and %lu string "
		       "bytes\n", nstabs, stab_strings);
	}
	if(cmd_flags->verification == TRUE)
	    printf("unstripped_binary\n");
	if(cmd_flags->trey == TRUE && nstabs == 0)
	    return;

	exit_status = EXIT_FAILURE;
	return;
}