File:  [Apple Darwin 0.x] / objc / objcopt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:13:58 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin01
Darwin 0.1 In-kernel Objective-C runtime

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the 'License').  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License."
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mach-o/loader.h>
#include <objc/objc-runtime.h>
#include <objc/NXString.h>
#include <sys/types.h>
#include "Protocol.h"

/* These are in libc in later updates */
void
swap_mach_header(
struct mach_header *mh,
enum NXByteOrder target_byte_order)
{
	mh->magic = NXSwapLong(mh->magic);
	mh->cputype = NXSwapLong(mh->cputype);
	mh->cpusubtype = NXSwapLong(mh->cpusubtype);
	mh->filetype = NXSwapLong(mh->filetype);
	mh->ncmds = NXSwapLong(mh->ncmds);
	mh->sizeofcmds = NXSwapLong(mh->sizeofcmds);
	mh->flags = NXSwapLong(mh->flags);
}

void
swap_load_command(
struct load_command *lc,
enum NXByteOrder target_byte_order)
{
	lc->cmd = NXSwapLong(lc->cmd);
	lc->cmdsize = NXSwapLong(lc->cmdsize);
}

void
swap_segment_command(
struct segment_command *sg,
enum NXByteOrder target_byte_order)
{
	/* segname[16] */
	sg->cmd = NXSwapLong(sg->cmd);
	sg->cmdsize = NXSwapLong(sg->cmdsize);
	sg->vmaddr = NXSwapLong(sg->vmaddr);
	sg->vmsize = NXSwapLong(sg->vmsize);
	sg->fileoff = NXSwapLong(sg->fileoff);
	sg->filesize = NXSwapLong(sg->filesize);
	sg->maxprot = NXSwapLong(sg->maxprot);
	sg->initprot = NXSwapLong(sg->initprot);
	sg->nsects = NXSwapLong(sg->nsects);
	sg->flags = NXSwapLong(sg->flags);
}

void
swap_section(
struct section *s,
unsigned long nsects,
enum NXByteOrder target_byte_order)
{
    unsigned long i;

	for(i = 0; i < nsects; i++){
	    /* sectname[16] */
	    /* segname[16] */
	    s[i].addr = NXSwapLong(s[i].addr);
	    s[i].size = NXSwapLong(s[i].size);
	    s[i].offset = NXSwapLong(s[i].offset);
	    s[i].align = NXSwapLong(s[i].align);
	    s[i].reloff = NXSwapLong(s[i].reloff);
	    s[i].nreloc = NXSwapLong(s[i].nreloc);
	    s[i].flags = NXSwapLong(s[i].flags);
	    s[i].reserved1 = NXSwapLong(s[i].reserved1);
	    s[i].reserved2 = NXSwapLong(s[i].reserved2);
	}
}

void
swap_symtab_command(
struct symtab_command *st,
enum NXByteOrder target_byte_order)
{
	st->cmd = NXSwapLong(st->cmd);
	st->cmdsize = NXSwapLong(st->cmdsize);
	st->symoff = NXSwapLong(st->symoff);
	st->nsyms = NXSwapLong(st->nsyms);
	st->stroff = NXSwapLong(st->stroff);
	st->strsize = NXSwapLong(st->strsize);
}

void
swap_symseg_command(
struct symseg_command *ss,
enum NXByteOrder target_byte_order)
{
	ss->cmd = NXSwapLong(ss->cmd);
	ss->cmdsize = NXSwapLong(ss->cmdsize);
	ss->offset = NXSwapLong(ss->offset);
	ss->size = NXSwapLong(ss->size);
}

/*
 * For system call errors the error messages allways contains
 * sys_errlist[errno] as part of the message.
 */
extern char *sys_errlist[];
extern int errno;

/* Name of this program for error messages (argv[0]) */
char *progname;

extern void _sel_writeHashTable(
	int start_addr, 
	char *myselectorstraddr, 
	char *shlibselectorstraddr,
	void **stuff, 
	int *stuffsize
);

/*
 * Declarations for the static routines in this file.
 */
static void usage();

