本工具从最初版的跳转分布图只为了更直观地分析反汇编代码的分支结构,第三版开始对直观图进行逆向分支代码的输出,第四版对分支输出策略的一些探索,第五版结合之前的探索进行改进。第六版在现在功能的基础上进行增强,利用第六版的基本功能-直译,对条件分支增加条件判断翻译,以及改进在函数调用处附带备选参数参考。
本篇选两个函数的分支逆向贴上:
void CA::Layer::prepare_commit(CA::Transaction* transaction) { // 64 call // %edx = 0x1000 // %edi = 0x400 // %rsi = &_1030 x_heap_new_with_ptr; // 82 call // %rdi = r15 CA::Transaction::lock(); // 162 call // %rdi = r14 // %rsi = &_1070 CA::Layer::collect_layers_(CA::Layer::CollectLayersData*); // 177 call // %rdi = r15 CA::Transaction::unlock(); // 182 goto _f188; _b184: // from 403 _b184: // from 386 _f188: // from 182 // 191 if (!) { // 188 (0 == rbx) // 208 if (!) { // 205 (0 == r14) // 217 call // %rdi = r15 CA::Transaction::lock(); // 232 call // %rsi = "contents" // %rdi = r14 objc_msgSend; // 244 if () { // 241 (0 == r13) // gen jmp 336 goto _f336; // 249 call // %rdi = r13 CFRetain; // 257 call // %rdi = r15 CA::Transaction::unlock(); // 265 call // %rdi = r13 CFGetTypeID; // 273 call CGImageGetTypeID; } // 281 else if () { // 278 (r15 != rax) // gen jmp 346 goto _f346; } else { // 281 next // 293 call // %rsi = "_renderImageCopyFlags" // %rdi = r14 objc_msgSend; // 312 call // %rdi = r15 CA::Context::current_colorspace(CA::Transaction*); // 329 call // %edx = r14d // %rsi = rax // %rdi = r13 // %xmm0 = 0.; CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double); // 334 goto _f369; _f336: // from 244 // 293 call // %rsi = "_renderImageCopyFlags" // %rdi = r14 objc_msgSend; // 312 call // %rdi = r15 CA::Context::current_colorspace(CA::Transaction*); // 329 call // %edx = r14d // %rsi = rax // %rdi = r13 // %xmm0 = 0.; CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double); } // 336 // 339 call // %rdi = r15 CA::Transaction::unlock(); // 344 goto _f377; _f346: // from 281 // 356 call // %rsi = "CA_prepareRenderValue" // %rdi = r13 objc_msgSend; _f369: // from 334 // 372 call // %rdi = r13 CFRelease; _f377: // from 344 } // 377 // 386 if () // 377 (r12->_98 == 0x0) goto _b184; // 398 call // %rsi = r15 // %rdi = r12 CA::Layer::prepare_animations(CA::Transaction*); // 403 goto _b184; } // 408 // 434 if () goto _f475; _b454: // from 473 // 460 call // %rdi = r15 CA::Transaction::unlock(); // 468 call // %rdi = r14 _Unwind_Resume; // 473 goto _b454; // 475 call __stack_chk_fail; _f475: // from 434 /***** * global variables * */ // 33 extern ent_off__0x7516a; movq 0x75142(%rip), %rax; (void *)0x00000001066f9070: __stack_chk_guard // 225 extern ent_off__0x6fa52; movq 0x6f96a(%rip), %rsi; "contents" // 286 extern ent_off__0x6fa12; movq 0x6f8ed(%rip), %rsi; "_renderImageCopyFlags" // 349 extern ent_off__0x6f6c2; movq 0x6f55e(%rip), %rsi; "CA_prepareRenderValue" // 420 extern ent_off__0x7516a; movq 0x74fbf(%rip), %rax; (void *)0x00000001066f9070: __stack_chk_guard /***** * registers modify overviewing * scale:50 */ // rbx: 01020 0001 // rdx: 01000 0100 // rdi: 02023 34212 // rsi: 10011 1210 // r12: 00010 0001 // r13: 00001 0001 // r14: 10010 10011 // r15: 10000 1111 /***** * registers test overviewing * scale:50 */ // rax: 00000 0001 // rbx: 00010 0000 // r13: 00001 0000 // r14: 00001 0000 // r15: 00000 1000 }
以及:
CA::Layer::State* CA::Layer::writable_state(CA::Transaction* transaction) { // 24 if (!) { // 16 (rbx->_90 != 0x0) // 37 if (!) { // 30 (0 == ((0x40<<8) & rbx->_84)) // 45 call // %rsi = r14 // %rdi = rbx CA::Layer::fetch_geometry(CA::Transaction*); } // 50 // 55 call // %edi = 0x6 x_mem_alloc_bucket; // 136 if (!) { // 133 (0 == rdi) // 138 call CFRetain; } // 143 // 156 if (!) { // 153 (0 == rdi) // 158 call CFRetain; } // 163 // 180 if (!) { // 175 (rbx->_78 == 0x0) // 185 call // %rdi = r14 CA::Transaction::lock(); // 199 if (!) { // 196 (0 == rdi) // 201 call CA::AttrList::copy(); } // 206 // 213 call // %rdi = r14 CA::Transaction::unlock(); } // 218 _b220: // from 239 // 239 if () // 235 (rax != 0x4) goto _b220; } // 253 // 270 ret return; // 274 goto _f287; // 282 call // %rdi = r14 CA::Transaction::unlock(); _f287: // from 274 // 290 call // %rdi = rbx _Unwind_Resume; /***** * registers modify overviewing * scale:50 */ // rbx: 10000 4 // rcx: 01001 // rdi: 11221 2 // rsi: 10000 // r14: 10000 1 // r15: 01000 1 /***** * registers test overviewing * scale:50 */ // rax: 00001 // rdi: 00120 }
相信大家会发现,在函数结尾处,有另外一些统计信息的输出,包括有全局变量的访问,寄存器在各范围段内修改次数的统计,寄存器在各范围段内用作条件检测比较次数的统计。
/***** * global variables * */ // 33 extern ent_off__0x7516a; movq 0x75142(%rip), %rax; (void *)0x00000001066f9070: __stack_chk_guard // 225 extern ent_off__0x6fa52; movq 0x6f96a(%rip), %rsi; "contents" // 286 extern ent_off__0x6fa12; movq 0x6f8ed(%rip), %rsi; "_renderImageCopyFlags" // 349 extern ent_off__0x6f6c2; movq 0x6f55e(%rip), %rsi; "CA_prepareRenderValue" // 420 extern ent_off__0x7516a; movq 0x74fbf(%rip), %rax; (void *)0x00000001066f9070: __stack_chk_guard /***** * registers modify overviewing * scale:50 */ // rbx: 01020 0001 // rdx: 01000 0100 // rdi: 02023 34212 // rsi: 10011 1210 // r12: 00010 0001 // r13: 00001 0001 // r14: 10010 10011 // r15: 10000 1111 /***** * registers test overviewing * scale:50 */ // rax: 00000 0001 // rbx: 00010 0000 // r13: 00001 0000 // r14: 00001 0000 // r15: 00000 1000
例如上面的例子,寄存器使用状况统计(overviewing),'scale:50'表现为统计口径为50个代码字节,‘r15: 10000 1111’表示寄存器r15在各个50个代码字节片段中被修改的次数,这个例子中,前250字节的代码中,r15只被修改过一次,后面侧每50字节的代码都被修改过只作为短距离有效。一般来说rdi修改的统计可以反映出函数调用的分布,只能作大体上参考。
这个额外的功能或许现阶段没有用处,但可能后面功能开发的基础。