举例
Small String
"control"
寄存器中:
(lldb) reg r x0 x1 sp
x0 = 0x006c6f72746e6f63
x1 = 0xe700000000000000
内存中:
(lldb) po 0x0000000281a4cea0
MainAppLibrary.OfflineAB.BucketInfo
(lldb) x/6xg 0x0000000281a4cea0
0x281a4cea0: 0x000000010415b460 0x0000000000000003
0x281a4ceb0: 0x006c6f72746e6f63 0xe700000000000000
0x281a4cec0: 0x0000000000002710 0x0000000281a4c930
(lldb) p/c 0x006c6f72746e6f63
(long) control\0
->字符串本身 = realString :
0xe700000000000000 0x006c6f72746e6f63
->
(lldb) p/c 0x006c6f72746e6f63
(unsigned long) control\0
->字符串是:"control"
第15个字节=8位,分2部分:
- 最高4位=discriminator
- 0xe
- = 0b 1110
- b63 = isImmortal -> 1
- isImmortal=True
- b62 = (large) isBridged / (small) isASCII -> 1
- Small String:ASCII=True
- b61 = isSmall -> 1
- 是Small string
- b60 = isForeign = isSlow -> 0
- isForeign=False
- b63 = isImmortal -> 1
- = 0b 1110
- 0xe
- 最低4位=count
- 0x7
- 字符串长度是:7
- = 7个字符
- 对应着:control字符串的长度=7
- = 7个字符
- 字符串长度是:7
- 0x7
Large String
Large String - Native
"ios_prod_latam_tos_reg_universe"
(lldb) po 0x00000002800f5e00
MainAppLibrary.OfflineAB.UniverseInfo
(lldb) x/6gx 0x00000002800f5e00
0x2800f5e00: 0x0000000105d3c398 0x0000000200000003
0x2800f5e10: 0xd00000000000001f 0x8000000105110930
0x2800f5e20: 0x6469725f72657375 0xe800000000000000
根据定义:
- MainAppLibrary.OfflineAB.UniverseInfo
- [+0x10~0x18] = name
- 类型:Swift的Large String(真正字符串地址是:name值+0x20)
- [+0x10~0x18] = name
此处值:
- [+0x10~0x18] = name
- 0x2800f5e10: 0xd00000000000001f 0x8000000105110930
-》真正字符串地址是:
- 0x8000000105110930 + 0x20 = 0x8000000105110950
(lldb) x/s 0x8000000105110950
0x105110950: "ios_prod_latam_tos_reg_universe"
额外说明
(1)如果不加0x20,则看到的字符串是别的(错位后的)值:
(lldb) x/s 0x8000000105110930
0x105110930: "os_reg_experiment"
(2)去掉最开始的0x8,也是可以用x/s看到字符串的:
(lldb) x/s 0x0000000105110930
0x105110930: "os_reg_experiment"
(lldb) x/s 0x0000000105110950
0x105110950: "ios_prod_latam_tos_reg_universe"
类似的:去掉0x8前缀,可以用po查看出字符串的值:
(lldb) po (char*)0x0000000105110950
"ios_prod_latam_tos_reg_universe"
(3)不论是否加0x20,直接po查看,则都是(异常的,不是我们要的)时间类型的值:
(lldb) po 0x8000000105110930
2001-01-01 00:00:00 +0000
(lldb) po 0x8000000105110950
2001-01-01 00:00:00 +0000
(lldb) po (char*)0x8000000105110950
2001-01-01 00:00:00 +0000
后记:
另外某次去po,却连异常的时间类型的值都看不到,而是:就是数字:
(lldb) reg r x0 x1
x0 = 0x000000000000007c
x1 = 0xe100000000000000
(lldb) reg r x20 sp
x20 = 0x000000016d658c20
sp = 0x000000016d658c20
(lldb) x/8gx 0x000000016d658c20
0x16d658c20: 0xd000000000000021 0x80000001051946f0
0x16d658c30: 0x0000000000000002 0x00000002833c1140
0x16d658c40: 0x0000000105da1628 0x0000000105dbbcd0
0x16d658c50: 0x00000002833c1140 0x00000002828d0780
(lldb) po 0x80000001051946f0
9223372041235285744
而换x/s字符串查看,是可以看出:
(虽然是错误的,但是是)字符串的值的
(lldb) x/s 0x80000001051946f0
0x1051946f0: "dummy_aa_offline_user_rid_ios"
当然,真正地址+0x20的字符串:
(lldb) p/x 0x80000001051946f0 + 0x20
(unsigned long) 0x8000000105194710
->但是po也还是看不出:
(lldb) po 0x8000000105194710
9223372041235285776
只能用字符串查看:
(lldb) x/s 0x8000000105194710
0x105194710: "dummy_aa_offline_rid_universe_ios"
Large String - Shared
"2.23.25.85"
此处:
0xc00000000000000a 0x400000028143c6c0
其中:
- Large String
- 0xc00000000000000a
- 0xC = 12 = 0b 1100
- b63 = ASCII = isASCII
- True
- b62 = NFC = isNFC
- True
- b61 = native = isNativelyStored
- False
- b60 = tail = isTailAllocated
- False
- b59 = UTF8 = isForeignUTF8
- False
- b63 = ASCII = isASCII
- 0xa = 10 :字符串长度是10
- 0xC = 12 = 0b 1100
- 0x400000028143c6c0
- discriminator = 0x4 = 0b 0100
- b63 = isImmortal
- False
- b62 = (large) isBridged / (small) isASCII
- True
- b61 = isSmall
- False
- b60 = isForeign = isSlow
- False
- b63 = isImmortal
- objectAddr = 0x28143c6c0
- discriminator = 0x4 = 0b 0100
- 0xc00000000000000a
->
- Large String
- length = 10
- flag
- isASCII = True
- isNFC = True
- isNativelyStored = False
- isTailAllocated = False
- isForeignUTF8 = False
- discriminator
- isImmortal = False
- isBridged = True
- isSmall = False
- isForeign == isSlow = False
- objectAddr = 0x28143c6c0
->
- Swift中的字符串
- 是bridged桥接的
- 字符串地址是:0x28143c6c0
- 其他细节
- 是ASCII的
- 是NFC(Normal Form C)的
- 不是尾部分配的TailAllocated
-> 此处对应着:从ObjC
的NSString
:"2.23.25.85"
(lldb) reg r x0
x0 = 0x000000028143c6c0
(lldb) po $x0
2.23.25.85
(lldb) po [$x0 class]
__NSCFString
调用
libswiftFoundation.dylib
static Swift.String._unconditionallyBridgeFromObjectiveC(Swift.Optional<__C.NSString>) -> Swift.String
而Bridge桥接过来的
->
此处:想要查看出字符串的值:
- (方式1)加上NSString强制类型转换去打印字符串
(lldb) po (NSString*)0x000000028143c6c0
2.23.25.85
- (方式2)自己查看ObjC的NSString的内存值,手动打印出字符串
此处(NSString类型的字符串的)内存值是:
(lldb) x/8xg 0x00000028143c6c0
0x28143c6c0: 0x000021a1efdfa941 0x000000030000078c
0x28143c6d0: 0x35322e33322e320a 0x000000000035382e
0x28143c6e0: 0x00004fcde1ddc6e0 0x0000000000000041
0x28143c6f0: 0x0000000000000000 0x0000000000000000
其中核心数据是:
0x28143c6d0: 0x35322e33322e320a 0x000000000035382e
->可以调试查看到具体字符串的值和长度:
(lldb) p/c 0x35322e33322e320a
(long) \n2.23.25
(lldb) p/c 0x000000000035382e
(int) .85\0
(lldb) x/8xb 0x28143c6d0
0x28143c6d0: 0x0a 0x32 0x2e 0x32 0x33 0x2e 0x32 0x35
(lldb) x/8xb 0x28143c6d8
0x28143c6d8: 0x2e 0x38 0x35 0x00 0x00 0x00 0x00 0x00
(lldb) x/s 0x28143c6d0
0x28143c6d0: "\n2.23.25.85"
(lldb) x/s 0x28143c6d8
0x28143c6d8: ".85"
(lldb) p/d 0xa
(int) 10
(lldb) x/s 0x28143c6d1
0x28143c6d1: "2.23.25.85"
即:
- 字符串:
- 长度:
10
- 值:
2.23.25.85
- 长度: