2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 // Copyright 1988-1996 NeXT Software, Inc.
26 #if defined(__APPLE__) && defined(__MACH__)
27 #import "objc-private.h"
28 #import <mach-o/ldsyms.h>
29 #import <mach-o/dyld.h>
33 #import <crt_externs.h>
35 /* prototype coming soon to <mach-o/getsect.h> */
36 extern char *getsectdatafromheader(
37 struct mach_header *mhp,
42 /* Returns an array of all the objc headers in the executable
43 * Caller is responsible for freeing.
45 headerType **_getObjcHeaders()
47 const struct mach_header **headers;
48 headers = malloc(sizeof(struct mach_header *) * 2);
49 headers[0] = (const struct mach_header *)_NSGetMachExecuteHeader();
51 return (headerType**)headers;
54 Module _getObjcModules(headerType *head, int *nmodules)
57 void *mods = getsectdatafromheader((headerType *)head,
61 *nmodules = size / sizeof(struct objc_module);
65 SEL *_getObjcMessageRefs(headerType *head, int *nmess)
68 void *refs = getsectdatafromheader ((headerType *)head,
69 SEG_OBJC, "__message_refs", &size);
70 *nmess = size / sizeof(SEL);
74 ProtocolTemplate *_getObjcProtocols(headerType *head, int *nprotos)
77 void *protos = getsectdatafromheader ((headerType *)head,
78 SEG_OBJC, "__protocol", &size);
79 *nprotos = size / sizeof(ProtocolTemplate);
80 return (ProtocolTemplate *)protos;
83 NXConstantStringTemplate *_getObjcStringObjects(headerType *head, int *nstrs)
89 Class *_getObjcClassRefs(headerType *head, int *nclasses)
92 void *classes = getsectdatafromheader ((headerType *)head,
93 SEG_OBJC, "__cls_refs", &size);
94 *nclasses = size / sizeof(Class);
95 return (Class *)classes;
98 /* returns start of all objective-c info and the size of the data */
99 void *_getObjcHeaderData(headerType *head, unsigned *size)
101 struct segment_command *sgp;
104 sgp = (struct segment_command *) ((char *)head + sizeof(headerType));
105 for(i = 0; i < ((headerType *)head)->ncmds; i++){
106 if(sgp->cmd == LC_SEGMENT)
107 if(strncmp(sgp->segname, "__OBJC", sizeof(sgp->segname)) == 0) {
108 *size = sgp->filesize;
111 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
117 static const headerType *_getExecHeader (void)
119 return (const struct mach_header *)_NSGetMachExecuteHeader();
122 const char *_getObjcHeaderName(headerType *header)
124 const headerType *execHeader;
125 const struct fvmlib_command *libCmd, *endOfCmds;
127 #if !defined(NeXT_PDO)
128 extern char ***_NSGetArgv();
129 argv = *_NSGetArgv();
131 extern char **NXArgv;
135 if (header && ((headerType *)header)->filetype == MH_FVMLIB) {
136 execHeader = _getExecHeader();
137 for (libCmd = (const struct fvmlib_command *)(execHeader + 1),
138 endOfCmds = ((void *)libCmd) + execHeader->sizeofcmds;
139 libCmd < endOfCmds; ((void *)libCmd) += libCmd->cmdsize) {
140 if ((libCmd->cmd == LC_LOADFVMLIB) && (libCmd->fvmlib.header_addr
141 == (unsigned long)header)) {
142 return (char *)libCmd
143 + libCmd->fvmlib.name.offset;
148 unsigned long i, n = _dyld_image_count();
149 for( i = 0; i < n ; i++ ) {
150 if ( _dyld_get_image_header(i) == header )
151 return _dyld_get_image_name(i);
157 #elif defined(hpux) || defined(__hpux__)
160 * Objective-C runtime information module.
161 * This module is specific to hp-ux a.out format files.
164 #import <pdo.h> // place where padding_bug would be
166 #include "objc-private.h"
168 OBJC_EXPORT int __argc_value;
169 OBJC_EXPORT char **__argv_value;
171 char **NXArgv = NULL;
173 OBJC_EXPORT unsigned SEG_OBJC_CLASS_START;
174 OBJC_EXPORT unsigned SEG_OBJC_METACLASS_START;
175 OBJC_EXPORT unsigned SEG_OBJC_CAT_CLS_METH_START;
176 OBJC_EXPORT unsigned SEG_OBJC_CAT_INST_METH_START;
177 OBJC_EXPORT unsigned SEG_OBJC_CLS_METH_START;
178 OBJC_EXPORT unsigned SEG_OBJC_INST_METHODS_START;
179 OBJC_EXPORT unsigned SEG_OBJC_MESSAGE_REFS_START;
180 OBJC_EXPORT unsigned SEG_OBJC_SYMBOLS_START;
181 OBJC_EXPORT unsigned SEG_OBJC_CATEGORY_START;
182 OBJC_EXPORT unsigned SEG_OBJC_PROTOCOL_START;
183 OBJC_EXPORT unsigned SEG_OBJC_CLASS_VARS_START;
184 OBJC_EXPORT unsigned SEG_OBJC_INSTANCE_VARS_START;
185 OBJC_EXPORT unsigned SEG_OBJC_MODULES_START;
186 OBJC_EXPORT unsigned SEG_OBJC_STRING_OBJECT_START;
187 OBJC_EXPORT unsigned SEG_OBJC_CLASS_NAMES_START;
188 OBJC_EXPORT unsigned SEG_OBJC_METH_VAR_NAMES_START;
189 OBJC_EXPORT unsigned SEG_OBJC_METH_VAR_TYPES_START;
190 OBJC_EXPORT unsigned SEG_OBJC_CLS_REFS_START;
192 OBJC_EXPORT unsigned SEG_OBJC_CLASS_END;
193 OBJC_EXPORT unsigned SEG_OBJC_METACLASS_END;
194 OBJC_EXPORT unsigned SEG_OBJC_CAT_CLS_METH_END;
195 OBJC_EXPORT unsigned SEG_OBJC_CAT_INST_METH_END;
196 OBJC_EXPORT unsigned SEG_OBJC_CLS_METH_END;
197 OBJC_EXPORT unsigned SEG_OBJC_INST_METHODS_END;
198 OBJC_EXPORT unsigned SEG_OBJC_MESSAGE_REFS_END;
199 OBJC_EXPORT unsigned SEG_OBJC_SYMBOLS_END;
200 OBJC_EXPORT unsigned SEG_OBJC_CATEGORY_END;
201 OBJC_EXPORT unsigned SEG_OBJC_PROTOCOL_END;
202 OBJC_EXPORT unsigned SEG_OBJC_CLASS_VARS_END;
203 OBJC_EXPORT unsigned SEG_OBJC_INSTANCE_VARS_END;
204 OBJC_EXPORT unsigned SEG_OBJC_MODULES_END;
205 OBJC_EXPORT unsigned SEG_OBJC_STRING_OBJECT_END;
206 OBJC_EXPORT unsigned SEG_OBJC_CLASS_NAMES_END;
207 OBJC_EXPORT unsigned SEG_OBJC_METH_VAR_NAMES_END;
208 OBJC_EXPORT unsigned SEG_OBJC_METH_VAR_TYPES_END;
209 OBJC_EXPORT unsigned SEG_OBJC_CLS_REFS_END;
211 typedef struct _simple_header_struct {
212 char * subspace_name ;
213 void * start_address ;
215 } simple_header_struct ;
217 static simple_header_struct our_objc_header[] = {
218 { "$$OBJC_CLASS$$", &SEG_OBJC_CLASS_START, &SEG_OBJC_CLASS_END },
219 { "$$OBJC_METACLASS$$", &SEG_OBJC_METACLASS_START, &SEG_OBJC_METACLASS_END },
220 { "$$OBJC_CAT_CLS_METH$$", &SEG_OBJC_CAT_CLS_METH_START, &SEG_OBJC_CAT_CLS_METH_END },
221 { "$$OBJC_CAT_INST_METH$$", &SEG_OBJC_CAT_INST_METH_START, &SEG_OBJC_CAT_INST_METH_END },
222 { "$$OBJC_CLS_METH$$", &SEG_OBJC_CLS_METH_START, &SEG_OBJC_CLS_METH_END },
223 { "$$OBJC_INST_METHODS$$", &SEG_OBJC_INST_METHODS_START, &SEG_OBJC_INST_METHODS_END },
224 { "$$OBJC_MESSAGE_REFS$$", &SEG_OBJC_MESSAGE_REFS_START, &SEG_OBJC_MESSAGE_REFS_END },
225 { "$$OBJC_SYMBOLS$$", &SEG_OBJC_SYMBOLS_START, &SEG_OBJC_SYMBOLS_END },
226 { "$$OBJC_CATEGORY$$", &SEG_OBJC_CATEGORY_START, &SEG_OBJC_CATEGORY_END },
227 { "$$OBJC_PROTOCOL$$", &SEG_OBJC_PROTOCOL_START, &SEG_OBJC_PROTOCOL_END },
228 { "$$OBJC_CLASS_VARS$$", &SEG_OBJC_CLASS_VARS_START, &SEG_OBJC_CLASS_VARS_END },
229 { "$$OBJC_INSTANCE_VARS$$", &SEG_OBJC_INSTANCE_VARS_START, &SEG_OBJC_INSTANCE_VARS_END },
230 { "$$OBJC_MODULES$$", &SEG_OBJC_MODULES_START, &SEG_OBJC_MODULES_END },
231 { "$$OBJC_STRING_OBJECT$$", &SEG_OBJC_STRING_OBJECT_START, &SEG_OBJC_STRING_OBJECT_END },
232 { "$$OBJC_CLASS_NAMES$$", &SEG_OBJC_CLASS_NAMES_START, &SEG_OBJC_CLASS_NAMES_END },
233 { "$$OBJC_METH_VAR_NAMES$$", &SEG_OBJC_METH_VAR_TYPES_START, &SEG_OBJC_METH_VAR_NAMES_END },
234 { "$$OBJC_METH_VAR_TYPES$$", &SEG_OBJC_METH_VAR_TYPES_START, &SEG_OBJC_METH_VAR_TYPES_END },
235 { "$$OBJC_CLS_REFS$$", &SEG_OBJC_CLS_REFS_START, &SEG_OBJC_CLS_REFS_END },
239 /* Returns an array of all the objc headers in the executable (and shlibs)
240 * Caller is responsible for freeing.
242 headerType **_getObjcHeaders()
245 /* Will need to fill in with any shlib info later as well. Need more
250 * this is truly ugly, hpux does not map in the header so we have to
251 * try and find it and map it in. their crt0 has some global vars
252 * that hold argv[0] which we will use to find the executable file
255 headerType **hdrs = (headerType**)malloc(2 * sizeof(headerType*));
256 NXArgv = __argv_value;
257 NXArgc = __argc_value;
258 hdrs[0] = &our_objc_header;
263 // I think we are getting the address of the table (ie the table itself)
264 // isn't that expensive ?
265 static void *getsubspace(headerType *objchead, char *sname, unsigned *size)
267 simple_header_struct *table = (simple_header_struct *)objchead;
270 while ( table[i].subspace_name){
271 if (!strcmp(table[i].subspace_name, sname)){
272 *size = table[i].end_address - table[i].start_address;
273 return table[i].start_address;
281 Module _getObjcModules(headerType *head, int *nmodules)
284 void *mods = getsubspace(head,"$$OBJC_MODULES$$",&size);
285 *nmodules = size / sizeof(struct objc_module);
289 SEL *_getObjcMessageRefs(headerType *head, int *nmess)
292 void *refs = getsubspace (head,"$$OBJC_MESSAGE_REFS$$", &size);
293 *nmess = size / sizeof(SEL);
297 struct proto_template *_getObjcProtocols(headerType *head, int *nprotos)
304 start = getsubspace (head,"$$OBJC_PROTOCOL$$", &size);
308 * XXX: Look for padding of 4 zero bytes and remove it.
309 * XXX: Depends upon first four bytes of a proto_template never being 0.
310 * XXX: Somebody should check to see if this is really the case.
313 for (p = start; p < end; p += sizeof(struct proto_template)) {
314 if (!p[0] && !p[1] && !p[2] && !p[3]) {
315 memcpy(p, p + sizeof(long), (end - p) - sizeof(long));
321 *nprotos = size / sizeof(struct proto_template);
322 return ((struct proto_template *)start);
325 NXConstantStringTemplate *_getObjcStringObjects(headerType *head, int *nstrs)
328 void *str = getsubspace (head,"$$OBJC_STRING_OBJECT$$", &size);
329 *nstrs = size / sizeof(NXConstantStringTemplate);
330 return (NXConstantStringTemplate *)str;
333 Class *_getObjcClassRefs(headerType *head, int *nclasses)
336 void *classes = getsubspace (head,"$$OBJC_CLS_REFS$$", &size);
337 *nclasses = size / sizeof(Class);
338 return (Class *)classes;
341 /* returns start of all objective-c info and the size of the data */
342 void *_getObjcHeaderData(headerType *head, unsigned *size)
344 #warning _getObjcHeaderData not implemented yet
350 const char *_getObjcHeaderName(headerType *header)
358 * Objective-C runtime information module.
359 * This module is generic for all object format files.
364 #import "objc-private.h"
370 char ** NXArgv = NULL;
373 char ***_NSGetArgv(void)
378 int *_NSGetArgc(void)
385 OBJC_EXPORT char ***_environ_dll;
386 #elif defined(NeXT_PDO)
387 OBJC_EXPORT char ***environ;
390 char ***_NSGetEnviron(void)
393 return (char ***)_environ_dll;
394 #elif defined(NeXT_PDO)
395 return (char ***)&environ;
397 #warning "_NSGetEnviron() is unimplemented for this architecture"
398 return (char ***)NULL;
403 #if !defined(__hpux__) && !defined(hpux) && !defined(__osf__)
404 const char OBJC_METH_VAR_NAME_FORWARD[10]="forward::";
406 OBJC_EXPORT char OBJC_METH_VAR_NAME_FORWARD[];
409 static objcSectionStruct objcHeaders = {0,0,sizeof(objcModHeader)};
410 objcModHeader *CMH = 0; // Current Module Header
412 int _objcModuleCount() {
413 return objcHeaders.count;
416 const char *_objcModuleNameAtIndex(int i) {
417 if ( i < 0 || i >= objcHeaders.count)
419 return ((objcModHeader*)objcHeaders.data + i)->name;
422 static inline void allocElements (objcSectionStruct *ptr, int nelmts)
424 if (ptr->data == 0) {
425 ptr->data = (void*)malloc ((ptr->count+nelmts) * ptr->size);
427 volatile void *tempData = (void *)realloc(ptr->data, (ptr->count+nelmts) * ptr->size);
428 ptr->data = (void **)tempData;
431 bzero((char*)ptr->data + ptr->count * ptr->size, ptr->size * nelmts);
434 OBJC_EXPORT void _objcInit(void);
435 void objc_finish_header (void)
438 CMH = (objcModHeader *)0;
439 // leaking like a stuck pig.
442 void objc_register_header_name (const char * name) {
444 CMH->name = malloc(strlen(name)+1);
445 #if defined(WIN32) || defined(__svr4__)
446 bzero(CMH->name, (strlen(name)+1));
448 strcpy(CMH->name, name);
452 void objc_register_header (const char * name)
455 // we've already registered a header (probably via __objc_execClass),
456 // so just update the name.
460 allocElements (&objcHeaders, 1);
461 CMH = (objcModHeader *)objcHeaders.data + objcHeaders.count;
463 bzero(CMH, sizeof(objcModHeader));
465 CMH->Modules.size = sizeof(struct objc_module);
466 CMH->Classes.size = sizeof(void *);
467 CMH->Protocols.size = sizeof(void *);
468 CMH->StringObjects.size = sizeof(void *);
470 objc_register_header_name(name);
474 void printModule(Module mod)
476 printf("name=\"%s\", symtab=%x\n", mod->name, mod->symtab);
479 void dumpModules(void)
485 printf("dumpModules(): found %d header(s)\n", objcHeaders.count);
486 for (j=0; j<objcHeaders.count; ++j) {
487 cmh = (objcModHeader *)objcHeaders.data + j;
489 printf("===%s, found %d modules\n", cmh->name, cmh->Modules.count);
492 mod = (Module)cmh->Modules.data;
494 for (i=0; i<cmh->Modules.count; i++) {
495 printf("\tname=\"%s\", symtab=%x, sel_ref_cnt=%d\n", mod->name, mod->symtab, (Symtab)(mod->symtab)->sel_ref_cnt);
502 static inline void addObjcProtocols(struct objc_protocol_list * pl)
508 struct objc_protocol_list *list = pl;
510 count += list->count;
513 allocElements( &CMH->Protocols, count );
518 while ( i < list->count )
519 CMH->Protocols.data[ CMH->Protocols.count++ ] = (void*) list->list[i++];
526 while ( i < list->count )
527 addObjcProtocols( ((ProtocolTemplate*)list->list[i++])->protocol_list );
534 _parseObjcModule(struct objc_symtab *symtab)
537 SEL *refs = symtab->refs, sel;
540 // Add the selector references
544 symtab->sel_ref_cnt = 0;
548 symtab->sel_ref_cnt++;
549 // don't touvh the VM page if not necessary
550 if ( (sel = sel_registerNameNoCopy ((const char *)*refs)) != *refs ) {
557 // Walk through all of the ObjC Classes
559 if ((k = symtab->cls_def_cnt))
561 allocElements (&CMH->Classes, k);
563 for ( i=0, j = symtab->cls_def_cnt; i < j; i++ )
565 struct objc_class *class;
568 class = (struct objc_class *)symtab->defs[i];
569 objc_addClass(class);
570 CMH->Classes.data[ CMH->Classes.count++ ] = (void*) class->name;
571 addObjcProtocols (class->protocols);
573 // ignore fixing up the selectors to be unique (for now; done lazily later)
578 // Walk through all of the ObjC Categories
580 if ((k = symtab->cat_def_cnt))
582 allocElements (&CMH->Classes, k);
584 for ( j += symtab->cat_def_cnt;
588 struct objc_category *category;
590 category = (struct objc_category *)symtab->defs[i];
591 CMH->Classes.data[ CMH->Classes.count++ ] =
592 (void*) category->class_name;
594 addObjcProtocols (category->protocols);
596 // ignore fixing the selectors to be unique
597 // this is now done lazily upon use
598 //_objc_inlined_fixup_selectors_in_method_list(category->instance_methods);
599 //_objc_inlined_fixup_selectors_in_method_list(category->class_methods);
604 // Walk through all of the ObjC Static Strings
606 if ((k = symtab->obj_defs))
608 allocElements (&CMH->StringObjects, k);
610 for ( j += symtab->obj_defs;
614 NXConstantStringTemplate *string = ( NXConstantStringTemplate *)symtab->defs[i];
615 CMH->StringObjects.data[ CMH->StringObjects.count++ ] =
620 // Walk through all of the ObjC Static Protocols
622 if ((k = symtab->proto_defs))
624 allocElements (&CMH->Protocols, k);
626 for ( j += symtab->proto_defs;
630 ProtocolTemplate *proto = ( ProtocolTemplate *)symtab->defs[i];
631 allocElements (&CMH->Protocols, 1);
632 CMH->Protocols.data[ CMH->Protocols.count++ ] =
635 addObjcProtocols(proto->protocol_list);
640 // used only as a dll initializer on Windows and/or hppa (!)
641 void __objc_execClass(Module mod)
643 sel_registerName ((const char *)OBJC_METH_VAR_NAME_FORWARD);
646 objc_register_header(NXArgv ? NXArgv[0] : "");
649 allocElements (&CMH->Modules, 1);
651 memcpy( (Module)CMH->Modules.data
652 + CMH->Modules.count,
654 sizeof(struct objc_module));
655 CMH->Modules.count++;
657 _parseObjcModule(mod->symtab);
660 const char * NSModulePathForClass(Class cls)
665 for (i = 0; i < objcHeaders.count; i++) {
666 volatile objcModHeader *aHeader = (objcModHeader *)objcHeaders.data + i;
667 for (j = 0; j < aHeader->Modules.count; j++) {
668 Module mod = (void *)(aHeader->Modules.data) + j * aHeader->Modules.size;
669 struct objc_symtab *symtab = mod->symtab;
670 for (k = 0; k < symtab->cls_def_cnt; k++) {
671 if (cls == (Class)symtab->defs[k])
672 return aHeader->name;
677 #warning "NSModulePathForClass is not fully implemented!"
682 unsigned int _objc_goff_headerCount (void)
684 return objcHeaders.count;
687 /* Build the header vector, of all headers seen so far. */
689 struct header_info *_objc_goff_headerVector ()
692 struct header_info *hdrVec;
694 hdrVec = malloc_zone_malloc (_objc_create_zone(),
695 objcHeaders.count * sizeof (struct header_info));
696 #if defined(WIN32) || defined(__svr4__)
697 bzero(hdrVec, (objcHeaders.count * sizeof (struct header_info)));
700 for (hidx = 0; hidx < objcHeaders.count; hidx++)
702 objcModHeader *aHeader = (objcModHeader *)objcHeaders.data + hidx;
704 hdrVec[hidx].mhdr = (headerType**) aHeader;
705 hdrVec[hidx].mod_ptr = (Module)(aHeader->Modules.data);
713 char ** __NXArgv = 0;
716 /* Returns an array of all the objc headers in the executable (and shlibs)
717 * Caller is responsible for freeing.
719 headerType **_getObjcHeaders()
722 #if defined(__hpux__) || defined(hpux)
723 OBJC_EXPORT int __argc_value;
724 OBJC_EXPORT char ** __argv_value;
727 /* Will need to fill in with any shlib info later as well. Need more
731 headerType **hdrs = (headerType**)malloc(2 * sizeof(headerType*));
732 #if defined(WIN32) || defined(__svr4__)
733 bzero(hdrs, (2 * sizeof(headerType*)));
735 #if defined(__hpux__) || defined(hpux)
736 NXArgv = __argv_value;
737 NXArgc = __argc_value;
738 #else /* __hpux__ || hpux */
743 #endif /* __hpux__ || hpux */
745 hdrs[0] = (headerType*)CMH;
750 static objcModHeader *_getObjcModHeader(headerType *head)
752 return (objcModHeader *)head;
755 Module _getObjcModules(headerType *head, int *size)
757 objcModHeader *modHdr = _getObjcModHeader(head);
759 *size = modHdr->Modules.count;
760 return (Module)(modHdr->Modules.data);
768 ProtocolTemplate **_getObjcProtocols(headerType *head, int *nprotos)
770 objcModHeader *modHdr = _getObjcModHeader(head);
773 *nprotos = modHdr->Protocols.count;
774 return (ProtocolTemplate **)modHdr->Protocols.data;
778 return (ProtocolTemplate **)0;
783 NXConstantStringTemplate **_getObjcStringObjects(headerType *head, int *nstrs)
785 objcModHeader *modHdr = _getObjcModHeader(head);
788 *nstrs = modHdr->StringObjects.count;
789 return (NXConstantStringTemplate **)modHdr->StringObjects.data;
793 return (NXConstantStringTemplate **)0;
797 Class *_getObjcClassRefs(headerType *head, int *nclasses)
799 objcModHeader *modHdr = _getObjcModHeader(head);
802 *nclasses = modHdr->Classes.count;
803 return (Class *)modHdr->Classes.data;
811 /* returns start of all objective-c info and the size of the data */
812 void *_getObjcHeaderData(headerType *head, unsigned *size)
818 SEL *_getObjcMessageRefs(headerType *head, int *nmess)
824 const char *_getObjcHeaderName(headerType *header)
826 return "InvalidHeaderName";