static Module get_objc(
	long fd, 
	char *filename, 
	struct section *objcsects, 
	int nsects
);
static void print_method_list(
	struct objc_method_list *mlist_before_reloc, 
	struct section *firstobjcsect, 
	int nsects
);
static void print_method_list2(
	struct objc_method_description_list *mlist_before_reloc, 
	struct section *firstobjcsect, 
	int nsects
);
static void getObjcSections(
	struct mach_header *mh,
	struct load_command *lc, 
	struct section **objcsects, 
	int *nsects
);
static void readObjcData(
	long fd,
	char *filename,
    	struct section *objcsects, 
	int nsects
);
static void swapObjcData(
    	struct section *objcsects, 
	int nsects
);
static void swap_objc_modules(
	struct objc_module *modules,
	unsigned long size
);
static void swap_objc_symtabs(
	struct objc_symtab *symtabs,
	unsigned long size
);
static void swap_objc_classes(
	struct objc_class *classes,
	unsigned long size
);
static void swap_objc_categories(
	struct objc_category *categories,
	unsigned long size
);
static void swap_objc_method_lists(
	struct objc_method_list *method_lists,
	unsigned long size
);
static void swap_objc_protocols(
	Protocol *protocols,
	unsigned long size
);
static void swap_objc_ivar_lists(
	struct objc_ivar_list *ivar_lists,
	unsigned long size
);
static void swap_objc_protocol_lists(
	struct objc_protocol_list *protocol_lists,
	unsigned long size
);
static void swap_objc_refs(
	unsigned long *refs,
	unsigned long size
);
static void swap_string_objects(
	NXConstantString *s,
	unsigned long size
);
static void swap_objc_method_description_lists(
	struct objc_method_description_list *mdls,
	unsigned long size
);
struct _hashEntry {
    struct _hashEntry *next;
    char *sel;
};
static void swap_hashEntries(
	struct _hashEntry *_hashEntries,
	unsigned long size
);
static void *getObjcData(
    	struct section *objcsects, 
	int nsects,
	const void *addr
);
static struct section *getObjcSection(
    	struct section *objcsects, 
	int nsects,
	char *name	
);

int swapped = 0;

void
main(argc, argv)
int argc;
char *argv[];
{
	long fd;
	char *filename;
	struct mach_header mh;
	struct load_command *lcp;

	progname = argv[0];

	if(argc == 1) {
	    fprintf(stderr, "%s: At least one file must be specified\n",
		    progname);
	    usage();
	    exit(1);
	}
	else if (argc == 2)
	  filename = argv[1];
	else
	  {
	    usage();
	    exit(1);
	  }
	
	fd = open(filename, O_RDONLY);
	if(fd < 0){
		fprintf(stderr, "%s : Can't open %s (%s)\n", progname,
			filename, sys_errlist[errno]);
	}
	lseek(fd, 0, 0);
	if(read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)){
	    fprintf(stderr, "%s : Can't read mach header of %s (%s)\n",
			progname, filename, sys_errlist[errno]);
	    return;
	}
	if(mh.magic == MH_MAGIC){
		if((lcp = (struct load_command *)malloc(mh.sizeofcmds))
		    == (struct load_command *)0){
		    fprintf(stderr, "%s : Ran out of memory (%s)\n",
			    progname, sys_errlist[errno]);
		    exit(1);
		}
		if(read(fd, (char *)lcp, mh.sizeofcmds) != mh.sizeofcmds){
		    fprintf(stderr,"%s : Can't read load commands of %s (%s)\n",
			       progname, filename, sys_errlist[errno]);
		    lcp = (struct load_command *)0;
		}
	}
	else if(mh.magic == NXSwapLong(MH_MAGIC)){
		if((lcp = (struct load_command *)
				malloc(NXSwapLong(mh.sizeofcmds)))
		    		== (struct load_command *)0){
		    fprintf(stderr, "%s : Ran out of memory (%s)\n",
			    progname, sys_errlist[errno]);
		    exit(1);
		}
		if(read(fd, (char *)lcp, NXSwapLong(mh.sizeofcmds)) !=
		   NXSwapLong(mh.sizeofcmds)){
		    fprintf(stderr,"%s : Can't read load commands of %s (%s)\n",
			       progname, filename, sys_errlist[errno]);
		    lcp = (struct load_command *)0;
		}
	}

	{
	struct section *firstobjcsect;
	int nsects, size;
	long vm_hashaddr;
	void *table; 
	struct section *sel, *tmp;
	char *selectors, tempfilename[] = "objcoptXXXXXX";

	getObjcSections(&mh, lcp, &firstobjcsect, &nsects);
	get_objc(fd, filename, firstobjcsect, nsects);

	if (strcmp(firstobjcsect[nsects-1].sectname, "__runtime_setup") == 0)
		// we are doing a `replace'
		vm_hashaddr = firstobjcsect[nsects-1].addr;
	else  
		vm_hashaddr = round(firstobjcsect[nsects-1].addr + 
			    	firstobjcsect[nsects-1].size, sizeof(long));

	sel = getObjcSection(firstobjcsect, nsects, "__meth_var_names");
	
	tmp = getObjcSection(firstobjcsect, nsects, "__selector_strs");
	
	if (sel && tmp)
	  {
	    fprintf (stderr,
		     "Cannot objcopt mixture of new and old strings\n");
	    exit (1);
	  }
	
	if (!sel)
	  sel = tmp;	// Use old-style strings
	
	selectors = (char *)sel->reserved1;

	_sel_writeHashTable(vm_hashaddr, (char *)selectors, (char *)sel->addr,
				 &table, &size);
	if(swapped)
	    swap_hashEntries((struct _hashEntry *)table, size);

	mktemp(tempfilename);
	add_objc_runtime_setup(filename,tempfilename,table, size);

	close(fd);
	unlink(filename);
	if (rename(tempfilename, filename) == -1) {
		fprintf(stderr, "%s : Cannot rename temporary file from: "
				"%s to %s\n", progname, tempfilename, filename);
		exit(1);
	}
	}

	exit(0);
}

