From 6c1499940130a408a8cd3d4b9c9e3510861860cb Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Thu, 16 Apr 2015 17:19:59 +0000 Subject: [PATCH] For llvm-objdump added support for printing Objc1 32-bit runtime meta data with the existing -objc-meta-data and -macho options for Mach-O files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235119 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Inputs/Objc1.32bit.exe.macho-i386 | Bin 0 -> 26256 bytes .../X86/Inputs/Objc1.32bit.obj.macho-i386 | Bin 0 -> 55784 bytes .../X86/macho-objc-meta-data.test | 285 ++++++ tools/llvm-objdump/MachODump.cpp | 847 +++++++++++++++++- 4 files changed, 1121 insertions(+), 11 deletions(-) create mode 100755 test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.exe.macho-i386 create mode 100644 test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.obj.macho-i386 diff --git a/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.exe.macho-i386 b/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.exe.macho-i386 new file mode 100755 index 0000000000000000000000000000000000000000..72b7ea83011a50ca005c3ca6976dd22eb1302ed7 GIT binary patch literal 26256 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 n2Ir+jlSections->size(); SectIdx++) { uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); + if (objc_only) { + StringRef SectName; + ((*(info->Sections))[SectIdx]).getName(SectName); + DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); + StringRef SegName = info->O->getSectionFinalSegmentName(Ref); + if (SegName != "__OBJC" && SectName != "__cstring") + continue; + } if (Address >= SectAddress && Address < SectAddress + SectSize) { S = (*(info->Sections))[SectIdx]; offset = Address - SectAddress; @@ -2425,8 +2435,9 @@ static const char *get_pointer_64(uint64_t Address, uint32_t &offset, static const char *get_pointer_32(uint32_t Address, uint32_t &offset, uint32_t &left, SectionRef &S, - DisassembleInfo *info) { - return get_pointer_64(Address, offset, left, S, info); + DisassembleInfo *info, + bool objc_only = false) { + return get_pointer_64(Address, offset, left, S, info, objc_only); } // get_symbol_64() returns the name of a symbol (or nullptr) and the address of @@ -2705,6 +2716,10 @@ struct objc_image_info32 { uint32_t version; uint32_t flags; }; +struct imageInfo_t { + uint32_t version; + uint32_t flags; +}; /* masks for objc_image_info.flags */ #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) @@ -2719,6 +2734,101 @@ struct message_ref32 { uint32_t sel; /* SEL (32-bit pointer) */ }; +// Objective-C 1 (32-bit only) meta data structs. + +struct objc_module_t { + uint32_t version; + uint32_t size; + uint32_t name; /* char * (32-bit pointer) */ + uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ +}; + +struct objc_symtab_t { + uint32_t sel_ref_cnt; + uint32_t refs; /* SEL * (32-bit pointer) */ + uint16_t cls_def_cnt; + uint16_t cat_def_cnt; + // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ +}; + +struct objc_class_t { + uint32_t isa; /* struct objc_class * (32-bit pointer) */ + uint32_t super_class; /* struct objc_class * (32-bit pointer) */ + uint32_t name; /* const char * (32-bit pointer) */ + int32_t version; + int32_t info; + int32_t instance_size; + uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ + uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ + uint32_t cache; /* struct objc_cache * (32-bit pointer) */ + uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ +}; + +#define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) +// class is not a metaclass +#define CLS_CLASS 0x1 +// class is a metaclass +#define CLS_META 0x2 + +struct objc_category_t { + uint32_t category_name; /* char * (32-bit pointer) */ + uint32_t class_name; /* char * (32-bit pointer) */ + uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ + uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ + uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ +}; + +struct objc_ivar_t { + uint32_t ivar_name; /* char * (32-bit pointer) */ + uint32_t ivar_type; /* char * (32-bit pointer) */ + int32_t ivar_offset; +}; + +struct objc_ivar_list_t { + int32_t ivar_count; + // struct objc_ivar_t ivar_list[1]; /* variable length structure */ +}; + +struct objc_method_list_t { + uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ + int32_t method_count; + // struct objc_method_t method_list[1]; /* variable length structure */ +}; + +struct objc_method_t { + uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ + uint32_t method_types; /* char * (32-bit pointer) */ + uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) + (32-bit pointer) */ +}; + +struct objc_protocol_list_t { + uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ + int32_t count; + // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * + // (32-bit pointer) */ +}; + +struct objc_protocol_t { + uint32_t isa; /* struct objc_class * (32-bit pointer) */ + uint32_t protocol_name; /* char * (32-bit pointer) */ + uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ + uint32_t instance_methods; /* struct objc_method_description_list * + (32-bit pointer) */ + uint32_t class_methods; /* struct objc_method_description_list * + (32-bit pointer) */ +}; + +struct objc_method_description_list_t { + int32_t count; + // struct objc_method_description_t list[1]; +}; + +struct objc_method_description_t { + uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ + uint32_t types; /* char * (32-bit pointer) */ +}; + inline void swapStruct(struct cfstring64_t &cfs) { sys::swapByteOrder(cfs.isa); sys::swapByteOrder(cfs.flags); @@ -2895,6 +3005,11 @@ inline void swapStruct(struct objc_image_info32 &o) { sys::swapByteOrder(o.flags); } +inline void swapStruct(struct imageInfo_t &o) { + sys::swapByteOrder(o.version); + sys::swapByteOrder(o.flags); +} + inline void swapStruct(struct message_ref64 &mr) { sys::swapByteOrder(mr.imp); sys::swapByteOrder(mr.sel); @@ -2905,6 +3020,84 @@ inline void swapStruct(struct message_ref32 &mr) { sys::swapByteOrder(mr.sel); } +inline void swapStruct(struct objc_module_t &module) { + sys::swapByteOrder(module.version); + sys::swapByteOrder(module.size); + sys::swapByteOrder(module.name); + sys::swapByteOrder(module.symtab); +}; + +inline void swapStruct(struct objc_symtab_t &symtab) { + sys::swapByteOrder(symtab.sel_ref_cnt); + sys::swapByteOrder(symtab.refs); + sys::swapByteOrder(symtab.cls_def_cnt); + sys::swapByteOrder(symtab.cat_def_cnt); +}; + +inline void swapStruct(struct objc_class_t &objc_class) { + sys::swapByteOrder(objc_class.isa); + sys::swapByteOrder(objc_class.super_class); + sys::swapByteOrder(objc_class.name); + sys::swapByteOrder(objc_class.version); + sys::swapByteOrder(objc_class.info); + sys::swapByteOrder(objc_class.instance_size); + sys::swapByteOrder(objc_class.ivars); + sys::swapByteOrder(objc_class.methodLists); + sys::swapByteOrder(objc_class.cache); + sys::swapByteOrder(objc_class.protocols); +}; + +inline void swapStruct(struct objc_category_t &objc_category) { + sys::swapByteOrder(objc_category.category_name); + sys::swapByteOrder(objc_category.class_name); + sys::swapByteOrder(objc_category.instance_methods); + sys::swapByteOrder(objc_category.class_methods); + sys::swapByteOrder(objc_category.protocols); +} + +inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { + sys::swapByteOrder(objc_ivar_list.ivar_count); +} + +inline void swapStruct(struct objc_ivar_t &objc_ivar) { + sys::swapByteOrder(objc_ivar.ivar_name); + sys::swapByteOrder(objc_ivar.ivar_type); + sys::swapByteOrder(objc_ivar.ivar_offset); +}; + +inline void swapStruct(struct objc_method_list_t &method_list) { + sys::swapByteOrder(method_list.obsolete); + sys::swapByteOrder(method_list.method_count); +} + +inline void swapStruct(struct objc_method_t &method) { + sys::swapByteOrder(method.method_name); + sys::swapByteOrder(method.method_types); + sys::swapByteOrder(method.method_imp); +} + +inline void swapStruct(struct objc_protocol_list_t &protocol_list) { + sys::swapByteOrder(protocol_list.next); + sys::swapByteOrder(protocol_list.count); +} + +inline void swapStruct(struct objc_protocol_t &protocol) { + sys::swapByteOrder(protocol.isa); + sys::swapByteOrder(protocol.protocol_name); + sys::swapByteOrder(protocol.protocol_list); + sys::swapByteOrder(protocol.instance_methods); + sys::swapByteOrder(protocol.class_methods); +} + +inline void swapStruct(struct objc_method_description_list_t &mdl) { + sys::swapByteOrder(mdl.count); +} + +inline void swapStruct(struct objc_method_description_t &md) { + sys::swapByteOrder(md.name); + sys::swapByteOrder(md.types); +} + static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, struct DisassembleInfo *info); @@ -3248,10 +3441,9 @@ static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, const char *indent) { struct method_list32_t ml; struct method32_t m; - const char *r; + const char *r, *name; uint32_t offset, xoffset, left, i; SectionRef S, xS; - const char *name; r = get_pointer_32(p, offset, left, S, info); if (r == nullptr) @@ -3306,6 +3498,78 @@ static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, } } +static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { + uint32_t offset, left, xleft; + SectionRef S; + struct objc_method_list_t method_list; + struct objc_method_t method; + const char *r, *methods, *name, *SymbolName; + int32_t i; + + r = get_pointer_32(p, offset, left, S, info, true); + if (r == nullptr) + return true; + + outs() << "\n"; + if (left > sizeof(struct objc_method_list_t)) { + memcpy(&method_list, r, sizeof(struct objc_method_list_t)); + } else { + outs() << "\t\t objc_method_list extends past end of the section\n"; + memset(&method_list, '\0', sizeof(struct objc_method_list_t)); + memcpy(&method_list, r, left); + } + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(method_list); + + outs() << "\t\t obsolete " + << format("0x%08" PRIx32, method_list.obsolete) << "\n"; + outs() << "\t\t method_count " << method_list.method_count << "\n"; + + methods = r + sizeof(struct objc_method_list_t); + for (i = 0; i < method_list.method_count; i++) { + if ((i + 1) * sizeof(struct objc_method_t) > left) { + outs() << "\t\t remaining method's extend past the of the section\n"; + break; + } + memcpy(&method, methods + i * sizeof(struct objc_method_t), + sizeof(struct objc_method_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(method); + + outs() << "\t\t method_name " + << format("0x%08" PRIx32, method.method_name); + if (info->verbose) { + name = get_pointer_32(method.method_name, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t method_types " + << format("0x%08" PRIx32, method.method_types); + if (info->verbose) { + name = get_pointer_32(method.method_types, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t method_imp " + << format("0x%08" PRIx32, method.method_imp) << " "; + if (info->verbose) { + SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); + if (SymbolName != nullptr) + outs() << SymbolName; + } + outs() << "\n"; + } + return false; +} + static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { struct protocol_list64_t pl; uint64_t q, n_value; @@ -3511,6 +3775,196 @@ static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { } } +static void print_indent(uint32_t indent) { + for (uint32_t i = 0; i < indent;) { + if (indent - i >= 8) { + outs() << "\t"; + i += 8; + } else { + for (uint32_t j = i; j < indent; j++) + outs() << " "; + return; + } + } +} + +static bool print_method_description_list(uint32_t p, uint32_t indent, + struct DisassembleInfo *info) { + uint32_t offset, left, xleft; + SectionRef S; + struct objc_method_description_list_t mdl; + struct objc_method_description_t md; + const char *r, *list, *name; + int32_t i; + + r = get_pointer_32(p, offset, left, S, info, true); + if (r == nullptr) + return true; + + outs() << "\n"; + if (left > sizeof(struct objc_method_description_list_t)) { + memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); + } else { + print_indent(indent); + outs() << " objc_method_description_list extends past end of the section\n"; + memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); + memcpy(&mdl, r, left); + } + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(mdl); + + print_indent(indent); + outs() << " count " << mdl.count << "\n"; + + list = r + sizeof(struct objc_method_description_list_t); + for (i = 0; i < mdl.count; i++) { + if ((i + 1) * sizeof(struct objc_method_description_t) > left) { + print_indent(indent); + outs() << " remaining list entries extend past the of the section\n"; + break; + } + print_indent(indent); + outs() << " list[" << i << "]\n"; + memcpy(&md, list + i * sizeof(struct objc_method_description_t), + sizeof(struct objc_method_description_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(md); + + print_indent(indent); + outs() << " name " << format("0x%08" PRIx32, md.name); + if (info->verbose) { + name = get_pointer_32(md.name, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + print_indent(indent); + outs() << " types " << format("0x%08" PRIx32, md.types); + if (info->verbose) { + name = get_pointer_32(md.types, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + } + return false; +} + +static bool print_protocol_list(uint32_t p, uint32_t indent, + struct DisassembleInfo *info); + +static bool print_protocol(uint32_t p, uint32_t indent, + struct DisassembleInfo *info) { + uint32_t offset, left; + SectionRef S; + struct objc_protocol_t protocol; + const char *r, *name; + + r = get_pointer_32(p, offset, left, S, info, true); + if (r == nullptr) + return true; + + outs() << "\n"; + if (left >= sizeof(struct objc_protocol_t)) { + memcpy(&protocol, r, sizeof(struct objc_protocol_t)); + } else { + print_indent(indent); + outs() << " Protocol extends past end of the section\n"; + memset(&protocol, '\0', sizeof(struct objc_protocol_t)); + memcpy(&protocol, r, left); + } + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(protocol); + + print_indent(indent); + outs() << " isa " << format("0x%08" PRIx32, protocol.isa) + << "\n"; + + print_indent(indent); + outs() << " protocol_name " + << format("0x%08" PRIx32, protocol.protocol_name); + if (info->verbose) { + name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + print_indent(indent); + outs() << " protocol_list " + << format("0x%08" PRIx32, protocol.protocol_list); + if (print_protocol_list(protocol.protocol_list, indent + 4, info)) + outs() << " (not in an __OBJC section)\n"; + + print_indent(indent); + outs() << " instance_methods " + << format("0x%08" PRIx32, protocol.instance_methods); + if (print_method_description_list(protocol.instance_methods, indent, info)) + outs() << " (not in an __OBJC section)\n"; + + print_indent(indent); + outs() << " class_methods " + << format("0x%08" PRIx32, protocol.class_methods); + if (print_method_description_list(protocol.class_methods, indent, info)) + outs() << " (not in an __OBJC section)\n"; + + return false; +} + +static bool print_protocol_list(uint32_t p, uint32_t indent, + struct DisassembleInfo *info) { + uint32_t offset, left, l; + SectionRef S; + struct objc_protocol_list_t protocol_list; + const char *r, *list; + int32_t i; + + r = get_pointer_32(p, offset, left, S, info, true); + if (r == nullptr) + return true; + + outs() << "\n"; + if (left > sizeof(struct objc_protocol_list_t)) { + memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); + } else { + outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; + memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); + memcpy(&protocol_list, r, left); + } + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(protocol_list); + + print_indent(indent); + outs() << " next " << format("0x%08" PRIx32, protocol_list.next) + << "\n"; + print_indent(indent); + outs() << " count " << protocol_list.count << "\n"; + + list = r + sizeof(struct objc_protocol_list_t); + for (i = 0; i < protocol_list.count; i++) { + if ((i + 1) * sizeof(uint32_t) > left) { + outs() << "\t\t remaining list entries extend past the of the section\n"; + break; + } + memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(l); + + print_indent(indent); + outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); + if (print_protocol(l, indent, info)) + outs() << "(not in an __OBJC section)\n"; + } + return false; +} + static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { struct ivar_list64_t il; struct ivar64_t i; @@ -4155,6 +4609,166 @@ static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { } } +static void print_objc_class_t(struct objc_class_t *objc_class, + struct DisassembleInfo *info) { + uint32_t offset, left, xleft; + const char *name, *p, *ivar_list; + SectionRef S; + int32_t i; + struct objc_ivar_list_t objc_ivar_list; + struct objc_ivar_t ivar; + + outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); + if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { + name = get_pointer_32(objc_class->isa, offset, left, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t super_class " + << format("0x%08" PRIx32, objc_class->super_class); + if (info->verbose) { + name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); + if (info->verbose) { + name = get_pointer_32(objc_class->name, offset, left, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) + << "\n"; + + outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); + if (info->verbose) { + if (CLS_GETINFO(objc_class, CLS_CLASS)) + outs() << " CLS_CLASS"; + else if (CLS_GETINFO(objc_class, CLS_META)) + outs() << " CLS_META"; + } + outs() << "\n"; + + outs() << "\t instance_size " + << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; + + p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); + outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); + if (p != nullptr) { + if (left > sizeof(struct objc_ivar_list_t)) { + outs() << "\n"; + memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); + } else { + outs() << " (entends past the end of the section)\n"; + memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); + memcpy(&objc_ivar_list, p, left); + } + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(objc_ivar_list); + outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; + ivar_list = p + sizeof(struct objc_ivar_list_t); + for (i = 0; i < objc_ivar_list.ivar_count; i++) { + if ((i + 1) * sizeof(struct objc_ivar_t) > left) { + outs() << "\t\t remaining ivar's extend past the of the section\n"; + break; + } + memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), + sizeof(struct objc_ivar_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(ivar); + + outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); + if (info->verbose) { + name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); + if (info->verbose) { + name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", xleft, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t ivar_offset " + << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; + } + } else { + outs() << " (not in an __OBJC section)\n"; + } + + outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); + if (print_method_list(objc_class->methodLists, info)) + outs() << " (not in an __OBJC section)\n"; + + outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) + << "\n"; + + outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); + if (print_protocol_list(objc_class->protocols, 16, info)) + outs() << " (not in an __OBJC section)\n"; +} + +static void print_objc_objc_category_t(struct objc_category_t *objc_category, + struct DisassembleInfo *info) { + uint32_t offset, left; + const char *name; + SectionRef S; + + outs() << "\t category name " + << format("0x%08" PRIx32, objc_category->category_name); + if (info->verbose) { + name = get_pointer_32(objc_category->category_name, offset, left, S, info, + true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t\t class name " + << format("0x%08" PRIx32, objc_category->class_name); + if (info->verbose) { + name = + get_pointer_32(objc_category->class_name, offset, left, S, info, true); + if (name != nullptr) + outs() << format(" %.*s", left, name); + else + outs() << " (not in an __OBJC section)"; + } + outs() << "\n"; + + outs() << "\t instance methods " + << format("0x%08" PRIx32, objc_category->instance_methods); + if (print_method_list(objc_category->instance_methods, info)) + outs() << " (not in an __OBJC section)\n"; + + outs() << "\t class methods " + << format("0x%08" PRIx32, objc_category->class_methods); + if (print_method_list(objc_category->class_methods, info)) + outs() << " (not in an __OBJC section)\n"; +} + static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { struct category64_t c; const char *r; @@ -4513,6 +5127,41 @@ static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { outs() << "\n"; } +static void print_image_info(SectionRef S, struct DisassembleInfo *info) { + uint32_t left, offset, p; + struct imageInfo_t o; + const char *r; + + StringRef SectName; + S.getName(SectName); + DataRefImpl Ref = S.getRawDataRefImpl(); + StringRef SegName = info->O->getSectionFinalSegmentName(Ref); + outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; + p = S.getAddress(); + r = get_pointer_32(p, offset, left, S, info); + if (r == nullptr) + return; + memset(&o, '\0', sizeof(struct imageInfo_t)); + if (left < sizeof(struct imageInfo_t)) { + memcpy(&o, r, left); + outs() << " (imageInfo entends past the end of the section)\n"; + } else + memcpy(&o, r, sizeof(struct imageInfo_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(o); + outs() << " version " << o.version << "\n"; + outs() << " flags " << format("0x%" PRIx32, o.flags); + if (o.flags & 0x1) + outs() << " F&C"; + if (o.flags & 0x2) + outs() << " GC"; + if (o.flags & 0x4) + outs() << " GC-only"; + else + outs() << " RR"; + outs() << "\n"; +} + static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { SymbolAddressMap AddrMap; if (verbose) @@ -4711,13 +5360,189 @@ static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { } static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { + uint32_t i, j, p, offset, xoffset, left, defs_left, def; + const char *r, *name, *defs; + struct objc_module_t module; + SectionRef S, xS; + struct objc_symtab_t symtab; + struct objc_class_t objc_class; + struct objc_category_t objc_category; + outs() << "Objective-C segment\n"; - const SectionRef S = get_section(O, "__OBJC", "__module_info"); - if (S != SectionRef()) { - outs() << "Printing Objc1 32-bit MetaData not yet supported\n"; - return true; + S = get_section(O, "__OBJC", "__module_info"); + if (S == SectionRef()) + return false; + + SymbolAddressMap AddrMap; + if (verbose) + CreateSymbolAddressMap(O, &AddrMap); + + std::vector Sections; + for (const SectionRef &Section : O->sections()) { + StringRef SectName; + Section.getName(SectName); + Sections.push_back(Section); } - return false; + + struct DisassembleInfo info; + // Set up the block of info used by the Symbolizer call backs. + info.verbose = verbose; + info.O = O; + info.AddrMap = &AddrMap; + info.Sections = &Sections; + info.class_name = nullptr; + info.selector_name = nullptr; + info.method = nullptr; + info.demangled_name = nullptr; + info.bindtable = nullptr; + info.adrp_addr = 0; + info.adrp_inst = 0; + + for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { + p = S.getAddress() + i; + r = get_pointer_32(p, offset, left, S, &info, true); + if (r == nullptr) + return true; + memset(&module, '\0', sizeof(struct objc_module_t)); + if (left < sizeof(struct objc_module_t)) { + memcpy(&module, r, left); + outs() << " (module extends past end of __module_info section)\n"; + } else + memcpy(&module, r, sizeof(struct objc_module_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(module); + + outs() << "Module " << format("0x%" PRIx32, p) << "\n"; + outs() << " version " << module.version << "\n"; + outs() << " size " << module.size << "\n"; + outs() << " name "; + name = get_pointer_32(module.name, xoffset, left, xS, &info, true); + if (name != nullptr) + outs() << format("%.*s", left, name); + else + outs() << format("0x%08" PRIx32, module.name) + << "(not in an __OBJC section)"; + outs() << "\n"; + + r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); + if (module.symtab == 0 || r == nullptr) { + outs() << " symtab " << format("0x%08" PRIx32, module.symtab) + << " (not in an __OBJC section)\n"; + continue; + } + outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; + memset(&symtab, '\0', sizeof(struct objc_symtab_t)); + defs_left = 0; + defs = nullptr; + if (left < sizeof(struct objc_symtab_t)) { + memcpy(&symtab, r, left); + outs() << "\tsymtab extends past end of an __OBJC section)\n"; + } else { + memcpy(&symtab, r, sizeof(struct objc_symtab_t)); + if (left > sizeof(struct objc_symtab_t)) { + defs_left = left - sizeof(struct objc_symtab_t); + defs = r + sizeof(struct objc_symtab_t); + } + } + if (O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(symtab); + + outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; + r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); + outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); + if (r == nullptr) + outs() << " (not in an __OBJC section)"; + outs() << "\n"; + outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; + outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; + if (symtab.cls_def_cnt > 0) + outs() << "\tClass Definitions\n"; + for (j = 0; j < symtab.cls_def_cnt; j++) { + if ((j + 1) * sizeof(uint32_t) > defs_left) { + outs() << "\t(remaining class defs entries entends past the end of the " + << "section)\n"; + break; + } + memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(def); + + r = get_pointer_32(def, xoffset, left, xS, &info, true); + outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); + if (r != nullptr) { + if (left > sizeof(struct objc_class_t)) { + outs() << "\n"; + memcpy(&objc_class, r, sizeof(struct objc_class_t)); + } else { + outs() << " (entends past the end of the section)\n"; + memset(&objc_class, '\0', sizeof(struct objc_class_t)); + memcpy(&objc_class, r, left); + } + if (O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(objc_class); + print_objc_class_t(&objc_class, &info); + } else { + outs() << "(not in an __OBJC section)\n"; + } + + if (CLS_GETINFO(&objc_class, CLS_CLASS)) { + outs() << "\tMeta Class"; + r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); + if (r != nullptr) { + if (left > sizeof(struct objc_class_t)) { + outs() << "\n"; + memcpy(&objc_class, r, sizeof(struct objc_class_t)); + } else { + outs() << " (entends past the end of the section)\n"; + memset(&objc_class, '\0', sizeof(struct objc_class_t)); + memcpy(&objc_class, r, left); + } + if (O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(objc_class); + print_objc_class_t(&objc_class, &info); + } else { + outs() << "(not in an __OBJC section)\n"; + } + } + } + if (symtab.cat_def_cnt > 0) + outs() << "\tCategory Definitions\n"; + for (j = 0; j < symtab.cat_def_cnt; j++) { + if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { + outs() << "\t(remaining category defs entries entends past the end of " + << "the section)\n"; + break; + } + memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), + sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(def); + + r = get_pointer_32(def, xoffset, left, xS, &info, true); + outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " + << format("0x%08" PRIx32, def); + if (r != nullptr) { + if (left > sizeof(struct objc_category_t)) { + outs() << "\n"; + memcpy(&objc_category, r, sizeof(struct objc_category_t)); + } else { + outs() << " (entends past the end of the section)\n"; + memset(&objc_category, '\0', sizeof(struct objc_category_t)); + memcpy(&objc_category, r, left); + } + if (O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(objc_category); + print_objc_objc_category_t(&objc_category, &info); + } else { + outs() << "(not in an __OBJC section)\n"; + } + } + } + const SectionRef II = get_section(O, "__OBJC", "__image_info"); + if (II != SectionRef()) + print_image_info(II, &info); + + return true; } static void printObjcMetaData(MachOObjectFile *O, bool verbose) { -- 2.34.1