avast / retdec

RetDec is a retargetable machine-code decompiler based on LLVM.
https://retdec.com/
MIT License
8.01k stars 946 forks source link

Mach-O: special analysis for dyld_stub_binder() function #165

Open PeterMatula opened 6 years ago

PeterMatula commented 6 years ago

Compare decompilation output for stripped and not-stripped binaries from: test.zip. What is dyld_stub_binder() doing? Looks like some kind of symbol lazy binding.

Another example 10f62cd02bb164433249522e6597f2eeaa6545a3a763ca8bb70af7b9e6308098 and its IDA: arm-macho-6ae192c4caa958a6d1c4479221a7785d-ida

Analyze and implement special handling if needed.

PeterMatula commented 6 years ago

From http://mirror.informatimago.com/next/developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/5rt_api_reference/chapter_11_section_50.html:

Assembly-language glue code that performs binding for a lazy function symbol.

.private_extern dyld_stub_binding_helper

Parameter Descriptions
PowerPC: r11 x86: stack-based parameter
    A pointer to the lazy symbol pointer for the function to be bound.

Discussion

The dyld stub binding helper is a glue function that assists the dynamic linker in lazily binding an external function. When the compiler sees a call to an external function,
it generates a symbol stub and a lazy pointer for the function. At the call site, the compiler generates a call to the symbol stub. The symbol stub is a sequence of code
that loads the lazy pointer and jumps to it. Initially, the sequence of code and the contents of the lazy pointer call dyld_stub_binding_helper, which calls the dynamic linker
 to bind the symbol. After the symbol is bound, the lazy pointer is set to the address of the symbol, and the symbol is reached directly by jumping to the lazy pointer.

Thereafter, because the address has been changed to the actual address of the function, all calls to the external function call the external function.

On entry, dyld_stub_binding_helper accepts the address of the lazy symbol pointer. On exit, the value of the lazy symbol pointer is set to the address of the external function.
The dyld stub binding helper is assembly-language based and does not use standard calling conventions, and as such, the location of the parameters are specific to each CPU
architecture. On PowerPC, the address of the lazy symbol pointer is expected to be in GPR11. On x86, the address of the lazy symbol pointer should be the pushed on the stack.

dyld_stub_binding_helper is located in the runtime startup files that are statically linked into the image. For executables, the file is /lib/crt1.o. For bundles, it is /lib/bundle1.o,
and for shared libraries, it is /lib/dylib1.o.