static void getObjcSections(
	struct mach_header *mh,
	struct load_command *lc, 
	struct section **objcsects, 
	int *nsects
)
{
	int i,j;
    	struct segment_command *sg;
	struct section *s;
    	struct load_command l, *initlc;

	swapped = mh->magic == NXSwapLong(MH_MAGIC);
	if(swapped)
	    swap_mach_header(mh, NXHostByteOrder());
	initlc = lc;

	for(i = 0 ; i < mh->ncmds; i++){
	    l = *lc;
	    if(swapped)
		swap_load_command(&l, NXHostByteOrder());
	    if(l.cmdsize % sizeof(long) != 0)
		printf("load command %d size not a multiple of sizeof(long)\n",
		       i);
	    if((char *)lc + l.cmdsize > (char *)initlc + mh->sizeofcmds)
		printf("load command %d extends past end of load commands\n",i);
	    if(l.cmd == LC_SEGMENT){
		sg = (struct segment_command *)lc;
		if(swapped)
		    swap_segment_command(sg, NXHostByteOrder());
		if(mh->filetype == MH_OBJECT ||
		   strcmp(sg->segname, SEG_OBJC) == 0){

		    s = (struct section *)
			((char *)sg + sizeof(struct segment_command));

		    *objcsects = s;
		    *nsects = sg->nsects;

		    for(j = 0 ; j < sg->nsects ; j++){
			if(swapped)
			    swap_section(s, 1, NXHostByteOrder());
			if((char *)s + sizeof(struct section) >
			   (char *)initlc + mh->sizeofcmds){
			    printf("section structure command extends past end "
				   "of load commands\n");
			}
			if((char *)s + sizeof(struct section) >
			   (char *)initlc + mh->sizeofcmds)
			    break;
			s++;
		    }
		}
	    }
	    if(l.cmdsize <= 0){
		printf("load command %d size negative or zero (can't "
		       "advance to other load commands)\n", i);
		break;
	    }
	    lc = (struct load_command *)((char *)lc + l.cmdsize);
	    if((char *)lc > (char *)initlc + mh->sizeofcmds)
		break;
	}
	if((char *)initlc + mh->sizeofcmds != (char *)lc)
	    printf("Inconsistant mh_sizeofcmds\n");
}

static void readObjcData(
	long fd,
	char *filename,
    	struct section *objcsects, 
	int nsects
)
{
	int i;

	for (i = 0; i < nsects; i++) {

		struct section *s;

		s = objcsects + i;

		if (s->size > 0) {
	    	  if((s->reserved1 = (long)malloc(s->size)) == 0) {
		    fprintf(stderr, "%s : Ran out of memory (%s)\n", 
			progname, sys_errlist[errno]);
		    exit(1);
	          }
	          lseek(fd, s->offset, 0);
	          if((read(fd, s->reserved1, s->size)) != s->size){
		    fprintf(stderr, "%s : Can't read modules of %s (%s)\n",
		    	progname, filename, sys_errlist[errno]);
		    free((void *)s->reserved1);
		    return;
	          }
		}
	}
}

struct objc_protocol
{
    @defs(Protocol)
};

struct objc_string_object
{
    @defs(NXConstantString)
};

