#include "stdio.h"
#include "string.h"
#include "mach-o/loader.h"
#include "objc/objc-runtime.h"
#include "stuff/allocate.h"
#include "stuff/bytesex.h"
#include "stuff/symbol.h"
#include "ofile_print.h"
struct objc_module_t {
uint32_t version;
uint32_t size;
uint32_t name;
uint32_t symtab;
};
struct objc_symtab_t {
uint32_t sel_ref_cnt;
uint32_t refs;
uint16_t cls_def_cnt;
uint16_t cat_def_cnt;
uint32_t defs[1];
};
struct objc_class_t {
uint32_t isa;
uint32_t super_class;
uint32_t name;
int32_t version;
int32_t info;
int32_t instance_size;
uint32_t ivars;
uint32_t methodLists;
uint32_t cache;
uint32_t protocols;
};
struct objc_category_t {
uint32_t category_name;
uint32_t class_name;
uint32_t instance_methods;
uint32_t class_methods;
uint32_t protocols;
};
struct objc_ivar_t {
uint32_t ivar_name;
uint32_t ivar_type;
int32_t ivar_offset;
};
struct objc_ivar_list_t {
int32_t ivar_count;
struct objc_ivar_t ivar_list[1];
};
struct objc_method_t {
uint32_t method_name;
uint32_t method_types;
uint32_t method_imp;
};
struct objc_method_list_t {
uint32_t obsolete;
int32_t method_count;
struct objc_method_t method_list[1];
};
struct objc_protocol_t {
uint32_t isa;
uint32_t protocol_name;
uint32_t protocol_list;
uint32_t instance_methods;
uint32_t class_methods;
};
struct objc_protocol_list_t {
uint32_t next;
int32_t count;
uint32_t list[1];
};
struct objc_method_description_t {
uint32_t name;
uint32_t types;
};
struct objc_method_description_list_t {
int32_t count;
struct objc_method_description_t list[1];
};
struct objc_string_object_t {
uint32_t isa;
uint32_t characters;
uint32_t _length;
};
typedef struct objc_string_object_t NXConstantString;
#define SIZEHASHTABLE 821
struct _hashEntry_t {
uint32_t next;
uint32_t sel;
};
struct imageInfo_t {
uint32_t version;
uint32_t flags;
};
static
void
swap_imageInfo_t(
struct imageInfo_t *o,
enum byte_sex target_byte_sex)
{
o->version = SWAP_INT(o->version);
o->flags = SWAP_INT(o->flags);
}
void
swap_objc_module_t(
struct objc_module_t *module,
enum byte_sex target_byte_sex)
{
module->version = SWAP_INT(module->version);
module->size = SWAP_INT(module->size);
module->name = SWAP_INT(module->name);
module->symtab = SWAP_INT(module->symtab);
}
void
swap_objc_symtab_t(
struct objc_symtab_t *symtab,
enum byte_sex target_byte_sex)
{
symtab->sel_ref_cnt = SWAP_INT(symtab->sel_ref_cnt);
symtab->refs = SWAP_INT(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_t(
struct objc_class_t *objc_class,
enum byte_sex target_byte_sex)
{
objc_class->isa = SWAP_INT(objc_class->isa);
objc_class->super_class = SWAP_INT(objc_class->super_class);
objc_class->name = SWAP_INT(objc_class->name);
objc_class->version = SWAP_INT(objc_class->version);
objc_class->info = SWAP_INT(objc_class->info);
objc_class->instance_size = SWAP_INT(objc_class->instance_size);
objc_class->ivars = SWAP_INT(objc_class->ivars);
objc_class->methodLists = SWAP_INT(objc_class->methodLists);
objc_class->cache = SWAP_INT(objc_class->cache);
objc_class->protocols = SWAP_INT(objc_class->protocols);
}
void
swap_objc_category_t(
struct objc_category_t *objc_category,
enum byte_sex target_byte_sex)
{
objc_category->category_name = SWAP_INT(objc_category->category_name);
objc_category->class_name = SWAP_INT(objc_category->class_name);
objc_category->instance_methods =
SWAP_INT(objc_category->instance_methods);
objc_category->class_methods =
SWAP_INT(objc_category->class_methods);
objc_category->protocols =
SWAP_INT(objc_category->protocols);
}
void
swap_objc_ivar_list_t(
struct objc_ivar_list_t *objc_ivar_list,
enum byte_sex target_byte_sex)
{
objc_ivar_list->ivar_count = SWAP_INT(objc_ivar_list->ivar_count);
}
void
swap_objc_ivar_t(
struct objc_ivar_t *objc_ivar,
enum byte_sex target_byte_sex)
{
objc_ivar->ivar_name = SWAP_INT(objc_ivar->ivar_name);
objc_ivar->ivar_type = SWAP_INT(objc_ivar->ivar_type);
objc_ivar->ivar_offset = SWAP_INT(objc_ivar->ivar_offset);
}
void
swap_objc_method_list_t(
struct objc_method_list_t *method_list,
enum byte_sex target_byte_sex)
{
method_list->obsolete = SWAP_INT(method_list->obsolete);
method_list->method_count = SWAP_INT(method_list->method_count);
}
void
swap_objc_method_t(
struct objc_method_t *method,
enum byte_sex target_byte_sex)
{
method->method_name = SWAP_INT(method->method_name);
method->method_types = SWAP_INT(method->method_types);
method->method_imp = SWAP_INT(method->method_imp);
}
void
swap_objc_protocol_list_t(
struct objc_protocol_list_t *protocol_list,
enum byte_sex target_byte_sex)
{
protocol_list->next = SWAP_INT(protocol_list->next);
protocol_list->count = SWAP_INT(protocol_list->count);
}
void
swap_objc_protocol_t(
struct objc_protocol_t *protocol,
enum byte_sex target_byte_sex)
{
protocol->isa = SWAP_INT(protocol->isa);
protocol->protocol_name = SWAP_INT(protocol->protocol_name);
protocol->protocol_list = SWAP_INT(protocol->protocol_list);
protocol->instance_methods = SWAP_INT(protocol->instance_methods);
protocol->class_methods = SWAP_INT(protocol->class_methods);
}
void
swap_objc_method_description_list_t(
struct objc_method_description_list_t *mdl,
enum byte_sex target_byte_sex)
{
mdl->count = SWAP_INT(mdl->count);
}
void
swap_objc_method_description_t(
struct objc_method_description_t *md,
enum byte_sex target_byte_sex)
{
md->name = SWAP_INT(md->name);
md->types = SWAP_INT(md->types);
}
void
swap_string_object_t(
struct objc_string_object_t *string_object,
enum byte_sex target_byte_sex)
{
string_object->isa = SWAP_INT(string_object->isa);
string_object->characters = SWAP_INT(string_object->characters);
string_object->_length = SWAP_INT(string_object->_length);
}
void
swap_hashEntry_t(
struct _hashEntry_t *_hashEntry,
enum byte_sex target_byte_sex)
{
_hashEntry->next = SWAP_INT(_hashEntry->next);
_hashEntry->sel = SWAP_INT(_hashEntry->sel);
}
struct section_info {
char *contents;
uint32_t addr;
uint32_t size;
uint32_t offset;
enum bool protected;
enum bool zerofill;
};
static void get_objc_sections(
struct load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
struct section_info **objc_sections,
uint32_t *nobjc_sections,
char *sectname,
char **sect,
uint32_t *sect_addr,
uint32_t *sect_size);
static void get_cstring_section(
struct load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
struct section_info *cstring_section_ptr);
static enum bool print_method_list(
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
struct symbol *sorted_symbols,
uint32_t nsorted_symbols,
enum bool verbose);
static enum bool print_protocol_list(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static void print_protocol(
uint32_t indent,
struct objc_protocol_t *protocol,
struct section_info *objc_sections,
uint32_t 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(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t 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(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose);
static void print_indent(
uint32_t indent);
static void *get_pointer(
uint32_t addr,
uint32_t *left,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr);
static enum bool get_symtab(
uint32_t addr,
struct objc_symtab_t *symtab,
uint32_t **defs,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_objc_class(
uint32_t addr,
struct objc_class_t *objc_class,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_objc_category(
uint32_t addr,
struct objc_category_t *objc_category,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_ivar_list(
uint32_t addr,
struct objc_ivar_list_t *objc_ivar_list,
struct objc_ivar_t **ivar_list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_method_list(
uint32_t addr,
struct objc_method_list_t *method_list,
struct objc_method_t **methods,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_protocol_list(
uint32_t addr,
struct objc_protocol_list_t *protocol_list,
uint32_t **list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_protocol(
uint32_t addr,
struct objc_protocol_t *protocol,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_method_description_list(
uint32_t addr,
struct objc_method_description_list_t *mdl,
struct objc_method_description_t **list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
static enum bool get_hashEntry(
uint32_t addr,
struct _hashEntry_t *_hashEntry,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped);
void
print_objc_segment(
struct load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
struct symbol *sorted_symbols,
uint32_t nsorted_symbols,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped, trunc;
uint32_t i, j, left, size, defs_left, def, ivar_list_left;
char *p;
struct section_info *objc_sections;
uint32_t nobjc_sections;
struct section_info cstring_section;
struct objc_module_t *modules, *m, module;
uint32_t modules_addr, modules_size;
struct objc_symtab_t symtab;
uint32_t *defs;
struct objc_class_t objc_class;
struct objc_ivar_list_t objc_ivar_list;
struct objc_ivar_t *ivar_list, ivar;
struct objc_category_t objc_category;
struct imageInfo_t *imageInfo, info;
uint32_t imageInfo_addr, imageInfo_size;
printf("Objective-C segment\n");
get_objc_sections(load_commands, ncmds, sizeofcmds, 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(load_commands, ncmds, sizeofcmds, 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_t));
for(m = modules;
(char *)m < (char *)modules + modules_size;
m = (struct objc_module_t *)((char *)m + module.size) ){
memset(&module, '\0', sizeof(struct objc_module_t));
left = modules_size - (m - modules);
size = left < sizeof(struct objc_module_t) ?
left : sizeof(struct objc_module_t);
memcpy(&module, m, size);
if(swapped)
swap_objc_module_t(&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 %u\n", module.version);
printf(" size %u\n", module.size);
if(verbose){
p = get_pointer(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 %u\n", symtab.sel_ref_cnt);
p = get_pointer(symtab.refs, &left,
objc_sections, nobjc_sections, &cstring_section);
if(p != NULL)
printf("\trefs 0x%08x", symtab.refs);
else
printf("\trefs 0x%08x (not in an " SEG_OBJC " section)\n",
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(uint32_t) > defs_left){
printf("\t(remaining class defs entries entends past "
"the end of the section)\n");
break;
}
memcpy(&def, defs + i, sizeof(uint32_t));
if(swapped)
def = SWAP_INT(def);
if(get_objc_class(def, &objc_class, &trunc, objc_sections,
nobjc_sections, host_byte_sex, swapped) == TRUE){
printf("\tdefs[%u] 0x%08x", i, 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", 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",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", objc_class.name);
if(verbose){
p = get_pointer(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 < (uint32_t)objc_ivar_list.ivar_count;
j++){
if((j + 1) * sizeof(struct objc_ivar_t) >
ivar_list_left){
printf("\t\t remaining ivar's extend past "
"the of the section\n");
break;
}
memcpy(&ivar, ivar_list + j,
sizeof(struct objc_ivar_t));
if(swapped)
swap_objc_ivar_t(&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(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((uint32_t)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[%u] 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(uint32_t) >
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(uint32_t));
if(swapped)
def = SWAP_INT(def);
if(get_objc_category(def, &objc_category, &trunc,
objc_sections, nobjc_sections,
host_byte_sex, swapped) == TRUE){
printf("\tdefs[%u] 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",
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", 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",
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",
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[%u] 0x%08x (not in an " SEG_OBJC
" section)\n", i + symtab.cls_def_cnt,
(unsigned int)def);
}
}
printf("Contents of (%s,%s) section\n", SEG_OBJC, "__image_info");
get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex,
object_addr, object_size, &objc_sections,
&nobjc_sections, "__image_info", (char **)&imageInfo,
&imageInfo_addr, &imageInfo_size);
memset(&info, '\0', sizeof(struct imageInfo_t));
if(imageInfo_size < sizeof(struct imageInfo_t)){
memcpy(&info, imageInfo, imageInfo_size);
printf(" (imageInfo entends past the end of the section)\n");
}
else
memcpy(&info, imageInfo, sizeof(struct imageInfo_t));
if(swapped)
swap_imageInfo_t(&info, host_byte_sex);
printf(" version %u\n", info.version);
printf(" flags 0x%x", info.flags);
if(info.flags & 0x1)
printf(" F&C");
if(info.flags & 0x2)
printf(" GC");
if(info.flags & 0x4)
printf(" GC-only");
else
printf(" RR");
printf("\n");
}
void
print_objc_protocol_section(
struct load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections, cstring_section;
uint32_t nobjc_sections;
struct objc_protocol_t *protocols, *p, protocol;
uint32_t protocols_addr, protocols_size;
uint32_t size, left;
printf("Contents of (" SEG_OBJC ",__protocol) section\n");
get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex,
object_addr, object_size, &objc_sections,
&nobjc_sections, "__protocol", (char **)&protocols,
&protocols_addr, &protocols_size);
if (verbose)
get_cstring_section(load_commands, ncmds, sizeofcmds, 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_t));
left = protocols_size - (p - protocols);
size = left < sizeof(struct objc_protocol_t) ?
left : sizeof(struct objc_protocol_t);
memcpy(&protocol, p, size);
if((char *)p + sizeof(struct objc_protocol_t) >
(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 load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections;
uint32_t nobjc_sections;
struct section_info cstring_section;
struct objc_string_object_t *string_objects, *s, string_object;
uint32_t string_objects_addr, string_objects_size;
uint32_t size, left;
char *p;
printf("Contents of (" SEG_OBJC ",%s) section\n", sectname);
get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex,
object_addr, object_size, &objc_sections,
&nobjc_sections, sectname, (char **)&string_objects,
&string_objects_addr, &string_objects_size);
get_cstring_section(load_commands, ncmds, sizeofcmds, 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_t));
left = string_objects_size - (s - string_objects);
size = left < sizeof(struct objc_string_object_t) ?
left : sizeof(struct objc_string_object_t);
memcpy(&string_object, s, size);
if((char *)s + sizeof(struct objc_string_object_t) >
(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_t(&string_object, host_byte_sex);
printf(" isa 0x%x\n", 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 load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
struct section_info *objc_sections, cstring_section;
uint32_t i, nobjc_sections, left;
struct _hashEntry_t **PHASH, *HASH, _hashEntry;
char *sect, *p;
uint32_t sect_addr, sect_size, phash;
printf("Contents of (" SEG_OBJC ",__runtime_setup) section\n");
get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex,
object_addr, object_size, &objc_sections,
&nobjc_sections, "__runtime_setup", §, §_addr,
§_size);
if (verbose)
get_cstring_section(load_commands, ncmds, sizeofcmds, 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_t **)sect;
for(i = 0;
i < SIZEHASHTABLE && (i + 1) * sizeof(uint32_t) < sect_size;
i++){
memcpy(&phash, PHASH + i, sizeof(uint32_t));
if(swapped)
phash = SWAP_INT(phash);
if(phash == 0)
continue;
printf("PHASH[%3u] 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_t *)(PHASH + SIZEHASHTABLE);
for(i = 0; (char *)(HASH + i) < sect + sect_size; i++){
memcpy((char *)&_hashEntry, HASH + i, sizeof(struct _hashEntry_t));
if(swapped)
swap_hashEntry_t(&_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 == 0){
printf("\n");
}
else{
if((uint32_t)_hashEntry.next < sect_addr ||
(uint32_t)_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 load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
struct section_info **objc_sections,
uint32_t *nobjc_sections,
char *sectname,
char **sect,
uint32_t *sect_addr,
uint32_t *sect_size)
{
enum byte_sex host_byte_sex;
enum bool swapped, encrypt_found;
uint32_t i, j, left, size;
struct load_command lcmd, *lc;
char *p;
struct segment_command sg;
struct section s;
struct encryption_info_command encrypt;
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;
encrypt_found = FALSE;
lc = load_commands;
for(i = 0 ; i < ncmds; i++){
memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&lcmd, host_byte_sex);
if(lcmd.cmdsize % sizeof(int32_t) != 0)
printf("load command %u size not a multiple of "
"sizeof(int32_t)\n", i);
if((char *)lc + lcmd.cmdsize >
(char *)load_commands + sizeofcmds)
printf("load command %u extends past end of load "
"commands\n", i);
left = 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 + sizeofcmds){
printf("section structure command extends past "
"end of load commands\n");
}
left = 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].addr = s.addr;
(*objc_sections)[*nobjc_sections].contents =
object_addr + s.offset;
(*objc_sections)[*nobjc_sections].offset = s.offset;
(*objc_sections)[*nobjc_sections].zerofill =
(s.flags & SECTION_TYPE) == S_ZEROFILL ? TRUE : FALSE;
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;
}
}
if(sg.flags & SG_PROTECTED_VERSION_1)
(*objc_sections)[*nobjc_sections].protected = TRUE;
else
(*objc_sections)[*nobjc_sections].protected = FALSE;
(*nobjc_sections)++;
}
if(p + sizeof(struct section) >
(char *)load_commands + sizeofcmds)
break;
p += size;
}
break;
case LC_ENCRYPTION_INFO:
memset((char *)&encrypt, '\0',
sizeof(struct encryption_info_command));
size = left < sizeof(struct encryption_info_command) ?
left : sizeof(struct encryption_info_command);
memcpy((char *)&encrypt, (char *)lc, size);
if(swapped)
swap_encryption_command(&encrypt, host_byte_sex);
encrypt_found = TRUE;
break;
}
if(lcmd.cmdsize == 0){
printf("load command %u 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 + sizeofcmds)
break;
}
if(encrypt_found == TRUE && encrypt.cryptid != 0){
for(i = 0; i < *nobjc_sections; i++){
if((*objc_sections)[i].size > 0 &&
(*objc_sections)[i].zerofill == FALSE){
if((*objc_sections)[i].offset >
encrypt.cryptoff + encrypt.cryptsize){
;
}
else if((*objc_sections)[i].offset +
(*objc_sections)[i].size < encrypt.cryptoff){
;
}
else{
(*objc_sections)[i].protected = TRUE;
}
}
}
}
}
static
void
get_cstring_section(
struct load_command *load_commands,
uint32_t ncmds,
uint32_t sizeofcmds,
enum byte_sex object_byte_sex,
char *object_addr,
uint32_t object_size,
struct section_info *cstring_section)
{
enum byte_sex host_byte_sex;
enum bool swapped;
uint32_t 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 < ncmds; i++){
memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&lcmd, host_byte_sex);
if(lcmd.cmdsize % sizeof(int32_t) != 0)
printf("load command %u size not a multiple of "
"sizeof(int32_t)\n", i);
if((char *)lc + lcmd.cmdsize >
(char *)load_commands + sizeofcmds)
printf("load command %u extends past end of load "
"commands\n", i);
left = 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 + sizeofcmds){
printf("section structure command extends past "
"end of load commands\n");
}
left = 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->addr = s.addr;
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;
if(sg.flags & SG_PROTECTED_VERSION_1)
cstring_section->protected = TRUE;
else
cstring_section->protected = FALSE;
return;
}
if(p + sizeof(struct section) >
(char *)load_commands + sizeofcmds)
break;
p += size;
}
break;
}
if(lcmd.cmdsize == 0){
printf("load command %u 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 + sizeofcmds)
break;
}
}
static
enum bool
print_method_list(
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
struct symbol *sorted_symbols,
uint32_t nsorted_symbols,
enum bool verbose)
{
struct objc_method_t *methods, method;
struct objc_method_list_t method_list;
enum bool trunc;
uint32_t 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 < (uint32_t)method_list.method_count; i++){
if((i + 1) * sizeof(struct objc_method_t) > methods_left){
printf("\t\t remaining method's extend past the of the "
"section\n");
break;
}
memcpy(&method, methods + i, sizeof(struct objc_method_t));
if(swapped)
swap_objc_method_t(&method, host_byte_sex);
printf("\t\t method_name 0x%08x", 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", 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 ", method.method_imp);
if(verbose)
print_label(method.method_imp, FALSE, sorted_symbols,
nsorted_symbols);
printf("\n");
}
return(TRUE);
}
static
enum bool
print_protocol_list(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
uint32_t *list;
struct objc_protocol_t protocol;
struct objc_protocol_list_t protocol_list;
enum bool trunc;
uint32_t l, 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 %u\n", protocol_list.count);
for(i = 0; i < protocol_list.count; i++){
if((i + 1) * sizeof(uint32_t) > list_left){
print_indent(indent);
printf(" remaining list entries extend past the of the "
"section\n");
break;
}
memcpy(&l, list + i, sizeof(uint32_t));
if(swapped)
l = SWAP_INT(l);
print_indent(indent);
printf(" list[%u] 0x%08x", i, l);
if(get_protocol(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");
}
print_protocol(indent, &protocol,
objc_sections, nobjc_sections, cstring_section_ptr,
host_byte_sex, swapped, verbose);
}
return(TRUE);
}
static
void
print_protocol(
uint32_t indent,
struct objc_protocol_t *protocol,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
uint32_t 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(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t 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_t mdl;
struct objc_method_description_t *list, md;
enum bool trunc;
uint32_t 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 < (uint32_t)mdl.count; i++){
if((i + 1) * sizeof(struct objc_method_description_t) > list_left){
print_indent(indent);
printf(" remaining list entries extend past the of the "
"section\n");
break;
}
print_indent(indent);
printf(" list[%u]\n", i);
memcpy(&md, list + i, sizeof(struct objc_method_description_t));
if(swapped)
swap_objc_method_description_t(&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(
uint32_t indent,
uint32_t addr,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr,
enum byte_sex host_byte_sex,
enum bool swapped,
enum bool verbose)
{
struct _hashEntry_t _hashEntry;
enum bool trunc;
uint32_t left;
char *p;
if(get_hashEntry(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 == 0){
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(
uint32_t indent)
{
uint32_t 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(
uint32_t addr,
uint32_t *left,
struct section_info *objc_sections,
uint32_t nobjc_sections,
struct section_info *cstring_section_ptr)
{
void* returnValue = NULL;
uint32_t i;
if(addr >= cstring_section_ptr->addr &&
addr < cstring_section_ptr->addr + cstring_section_ptr->size){
*left = cstring_section_ptr->size -
(addr - cstring_section_ptr->addr);
if(cstring_section_ptr->protected == TRUE)
returnValue = "some string from a protected section";
else
returnValue = (cstring_section_ptr->contents +
(addr - cstring_section_ptr->addr));
}
for(i = 0; returnValue != NULL && i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
returnValue = (objc_sections[i].contents +
(addr - objc_sections[i].addr));
}
}
return(returnValue);
}
static
enum bool
get_symtab(
uint32_t addr,
struct objc_symtab_t *symtab,
uint32_t **defs,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t i;
memset(symtab, '\0', sizeof(struct objc_symtab_t));
if(addr == 0)
return(0);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(*left >= sizeof(struct objc_symtab_t) - sizeof(uint32_t)){
memcpy(symtab,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_symtab_t) - sizeof(uint32_t));
*left -= sizeof(struct objc_symtab_t) - sizeof(uint32_t);
*defs = (uint32_t *)(objc_sections[i].contents +
(addr - objc_sections[i].addr) +
sizeof(struct objc_symtab_t) -
sizeof(uint32_t));
*trunc = FALSE;
}
else{
memcpy(symtab,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
*left);
*left = 0;
*defs = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_symtab_t(symtab, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_objc_class(
uint32_t addr,
struct objc_class_t *objc_class,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t left, i;
memset(objc_class, '\0', sizeof(struct objc_class_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(left >= sizeof(struct objc_class_t)){
memcpy(objc_class,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_class_t));
*trunc = FALSE;
}
else{
memcpy(objc_class,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_class_t(objc_class, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_objc_category(
uint32_t addr,
struct objc_category_t *objc_category,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t left, i;
memset(objc_category, '\0', sizeof(struct objc_category_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(left >= sizeof(struct objc_category_t)){
memcpy(objc_category,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_category_t));
*trunc = FALSE;
}
else{
memcpy(objc_category,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_category_t(objc_category, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_ivar_list(
uint32_t addr,
struct objc_ivar_list_t *objc_ivar_list,
struct objc_ivar_t **ivar_list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t i;
memset(objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(*left >= sizeof(struct objc_ivar_list_t) -
sizeof(struct objc_ivar_t)){
memcpy(objc_ivar_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_ivar_list_t) -
sizeof(struct objc_ivar_t));
*left -= sizeof(struct objc_ivar_list_t) -
sizeof(struct objc_ivar_t);
*ivar_list = (struct objc_ivar_t *)
(objc_sections[i].contents +
(addr - objc_sections[i].addr) +
sizeof(struct objc_ivar_list_t) -
sizeof(struct objc_ivar_t));
*trunc = FALSE;
}
else{
memcpy(objc_ivar_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
*left);
*left = 0;
*ivar_list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_ivar_list_t(objc_ivar_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_method_list(
uint32_t addr,
struct objc_method_list_t *method_list,
struct objc_method_t **methods,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t i;
memset(method_list, '\0', sizeof(struct objc_method_list_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(*left >= sizeof(struct objc_method_list_t) -
sizeof(struct objc_method_t)){
memcpy(method_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_method_list_t) -
sizeof(struct objc_method_t));
*left -= sizeof(struct objc_method_list_t) -
sizeof(struct objc_method_t);
*methods = (struct objc_method_t *)
(objc_sections[i].contents +
(addr - objc_sections[i].addr) +
sizeof(struct objc_method_list_t) -
sizeof(struct objc_method_t));
*trunc = FALSE;
}
else{
memcpy(method_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
*left);
*left = 0;
*methods = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_method_list_t(method_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_protocol_list(
uint32_t addr,
struct objc_protocol_list_t *protocol_list,
uint32_t **list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t i;
memset(protocol_list, '\0', sizeof(struct objc_protocol_list_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(*left >= sizeof(struct objc_protocol_list_t) -
sizeof(uint32_t)){
memcpy(protocol_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_protocol_list_t) -
sizeof(uint32_t));
*left -= sizeof(struct objc_protocol_list_t) -
sizeof(uint32_t);
*list = (uint32_t *)
(objc_sections[i].contents +
(addr - objc_sections[i].addr) +
sizeof(struct objc_protocol_list_t) -
sizeof(uint32_t));
*trunc = FALSE;
}
else{
memcpy(protocol_list,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
*left);
*left = 0;
*list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_protocol_list_t(protocol_list, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_protocol(
uint32_t addr,
struct objc_protocol_t *protocol,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t left, i;
memset(protocol, '\0', sizeof(struct objc_protocol_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(left >= sizeof(struct objc_protocol_t)){
memcpy(protocol,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_protocol_t));
*trunc = FALSE;
}
else{
memcpy(protocol,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_objc_protocol_t(protocol, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_method_description_list(
uint32_t addr,
struct objc_method_description_list_t *mdl,
struct objc_method_description_t **list,
uint32_t *left,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t i;
memset(mdl, '\0', sizeof(struct objc_method_description_list_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
*left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(*left >= sizeof(struct objc_method_description_list_t) -
sizeof(struct objc_method_description_t)){
memcpy(mdl,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct objc_method_description_list_t) -
sizeof(struct objc_method_description_t));
*left -= sizeof(struct objc_method_description_list_t) -
sizeof(struct objc_method_description_t);
*list = (struct objc_method_description_t *)
(objc_sections[i].contents +
(addr - objc_sections[i].addr) +
sizeof(struct objc_method_description_list_t) -
sizeof(struct objc_method_description_t));
*trunc = FALSE;
}
else{
memcpy(mdl,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
*left);
*left = 0;
*list = NULL;
*trunc = TRUE;
}
if(swapped)
swap_objc_method_description_list_t(mdl, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}
static
enum bool
get_hashEntry(
uint32_t addr,
struct _hashEntry_t *_hashEntry,
enum bool *trunc,
struct section_info *objc_sections,
uint32_t nobjc_sections,
enum byte_sex host_byte_sex,
enum bool swapped)
{
uint32_t left, i;
memset(_hashEntry, '\0', sizeof(struct _hashEntry_t));
if(addr == 0)
return(FALSE);
for(i = 0; i < nobjc_sections; i++){
if(addr >= objc_sections[i].addr &&
addr < objc_sections[i].addr + objc_sections[i].size){
left = objc_sections[i].size -
(addr - objc_sections[i].addr);
if(left >= sizeof(struct _hashEntry_t)){
memcpy(_hashEntry,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
sizeof(struct _hashEntry_t));
*trunc = FALSE;
}
else{
memcpy(_hashEntry,
objc_sections[i].contents +
(addr - objc_sections[i].addr),
left);
*trunc = TRUE;
}
if(swapped)
swap_hashEntry_t(_hashEntry, host_byte_sex);
return(TRUE);
}
}
return(FALSE);
}