I don’t know what’s under the hood at the moment, please just follow the example below. If you’re curious, figure it out yourself and post a topic explaining the principles, thanks.
(lldb) po $x5
<__NSStackBlock__: 0x16fd26ac8>
(lldb) memory read --size 8 --format x 0x16fd26ac8
0x16fd26ac8: 0x00000001a0d11558 0x00000000c2000000
0x16fd26ad8: 0x00000001022d4638 0x00000001037ab4f0
0x16fd26ae8: 0x0000000126f4a1c0 0x0000000126ac9ae0
0x16fd26af8: 0x00000001821e7f00 0x0000000124d31400
Note, for arm64, the 2nd command is memory read --size 8
, while for armv7/armv7s it should be memory read --size 4
.
The value you get from 0x00000001022d4638 - ASLR offset
is the address of the block. Go to this address in IDA or hopper then you’ll see the block implementation.
5 个赞
budou
2016 年11 月 17 日 13:39
2
太感谢了!自己苦想一天都没什么头绪,这样一下就找到了,谢谢楼主!
根据Block的结构体,函数指针是void (*invoke)(void *, …); 所以楼主选了17个字节(也即第3个16Byte)的那个:
struct Block_literal_1 {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor_1 {
unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
void (*dispose_helper)(void *src); // IFF (1<<25)
// required ABI.2010.3.16
const char *signature; // IFF (1<<30)
} *descriptor;
// imported variables
};
2 个赞
syx
(syx)
2020 年11 月 21 日 09:30
8
block做属性怎么分析呢
@property (nonatomic, strong) void(^TestBlock)(NSString *);
self.TestBlock(@“123”);
0x100a6bf00: 6c 3a 00 73 65 6c 66 00 70 65 72 66 6f 72 6d 53 l:.self.performS
(lldb) p/x $x1
(unsigned long) $5 = 0x0000000100a6bef0
(lldb) memory read --format x 0x100a6bef0
0x100a6bef0: 0x74736554 0x636f6c42 0x7369006b 0x61757145
0x100a6bf00: 0x73003a6c 0x00666c65 0x66726570 0x536d726f
(lldb) memory read --size 8 --format x 0x100a6bef0
0x100a6bef0: 0x636f6c4274736554 0x617571457369006b
0x100a6bf00: 0x00666c6573003a6c 0x536d726f66726570
0x100a6bf10: 0x3a7267463656c65 0x6d726f6672657000
0x100a6bf20: 0x726f7463656c6553 0x6a624f687469773a
(lldb) x/4gx 0x0000000100a6bef0
0x100a6bef0: 0x636f6c4274736554 0x617571457369006b
0x100a6bf00: 0x00666c6573003a6c 0x536d726f66726570
这么大的地址看起来是栈上的地址吗
syx
(syx)
2020 年11 月 21 日 09:44
10
syx:
0x00666c6573003a6c
上面那个是我用xcode直接运行的一个例子,我想顺着想看怎么找到block的Imp.
我在我手机的lldb里面调试的这个值非常大。
#######这个是头文件的属性 ,看得到是一个block######
@property (copy, nonatomic) CDUnknownBlockType sendContent;
######这个是lldb ,###########
(lldb) po/x (char*)$x1
“sendContent”
(lldb) po/x $x1
0x000000010675e808
(lldb) x/4gx 0x000000010675e808
0x10675e808: 0x746e6f43646e6573 0x4374657300746e65
0x10675e818: 0x6f697463656c6c6f 0x79614c776569566e
偏移一个指针8+两个int(4*2),那么0x6f697463656c6c6f就是这个地址了。。。
这个地址没搜到。。。感觉太大了。
我是这样想的,这个x1应该是这个get方法的地址吧。。。返回值才是这个block的函数地址。。。需要获取到这个返回值才行,怎么获取返回值呢。张总能不能指点一二
Zhang
2020 年11 月 21 日 09:52
11
CompilerRT里有Block运行时,里面有用来查看Block信息的C接口我记得
syx
(syx)
2020 年11 月 21 日 12:06
14
我自己犯蠢了。。。
这个block是个属性,直接调用对象的get方法就能拿到这个属性的地址了。。。
再偏移16个字节就是IMP的地址了。。。。
完结。。。
(lldb) po $x0
<TestObject: 0x2807b05f0>
(lldb) po $x1
4310134979
(lldb) po (char )$x1 *
“TestBlock”
(lldb) po [$x0 TestBlock]
<NSGlobalBlock : 0x100e78028>
signature: "v16@?0@“NSString"8”
invoke : 0x100e75944 (/private/var/containers/Bundle/Application/16652EAA-FDB0-40F3-ADA7-887649259FD1/TestSign.app/TestSign`__29-[ViewController viewDidLoad]_block_invoke)
(lldb) x/4gx 0x100e78038
0x100e78038: 0x0000000100e75944 0x0000000100e78008
0x100e78048: 0x0000000207146280 0x00000000000007c8
(lldb) br set -a 0x0000000100e75944
Breakpoint 2: where = TestSign`__29-[ViewController viewDidLoad]_block_invoke at ViewController.m:23, address = 0x0000000100e75944