static void swapObjcData(
    	struct section *objcsects, 
	int nsects
)
{
	int i, categories_size = 0, protocols_size = 0;
	struct objc_category *categories = NULL;
	struct objc_protocol *protocols = NULL;
	struct section *s, *cat_inst = NULL, *cat_cls = NULL;
	struct objc_method_list *method_list;
	struct objc_protocol_list *protocol_list;
	struct objc_method_description_list *mdl;

	for (i = 0; i < nsects; i++) {

		s = objcsects + i;
		if(strncmp(s->sectname, "__class", 16) == 0 ||
		   strncmp(s->sectname, "__meta_class", 16) == 0){
		    swap_objc_classes((struct objc_class *)s->reserved1,
				      s->size);
		}
		else if(strncmp(s->sectname, "__string_object", 16) == 0){
		    swap_string_objects((NXConstantString *)s->reserved1,
				        s->size);
		}
		else if(strncmp(s->sectname, "__protocol", 16) == 0){
		    protocols = (struct objc_protocol *)s->reserved1;
		    protocols_size = s->size;
		    swap_objc_protocols((Protocol *)s->reserved1,
				        s->size);
		}
		else if(strncmp(s->sectname, "__cat_cls_meth", 16) == 0){
		    /* handled special below */
		    cat_cls = s;
		}
		else if(strncmp(s->sectname, "__cat_inst_meth", 16) == 0){
		    /* handled special below */
		    cat_inst = s;
		}
		else if(strncmp(s->sectname, "__cls_meth", 16) == 0 ||
		        strncmp(s->sectname, "__inst_meth", 16) == 0){
		    swap_objc_method_lists((struct objc_method_list *)
					   s->reserved1, s->size);
		}
		else if(strncmp(s->sectname, "__message_refs", 16) == 0 ||
		        strncmp(s->sectname, "__selector_refs", 16) == 0 ||
			strncmp(s->sectname, "__cls_refs", 16) == 0){
		    swap_objc_refs((unsigned long *)s->reserved1, s->size);
		}
		else if(strncmp(s->sectname, "__class_names", 16) == 0 ||
			strncmp(s->sectname, "__meth_var_names", 16) == 0 ||
			strncmp(s->sectname, "__meth_var_types", 16) == 0 ||
		        strncmp(s->sectname, "__selector_strs", 16) == 0){
			; /* character strings, no swapping */
		}
		else if(strncmp(s->sectname, "__module_info", 16) == 0){
		    swap_objc_modules((struct objc_module *)s->reserved1,
				      s->size);
		}
		else if(strncmp(s->sectname, "__symbols", 16) == 0){
		    swap_objc_symtabs((struct objc_symtab *)s->reserved1,
				      s->size);
		}
		else if(strncmp(s->sectname, "__category", 16) == 0){
		    categories = (struct objc_category *)s->reserved1;
		    categories_size = s->size;
		    swap_objc_categories((struct objc_category *)s->reserved1,
				      s->size);
		}
		else if(strncmp(s->sectname, "__class_vars", 16) == 0 ||
			strncmp(s->sectname, "__instance_vars", 16) == 0){
		    swap_objc_ivar_lists((struct objc_ivar_list *)s->reserved1,
				         s->size);
		}
		else if(strncmp(s->sectname, "__runtime_setup", 16) == 0){
		    ; /* do nothing it will be tossed */
		}
                else if(strncmp(s->sectname, "__cstring_object", 16)) {
                   ; /* do nothing */
                }
                else if(strncmp(s->sectname, "__sel_fixup", 16)) {
                   ; /* do nothing */
                }
		else{
		    fprintf(stderr, "%s : unknown __OBJC section: %s\n",
			    progname, s->sectname);
		    exit(1);
		}
	}

	for (i = 0; i < categories_size; i += sizeof(struct objc_category)){
	    if(categories->instance_methods != 0){
		method_list = (struct objc_method_list *)
				(cat_inst->reserved1 + 
				((unsigned long)categories->instance_methods -
				(unsigned long)cat_inst->addr));
		swap_objc_method_lists(method_list,
		    sizeof(struct objc_method_list) -
			   sizeof(struct objc_method));
	    }

	    if(categories->class_methods != 0){
		method_list = (struct objc_method_list *)
				(cat_cls->reserved1 + 
				((unsigned long)categories->class_methods -
				(unsigned long)cat_cls->addr));
		swap_objc_method_lists(method_list,
		    sizeof(struct objc_method_list) -
		    sizeof(struct objc_method));
	    }

	    if(categories->protocols != 0){
		protocol_list = (struct objc_protocol_list *)
				(cat_cls->reserved1 + 
				((unsigned long)categories->protocols -
				(unsigned long)cat_cls->addr));
		swap_objc_protocol_lists(protocol_list, 
					 sizeof(struct objc_protocol_list) -
					 sizeof(struct objc_protocol *));
	    }
	    categories++;
	}
	for (i = 0; i < protocols_size; i += sizeof(struct objc_protocol)){
	    if(protocols->instance_methods != 0){
		mdl = (struct objc_method_description_list *)
			    (cat_inst->reserved1 + 
			    ((unsigned long)protocols->instance_methods -
			    (unsigned long)cat_inst->addr));
		swap_objc_method_description_lists(mdl,
			sizeof(struct objc_method_description_list) -
			sizeof(struct objc_method_description));
	    }

	    if(protocols->class_methods != 0){
		mdl = (struct objc_method_description_list *)
			    (cat_cls->reserved1 + 
			    ((unsigned long)protocols->class_methods -
			    (unsigned long)cat_cls->addr));
		swap_objc_method_description_lists(mdl,
			sizeof(struct objc_method_description_list) -
			sizeof(struct objc_method_description));
	    }
	    protocols++;
	}
}

static
void
swap_objc_module(
struct objc_module *module,
enum NXByteOrder target_byte_order)
{
	module->version = NXSwapLong(module->version);
	module->size = NXSwapLong(module->size);
	module->name = (char *) NXSwapLong((long)module->name);
	module->symtab = (Symtab) NXSwapLong((long)module->symtab);
}

