From: Kevin Enderby Date: Thu, 16 Apr 2015 17:19:59 +0000 (+0000) Subject: For llvm-objdump added support for printing Objc1 32-bit runtime meta data X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6c1499940130a408a8cd3d4b9c9e3510861860cb;p=oota-llvm.git 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 --- 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 00000000000..72b7ea83011 Binary files /dev/null and b/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.exe.macho-i386 differ diff --git a/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.obj.macho-i386 b/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.obj.macho-i386 new file mode 100644 index 00000000000..7f62ad1daea Binary files /dev/null and b/test/tools/llvm-objdump/X86/Inputs/Objc1.32bit.obj.macho-i386 differ diff --git a/test/tools/llvm-objdump/X86/macho-objc-meta-data.test b/test/tools/llvm-objdump/X86/macho-objc-meta-data.test index c961351b8d9..1ff42df7e1a 100644 --- a/test/tools/llvm-objdump/X86/macho-objc-meta-data.test +++ b/test/tools/llvm-objdump/X86/macho-objc-meta-data.test @@ -2,6 +2,8 @@ # RUN: llvm-objdump -m -objc-meta-data %p/Inputs/Objc2.64bit.obj.macho-x86_64 | FileCheck %s -check-prefix=OBJC2_64BIT_OBJ # RUN: llvm-objdump -m -objc-meta-data %p/Inputs/Objc2.32bit.exe.macho-i386 | FileCheck %s -check-prefix=OBJC2_32BIT_EXE # RUN: llvm-objdump -m -objc-meta-data %p/Inputs/Objc2.32bit.obj.macho-i386 | FileCheck %s -check-prefix=OBJC2_32BIT_OBJ +# RUN: llvm-objdump -m -objc-meta-data %p/Inputs/Objc1.32bit.exe.macho-i386 | FileCheck %s -check-prefix=OBJC1_32BIT_EXE +# RUN: llvm-objdump -m -objc-meta-data %p/Inputs/Objc1.32bit.obj.macho-i386 | FileCheck %s -check-prefix=OBJC1_32BIT_OBJ OBJC2_64BIT_EXE: Contents of (__DATA,__objc_classlist) section OBJC2_64BIT_EXE: 0000000100002028 0x1000029f0 @@ -613,3 +615,286 @@ OBJC2_32BIT_OBJ: 0000393c 0x3914 _OBJC_CLASS_$_DetailViewController OBJC2_32BIT_OBJ: Contents of (__DATA,__objc_imageinfo) section OBJC2_32BIT_OBJ: version 0 OBJC2_32BIT_OBJ: flags 0x20 + +OBJC1_32BIT_EXE: Objective-C segment +OBJC1_32BIT_EXE: Module 0x4128 +OBJC1_32BIT_EXE: version 7 +OBJC1_32BIT_EXE: size 16 +OBJC1_32BIT_EXE: name +OBJC1_32BIT_EXE: symtab 0x00004108 +OBJC1_32BIT_EXE: sel_ref_cnt 0 +OBJC1_32BIT_EXE: refs 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: cls_def_cnt 1 +OBJC1_32BIT_EXE: cat_def_cnt 0 +OBJC1_32BIT_EXE: Class Definitions +OBJC1_32BIT_EXE: defs[0] 0x00004000 +OBJC1_32BIT_EXE: isa 0x00004068 +OBJC1_32BIT_EXE: super_class 0x000025b8 NSViewController +OBJC1_32BIT_EXE: name 0x000025c9 ViewController +OBJC1_32BIT_EXE: version 0x00000000 +OBJC1_32BIT_EXE: info 0x00000001 CLS_CLASS +OBJC1_32BIT_EXE: instance_size 0x00000034 +OBJC1_32BIT_EXE: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: methods 0x000040c8 +OBJC1_32BIT_EXE: obsolete 0x00000000 +OBJC1_32BIT_EXE: method_count 2 +OBJC1_32BIT_EXE: method_name 0x0000257c viewDidLoad +OBJC1_32BIT_EXE: method_types 0x0000259e v8@0:4 +OBJC1_32BIT_EXE: method_imp 0x00002430 +OBJC1_32BIT_EXE: method_name 0x00002588 setRepresentedObject: +OBJC1_32BIT_EXE: method_types 0x000025a5 v12@0:4@8 +OBJC1_32BIT_EXE: method_imp 0x00002480 +OBJC1_32BIT_EXE: cache 0x00000000 +OBJC1_32BIT_EXE: protocols 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: Meta Class +OBJC1_32BIT_EXE: isa 0x000025af NSObject +OBJC1_32BIT_EXE: super_class 0x000025b8 NSViewController +OBJC1_32BIT_EXE: name 0x000025c9 ViewController +OBJC1_32BIT_EXE: version 0x00000000 +OBJC1_32BIT_EXE: info 0x00000002 CLS_META +OBJC1_32BIT_EXE: instance_size 0x00000030 +OBJC1_32BIT_EXE: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: cache 0x00000000 +OBJC1_32BIT_EXE: protocols 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: Module 0x4138 +OBJC1_32BIT_EXE: version 7 +OBJC1_32BIT_EXE: size 16 +OBJC1_32BIT_EXE: name +OBJC1_32BIT_EXE: symtab 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: Module 0x4148 +OBJC1_32BIT_EXE: version 7 +OBJC1_32BIT_EXE: size 16 +OBJC1_32BIT_EXE: name +OBJC1_32BIT_EXE: symtab 0x00004118 +OBJC1_32BIT_EXE: sel_ref_cnt 0 +OBJC1_32BIT_EXE: refs 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: cls_def_cnt 1 +OBJC1_32BIT_EXE: cat_def_cnt 0 +OBJC1_32BIT_EXE: Class Definitions +OBJC1_32BIT_EXE: defs[0] 0x00004030 +OBJC1_32BIT_EXE: isa 0x00004098 +OBJC1_32BIT_EXE: super_class 0x000025af NSObject +OBJC1_32BIT_EXE: name 0x00002faa AppDelegate +OBJC1_32BIT_EXE: version 0x00000000 +OBJC1_32BIT_EXE: info 0x00000001 CLS_CLASS +OBJC1_32BIT_EXE: instance_size 0x00000004 +OBJC1_32BIT_EXE: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: methods 0x000040e8 +OBJC1_32BIT_EXE: obsolete 0x00000000 +OBJC1_32BIT_EXE: method_count 2 +OBJC1_32BIT_EXE: method_name 0x00002c5b applicationDidFinishLaunching: +OBJC1_32BIT_EXE: method_types 0x000025a5 v12@0:4@8 +OBJC1_32BIT_EXE: method_imp 0x00002510 +OBJC1_32BIT_EXE: method_name 0x00002d6f applicationWillTerminate: +OBJC1_32BIT_EXE: method_types 0x000025a5 v12@0:4@8 +OBJC1_32BIT_EXE: method_imp 0x00002530 +OBJC1_32BIT_EXE: cache 0x00000000 +OBJC1_32BIT_EXE: protocols 0x000043b4 +OBJC1_32BIT_EXE: next 0x00000000 +OBJC1_32BIT_EXE: count 1 +OBJC1_32BIT_EXE: list[0] 0x00004390 +OBJC1_32BIT_EXE: isa 0x000030b0 +OBJC1_32BIT_EXE: protocol_name 0x00002dd3 NSApplicationDelegate +OBJC1_32BIT_EXE: protocol_list 0x000043a4 +OBJC1_32BIT_EXE: next 0x00000000 +OBJC1_32BIT_EXE: count 1 +OBJC1_32BIT_EXE: list[0] 0x0000437c +OBJC1_32BIT_EXE: isa 0x00003120 +OBJC1_32BIT_EXE: protocol_name 0x000025af NSObject +OBJC1_32BIT_EXE: protocol_list 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: instance_methods 0x00004290 +OBJC1_32BIT_EXE: count 19 +OBJC1_32BIT_EXE: list[0] +OBJC1_32BIT_EXE: name 0x00002de9 isEqual: +OBJC1_32BIT_EXE: types 0x000026e7 c12@0:4@8 +OBJC1_32BIT_EXE: list[1] +OBJC1_32BIT_EXE: name 0x00002df2 class +OBJC1_32BIT_EXE: types 0x00002df8 #8@0:4 +OBJC1_32BIT_EXE: list[2] +OBJC1_32BIT_EXE: name 0x00002dff self +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[3] +OBJC1_32BIT_EXE: name 0x00002e0b performSelector: +OBJC1_32BIT_EXE: types 0x00002e1c @12@0:4:8 +OBJC1_32BIT_EXE: list[4] +OBJC1_32BIT_EXE: name 0x00002e26 performSelector:withObject: +OBJC1_32BIT_EXE: types 0x00002e42 @16@0:4:8@12 +OBJC1_32BIT_EXE: list[5] +OBJC1_32BIT_EXE: name 0x00002e4f performSelector:withObject:withObject: +OBJC1_32BIT_EXE: types 0x00002e76 @20@0:4:8@12@16 +OBJC1_32BIT_EXE: list[6] +OBJC1_32BIT_EXE: name 0x00002e86 isProxy +OBJC1_32BIT_EXE: types 0x00002e8e c8@0:4 +OBJC1_32BIT_EXE: list[7] +OBJC1_32BIT_EXE: name 0x00002e95 isKindOfClass: +OBJC1_32BIT_EXE: types 0x00002ea4 c12@0:4#8 +OBJC1_32BIT_EXE: list[8] +OBJC1_32BIT_EXE: name 0x00002eae isMemberOfClass: +OBJC1_32BIT_EXE: types 0x00002ea4 c12@0:4#8 +OBJC1_32BIT_EXE: list[9] +OBJC1_32BIT_EXE: name 0x00002ebf conformsToProtocol: +OBJC1_32BIT_EXE: types 0x000026e7 c12@0:4@8 +OBJC1_32BIT_EXE: list[10] +OBJC1_32BIT_EXE: name 0x00002ee7 respondsToSelector: +OBJC1_32BIT_EXE: types 0x00002efb c12@0:4:8 +OBJC1_32BIT_EXE: list[11] +OBJC1_32BIT_EXE: name 0x00002f05 retain +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[12] +OBJC1_32BIT_EXE: name 0x00002f0c release +OBJC1_32BIT_EXE: types 0x00002f14 Vv8@0:4 +OBJC1_32BIT_EXE: list[13] +OBJC1_32BIT_EXE: name 0x00002f1c autorelease +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[14] +OBJC1_32BIT_EXE: name 0x00002f28 retainCount +OBJC1_32BIT_EXE: types 0x00002f34 I8@0:4 +OBJC1_32BIT_EXE: list[15] +OBJC1_32BIT_EXE: name 0x00002f3b zone +OBJC1_32BIT_EXE: types 0x00002f40 ^{_NSZone=}8@0:4 +OBJC1_32BIT_EXE: list[16] +OBJC1_32BIT_EXE: name 0x00002f51 hash +OBJC1_32BIT_EXE: types 0x00002f34 I8@0:4 +OBJC1_32BIT_EXE: list[17] +OBJC1_32BIT_EXE: name 0x00002f56 superclass +OBJC1_32BIT_EXE: types 0x00002df8 #8@0:4 +OBJC1_32BIT_EXE: list[18] +OBJC1_32BIT_EXE: name 0x00002f61 description +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: class_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: instance_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: class_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: Meta Class +OBJC1_32BIT_EXE: isa 0x000025af NSObject +OBJC1_32BIT_EXE: super_class 0x000025af NSObject +OBJC1_32BIT_EXE: name 0x00002faa AppDelegate +OBJC1_32BIT_EXE: version 0x00000000 +OBJC1_32BIT_EXE: info 0x00000002 CLS_META +OBJC1_32BIT_EXE: instance_size 0x00000030 +OBJC1_32BIT_EXE: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: cache 0x00000000 +OBJC1_32BIT_EXE: protocols 0x000043b4 +OBJC1_32BIT_EXE: next 0x00000000 +OBJC1_32BIT_EXE: count 1 +OBJC1_32BIT_EXE: list[0] 0x00004390 +OBJC1_32BIT_EXE: isa 0x000030b0 +OBJC1_32BIT_EXE: protocol_name 0x00002dd3 NSApplicationDelegate +OBJC1_32BIT_EXE: protocol_list 0x000043a4 +OBJC1_32BIT_EXE: next 0x00000000 +OBJC1_32BIT_EXE: count 1 +OBJC1_32BIT_EXE: list[0] 0x0000437c +OBJC1_32BIT_EXE: isa 0x00003120 +OBJC1_32BIT_EXE: protocol_name 0x000025af NSObject +OBJC1_32BIT_EXE: protocol_list 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: instance_methods 0x00004290 +OBJC1_32BIT_EXE: count 19 +OBJC1_32BIT_EXE: list[0] +OBJC1_32BIT_EXE: name 0x00002de9 isEqual: +OBJC1_32BIT_EXE: types 0x000026e7 c12@0:4@8 +OBJC1_32BIT_EXE: list[1] +OBJC1_32BIT_EXE: name 0x00002df2 class +OBJC1_32BIT_EXE: types 0x00002df8 #8@0:4 +OBJC1_32BIT_EXE: list[2] +OBJC1_32BIT_EXE: name 0x00002dff self +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[3] +OBJC1_32BIT_EXE: name 0x00002e0b performSelector: +OBJC1_32BIT_EXE: types 0x00002e1c @12@0:4:8 +OBJC1_32BIT_EXE: list[4] +OBJC1_32BIT_EXE: name 0x00002e26 performSelector:withObject: +OBJC1_32BIT_EXE: types 0x00002e42 @16@0:4:8@12 +OBJC1_32BIT_EXE: list[5] +OBJC1_32BIT_EXE: name 0x00002e4f performSelector:withObject:withObject: +OBJC1_32BIT_EXE: types 0x00002e76 @20@0:4:8@12@16 +OBJC1_32BIT_EXE: list[6] +OBJC1_32BIT_EXE: name 0x00002e86 isProxy +OBJC1_32BIT_EXE: types 0x00002e8e c8@0:4 +OBJC1_32BIT_EXE: list[7] +OBJC1_32BIT_EXE: name 0x00002e95 isKindOfClass: +OBJC1_32BIT_EXE: types 0x00002ea4 c12@0:4#8 +OBJC1_32BIT_EXE: list[8] +OBJC1_32BIT_EXE: name 0x00002eae isMemberOfClass: +OBJC1_32BIT_EXE: types 0x00002ea4 c12@0:4#8 +OBJC1_32BIT_EXE: list[9] +OBJC1_32BIT_EXE: name 0x00002ebf conformsToProtocol: +OBJC1_32BIT_EXE: types 0x000026e7 c12@0:4@8 +OBJC1_32BIT_EXE: list[10] +OBJC1_32BIT_EXE: name 0x00002ee7 respondsToSelector: +OBJC1_32BIT_EXE: types 0x00002efb c12@0:4:8 +OBJC1_32BIT_EXE: list[11] +OBJC1_32BIT_EXE: name 0x00002f05 retain +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[12] +OBJC1_32BIT_EXE: name 0x00002f0c release +OBJC1_32BIT_EXE: types 0x00002f14 Vv8@0:4 +OBJC1_32BIT_EXE: list[13] +OBJC1_32BIT_EXE: name 0x00002f1c autorelease +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: list[14] +OBJC1_32BIT_EXE: name 0x00002f28 retainCount +OBJC1_32BIT_EXE: types 0x00002f34 I8@0:4 +OBJC1_32BIT_EXE: list[15] +OBJC1_32BIT_EXE: name 0x00002f3b zone +OBJC1_32BIT_EXE: types 0x00002f40 ^{_NSZone=}8@0:4 +OBJC1_32BIT_EXE: list[16] +OBJC1_32BIT_EXE: name 0x00002f51 hash +OBJC1_32BIT_EXE: types 0x00002f34 I8@0:4 +OBJC1_32BIT_EXE: list[17] +OBJC1_32BIT_EXE: name 0x00002f56 superclass +OBJC1_32BIT_EXE: types 0x00002df8 #8@0:4 +OBJC1_32BIT_EXE: list[18] +OBJC1_32BIT_EXE: name 0x00002f61 description +OBJC1_32BIT_EXE: types 0x00002e04 @8@0:4 +OBJC1_32BIT_EXE: class_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: instance_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: class_methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_EXE: Contents of (__OBJC,__image_info) section +OBJC1_32BIT_EXE: version 0 +OBJC1_32BIT_EXE: flags 0x0 RR + +OBJC1_32BIT_OBJ: Objective-C segment +OBJC1_32BIT_OBJ: Module 0xb344 +OBJC1_32BIT_OBJ: version 7 +OBJC1_32BIT_OBJ: size 16 +OBJC1_32BIT_OBJ: name +OBJC1_32BIT_OBJ: symtab 0x0000b334 +OBJC1_32BIT_OBJ: sel_ref_cnt 0 +OBJC1_32BIT_OBJ: refs 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: cls_def_cnt 1 +OBJC1_32BIT_OBJ: cat_def_cnt 0 +OBJC1_32BIT_OBJ: Class Definitions +OBJC1_32BIT_OBJ: defs[0] 0x0000b24c +OBJC1_32BIT_OBJ: isa 0x0000b2e4 +OBJC1_32BIT_OBJ: super_class 0x0000b2b8 NSViewController +OBJC1_32BIT_OBJ: name 0x0000b2c9 ViewController +OBJC1_32BIT_OBJ: version 0x00000000 +OBJC1_32BIT_OBJ: info 0x00000001 CLS_CLASS +OBJC1_32BIT_OBJ: instance_size 0x00000034 +OBJC1_32BIT_OBJ: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: methods 0x0000b314 +OBJC1_32BIT_OBJ: obsolete 0x00000000 +OBJC1_32BIT_OBJ: method_count 2 +OBJC1_32BIT_OBJ: method_name 0x0000b27c viewDidLoad +OBJC1_32BIT_OBJ: method_types 0x0000b29e v8@0:4 +OBJC1_32BIT_OBJ: method_imp 0x00000000 -[ViewController viewDidLoad] +OBJC1_32BIT_OBJ: method_name 0x0000b288 setRepresentedObject: +OBJC1_32BIT_OBJ: method_types 0x0000b2a5 v12@0:4@8 +OBJC1_32BIT_OBJ: method_imp 0x00000050 -[ViewController setRepresentedObject:] +OBJC1_32BIT_OBJ: cache 0x00000000 +OBJC1_32BIT_OBJ: protocols 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: Meta Class +OBJC1_32BIT_OBJ: isa 0x0000b2af NSObject +OBJC1_32BIT_OBJ: super_class 0x0000b2b8 NSViewController +OBJC1_32BIT_OBJ: name 0x0000b2c9 ViewController +OBJC1_32BIT_OBJ: version 0x00000000 +OBJC1_32BIT_OBJ: info 0x00000002 CLS_META +OBJC1_32BIT_OBJ: instance_size 0x00000030 +OBJC1_32BIT_OBJ: ivars 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: methods 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: cache 0x00000000 +OBJC1_32BIT_OBJ: protocols 0x00000000 (not in an __OBJC section) +OBJC1_32BIT_OBJ: Contents of (__OBJC,__image_info) section +OBJC1_32BIT_OBJ: version 0 +OBJC1_32BIT_OBJ: flags 0x0 RR diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 36b83f7ef63..6b94749e471 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -612,7 +612,8 @@ static void CreateSymbolAddressMap(MachOObjectFile *O, Symbol.getAddress(Address); StringRef SymName; Symbol.getName(SymName); - (*AddrMap)[Address] = SymName; + if (!SymName.startswith(".objc")) + (*AddrMap)[Address] = SymName; } } } @@ -2404,13 +2405,22 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue, // section nullptr is returned. static const char *get_pointer_64(uint64_t Address, uint32_t &offset, uint32_t &left, SectionRef &S, - DisassembleInfo *info) { + DisassembleInfo *info, + bool objc_only = false) { offset = 0; left = 0; S = SectionRef(); for (unsigned SectIdx = 0; SectIdx != info->Sections->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) {