Ejemplo n.º 1
0
int main(int argc, char * argv[])
{
    KXKextManagerError	err;
    int			fd;
    const char *	output_name = NULL;
    uint32_t		i, zero = 0, num_files = 0;
    uint32_t		filenum;
    uint32_t		strx, strtabsize, strtabpad;
    struct symbol *	import_symbols;
    struct symbol *	export_symbols;
    uint32_t		num_import_syms, num_export_syms, num_removed_syms;
    uint32_t		import_idx, export_idx;
    const NXArchInfo *	host_arch;
    const NXArchInfo *	target_arch;
    boolean_t		require_imports = true;
    boolean_t		diff = false;

    struct {
	struct mach_header    hdr;
	struct symtab_command symcmd;
    } load_cmds;

    struct file {
        vm_offset_t  mapped;
        vm_size_t    mapped_size;
	uint32_t     nsyms;
	boolean_t    import;
	const char * path;
    };
    struct file files[64];
    
    host_arch = NXGetLocalArchInfo();
    target_arch = host_arch;

    for( i = 1; i < argc; i += 2)
    {
	boolean_t import;

        if (!strcmp("-sect", argv[i]))
        {
	    require_imports = false;
	    i--;
	    continue;
        }
        if (!strcmp("-diff", argv[i]))
        {
	    require_imports = false;
	    diff = true;
	    i--;
	    continue;
        }

	if (i == (argc - 1))
	{
	    fprintf(stderr, "bad arguments: %s\n", argv[i]);
	    exit(1);
	}

        if (!strcmp("-arch", argv[i]))
        {
            target_arch = NXGetArchInfoFromName(argv[i + 1]);
	    if (!target_arch)
	    {
		fprintf(stderr, "unknown architecture name: %s\n", argv[i+1]);
		exit(1);
	    }
            continue;
        }
        if (!strcmp("-output", argv[i]))
        {
	    output_name = argv[i+1];
            continue;
        }

        if (!strcmp("-import", argv[i]))
	    import = true;
	else if (!strcmp("-export", argv[i]))
	    import = false;
	else
	{
	    fprintf(stderr, "unknown option: %s\n", argv[i]);
	    exit(1);
	}

        err = readFile(argv[i+1], &files[num_files].mapped, &files[num_files].mapped_size);
        if (kKXKextManagerErrorNone != err)
            exit(1);

        if (files[num_files].mapped && files[num_files].mapped_size)
	{
	    files[num_files].import = import;
	    files[num_files].path   = argv[i+1];
            num_files++;
	}
    }

    if (!output_name)
    {
	fprintf(stderr, "no output file\n");
	exit(1);
    }

    num_import_syms = 0;
    num_export_syms = 0;
    for (filenum = 0; filenum < num_files; filenum++)
    {
        files[filenum].nsyms = count_symbols((char *) files[filenum].mapped);
	if (files[filenum].import)
	    num_import_syms += files[filenum].nsyms;
	else
	    num_export_syms += files[filenum].nsyms;
    }
    if (!num_export_syms)
    {
	fprintf(stderr, "no export names\n");
	exit(1);
    }

    import_symbols = calloc(num_import_syms, sizeof(struct symbol));
    export_symbols = calloc(num_export_syms, sizeof(struct symbol));

    strtabsize = 4;
    import_idx = 0;
    export_idx = 0;

    for (filenum = 0; filenum < num_files; filenum++)
    {
	if (files[filenum].import)
	{
	    store_symbols((char *) files[filenum].mapped,
					import_symbols, import_idx, num_import_syms);
	    import_idx += files[filenum].nsyms;
	}
	else
	{
	    strtabsize += store_symbols((char *) files[filenum].mapped,
					export_symbols, export_idx, num_export_syms);
	    export_idx += files[filenum].nsyms;
	}
	if (!files[filenum].nsyms)
	{
	    fprintf(stderr, "warning: file %s contains no names\n", files[filenum].path);
	}
    }


    qsort(import_symbols, num_import_syms, sizeof(struct symbol), &qsort_cmp);
    qsort(export_symbols, num_export_syms, sizeof(struct symbol), &qsort_cmp);

    num_removed_syms = 0;
    if (num_import_syms)
    {
	for (export_idx = 0; export_idx < num_export_syms; export_idx++)
	{
	    boolean_t found = true;
	    if (!bsearch(export_symbols[export_idx].name, import_symbols, 
			    num_import_syms, sizeof(struct symbol), &bsearch_cmp))
	    {
		if (require_imports)
		    fprintf(stderr, "exported name not in import list: %s\n", 
				export_symbols[export_idx].name);
		found = false;
	    }
    
	    if (export_symbols[export_idx].indirect)
	    {
		if (!bsearch(export_symbols[export_idx].indirect, import_symbols, 
				num_import_syms, sizeof(struct symbol), &bsearch_cmp))
		{
		    if (require_imports)
			fprintf(stderr, "exported name not in import list: %s\n", 
				    export_symbols[export_idx].indirect);
		    found = false;
		}
	    }
	    if (found && !diff)
		continue;
	    if (!found && diff)
		continue;

	    num_removed_syms++;
	    strtabsize -= (export_symbols[export_idx].name_len + export_symbols[export_idx].indirect_len);
	    export_symbols[export_idx].name = 0;
	}
    }

    if (require_imports && num_removed_syms)
    {
	err = kKXKextManagerErrorUnspecified;
	goto finish;
    }

    fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755);
    if (-1 == fd)
    {
	perror("couldn't write output");
	err = kKXKextManagerErrorFileAccess;
	goto finish;
    }

    strtabpad = (strtabsize + 3) & ~3;

    load_cmds.hdr.magic		= MH_MAGIC;
    load_cmds.hdr.cputype	= target_arch->cputype;
    load_cmds.hdr.cpusubtype	= target_arch->cpusubtype;
    load_cmds.hdr.filetype	= MH_OBJECT;
    load_cmds.hdr.ncmds		= 1;
    load_cmds.hdr.sizeofcmds	= sizeof(load_cmds.symcmd);
    load_cmds.hdr.flags		= MH_INCRLINK;

    load_cmds.symcmd.cmd	= LC_SYMTAB;
    load_cmds.symcmd.cmdsize	= sizeof(load_cmds.symcmd);
    load_cmds.symcmd.symoff	= sizeof(load_cmds);
    load_cmds.symcmd.nsyms	= (num_export_syms - num_removed_syms);
    load_cmds.symcmd.stroff	= (num_export_syms - num_removed_syms) * sizeof(struct nlist) 
				+ load_cmds.symcmd.symoff;
    load_cmds.symcmd.strsize	= strtabpad;

    if (target_arch->byteorder != host_arch->byteorder)
    {
	swap_mach_header(&load_cmds.hdr, target_arch->byteorder);
	swap_symtab_command(&load_cmds.symcmd, target_arch->byteorder);
    }

    err = writeFile(fd, &load_cmds, sizeof(load_cmds));
    if (kKXKextManagerErrorNone != err)
	goto finish;

    strx = 4;
    for (export_idx = 0; export_idx < num_export_syms; export_idx++)
    {
	struct nlist nl;

	if (!export_symbols[export_idx].name)
	    continue;

	nl.n_sect  = 0;
	nl.n_desc  = 0;

	nl.n_un.n_strx = strx;
	strx += export_symbols[export_idx].name_len;

	if (export_symbols[export_idx].indirect)
	{
	    nl.n_type  = N_INDR | N_EXT;
	    nl.n_value = strx;
	    strx += export_symbols[export_idx].indirect_len;
	}
	else
	{
	    nl.n_type  = N_UNDF | N_EXT;
	    nl.n_value = 0;
	}

	if (target_arch->byteorder != host_arch->byteorder)
	    swap_nlist(&nl, 1, target_arch->byteorder);

	err = writeFile(fd, &nl, sizeof(nl));
	if (kKXKextManagerErrorNone != err)
	    goto finish;
    }

    strx = sizeof(uint32_t);
    err = writeFile(fd, &zero, strx);
    if (kKXKextManagerErrorNone != err)
	goto finish;

    for (export_idx = 0; export_idx < num_export_syms; export_idx++)
    {
	if (!export_symbols[export_idx].name)
	    continue;
	err = writeFile(fd, export_symbols[export_idx].name, 
		    export_symbols[export_idx].name_len + export_symbols[export_idx].indirect_len);
	if (kKXKextManagerErrorNone != err)
	    goto finish;
    }

    err = writeFile(fd, &zero, strtabpad - strtabsize);
    if (kKXKextManagerErrorNone != err)
	goto finish;
	
    close(fd);