static
void
swap_objc_symtab(
struct objc_symtab *symtab,
enum NXByteOrder target_byte_order)
{
	symtab->sel_ref_cnt = NXSwapLong(symtab->sel_ref_cnt);
	symtab->refs = (SEL *) NXSwapLong((long)symtab->refs);
	symtab->cls_def_cnt = NXSwapShort(symtab->cls_def_cnt);
	symtab->cat_def_cnt = NXSwapShort(symtab->cat_def_cnt);
}

static
void
swap_objc_class(
struct objc_class *objc_class,
enum NXByteOrder target_byte_order)
{
	objc_class->isa = (struct objc_class *)
		NXSwapLong((long)objc_class->isa);
	objc_class->super_class = (struct objc_class *)
		NXSwapLong((long)objc_class->super_class);
	objc_class->name = (const char *)
		NXSwapLong((long)objc_class->name);		
	objc_class->version =
		NXSwapLong(objc_class->version);
	objc_class->info =
		NXSwapLong(objc_class->info);
	objc_class->instance_size =
		NXSwapLong(objc_class->instance_size);
	objc_class->ivars = (struct objc_ivar_list *)
		NXSwapLong((long)objc_class->ivars);
	objc_class->methods = (struct objc_method_list *)
		NXSwapLong((long)objc_class->methods);
	objc_class->cache = (struct objc_cache *)
		NXSwapLong((long)objc_class->cache);
	objc_class->protocols = (struct objc_protocol_list *)
		NXSwapLong((long)objc_class->protocols);
}

static
void
swap_objc_category(
struct objc_category *objc_category,
enum NXByteOrder target_byte_order)
{
	objc_category->category_name = (char *)
		NXSwapLong((long)objc_category->category_name);
	objc_category->class_name = (char *)
		NXSwapLong((long)objc_category->class_name);
	objc_category->instance_methods = (struct objc_method_list *)
		NXSwapLong((long)objc_category->instance_methods);
	objc_category->class_methods = (struct objc_method_list *)
		NXSwapLong((long)objc_category->class_methods);
	objc_category->protocols = (struct objc_protocol_list *)
		NXSwapLong((long)objc_category->protocols);
}

static
void
swap_objc_ivar_list(
struct objc_ivar_list *objc_ivar_list,
enum NXByteOrder target_byte_order)
{
	objc_ivar_list->ivar_count = NXSwapLong(objc_ivar_list->ivar_count);
}

static
void
swap_objc_ivar(
struct objc_ivar *objc_ivar,
enum NXByteOrder target_byte_order)
{
	objc_ivar->ivar_name = (char *)
		NXSwapLong((long)objc_ivar->ivar_name);
	objc_ivar->ivar_type = (char *)
		NXSwapLong((long)objc_ivar->ivar_type);
	objc_ivar->ivar_offset = 
		NXSwapLong(objc_ivar->ivar_offset);
}

static
void
swap_objc_method_list(
struct objc_method_list *method_list,
enum NXByteOrder target_byte_order)
{
	method_list->method_next = (struct objc_method_list *)
		NXSwapLong((long)method_list->method_next);
	method_list->method_count = 
		NXSwapLong(method_list->method_count);
}

static
void
swap_objc_method(
struct objc_method *method,
enum NXByteOrder target_byte_order)
{
	method->method_name = (SEL)
		NXSwapLong((long)method->method_name);
	method->method_types = (char *)
		NXSwapLong((long)method->method_types);
	method->method_imp = (IMP)
		NXSwapLong((long)method->method_imp);
}

static
void
swap_objc_protocol_list(
struct objc_protocol_list *protocol_list,
enum NXByteOrder target_byte_order)
{
	protocol_list->next = (struct objc_protocol_list *)
		NXSwapLong((long)protocol_list->next);
	protocol_list->count =
		NXSwapLong(protocol_list->count);
}

static
void
swap_objc_protocol(
Protocol *p,
enum NXByteOrder target_byte_order)
{
    struct objc_protocol *protocol;

	protocol = (struct objc_protocol *)p;

	protocol->isa = (struct objc_class *)
		NXSwapLong((long)protocol->isa);
	protocol->protocol_name = (char *)
		NXSwapLong((long)protocol->protocol_name);
	protocol->protocol_list = (struct objc_protocol_list *)
		NXSwapLong((long)protocol->protocol_list);
	protocol->instance_methods = (struct objc_method_description_list *)
		NXSwapLong((long)protocol->instance_methods);
	protocol->class_methods = (struct objc_method_description_list *)
		NXSwapLong((long)protocol->class_methods);

}

static
void
swap_objc_method_description_list(
struct objc_method_description_list *mdl,
enum NXByteOrder target_byte_order)
{
	mdl->count = NXSwapLong(mdl->count);
}

