CPU监控
统计进程下所有线程的消息。
struct thread_basic_info {
time_value_t user_time; // 用户运行时长
time_value_t system_time; // 系统运行时长
integer_t cpu_usage; // CPU使用率(理论上限为1000)
policy_t policy; // 调度策略
integer_t run_state; // 运行状态
integer_t flags; // 各种标记
integer_t suspend_count; // 暂停线程的计数
integer_t sleep_time; // 休眠时间
};
MachO文件结构
Mach Header + LoadCommands + Data + Loader Info
头部
加载命令:用于告诉loader设置如何加载二进制数据
数据段:存放代码、字符常量、类、方法。可以拥有多个segment,每个segment可以有零到多个section。
每个段都有一段虚拟地址映射到进程的地址空间。
链接信息:一个完整的用户级MachO文件的末端是一系列链接信息。包含了动态加载器用来链接可执行文件或者依赖所需使用的符号表字符串表等。
lazy bind 主要用于模块外部的函数调用,延迟绑定有利于提高动态库的加载速度。
no lazy bind 主要用于模块外部调用一些全局变量,启动时绑定。
arm64汇编
https://juejin.cn/post/6844904175357132808
寄存器
r0-r30 通用整型寄存器,64位,x0-x30 表示64位,w0-w30表示低32位。
fp(x29) 栈帧地址
lr(x30) 程序链接寄存器,保存子程序结束后需要执行的下一条指令
sp(x31) 栈指针,使用sp/wsp 来进行对 sp 寄存器的访问
pc 当前执行的指令地址,在arm64中,软件是不能改写pc寄存器的。
SPRs 状态寄存器,存放状态标识符。可分为CPSR和SPSR。发生异常时,CPSR会存入SPSR。异常恢复时,再拷贝回CPSR
zr 零寄存器(x31),里面存的是0. 一般使用wzr/xzr 分别表示32、64位
v0-v31 向量寄存器,也叫浮点寄存器。大小128位。可以用 Bn Hn Sn Dn Qn 来访问不同的位数(8 16 32 64 128)
arm64 的 目的操作数位于第一位。
mov x1, x0
add x0, x1, x2
sub x0, x1, x2
mul x0, x1, x2
sdiv x0, x1, x2
and x0, x0, #0xF
orr x0, x0, #9 或
eor x0, x0, #0xF 异或
lsl x0, #1 逻辑左移
状态寄存器:
N, negative condition flag 一般表示运算结果是负数
Z, zero condition flag 运算结果是0
C, carry condtion flag 无符号运算有溢出 C=1
V, overflow condition flag. 有符号运算有溢出 V=1
寻址
L开头的指令是 取值, S开头是存值。
; 寄存器取址
ldr x0, [x1] ; 从x1指向的地址里面取出一个64位大小的数 存入x0
ldp x1, x2, [x10, #0x10] ; 从x10+0x10指向的地址里面取出两个64位的数,分别存入x1, x2
str x5, [sp, #24] ; 往内存中写数据(偏移值为正), 把x5的值 存入 sp+24 指向的内存地址
stur w0, [x29, #0x8] ; 往内存中写数据,偏移值为负,把w0的值存到 x29 - 8 位置
stp x29, x30, [sp, #-16]! ; 把x29 x30 值存到 sp -16的地址上,并且把 sp-= 16
ldp x29, x30, [sp], #16 从sp地址取出16字节数据,存入x29, x30.. sp+=16
寻址格式:
[x0, #0x10] 从x10 + 0x10 的地址取值
[sp, #-16]! // pre-index 从sp-16取值, 取值完后,把sp-16 writeback 回 sp
[sp], #16 // post-index 从sp地址取值,取值完后把 sp+16 writeback会sp
跳转指令
bl/b
bl 有返回跳转
b 无返回跳转
adr/adrp指令
https://www.pianshen.com/article/54901138610/
adr指令:
作用:小范围的地址读取指令。ADR 指令将基于PC 相对偏移的地址值读取到寄存器中。
原理:将有符号的21位的偏移,加上PC, 结果写入到通用寄存器,可用来计算 +/- 1MB范围的任意字节的有效地址。
adrp x0, 1
(1) 将1的值,左移12位 ==> 0x1000
(2) 将PC寄存器的低12位清零
(3) 将1和2的结果相加 给X0寄存器
编译时,首先会计算出当前PC到exper的偏移量#offset_to_exper
pc的低12位清零,然后加上偏移量,给register
得到的地址,是含有label的4KB对齐内存区域的base地址;
ptrace反调试
mov x0, #31
mov x1, #0
mov x2, #0
mov x3, #0
mov x16, #26
svc #0x80
常用汇编指令
MOV X1, X0 ; 将寄存器X0的值传送到寄存器1
ADD X0, X1, X2 ; X0 = X1 + X2
SUB X0, X1, X2 ; X0 = X1 - X2
AND X0, X0, #0xF ; X0 = X0 & 0xF
ORR X0, X0, #9 ; X0 = X0 | 9
EOR X0, X0, #0xF ; X0 = X0 ^ 0xF
LDR X5, [X6, #0x08] ; load register 吧X6寄存器偏移8的地址的值传送到X5
LDP x29, x30, [sp, #0x01] ; load pair
STR x0, [SP, #0x8] ; ;st:store,str:往内存中写数据(偏移值为正); X0寄存器的数据传送到SP+0x8地址值指向的存储空间
STUR w0, [x29, #-0x8] ; 往内存中写数据(偏移值为负)
STP x29, x30, [sp, #0x10] ; store pair. 存放一堆数据,入栈指令
CBZ 比较;如果未零就跳转
CBNZ
CMP
B ; 跳转指令
BL ; 带返回的跳转指令,返回地址保存到LR(x30)中
BLR ; 带返回的跳转指令,跳转到指令后面跟随寄存器中保存的地址
RET ;子程序返回指令,返回地址默认保存在LR
ref
https://juejin.cn/post/6844904033845526536
https://juejin.cn/post/6844903780853481479 Macho文件结构详解
https://www.jianshu.com/p/5a43b906d4af MachO动态库绑定详解
https://www.jianshu.com/p/2f4a5f74ac7a ARM64汇编