#include "stdio.h"
#include "string.h"
#include "mach-o/loader.h"
#include "objc/objc-runtime.h"
#include "objc/Protocol.h"
#include "stuff/allocate.h"
#include "stuff/bytesex.h"
#include "ofile_print.h"
struct objc_protocol
{
@defs(Protocol)
};
struct objc_string_object {
struct objc_class *isa;
char *characters;
unsigned int _length;
};
typedef struct objc_string_object NXConstantString;
#define SIZEHASHTABLE 821
struct _hashEntry {
struct _hashEntry *next;
char *sel;
};
void
swap_objc_module(
struct objc_module *module,
enum byte_sex target_byte_sex)
{
module->version = SWAP_LONG(module->version);
module->size = SWAP_LONG(module->size);
module->name = (char *) SWAP_LONG((long)module->name);
module->symtab = (Symtab) SWAP_LONG((long)module->symtab);
}
void
swap_objc_symtab(
struct objc_symtab *symtab,
enum byte_sex target_byte_sex)
{
symtab->sel_ref_cnt = SWAP_LONG(symtab->sel_ref_cnt);
symtab->refs = (SEL *) SWAP_LONG((long)symtab->refs);
symtab->cls_def_cnt = SWAP_SHORT(symtab->cls_def_cnt);
symtab->cat_def_cnt = SWAP_SHORT(symtab->cat_def_cnt);
}
void
swap_objc_class(
struct objc_class *objc_class,
enum byte_sex target_byte_sex)
{
objc_class->isa = (struct objc_class *)
SWAP_LONG((long)objc_class->isa);
objc_class->super_class = (struct objc_class *)
SWAP_LONG((long)objc_class->super_class);
objc_class->name = (const char *)
SWAP_LONG((long)objc_class->name);
objc_class->version =
SWAP_LONG(objc_class->version);
objc_class->info =
SWAP_LONG(objc_class->info);
objc_class->instance_size =
SWAP_LONG(objc_class->instance_size);
objc_class->ivars = (struct objc_ivar_list *)
SWAP_LONG((long)objc_class->ivars);
objc_class->methodLists = (struct objc_method_list **)
SWAP_LONG((long)objc_class->methodLists);
objc_class->cache = (struct objc_cache *)
SWAP_LONG((long)objc_class->cache);
objc_class->protocols = (struct objc_protocol_list *)
SWAP_LONG((long)objc_class->protocols);
}
void
swap_objc_category(
struct objc_category *objc_category,
enum byte_sex target_byte_sex)
{
objc_category->category_name = (char *)
SWAP_LONG((long)objc_category->category_name);
objc_category->class_name = (char *)
SWAP_LONG((long)objc_category->class_name);
objc_category->instance_methods = (struct objc_method_list *)
SWAP_LONG((long)objc_category->instance_methods);
objc_category->class_methods = (struct objc_method_list *)
SWAP_LONG((long)objc_category->class_methods);
objc_category->protocols = (struct objc_protocol_list *)
SWAP_LONG((long)objc_category->protocols);
}
void
swap_objc_ivar_list(
struct objc_ivar_list *objc_ivar_list,
enum byte_sex target_byte_sex)
{
objc_ivar_list->ivar_count = SWAP_LONG(objc_ivar_list->ivar_count);
}
void
swap_objc_ivar(
struct objc_ivar *objc_ivar,
enum byte_sex target_byte_sex)
{
objc_ivar->ivar_name = (char *)
SWAP_LONG((long)objc_ivar->ivar_name);
objc_ivar->ivar_type = (char *)
SWAP_LONG((long)objc_ivar->ivar_type);
objc_ivar->ivar_offset =
SWAP_LONG(objc_ivar->ivar_offset);
}
void
swap_objc_method_list(
struct objc_method_list *method_list,
enum byte_sex target_byte_sex)
{
method_list->obsolete = (struct objc_method_list *)
SWAP_LONG((long)method_list->obsolete);
method_list->method_count =
SWAP_LONG(method_list->method_count);
}
void
swap_objc_method(
struct objc_method *method,
enum byte_sex target_byte_sex)
{
method->method_name = (SEL)
SWAP_LONG((long)method->method_name);
method->method_types = (char *)
SWAP_LONG((long)method->method_types);
method->method_imp = (IMP)
SWAP_LONG((long)method->method_imp);
}
void
swap_objc_protocol_list(
struct objc_protocol_list *protocol_list,
enum byte_sex target_byte_sex)
{
protocol_list->next = (struct objc_protocol_list *)
SWAP_LONG((long)protocol_list->next);
protocol_list->count =
SWAP_LONG(protocol_list->count);
}
void
swap_objc_protocol(
Protocol *p,
enum byte_sex target_byte_sex)
{
struct objc_protocol *protocol;
protocol = (struct objc_protocol *)p;
protocol->isa = (struct objc_class *)
SWAP_LONG((long)protocol->isa);
protocol->protocol_name = (char *)
SWAP_LONG((long)protocol->protocol_name);
protocol->protocol_list = (struct objc_protocol_list *)
SWAP_LONG((long)protocol->protocol_list);
protocol->instance_methods = (struct objc_method_description_list *)
SWAP_LONG((long)protocol->instance_methods);
protocol->class_methods = (struct objc_method_description_list *)
SWAP_LONG((long)protocol->class_methods);
}
void
swap_objc_method_description_list(
struct objc_method_description_list *mdl,
enum byte_sex target_byte_sex)
{
mdl->count = SWAP_LONG(mdl->count);
}
void
swap_objc_method_description(
struct objc_method_description *md,
enum byte_sex target_byte_sex)
{
md->name = (SEL)SWAP_LONG((long)md->name);
md->types = (char *)SWAP_LONG((long)md->types);
}
void
swap_string_object(
NXConstantString *p,
enum byte_sex target_byte_sex)
{
struct objc_string_object *string_object;
string_object = (struct objc_string_object *)p;
string_object->isa = (struct objc_class *)
SWAP_LONG((long)string_object->isa);
string_object->characters = (char *)
SWAP_LONG((long)string_object->characters);
string_object->_length =
SWAP_LONG(string_object->_length);
}
void
swap_hashEntry(
struct _hashEntry *_hashEntry,
enum byte_sex target_byte_sex)
{
_hashEntry->next = (struct _hashEntry *)
SWAP_LONG((long)_hashEntry->next);
_hashEntry->sel = (char *)
SWAP_LONG((long)_hashEntry->sel);
}
struct section_info {
struct section s;
char *contents;
unsigned long size;
};
static void get_objc_sections(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
struct section_info **objc_sections,
unsigned long *nobjc_sections,
char *sectname,
char **sect,
unsigned long *sect_addr,
unsigned long *sect_size);
static void get_cstring_section(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
struct section_info *cstring_section_ptr);
static enum bool print_method_list(
struct objc_method_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
enum bool verbose);
static enum bool print_protocol_list(
unsigned long indent,
struct objc_protocol_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static void print_protocol(
unsigned long indent,
struct objc_protocol *protocol,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static enum bool print_method_description_list(
unsigned long indent,
struct objc_method_description_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static enum bool print_PHASH(
unsigned long indent,
struct _hashEntry *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static void print_indent(
unsigned long indent);
static void *get_pointer(
void *p,
unsigned long *left,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr);
static enum bool get_symtab(
void *p,
struct objc_symtab *symtab,
void ***defs,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_objc_class(
unsigned long addr,
struct objc_class *objc_class,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_objc_category(
unsigned long addr,
struct objc_category *objc_category,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_ivar_list(
void *p,
struct objc_ivar_list *objc_ivar_list,
struct objc_ivar **ivar_list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_method_list(
void *p,
struct objc_method_list *method_list,
struct objc_method **methods,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_protocol_list(
void *p,
struct objc_protocol_list *protocol_list,
struct objc_protocol ***list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_protocol(
unsigned long addr,
struct objc_protocol *protocol,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_method_description_list(
void *p,
struct objc_method_description_list *mdl,
struct objc_method_description **list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_hashEntry(
unsigned long addr,
struct _hashEntry *_hashEntry,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
void
print_objc_segment(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped, trunc;
unsigned long i, j, left, size, defs_left, def, ivar_list_left;
char *p;
struct section_info *objc_sections;
unsigned long nobjc_sections;
struct section_info cstring_section;
struct objc_module *modules, *m, module;
unsigned long modules_addr, modules_size;
struct objc_symtab symtab;
void **defs;
struct objc_class objc_class;
struct objc_ivar_list objc_ivar_list;
struct objc_ivar *ivar_list, ivar;
struct objc_category objc_category;
printf("Objective-C segment\n");
get_objc_sections(mh, load_commands, object_byte_sex, object_addr,
object_size, &objc_sections, &nobjc_sections, SECT_OBJC_MODULES,
(char **)&modules, &modules_addr, &modules_size);
if(modules == NULL){
printf("can't print objective-C information no (" SEG_OBJC ","
SECT_OBJC_MODULES ") section\n");
return;
}
if (verbose)
get_cstring_section(mh, load_commands, object_byte_sex,
object_addr, object_size, &cstring_section);
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
memset(&module, '\0', sizeof(struct objc_module));
for(m = modules;
(char *)m < (char *)modules + modules_size;
m = (struct objc_module *)((char *)m + module.size) ){
memset(&module, '\0', sizeof(struct objc_module));
left = modules_size - (m - modules);
size = left < sizeof(struct objc_module) ?
left : sizeof(struct objc_module);
memcpy(&module, m, size);
if(swapped)
swap_objc_module(&module, host_byte_sex);
if((char *)m + module.size > (char *)m + modules_size)
printf("module extends past end of " SECT_OBJC_MODULES
" section\n");
printf("Module 0x%x\n", (unsigned int)
(modules_addr + (char *)m - (char *)modules));
printf(" version %lu\n", module.version);
printf(" size %lu\n", module.size);
if(verbose){
p = get_pointer((void *)module.name, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" name %.*s\n", (int)left, p);
else
printf(" name 0x%08x (not in an " SEG_OBJC
" section)\n", (unsigned int)module.name);
}
else
printf(" name 0x%08x\n", (unsigned int)(module.name));
if(get_symtab(module.symtab, &symtab, &defs, &defs_left, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE){
printf(" symtab 0x%08x (not in an " SEG_OBJC
" section)\n", (unsigned int)module.symtab);
continue;
}
printf(" symtab 0x%08x\n", (unsigned int)module.symtab);
if(trunc == TRUE)
printf("\tsymtab extends past end of an " SEG_OBJC
" section\n");
printf("\tsel_ref_cnt %lu\n", symtab.sel_ref_cnt);
p = get_pointer(symtab.refs, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf("\trefs 0x%08x", (unsigned int)symtab.refs);
else
printf("\trefs 0x%08x (not in an " SEG_OBJC " section)\n",
(unsigned int)symtab.refs);
printf("\tcls_def_cnt %d\n", symtab.cls_def_cnt);
printf("\tcat_def_cnt %d\n", symtab.cat_def_cnt);
if(symtab.cls_def_cnt > 0)
printf("\tClass Definitions\n");
for(i = 0; i < symtab.cls_def_cnt; i++){
if((i + 1) * sizeof(void *) > defs_left){
printf("\t(remaining class defs entries entends past "
"the end of the section)\n");
break;
}
memcpy(&def, defs + i, sizeof(void *));
if(swapped)
def = SWAP_LONG(def);
if(get_objc_class(def, &objc_class, &trunc, objc_sections,
nobjc_sections, host_byte_sex, swapped) == TRUE){
printf("\tdefs[%lu] 0x%08x", i, (unsigned int)def);
print_objc_class:
if(trunc == TRUE)
printf(" (entends past the end of the section)\n");
else
printf("\n");
printf("\t\t isa 0x%08x",
(unsigned int)objc_class.isa);
if(verbose && CLS_GETINFO(&objc_class, CLS_META)){
p = get_pointer(objc_class.isa, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t super_class 0x%08x",
(unsigned int)objc_class.super_class);
if(verbose){
p = get_pointer(objc_class.super_class, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t\t name 0x%08x",
(unsigned int)objc_class.name);
if(verbose){
p = get_pointer((void *)objc_class.name, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t\t version 0x%08x\n",
(unsigned int)objc_class.version);
printf("\t\t info 0x%08x",
(unsigned int)objc_class.info);
if(verbose){
if(CLS_GETINFO(&objc_class, CLS_CLASS))
printf(" CLS_CLASS\n");
else if(CLS_GETINFO(&objc_class, CLS_META))
printf(" CLS_META\n");
else
printf("\n");
}
else
printf("\n");
printf("\t instance_size 0x%08x\n",
(unsigned int)objc_class.instance_size);
if(get_ivar_list(objc_class.ivars, &objc_ivar_list,
&ivar_list, &ivar_list_left, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == TRUE){
printf("\t\t ivars 0x%08x\n",
(unsigned int)objc_class.ivars);
if(trunc == TRUE)
printf("\t\t objc_ivar_list extends past end "
"of " SECT_OBJC_SYMBOLS " section\n");
printf("\t\t ivar_count %d\n",
objc_ivar_list.ivar_count);
for(j = 0;
j < (unsigned long)objc_ivar_list.ivar_count;
j++){
if((j + 1) * sizeof(struct objc_ivar) >
ivar_list_left){
printf("\t\t remaining ivar's extend past "
" the of the section\n");
continue;
}
memcpy(&ivar, ivar_list + j,
sizeof(struct objc_ivar));
if(swapped)
swap_objc_ivar(&ivar, host_byte_sex);
printf("\t\t\tivar_name 0x%08x",
(unsigned int)ivar.ivar_name);
if(verbose){
p = get_pointer(ivar.ivar_name, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC
" section)\n");
}
else
printf("\n");
printf("\t\t\tivar_type 0x%08x",
(unsigned int)ivar.ivar_type);
if(verbose){
p = get_pointer(ivar.ivar_type, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC
" section)\n");
}
else
printf("\n");
printf("\t\t ivar_offset 0x%08x\n",
(unsigned int)ivar.ivar_offset);
}
}
else{
printf("\t\t ivars 0x%08x (not in an " SEG_OBJC
" section)\n",
(unsigned int)objc_class.ivars);
}
printf("\t\t methods 0x%08x",
(unsigned int)objc_class.methodLists);
if(print_method_list((struct objc_method_list *)
objc_class.methodLists,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped, sorted_symbols,
nsorted_symbols, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
printf("\t\t cache 0x%08x\n",
(unsigned int)objc_class.cache);
printf("\t\tprotocols 0x%08x",
(unsigned int)objc_class.protocols);
if(print_protocol_list(16, objc_class.protocols,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
if(CLS_GETINFO((&objc_class), CLS_CLASS)){
printf("\tMeta Class");
if(get_objc_class((unsigned long)objc_class.isa,
&objc_class, &trunc, objc_sections, nobjc_sections,
host_byte_sex, swapped) == TRUE){
goto print_objc_class;
}
else
printf(" (not in " SECT_OBJC_SYMBOLS
" section)\n");
}
}
else
printf("\tdefs[%lu] 0x%08x (not in an " SEG_OBJC
" section)\n", i, (unsigned int)def);
}
if(symtab.cat_def_cnt > 0)
printf("\tCategory Definitions\n");
for(i = 0; i < symtab.cat_def_cnt; i++){
if((i + symtab.cls_def_cnt + 1) * sizeof(void *) >
defs_left){
printf("\t(remaining category defs entries entends "
"past the end of the section)\n");
break;
}
memcpy(&def, defs + i + symtab.cls_def_cnt, sizeof(void *));
if(swapped)
def = SWAP_LONG(def);
if(get_objc_category(def, &objc_category, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == TRUE){
printf("\tdefs[%lu] 0x%08x", i + symtab.cls_def_cnt,
(unsigned int)def);
if(trunc == TRUE)
printf(" (entends past the end of the section)\n");
else
printf("\n");
printf("\t category name 0x%08x",
(unsigned int)objc_category.category_name);
if(verbose){
p = get_pointer(objc_category.category_name, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t\t class name 0x%08x",
(unsigned int)objc_category.class_name);
if(verbose){
p = get_pointer(objc_category.class_name, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t instance methods 0x%08x",
(unsigned int)objc_category.instance_methods);
if(print_method_list(objc_category.instance_methods,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped,
sorted_symbols, nsorted_symbols,
verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
printf("\t class methods 0x%08x",
(unsigned int)objc_category.class_methods);
if(print_method_list(objc_category.class_methods,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped,
sorted_symbols, nsorted_symbols,
verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\tdefs[%lu] 0x%08x (not in an " SEG_OBJC
" section)\n", i + symtab.cls_def_cnt,
(unsigned int)def);
}
}
}
void
print_objc_protocol_section(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections, cstring_section;
unsigned long nobjc_sections;
struct objc_protocol *protocols, *p, protocol;
unsigned long protocols_addr, protocols_size;
unsigned long size, left;
printf("Contents of (" SEG_OBJC ",__protocol) section\n");
get_objc_sections(mh, load_commands, object_byte_sex, object_addr,
object_size, &objc_sections, &nobjc_sections, "__protocol",
(char **)&protocols, &protocols_addr, &protocols_size);
if (verbose)
get_cstring_section(mh, load_commands, object_byte_sex,
object_addr, object_size, &cstring_section);
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
for(p = protocols; (char *)p < (char *)protocols + protocols_size; p++){
memset(&protocol, '\0', sizeof(struct objc_protocol));
left = protocols_size - (p - protocols);
size = left < sizeof(struct objc_protocol) ?
left : sizeof(struct objc_protocol);
memcpy(&protocol, p, size);
if((char *)p + sizeof(struct objc_protocol) >
(char *)p + protocols_size)
printf("Protocol extends past end of __protocol section\n");
printf("Protocol 0x%x\n", (unsigned int)
(protocols_addr + (char *)p - (char *)protocols));
print_protocol(0, &protocol,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped, verbose);
}
}
void
print_objc_string_object_section(
char *sectname,
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections;
unsigned long nobjc_sections;
struct section_info cstring_section;
struct objc_string_object *string_objects, *s, string_object;
unsigned long string_objects_addr, string_objects_size;
unsigned long size, left;
char *p;
printf("Contents of (" SEG_OBJC ",%s) section\n", sectname);
get_objc_sections(mh, load_commands, object_byte_sex, object_addr,
object_size, &objc_sections, &nobjc_sections, sectname,
(char **)&string_objects, &string_objects_addr,
&string_objects_size);
get_cstring_section(mh, load_commands, object_byte_sex, object_addr,
object_size, &cstring_section);
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
for(s = string_objects;
(char *)s < (char *)string_objects + string_objects_size;
s++){
memset(&string_object, '\0', sizeof(struct objc_string_object));
left = string_objects_size - (s - string_objects);
size = left < sizeof(struct objc_string_object) ?
left : sizeof(struct objc_string_object);
memcpy(&string_object, s, size);
if((char *)s + sizeof(struct objc_string_object) >
(char *)s + string_objects_size)
printf("String Object extends past end of %s section\n",
sectname);
printf("String Object 0x%x\n", (unsigned int)
(string_objects_addr + (char *)s - (char *)string_objects));
if(swapped)
swap_string_object((NXConstantString *)&string_object,
host_byte_sex);
printf(" isa 0x%x\n", (unsigned int)string_object.isa);
printf(" characters 0x%x",
(unsigned int)string_object.characters);
if(verbose){
p = get_pointer(string_object.characters, &left,
&cstring_section, 1, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in the (" SEG_TEXT ",__cstring) section)\n");
}
else
printf("\n");
printf(" _length %u\n", string_object._length);
}
}
void
print_objc_runtime_setup_section(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections, cstring_section;
unsigned long i, nobjc_sections, left;
struct _hashEntry **PHASH, *phash, *HASH, _hashEntry;
char *sect, *p;
unsigned long sect_addr, sect_size;
printf("Contents of (" SEG_OBJC ",__runtime_setup) section\n");
get_objc_sections(mh, load_commands, object_byte_sex, object_addr,
object_size, &objc_sections, &nobjc_sections, "__runtime_setup",
§, §_addr, §_size);
if (verbose)
get_cstring_section(mh, load_commands, object_byte_sex,
object_addr, object_size, &cstring_section);
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
PHASH = (struct _hashEntry **)sect;
for(i = 0;
i < SIZEHASHTABLE &&
(i + 1) * sizeof(struct _hashEntry *) < sect_size;
i++){
memcpy(&phash, PHASH + i, sizeof(struct _hashEntry *));
if(swapped)
phash = (struct _hashEntry *)SWAP_LONG((long)phash);
if(phash == 0)
continue;
printf("PHASH[%3lu] 0x%x", i, (unsigned int)phash);
if(print_PHASH(4, phash,
objc_sections, nobjc_sections, &cstring_section,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
}
HASH = (struct _hashEntry *)(PHASH + SIZEHASHTABLE);
for(i = 0; (char *)(HASH + i) < sect + sect_size; i++){
memcpy((char *)&_hashEntry, HASH + i, sizeof(struct _hashEntry));
if(swapped)
swap_hashEntry(&_hashEntry, host_byte_sex);
printf("HASH at 0x%08x\n",
(unsigned int)(sect_addr + (char *)(HASH + i) - sect));
printf(" sel 0x%08x", (unsigned int)_hashEntry.sel);
if(verbose){
p = get_pointer(_hashEntry.sel, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf(" next 0x%08x", (unsigned int)_hashEntry.next);
if(_hashEntry.next == NULL){
printf("\n");
}
else{
if((unsigned long)_hashEntry.next < sect_addr ||
(unsigned long)_hashEntry.next >= sect_addr + sect_size)
printf(" (not in the ("SEG_OBJC ",__runtime_setup "
"section)\n");
else
printf("\n");
}
}
}
static
void
get_objc_sections(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
struct section_info **objc_sections,
unsigned long *nobjc_sections,
char *sectname,
char **sect,
unsigned long *sect_addr,
unsigned long *sect_size)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, j, left, size;
struct load_command lcmd, *lc;
char *p;
struct segment_command sg;
struct section s;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
*objc_sections = NULL;
*nobjc_sections = 0;
*sect = NULL;
*sect_addr = 0;
*sect_size = 0;
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&lcmd, host_byte_sex);
if(lcmd.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + lcmd.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(lcmd.cmd){
case LC_SEGMENT:
memset((char *)&sg, '\0', sizeof(struct segment_command));
size = left < sizeof(struct segment_command) ?
left : sizeof(struct segment_command);
memcpy((char *)&sg, (char *)lc, size);
if(swapped)
swap_segment_command(&sg, host_byte_sex);
p = (char *)lc + sizeof(struct segment_command);
for(j = 0 ; j < sg.nsects ; j++){
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds){
printf("section structure command extends past "
"end of load commands\n");
}
left = mh->sizeofcmds - (p - (char *)load_commands);
memset((char *)&s, '\0', sizeof(struct section));
size = left < sizeof(struct section) ?
left : sizeof(struct section);
memcpy((char *)&s, p, size);
if(swapped)
swap_section(&s, 1, host_byte_sex);
if(strcmp(s.segname, SEG_OBJC) == 0){
*objc_sections = reallocate(*objc_sections,
sizeof(struct section_info) * (*nobjc_sections + 1));
(*objc_sections)[*nobjc_sections].s = s;
(*objc_sections)[*nobjc_sections].contents =
object_addr + s.offset;
if(s.offset > object_size){
printf("section contents of: (%.16s,%.16s) is past "
"end of file\n", s.segname, s.sectname);
(*objc_sections)[*nobjc_sections].size = 0;
}
else if(s.offset + s.size > object_size){
printf("part of section contents of: (%.16s,%.16s) "
"is past end of file\n",
s.segname, s.sectname);
(*objc_sections)[*nobjc_sections].size =
object_size - s.offset;
}
else
(*objc_sections)[*nobjc_sections].size = s.size;
if(strncmp(s.sectname, sectname, 16) == 0){
if(*sect != NULL)
printf("more than one (" SEG_OBJC ",%s) "
"section\n", sectname);
else{
*sect = (object_addr + s.offset);
*sect_size = s.size;
*sect_addr = s.addr;
}
}
(*nobjc_sections)++;
}
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds)
break;
p += size;
}
break;
}
if(lcmd.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
#ifdef notdef
printf("*nobjc_sections %lu\n", *nobjc_sections);
for(i = 0; i < *nobjc_sections; i++){
printf("(%.16s,%.16s) addr = 0x%x size = 0x%x\n",
(*objc_sections)[i].s.segname,
(*objc_sections)[i].s.sectname,
(unsigned int)((*objc_sections)[i].s.addr),
(unsigned int)((*objc_sections)[i].size));
}
#endif
}
static
void
get_cstring_section(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex object_byte_sex,
char *object_addr,
unsigned long object_size,
struct section_info *cstring_section)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, j, left, size;
struct load_command lcmd, *lc;
char *p;
struct segment_command sg;
struct section s;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
memset(cstring_section, '\0', sizeof(struct section_info));
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&lcmd, host_byte_sex);
if(lcmd.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + lcmd.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(lcmd.cmd){
case LC_SEGMENT:
memset((char *)&sg, '\0', sizeof(struct segment_command));
size = left < sizeof(struct segment_command) ?
left : sizeof(struct segment_command);
memcpy((char *)&sg, (char *)lc, size);
if(swapped)
swap_segment_command(&sg, host_byte_sex);
p = (char *)lc + sizeof(struct segment_command);
for(j = 0 ; j < sg.nsects ; j++){
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds){
printf("section structure command extends past "
"end of load commands\n");
}
left = mh->sizeofcmds - (p - (char *)load_commands);
memset((char *)&s, '\0', sizeof(struct section));
size = left < sizeof(struct section) ?
left : sizeof(struct section);
memcpy((char *)&s, p, size);
if(swapped)
swap_section(&s, 1, host_byte_sex);
if(strcmp(s.segname, SEG_TEXT) == 0 &&
strcmp(s.sectname, "__cstring") == 0){
cstring_section->s = s;
cstring_section->contents = object_addr + s.offset;
if(s.offset > object_size){
printf("section contents of: (%.16s,%.16s) is past "
"end of file\n", s.segname, s.sectname);
cstring_section->size = 0;
}
else if(s.offset + s.size > object_size){
printf("part of section contents of: (%.16s,%.16s) "
"is past end of file\n",
s.segname, s.sectname);
cstring_section->size = object_size - s.offset;
}
else
cstring_section->size = s.size;
return;
}
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds)
break;
p += size;
}
break;
}
if(lcmd.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
}
static
enum bool
print_method_list(
struct objc_method_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
enum bool verbose)
{
struct objc_method *methods, method;
struct objc_method_list method_list;
enum bool trunc;
unsigned long i, methods_left, left;
char *p;
if(get_method_list(addr, &method_list, &methods, &methods_left, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE)
return(FALSE);
printf("\n");
if(trunc == TRUE)
printf("\t\t objc_method_list extends past end of the section\n");
printf("\t\t obsolete 0x%08x\n",
(unsigned int)method_list.obsolete);
printf("\t\t method_count %d\n",
method_list.method_count);
for(i = 0; i < (unsigned long)method_list.method_count; i++){
if((i + 1) * sizeof(struct objc_method) > methods_left){
printf("\t\t remaining method's extend past the of the "
"section\n");
continue;
}
memcpy(&method, methods + i, sizeof(struct objc_method));
if(swapped)
swap_objc_method(&method, host_byte_sex);
printf("\t\t method_name 0x%08x",
(unsigned int)method.method_name);
if(verbose){
p = get_pointer(method.method_name, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t\t method_types 0x%08x",
(unsigned int)method.method_types);
if(verbose){
p = get_pointer(method.method_types, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
printf("\t\t method_imp 0x%08x ",
(unsigned int)method.method_imp);
if(verbose)
print_label((long)method.method_imp, FALSE, sorted_symbols,
nsorted_symbols);
printf("\n");
}
return(TRUE);
}
static
enum bool
print_protocol_list(
unsigned long indent,
struct objc_protocol_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
struct objc_protocol **list, *l, protocol;
struct objc_protocol_list protocol_list;
enum bool trunc;
unsigned long i, list_left;
if(get_protocol_list(addr, &protocol_list, &list, &list_left, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE)
return(FALSE);
printf("\n");
if(trunc == TRUE){
print_indent(indent);
printf(" objc_protocol_list extends past end of the section\n");
}
print_indent(indent);
printf(" next 0x%08x\n",
(unsigned int)protocol_list.next);
print_indent(indent);
printf(" count %d\n",
protocol_list.count);
for(i = 0; i < (unsigned long)protocol_list.count; i++){
if((i + 1) * sizeof(struct objc_protocol *) > list_left){
print_indent(indent);
printf(" remaining list entries extend past the of the "
"section\n");
continue;
}
memcpy(&l, list + i, sizeof(struct objc_protocol *));
if(swapped)
l = (struct objc_protocol *)SWAP_LONG((long)l);
print_indent(indent);
printf(" list[%lu] 0x%08x", i, (unsigned int)l);
if(get_protocol((unsigned long)l, &protocol, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE){
printf(" (not in an " SEG_OBJC " section)\n");
continue;
}
printf("\n");
if(trunc == TRUE){
print_indent(indent);
printf(" Protocol extends past end of the "
"section\n");
}
if(swapped)
swap_objc_protocol((Protocol *)&protocol, host_byte_sex);
print_protocol(indent, &protocol,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose);
}
return(TRUE);
}
static
void
print_protocol(
unsigned long indent,
struct objc_protocol *protocol,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
unsigned long left;
char *p;
print_indent(indent);
printf(" isa 0x%08x\n",
(unsigned int)protocol->isa);
print_indent(indent);
printf(" protocol_name 0x%08x",
(unsigned int)protocol->protocol_name);
if(verbose){
p = get_pointer(protocol->protocol_name, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
print_indent(indent);
printf(" protocol_list 0x%08x",
(unsigned int)protocol->protocol_list);
if(print_protocol_list(indent + 4, protocol->protocol_list,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
print_indent(indent);
printf(" instance_methods 0x%08x",
(unsigned int)protocol->instance_methods);
if(print_method_description_list(indent, protocol->instance_methods,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
print_indent(indent);
printf(" class_methods 0x%08x",
(unsigned int)protocol->class_methods);
if(print_method_description_list(indent, protocol->class_methods,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
}
static
enum bool
print_method_description_list(
unsigned long indent,
struct objc_method_description_list *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
struct objc_method_description_list mdl;
struct objc_method_description *list, md;
enum bool trunc;
unsigned long i, list_left, left;
char *p;
if(get_method_description_list(addr, &mdl, &list, &list_left,
&trunc, objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE)
return(FALSE);
printf("\n");
if(trunc == TRUE){
print_indent(indent);
printf(" objc_method_description_list extends past end of the "
"section\n");
}
print_indent(indent);
printf(" count %d\n", mdl.count);
for(i = 0; i < (unsigned long)mdl.count; i++){
if((i + 1) * sizeof(struct objc_method_description) > list_left){
print_indent(indent);
printf(" remaining list entries extend past the of the "
"section\n");
continue;
}
print_indent(indent);
printf(" list[%lu]\n", i);
memcpy(&md, list + i, sizeof(struct objc_method_description));
if(swapped)
swap_objc_method_description(&md, host_byte_sex);
print_indent(indent);
printf(" name 0x%08x", (unsigned int)md.name);
if(verbose){
p = get_pointer(md.name, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
print_indent(indent);
printf(" types 0x%08x", (unsigned int)md.types);
if(verbose){
p = get_pointer(md.types, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
}
return(TRUE);
}
static enum bool
print_PHASH(
unsigned long indent,
struct _hashEntry *addr,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
struct _hashEntry _hashEntry;
enum bool trunc;
unsigned long left;
char *p;
if(get_hashEntry((unsigned long)addr, &_hashEntry, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == FALSE)
return(FALSE);
printf("\n");
if(trunc == TRUE){
print_indent(indent);
printf("_hashEntry extends past end of the section\n");
}
print_indent(indent);
printf(" sel 0x%08x", (unsigned int)_hashEntry.sel);
if(verbose){
p = get_pointer(_hashEntry.sel, &left,
objc_sections, nobjc_sections, cstring_section_ptr);
if(p != NULL)
printf(" %.*s\n", (int)left, p);
else
printf(" (not in an " SEG_OBJC " section)\n");
}
else
printf("\n");
print_indent(indent);
printf("next 0x%08x", (unsigned int)_hashEntry.next);
if(_hashEntry.next == NULL){
printf("\n");
return(TRUE);
}
if(print_PHASH(indent+4, _hashEntry.next,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose) == FALSE)
printf(" (not in an " SEG_OBJC " section)\n");
return(TRUE);
}
static
void
print_indent(
unsigned long indent)
{
unsigned long i;
for(i = 0; i < indent; ){
if(indent - i >= 8){
printf("\t");
i += 8;
}
else{
printf("%.*s", (int)(indent - i), " ");
return;
}
}
}
static
void *
get_pointer(
void *p,
unsigned long *left,
struct section_info *objc_sections,
unsigned long nobjc_sections,
struct section_info *cstring_section_ptr)
{
void* returnValue = NULL;
unsigned long i, addr;
addr = (unsigned long)p;
if(addr >= cstring_section_ptr->s.addr &&
addr < cstring_section_ptr->s.addr + cstring_section_ptr->size){
*left = cstring_section_ptr->size -
(addr - cstring_section_ptr->s.addr);
returnValue = (cstring_section_ptr->contents +
(addr - cstring_section_ptr->s.addr));
}
for(i = 0; !returnValue && i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
returnValue = (objc_sections[i].contents +
(addr - objc_sections[i].s.addr));
}
}
return returnValue;
}
static
enum bool
get_symtab(
void *p,
struct objc_symtab *symtab,
void ***defs,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long addr, i;
addr = (unsigned long)p;
memset(symtab, '\0', sizeof(struct objc_symtab));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(*left >= sizeof(struct objc_symtab) - sizeof(void *)){
memcpy(symtab,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_symtab) - sizeof(void *));
*left -= sizeof(struct objc_symtab) - sizeof(void *);
*defs = (void **)(objc_sections[i].contents +
(addr - objc_sections[i].s.addr) +
sizeof(struct objc_symtab)-sizeof(void *));
*trunc = FALSE;
}
else{
memcpy(symtab,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
*left);
*left = 0;
*defs = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_symtab(symtab, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_objc_class(
unsigned long addr,
struct objc_class *objc_class,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long left, i;
memset(objc_class, '\0', sizeof(struct objc_class));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(left >= sizeof(struct objc_class)){
memcpy(objc_class,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_class));
*trunc = FALSE;
}
else{
memcpy(objc_class,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_class(objc_class, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_objc_category(
unsigned long addr,
struct objc_category *objc_category,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long left, i;
memset(objc_category, '\0', sizeof(struct objc_category));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(left >= sizeof(struct objc_category)){
memcpy(objc_category,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_category));
*trunc = FALSE;
}
else{
memcpy(objc_category,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_category(objc_category, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_ivar_list(
void *p,
struct objc_ivar_list *objc_ivar_list,
struct objc_ivar **ivar_list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long addr, i;
addr = (unsigned long)p;
memset(objc_ivar_list, '\0', sizeof(struct objc_ivar_list));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(*left >= sizeof(struct objc_ivar_list) -
sizeof(struct objc_ivar)){
memcpy(objc_ivar_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_ivar_list) -
sizeof(struct objc_ivar));
*left -= sizeof(struct objc_ivar_list) -
sizeof(struct objc_ivar);
*ivar_list = (struct objc_ivar *)
(objc_sections[i].contents +
(addr - objc_sections[i].s.addr) +
sizeof(struct objc_ivar_list) -
sizeof(struct objc_ivar));
*trunc = FALSE;
}
else{
memcpy(objc_ivar_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
*left);
*left = 0;
*ivar_list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_ivar_list(objc_ivar_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_method_list(
void *p,
struct objc_method_list *method_list,
struct objc_method **methods,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long addr, i;
addr = (unsigned long)p;
memset(method_list, '\0', sizeof(struct objc_method_list));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(*left >= sizeof(struct objc_method_list) -
sizeof(struct objc_method)){
memcpy(method_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_method_list) -
sizeof(struct objc_method));
*left -= sizeof(struct objc_method_list) -
sizeof(struct objc_method);
*methods = (struct objc_method *)
(objc_sections[i].contents +
(addr - objc_sections[i].s.addr) +
sizeof(struct objc_method_list) -
sizeof(struct objc_method));
*trunc = FALSE;
}
else{
memcpy(method_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
*left);
*left = 0;
*methods = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_method_list(method_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_protocol_list(
void *p,
struct objc_protocol_list *protocol_list,
struct objc_protocol ***list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long addr, i;
addr = (unsigned long)p;
memset(protocol_list, '\0', sizeof(struct objc_protocol_list));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(*left >= sizeof(struct objc_protocol_list) -
sizeof(struct objc_protocol *)){
memcpy(protocol_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_protocol_list) -
sizeof(struct objc_protocol *));
*left -= sizeof(struct objc_protocol_list) -
sizeof(struct objc_protocol *);
*list = (struct objc_protocol **)
(objc_sections[i].contents +
(addr - objc_sections[i].s.addr) +
sizeof(struct objc_protocol_list) -
sizeof(struct objc_protocol **));
*trunc = FALSE;
}
else{
memcpy(protocol_list,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
*left);
*left = 0;
*list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_protocol_list(protocol_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_protocol(
unsigned long addr,
struct objc_protocol *protocol,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long left, i;
memset(protocol, '\0', sizeof(struct objc_protocol));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(left >= sizeof(struct objc_protocol)){
memcpy(protocol,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_protocol));
*trunc = FALSE;
}
else{
memcpy(protocol,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_protocol((Protocol *)protocol, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_method_description_list(
void *p,
struct objc_method_description_list *mdl,
struct objc_method_description **list,
unsigned long *left,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long addr, i;
addr = (unsigned long)p;
memset(mdl, '\0', sizeof(struct objc_method_description_list));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(*left >= sizeof(struct objc_method_description_list) -
sizeof(struct objc_method_description)){
memcpy(mdl,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct objc_method_description_list) -
sizeof(struct objc_method_description));
*left -= sizeof(struct objc_method_description_list) -
sizeof(struct objc_method_description);
*list = (struct objc_method_description *)
(objc_sections[i].contents +
(addr - objc_sections[i].s.addr) +
sizeof(struct objc_method_description_list) -
sizeof(struct objc_method_description));
*trunc = FALSE;
}
else{
memcpy(mdl,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
*left);
*left = 0;
*list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_method_description_list(mdl, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_hashEntry(
unsigned long addr,
struct _hashEntry *_hashEntry,
enum bool *trunc,
struct section_info *objc_sections,
unsigned long nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
unsigned long left, i;
memset(_hashEntry, '\0', sizeof(struct _hashEntry));
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].s.addr &&
addr < objc_sections[i].s.addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].s.addr);
if(left >= sizeof(struct _hashEntry)){
memcpy(_hashEntry,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
sizeof(struct _hashEntry));
*trunc = FALSE;
}
else{
memcpy(_hashEntry,
objc_sections[i].contents +
(addr - objc_sections[i].s.addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_hashEntry(_hashEntry, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}