static
void
swap_objc_method_description(
struct objc_method_description *md,
enum NXByteOrder target_byte_order)
{
	md->name = (SEL)NXSwapLong((long)md->name);
	md->types = (char *)NXSwapLong((long)md->types);
}

void
swap_string_object(
NXConstantString *p,
enum NXByteOrder target_byte_order)
{
    struct objc_string_object *string_object;

	string_object = (struct objc_string_object *)p;

	string_object->isa = (struct objc_class *)
		NXSwapLong((long)string_object->isa);
	string_object->characters = (char *)
		NXSwapLong((long)string_object->characters);
	string_object->_length =
		NXSwapLong(string_object->_length);
}

static
void
swap_hashEntry(
struct _hashEntry *_hashEntry,
enum NXByteOrder target_byte_order)
{
	_hashEntry->next = (struct _hashEntry *)
		NXSwapLong((long)_hashEntry->next);
	_hashEntry->sel = (char *)
		NXSwapLong((long)_hashEntry->sel);
}

static void swap_objc_modules(
	struct objc_module *modules,
	unsigned long size
)
{
	int i, j;

	for (i = 0, j = 0; i < size; i += sizeof(struct objc_module), j++)
		swap_objc_module(modules + j, NXHostByteOrder());
}

static void swap_objc_symtabs(
	struct objc_symtab *symtabs,
	unsigned long size
)
{
	int i, j;
	struct objc_symtab *symtab;

	symtab = symtabs;
	while ((unsigned long)symtab - (unsigned long)symtabs < size){
		swap_objc_symtab(symtab, NXHostByteOrder());
		for(j = 0; j < symtab->cls_def_cnt; j++){
		    symtab->defs[j] = (struct objc_class *)
			NXSwapLong((long)symtab->defs[j]);
		}
		for(j = 0; j < symtab->cat_def_cnt; j++){
		    symtab->defs[j + symtab->cls_def_cnt] =
			(struct objc_class *)
			NXSwapLong((long)symtab->defs[j + symtab->cls_def_cnt]);
		}
		symtab = (struct objc_symtab *)
		    (&(symtab->defs[symtab->cls_def_cnt +
				    symtab->cat_def_cnt]));
	}
}

static void swap_objc_classes(
	struct objc_class *classes,
	unsigned long size
)
{
	int i, j;

	for (i = 0, j = 0; i < size; i += sizeof(struct objc_class), j++)
		swap_objc_class(classes + j, NXHostByteOrder());
}

static void swap_objc_categories(
	struct objc_category *categories,
	unsigned long size
)
{
	int i, j;

	for (i = 0, j = 0; i < size; i += sizeof(struct objc_category), j++)
		swap_objc_category(categories + j, NXHostByteOrder());
}

static void swap_objc_method_lists(
	struct objc_method_list *method_lists,
	unsigned long size
)
{
	int i, j;
	struct objc_method_list *method_list;

	method_list = method_lists;
	while ((unsigned long)method_list - (unsigned long)method_lists < size){
		swap_objc_method_list(method_list, NXHostByteOrder());
		for (j = 0; j < method_list->method_count; j++){
		    swap_objc_method(&(method_list->method_list[j]),
				     NXHostByteOrder());
		}
		method_list = (struct objc_method_list *)
		    (&(method_list->method_list[method_list->method_count]));
	}
}

static void swap_objc_protocols(
	Protocol *protocols,
	unsigned long size
)
{
	int i, j;

	for (i = 0, j = 0; i < size; i += sizeof(struct objc_protocol), j++)
		swap_objc_protocol(protocols + j, NXHostByteOrder());
}

static void swap_objc_ivar_lists(
	struct objc_ivar_list *ivar_lists,
	unsigned long size
)
{
	int i, j;
	struct objc_ivar_list *ivar_list;

	ivar_list = ivar_lists;
	while ((unsigned long)ivar_list - (unsigned long)ivar_lists < size){
		swap_objc_ivar_list(ivar_list, NXHostByteOrder());
		for (j = 0; j < ivar_list->ivar_count; j++){
		    swap_objc_ivar(&(ivar_list->ivar_list[j]),
				     NXHostByteOrder());
		}
		ivar_list = (struct objc_ivar_list *)
		    (&(ivar_list->ivar_list[ivar_list->ivar_count]));
	}
}

static void swap_objc_protocol_lists(
	struct objc_protocol_list *protocol_lists,
	unsigned long size
)
{
	int i, j;
	struct objc_protocol_list *protocol_list;

	protocol_list = protocol_lists;
	while ((unsigned long)protocol_list -
	       (unsigned long)protocol_lists < size){
		swap_objc_protocol_list(protocol_list, NXHostByteOrder());
		for (j = 0; j < protocol_list->count; j++){
		    protocol_list->list[j] = (Protocol *)
			NXSwapLong((long)(protocol_list->list[j]));
		}
		protocol_list = (struct objc_protocol_list *)
		    (&(protocol_list->list[protocol_list->count]));
	}
}

