越狱开发Swift之String内存结构分析
本帖最后由 元始天尊 于 2021-8-8 16:46 编辑  String是Swift的常见结构,下面来动手分析
```
let s1 = "abc" as String
test(s:s1)
let s2 = "abcabcabcabcabcabcabcabcabcabc" as String
test(s:s2)
let s3 = "bcd" as StaticString
test(s:s3)
let s4 = "bcdbcdbcdbcdbcdbcdbcdbcdbcdbcd" as StaticString
test(s:s4)
```
  其伪代码如下:
```
v14.n128_u64 = 6513249LL;
v16 = &_sSSN;
v14.n128_u64 = -2089670227099910144LL;
v1 = __swift_instantiateConcreteTypeFromMangledName(&_ss23_ContiguousArrayStorageCyypGMD);
v2 = v1;
v3 = swift_allocObject(v1, 64LL, 7LL);
v4 = v3;
*(_OWORD *)(v3 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v3 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v4, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v4);
__swift_destroy_boxed_opaque_existential_0(&v14);
v14.n128_u64 = -3458764513820540898LL;
v16 = &_sSSN;
v14.n128_u64 = (unsigned __int64)"" | 0x8000000000000000LL;
v5 = swift_allocObject(v2, 64LL, 7LL);
v6 = v5;
*(_OWORD *)(v5 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v5 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v6, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v6);
__swift_destroy_boxed_opaque_existential_0(&v14);
v7 = vdupq_n_s64(3uLL);
v16 = &_ss12StaticStringVN;
v7.n128_u64 = (unsigned __int64)"bcd";
v14 = v7;
v15 = 2;
v8 = swift_allocObject(v2, 64LL, 7LL);
v9 = v8;
*(_OWORD *)(v8 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v8 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v9, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v9);
__swift_destroy_boxed_opaque_existential_0(&v14);
v16 = &_ss12StaticStringVN;
v10 = vdupq_n_s64(0x1EuLL);
v10.n128_u64 = (unsigned __int64)"bcdbcdbcdbcdbcdbcdbcdbcdbcdbcd";
v14 = v10;
v15 = 2;
v11 = swift_allocObject(v2, 64LL, 7LL);
v12 = v11;
*(_OWORD *)(v11 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v11 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v12, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
```
  经过调试分析,可以知道String类大小为16字节,在函数传参中默认以值传递(X0/X1),而返回时也以值传递(X0/X1),可以得到如下结构。可以看到String结构在长度<=15时使用short方式存储,长度>=16时使用long方式存储。使用long方式存储时,还有存在偏移,不知道为何如此设计。从总体看形似std::string结构,但是更复杂。
```
struct Swift.StaticString {
int64_t _addr; // 指向实际字符串
int64_t _len;
};
union Swift.String {
struct {
char _buf; // 实际字符串
int _type : 4; // short的type=0xe
int _len : 4; // 字符串长度
} short,
struct {
int64_t _len : 60;// 字符串长度
int64_t _type : 4;// long的type=0xd
int64_t _addr; // (_addr&0x7ffffffffffffffff)+0x20指向实际字符串,最高位固定为1
} long
}
```
页:
[1]