finish:
    if (kKXKextManagerErrorNone != err)
    {
	if (output_name)
	    unlink(output_name);
        exit(1);
    }
    else
        exit(0);
    return(0);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
	    }
	}
}
Ejemplo n.º 4
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;
	    }
	}
}
Ejemplo n.º 5
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));
        }
    }
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
int main(int argc, char * argv[])
{
    ToolError	err;
    int			i, fd;
    const char *	output_name = NULL;
    uint32_t		zero = 0, num_files = 0;
    uint32_t		filenum;
    uint32_t		strx, strtabsize, strtabpad;
    struct symbol *	import_symbols;
    struct symbol *	export_symbols;
    uint32_t		num_import_syms, num_export_syms;
    uint32_t		result_count, num_removed_syms;
    uint32_t		import_idx, export_idx;
    const NXArchInfo *	host_arch;
    const NXArchInfo *	target_arch;
    boolean_t		require_imports = true;
    boolean_t		diff = false;


    struct file {
        vm_offset_t  mapped;
        vm_size_t    mapped_size;
	uint32_t     nsyms;
	boolean_t    import;
	const char * path;
    };
    struct file files[64];
    
    host_arch = NXGetLocalArchInfo();
    target_arch = host_arch;

    for( i = 1; i < argc; i += 2)
    {
	boolean_t import;

        if (!strcmp("-sect", argv[i]))
        {
	    require_imports = false;
	    i--;
	    continue;
        }
        if (!strcmp("-diff", argv[i]))
        {
	    require_imports = false;
	    diff = true;
	    i--;
	    continue;
        }

	if (i == (argc - 1))
	{
	    fprintf(stderr, "bad arguments: %s\n", argv[i]);
	    exit(1);
	}

        if (!strcmp("-arch", argv[i]))
        {
            target_arch = DL_NXGetArchInfoFromName(argv[i + 1]);
	    if (!target_arch)
	    {
		fprintf(stderr, "unknown architecture name: %s\n", argv[i+1]);
		exit(1);
	    }
            continue;
        }
        if (!strcmp("-output", argv[i]))
        {
	    output_name = argv[i+1];
            continue;
        }

        if (!strcmp("-import", argv[i]))
	    import = true;
	else if (!strcmp("-export", argv[i]))
	    import = false;
	else
	{
	    fprintf(stderr, "unknown option: %s\n", argv[i]);
	    exit(1);
	}

        err = readFile(argv[i+1], &files[num_files].mapped, &files[num_files].mapped_size);
        if (kErrorNone != err)
            exit(1);

        if (files[num_files].mapped && files[num_files].mapped_size)
	{
	    files[num_files].import = import;
	    files[num_files].path   = argv[i+1];
            num_files++;
	}
    }

    if (!output_name)
    {
	fprintf(stderr, "no output file\n");
	exit(1);
    }

    num_import_syms = 0;
    num_export_syms = 0;
    for (filenum = 0; filenum < num_files; filenum++)
    {
        files[filenum].nsyms = count_symbols((char *) files[filenum].mapped, files[filenum].mapped_size);
	if (files[filenum].import)
	    num_import_syms += files[filenum].nsyms;
	else
	    num_export_syms += files[filenum].nsyms;
    }
    if (!num_export_syms)
    {
	fprintf(stderr, "no export names\n");
	exit(1);
    }

    import_symbols = calloc(num_import_syms, sizeof(struct symbol));
    export_symbols = calloc(num_export_syms, sizeof(struct symbol));

    import_idx = 0;
    export_idx = 0;

    for (filenum = 0; filenum < num_files; filenum++)
    {
	if (files[filenum].import)
	{
	    store_symbols((char *) files[filenum].mapped, files[filenum].mapped_size,
					import_symbols, import_idx, num_import_syms);
	    import_idx += files[filenum].nsyms;
	}
	else
	{
	    store_symbols((char *) files[filenum].mapped, files[filenum].mapped_size,
					export_symbols, export_idx, num_export_syms);
	    export_idx += files[filenum].nsyms;
	}
	if (false && !files[filenum].nsyms)
	{
	    fprintf(stderr, "warning: file %s contains no names\n", files[filenum].path);
	}
    }


    qsort(import_symbols, num_import_syms, sizeof(struct symbol), &qsort_cmp);
    qsort(export_symbols, num_export_syms, sizeof(struct symbol), &qsort_cmp);

    result_count = 0;
    num_removed_syms = 0;
    strtabsize = 4;
    if (num_import_syms)
    {
	for (export_idx = 0; export_idx < num_export_syms; export_idx++)
	{
	    struct symbol * result;
	    char * name;
	    size_t len;
	    boolean_t wild;

	    name = export_symbols[export_idx].indirect;
	    len  = export_symbols[export_idx].indirect_len;
	    if (!name)
	    {
		name = export_symbols[export_idx].name;
		len  = export_symbols[export_idx].name_len;
	    }
	    wild = ((len > 2) && ('*' == name[len-=2]));
	    if (wild)
	    {
		struct bsearch_key key;
		key.name = name;
		key.name_len = len;
		result = bsearch(&key, import_symbols, 
				    num_import_syms, sizeof(struct symbol), &bsearch_cmp_prefix);

		if (result)
		{
		    struct symbol * first;
		    struct symbol * last;

		    strtabsize += (result->name_len + result->indirect_len);

		    first = result;
		    while (--first >= &import_symbols[0])
		    {
			if (bsearch_cmp_prefix(&key, first))
			    break;
			strtabsize += (first->name_len + first->indirect_len);
		    }
		    first++;

		    last = result;
		    while (++last < (&import_symbols[0] + num_import_syms))
		    {
			if (bsearch_cmp_prefix(&key, last))
			    break;
			strtabsize += (last->name_len + last->indirect_len);
		    }
		    result_count += last - first;
		    result = first;
		    export_symbols[export_idx].list = first;
		    export_symbols[export_idx].list_count = last - first;
		    export_symbols[export_idx].flags |= kExported;
		}
	    }
	    else
		result = bsearch(name, import_symbols, 
				    num_import_syms, sizeof(struct symbol), &bsearch_cmp);

	    if (!result && require_imports)
	    {
		int status;
		char * demangled_result = 
			__cxa_demangle(export_symbols[export_idx].name + 1, NULL, NULL, &status);
		fprintf(stderr, "exported name not in import list: %s\n",
					demangled_result ? demangled_result : export_symbols[export_idx].name);
//		fprintf(stderr, "                                : %s\n", export_symbols[export_idx].name);
		if (demangled_result) {
			free(demangled_result);
		}
		num_removed_syms++;
	    }
	    if (diff)
	    {
		if (!result)
		    result = &export_symbols[export_idx];
		else
		    result = NULL;
	    }
	    if (result && !wild)
	    {
		export_symbols[export_idx].flags |= kExported;
		strtabsize += (export_symbols[export_idx].name_len + export_symbols[export_idx].indirect_len);
		result_count++;
		export_symbols[export_idx].list = &export_symbols[export_idx];
		export_symbols[export_idx].list_count = 1;
	    }
	}
    }
    strtabpad = (strtabsize + 3) & ~3;

    if (require_imports && num_removed_syms)
    {
	err = kError;
	goto finish;
    }

    fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755);
    if (-1 == fd)
    {
	perror("couldn't write output");
	err = kErrorFileAccess;
	goto finish;
    }

    struct symtab_command symcmd;
    struct uuid_command uuidcmd;

    symcmd.cmd		= LC_SYMTAB;
    symcmd.cmdsize	= sizeof(symcmd);
    symcmd.symoff	= sizeof(symcmd) + sizeof(uuidcmd);
    symcmd.nsyms	= result_count;
    symcmd.strsize	= strtabpad;

    uuidcmd.cmd         = LC_UUID;
    uuidcmd.cmdsize     = sizeof(uuidcmd);
    uuid_generate(uuidcmd.uuid);

    if (CPU_ARCH_ABI64 & target_arch->cputype)
    {
	struct mach_header_64 hdr;
	hdr.magic	= MH_MAGIC_64;
	hdr.cputype	= target_arch->cputype;
	hdr.cpusubtype	= target_arch->cpusubtype;
	hdr.filetype	= MH_KEXT_BUNDLE;
	hdr.ncmds	= 2;
	hdr.sizeofcmds	= sizeof(symcmd) + sizeof(uuidcmd);
	hdr.flags	= MH_INCRLINK;

	symcmd.symoff	+= sizeof(hdr);
	symcmd.stroff	= result_count * sizeof(struct nlist_64) 
				+ symcmd.symoff;

	if (target_arch->byteorder != host_arch->byteorder)
	    swap_mach_header_64(&hdr, target_arch->byteorder);
	err = writeFile(fd, &hdr, sizeof(hdr));
    }
    else
    {
	struct mach_header    hdr;
	hdr.magic	= MH_MAGIC;
	hdr.cputype	= target_arch->cputype;
	hdr.cpusubtype	= target_arch->cpusubtype;
	hdr.filetype	= (target_arch->cputype == CPU_TYPE_I386) ? MH_OBJECT : MH_KEXT_BUNDLE;
	hdr.ncmds	= 2;
	hdr.sizeofcmds	= sizeof(symcmd) + sizeof(uuidcmd);
	hdr.flags	= MH_INCRLINK;

	symcmd.symoff	+= sizeof(hdr);
	symcmd.stroff	= result_count * sizeof(struct nlist) 
				+ symcmd.symoff;

	if (target_arch->byteorder != host_arch->byteorder)
	    swap_mach_header(&hdr, target_arch->byteorder);
	err = writeFile(fd, &hdr, sizeof(hdr));
    }

    if (kErrorNone != err)
	goto finish;

    if (target_arch->byteorder != host_arch->byteorder) {
        swap_symtab_command(&symcmd, target_arch->byteorder);
        swap_uuid_command(&uuidcmd, target_arch->byteorder);
    }
    err = writeFile(fd, &symcmd, sizeof(symcmd));
    if (kErrorNone != err)
	goto finish;
    err = writeFile(fd, &uuidcmd, sizeof(uuidcmd));
    if (kErrorNone != err)
        goto finish;

    strx = 4;
    for (export_idx = 0; export_idx < num_export_syms; export_idx++)
    {
	if (!export_symbols[export_idx].name)
	    continue;
	if (!(kExported & export_symbols[export_idx].flags))
	    continue;

	if (export_idx
	  && export_symbols[export_idx - 1].name
	  && !strcmp(export_symbols[export_idx - 1].name, export_symbols[export_idx].name))
	{
	    fprintf(stderr, "duplicate export: %s\n", export_symbols[export_idx - 1].name);
	    err = kErrorDuplicate;
	    goto finish;
	}

	for (import_idx = 0; import_idx < export_symbols[export_idx].list_count; import_idx++)
	{

	    if (export_symbols[export_idx].list != &export_symbols[export_idx])
	    {
		printf("wild: %s, %s\n", export_symbols[export_idx].name, 
			export_symbols[export_idx].list[import_idx].name);
	    }
	    if (CPU_ARCH_ABI64 & target_arch->cputype)
	    {
		struct nlist_64 nl;

		nl.n_sect  = 0;
                nl.n_desc  = 0;
		nl.n_un.n_strx = strx;
		strx += export_symbols[export_idx].list[import_idx].name_len;
                
                if (export_symbols[export_idx].flags & kObsolete) {
                    nl.n_desc |= N_DESC_DISCARDED;
                }

		if (export_symbols[export_idx].list[import_idx].indirect)
		{
		    nl.n_type  = N_INDR | N_EXT;
		    nl.n_value = strx;
		    strx += export_symbols[export_idx].list[import_idx].indirect_len;
		}
		else
		{
		    nl.n_type  = N_UNDF | N_EXT;
		    nl.n_value = 0;
		}

		if (target_arch->byteorder != host_arch->byteorder)
		    swap_nlist_64(&nl, 1, target_arch->byteorder);

		err = writeFile(fd, &nl, sizeof(nl));
	    }
	    else
	    {
		struct nlist nl;

		nl.n_sect  = 0;
		nl.n_desc  = 0;
		nl.n_un.n_strx = strx;
		strx += export_symbols[export_idx].list[import_idx].name_len;
 
                if (export_symbols[export_idx].flags & kObsolete) {
                    nl.n_desc |= N_DESC_DISCARDED;
                }

		if (export_symbols[export_idx].list[import_idx].indirect)
		{
		    nl.n_type  = N_INDR | N_EXT;
		    nl.n_value = strx;
		    strx += export_symbols[export_idx].list[import_idx].indirect_len;
		}
		else
		{
		    nl.n_type  = N_UNDF | N_EXT;
		    nl.n_value = 0;
		}

		if (target_arch->byteorder != host_arch->byteorder)
		    swap_nlist(&nl, 1, target_arch->byteorder);

		err = writeFile(fd, &nl, sizeof(nl));
	    }
	}

	if (kErrorNone != err)
	    goto finish;
    }

    strx = sizeof(uint32_t);
    err = writeFile(fd, &zero, strx);
    if (kErrorNone != err)
	goto finish;

    for (export_idx = 0; export_idx < num_export_syms; export_idx++)
    {
	if (!export_symbols[export_idx].name)
	    continue;

	for (import_idx = 0; import_idx < export_symbols[export_idx].list_count; import_idx++)
	{
	    err = writeFile(fd, export_symbols[export_idx].list[import_idx].name, 
			export_symbols[export_idx].list[import_idx].name_len);
	    if (kErrorNone != err)
		goto finish;
	    if (export_symbols[export_idx].list[import_idx].indirect)
	    {
		err = writeFile(fd, export_symbols[export_idx].list[import_idx].indirect, 
			    export_symbols[export_idx].list[import_idx].indirect_len);
		if (kErrorNone != err)
		    goto finish;
	    }
	}
    }

    err = writeFile(fd, &zero, strtabpad - strtabsize);
    if (kErrorNone != err)
	goto finish;
	
    close(fd);


finish:
    for (filenum = 0; filenum < num_files; filenum++) {
        // unmap file
        if (files[filenum].mapped_size)
        {
            munmap((caddr_t)files[filenum].mapped, files[filenum].mapped_size);
            files[filenum].mapped     = 0;
            files[filenum].mapped_size = 0;
        }

    }

    if (kErrorNone != err)
    {
	if (output_name)
	    unlink(output_name);
        exit(1);
    }
    else
        exit(0);
    return(0);
}
Ejemplo n.º 9
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;
}