static void swap_objc_method_description_lists(
	struct objc_method_description_list *mdls,
	unsigned long size
)
{
	int i, j;
	struct objc_method_description_list *mdl;

	mdl = mdls;
	while ((unsigned long)mdl - (unsigned long)mdls < size){
		swap_objc_method_description_list(mdl, NXHostByteOrder());
		for (j = 0; j < mdl->count; j++){
		    swap_objc_method_description( &(mdl->list[j]),
				     		 NXHostByteOrder());
		}
		mdl = (struct objc_method_description_list *)
			(&(mdl->list[mdl->count]));
	}
}

static void *getObjcData(
    	struct section *objcsects, 
	int nsects,
	const void *addr
)
{
	int i;

	if (addr == 0)
		return 0;

	for (i = 0; i < nsects; i++) {
		struct section *s;

		s = objcsects + i;
		if (((long)addr >= s->addr) && 
			((long)addr < (s->addr + s->size)))
		  return (void *)(s->reserved1 + ((long)addr - s->addr));
	}
    	fprintf(stderr, "%s : Could not `getObjcData'\n", progname);
	exit(1);
}

static void swap_objc_refs(
	unsigned long *refs,
	unsigned long size
)
{
	int i,j;

	for (i = 0, j = 0; i < size; i += sizeof(unsigned long), j++)
		refs[j] = NXSwapLong(refs[j]);
}

static struct section *getObjcSection(
    	struct section *objcsects, 
	int nsects,
	char *name	
)
{
	int i;

	for (i = 0; i < nsects; i++) {
		struct section *s;

		s = objcsects + i;
		if (strncmp(s->sectname,name,16) == 0)
		  return s;
	}
        return 0;
}

static void swap_string_objects(
	NXConstantString *s,
	unsigned long size
)
{
	int i, j;

	for (i = 0, j = 0; i < size; i += sizeof(struct objc_string_object), j++)
		swap_string_object(s + j, NXHostByteOrder());
}

static void swap_hashEntries(
	struct _hashEntry *_hashEntries,
	unsigned long size
)
{
	int i, j;
	enum NXByteOrder target_byte_order;

	target_byte_order = NXHostByteOrder() == NX_BigEndian ?
			    NX_LittleEndian : NX_BigEndian;

	for (i = 0, j = 0; i < size; i += sizeof(struct _hashEntry), j++)
		swap_hashEntry(_hashEntries + j, target_byte_order);
}

/*
 * Print the objc segment.
 */
