布景
如果想在 自界说section 存储具体服务类,实现服务的操控回转,在常见的做法是界说一个字符串指针,指向方针类的类名,用运行时的方法获得方针类。下面列出一个简单的比如
// 界说
char *className = "MyClass" __attribute((used, section("__DATA,__mysection")));
// 读取
const struct mach_header_64 *mhp = (const struct mach_header_64 *)_dyld_get_image_header(0); // 注:主macho纷歧定是0
const char *className = (const char *)getsectiondata(mhp, "__DATA", "__mysection", NULL);
Class classObjc = NSClassFromString([NSString stringWithFormat:@"%s", className]);
本文将介绍另外一种写法,直接在 自界说section 存储Objective-C的类目标,就像 __objc_classlist 的 section 相同,大约作用如下。
// 界说
Class classObjc = [MyClass class] __attribute((used, section("__DATA,__mysection")));
// 读取
const struct mach_header_64 *mhp = (const struct mach_header_64 *)_dyld_get_image_header(0); // 注:主macho纷歧定是0
Class classObjc = (Class)getsectiondata(mhp, "__DATA", "__mysection", NULL);
完好代码地址
推理过程
- 界说一个空类文件 objc.m
@interface MyClass : NSObject
@end
@implementation MyClass
@end
- 用指令重写成C++文件 objc.cpp
clang -framework Foundation -rewrite-objc -fobjc-arc objc.m -o objc.cpp
- 从C++文件 objc.cpp 提取代码
- 类结构体界说(struct _class_t)
// 类结构体
struct _class_t {
struct _class_t *isa;
struct _class_t *superclass;
void *cache;
void *vtable;
struct _class_ro_t *ro;
};
// 以下是其它相关的结构体
struct _prop_t {
const char *name;
const char *attributes;
};
struct _protocol_t;
struct _objc_method {
struct objc_selector * _cmd;
const char *method_type;
void *_imp;
};
struct _protocol_t {
void * isa; // NULL
const char *protocol_name;
const struct _protocol_list_t * protocol_list; // super protocols
const struct method_list_t *instance_methods;
const struct method_list_t *class_methods;
const struct method_list_t *optionalInstanceMethods;
const struct method_list_t *optionalClassMethods;
const struct _prop_list_t * properties;
const unsigned int size; // sizeof(struct _protocol_t)
const unsigned int flags; // = 0
const char ** extendedMethodTypes;
};
struct _ivar_t {
unsigned long int *offset; // pointer to ivar offset location
const char *name;
const char *type;
unsigned int alignment;
unsigned int size;
};
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
unsigned int reserved;
const unsigned char *ivarLayout;
const char *name;
const struct _method_list_t *baseMethods;
const struct _objc_protocol_list *baseProtocols;
const struct _ivar_list_t *ivars;
const unsigned char *weakIvarLayout;
const struct _prop_list_t *properties;
};
- MyClass 的类数据
// MyClass的类数据
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_MyClass __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_MyClass,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_MyClass,
};
// 以下是其它相关数据
extern "C" __declspec(dllimport) struct objc_cache _objc_empty_cache;
static struct _class_ro_t _OBJC_METACLASS_RO_$_MyClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
1, sizeof(struct _class_t), sizeof(struct _class_t),
(unsigned int)0,
0,
"MyClass",
0,
0,
0,
0,
0,
};
static struct _class_ro_t _OBJC_CLASS_RO_$_MyClass __attribute__ ((used, section ("__DATA,__objc_const"))) = {
0, sizeof(struct MyClass_IMPL), sizeof(struct MyClass_IMPL),
(unsigned int)0,
0,
"MyClass",
0,
0,
0,
0,
0,
};
extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;
extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_MyClass __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_NSObject,
0, // &OBJC_METACLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_METACLASS_RO_$_MyClass,
};
extern "C" __declspec(dllimport) struct _class_t OBJC_CLASS_$_NSObject;
从C++文件 objc.cpp 提取的代码,大致能够获取以下信息
信息 | 比如 |
---|---|
类的符号格局 | OBJC_CLASS_$_ + 类名 |
指向类目标地址写法 | &OBJC_CLASS_$_NSObject |
结论
在 自界说section 存储Objective-C的类目标,代码如下
// 结构体声明
struct _prop_t {
const char *name;
const char *attributes;
};
struct _protocol_t;
struct _objc_method {
struct objc_selector * _cmd;
const char *method_type;
void *_imp;
};
struct _protocol_t {
void * isa; // NULL
const char *protocol_name;
const struct _protocol_list_t * protocol_list; // super protocols
const struct method_list_t *instance_methods;
const struct method_list_t *class_methods;
const struct method_list_t *optionalInstanceMethods;
const struct method_list_t *optionalClassMethods;
const struct _prop_list_t * properties;
const unsigned int size; // sizeof(struct _protocol_t)
const unsigned int flags; // = 0
const char ** extendedMethodTypes;
};
struct _ivar_t {
unsigned long int *offset; // pointer to ivar offset location
const char *name;
const char *type;
unsigned int alignment;
unsigned int size;
};
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
unsigned int reserved;
const unsigned char *ivarLayout;
const char *name;
const struct _method_list_t *baseMethods;
const struct _objc_protocol_list *baseProtocols;
const struct _ivar_list_t *ivars;
const unsigned char *weakIvarLayout;
const struct _prop_list_t *properties;
};
struct _class_t {
struct _class_t *isa;
struct _class_t *superclass;
void *cache;
void *vtable;
struct _class_ro_t *ro;
};
// 界说
__attribute__((dllimport)) struct _class_t OBJC_CLASS_$_MyClass;
struct _class_t *classObjc = &OBJC_CLASS_$__MyClass __attribute((used, section("__DATA,__mysection")));
// 读取
const struct mach_header_64 *mhp = (const struct mach_header_64 *)_dyld_get_image_header(0); // 注:主macho纷歧定是0
Class classObjc = (Class)getsectiondata(mhp, "__DATA", "__mysection", NULL);
More
- 这种写法,能够利用编译检查拼写的正确性,并减少读取过程。