static
struct objc_module *
get_objc(fd, filename, firstobjcsect, nsects)
long fd;
char *filename;
struct section *firstobjcsect;
int nsects;
{
	long i, j;
	struct section *modsect, *msgsect, *selsect, *protosect;
	struct objc_module *modules, *m;
	struct objc_symtab *t;

	readObjcData(fd, filename, firstobjcsect, nsects);
	if(swapped)
	    swapObjcData(firstobjcsect, nsects);

	modsect = getObjcSection(firstobjcsect, nsects, "__module_info");
	msgsect = getObjcSection(firstobjcsect, nsects, "__message_refs");
  	if (msgsect) {
		int i, cnt = msgsect->size/sizeof(SEL);
   		SEL *sels = (SEL *)msgsect->reserved1;

		/* overwrite the string with a unique identifier */
		for (i = 0; i < cnt; i++) 
			sels[i] = (SEL)sel_registerName(
   				getObjcData(firstobjcsect, nsects,
						sels[i]));
	}
	selsect = getObjcSection(firstobjcsect, nsects, "__selector_refs");
  	if (selsect) {
		int i, cnt = selsect->size/sizeof(SEL);
   		SEL *sels = (SEL *)selsect->reserved1;

		/* overwrite the string with a unique identifier */
		for (i = 0; i < cnt; i++) 
			sels[i] = (SEL)sel_registerName(
   				getObjcData(firstobjcsect, nsects,
						sels[i]));
	}
	modules = (Module)modsect->reserved1;

	for(m = modules ;
	    (char *)m < (char *)modules + modsect->size;
	    m = (struct objc_module *)((char *)m + m->size) ){

		/* relocate fields in module structure */

		m->name = (char *)getObjcData(firstobjcsect, nsects, 
						m->name);
		m->symtab = t = (Symtab)getObjcData(firstobjcsect, nsects, 
						m->symtab);
						
		if (t) {

		  /* Simulate map! */
		  if (m->version == 1) { 
		    int i, cnt = m->symtab->sel_ref_cnt;
   		    SEL *sels = (SEL *)getObjcData(firstobjcsect, nsects,
						m->symtab->refs);

		    /* overwrite the string with a unique identifier */
		    for (i = 0; i < cnt; i++) 
			  sels[i] = (SEL)sel_registerName(
   				getObjcData(firstobjcsect, nsects,
						sels[i]));
		  }

		  for(i = 0; i < t->cls_def_cnt; i++){

    			struct objc_class *objc_class;

			t->defs[i] = objc_class = 
   				(Class)getObjcData(firstobjcsect, nsects,
						t->defs[i]);
print_objc_class:
			/* relocate class structure */

			if(CLS_GETINFO(objc_class, CLS_META)){
				objc_class->isa = (Class)getObjcData(
					firstobjcsect, nsects, objc_class->isa);
			}

			objc_class->super_class = (Class)getObjcData(
						firstobjcsect, nsects, 
						objc_class->super_class);

			objc_class->name = (char *)getObjcData(
						firstobjcsect, nsects, 
						objc_class->name);

			if (objc_class->ivars) {
    				struct objc_ivar_list *ilist;
    				struct objc_ivar *ivar;

				objc_class->ivars = ilist = 
					(struct objc_ivar_list *)getObjcData(
						firstobjcsect, nsects, 
						objc_class->ivars);

				ivar = ilist->ivar_list;
				for(j = 0; j < ilist->ivar_count; j++, ivar++){
					ivar->ivar_name= (char *)getObjcData(
						firstobjcsect, nsects, 
						ivar->ivar_name);

					ivar->ivar_type= (char *)getObjcData(
						firstobjcsect, nsects, 
						ivar->ivar_type);
				}
			}

			if (objc_class->methods) {
				print_method_list(objc_class->methods, 
						firstobjcsect, nsects);
			}

			if(CLS_GETINFO(objc_class, CLS_CLASS)){
			    objc_class->isa = objc_class = 
   					(Class)getObjcData(
						firstobjcsect, nsects,
						objc_class->isa);
			    goto print_objc_class;
			}
		  }

		  for(i = 0; i < t->cat_def_cnt; i++){

    			struct objc_category *objc_category;

			t->defs[i + t->cls_def_cnt] = objc_category = 
   				(Category)getObjcData(firstobjcsect, nsects,
						t->defs[i+t->cls_def_cnt]);

			objc_category->category_name = (char *)getObjcData(
						firstobjcsect, nsects, 
				       		objc_category->category_name);

			objc_category->class_name = (char *)getObjcData(
						firstobjcsect, nsects, 
				       		objc_category->class_name);

			if (objc_category->instance_methods) {
			    print_method_list(objc_category->instance_methods, 
						firstobjcsect, nsects);
			}

			if (objc_category->class_methods) {
			    print_method_list(objc_category->class_methods, 
						firstobjcsect, nsects);
			}
		  }
	        }
	}
	protosect = getObjcSection(firstobjcsect, nsects, "__protocol");
  	if (protosect) {
		int i, cnt = protosect->size/sizeof(Protocol);
		struct proto_template { @defs(Protocol) } *protos;
   		
		protos = (struct proto_template *) protosect->reserved1;

		for (i = 0; i < cnt; i++)
		  {
		    if (protos[i].instance_methods) {
			print_method_list2(protos[i].instance_methods, 
					    firstobjcsect, nsects);
		    }

		    if (protos[i].class_methods) {
			print_method_list2(protos[i].class_methods, 
					    firstobjcsect, nsects);
		    }
		  }
	}
	return modules;
}

static
void
print_method_list(struct objc_method_list *mlist_before_reloc, 
		  struct section *firstobjcsect, 
		  int nsects)
{
    long i;
    struct objc_method *method;
    struct objc_method_list *mlist;

	mlist = (struct objc_method_list *)getObjcData(firstobjcsect, nsects,
				    		mlist_before_reloc);
	method = mlist->method_list;
	for(i = 0; i < mlist->method_count; i++, method++){

	    method->method_name = (SEL)getObjcData(firstobjcsect, nsects, 
		           			method->method_name);

	    method->method_types = (char *)getObjcData(firstobjcsect, nsects, 
		           			method->method_types);

	    method->method_name = 
		(SEL)sel_registerName((STR)method->method_name);

	}
}

static
void
print_method_list2(struct objc_method_description_list *mlist_before_reloc, 
		  struct section *firstobjcsect, 
		  int nsects)
{
    long i;
    struct objc_method_description *method;
    struct objc_method_description_list *mlist;

	mlist = (struct objc_method_description_list *)getObjcData(firstobjcsect, nsects,
				    		mlist_before_reloc);
	method = mlist->list;
	for(i = 0; i < mlist->count; i++, method++){

	    method->name = (SEL)getObjcData(firstobjcsect, nsects, 
		           			method->name);
	    method->name = 
		(SEL)sel_registerName((STR)method->name);

	}
}

/*
 * Print the current usage message.
 */
static
void
usage()
{
	fprintf(stderr,
		"Usage: %s <shlib file>\n",
		progname);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.