Linker—android里面的加载器ld
这类的基础库要想调试基本上gdb是派不上用场的,最好用的还是printf,这里的printf是个泛指
android 的调试基本上都是通过logcat 输出的,当然你也可以自己打开一个文件写,不过那样子会带来各种权限问题,阻止的让你崩溃!
Linker 的debug 主要靠printf
分为三个档
#define PRINT(x...) _PRINTVF(-1, x)
#define INFO(x...) _PRINTVF(0, x)
#define TRACE(x...) _PRINTVF(1, x)
可以输出到两个方向
#if LINKER_DEBUG_TO_LOG
#define _PRINTVF(v, x...) \
do { \
if (g_ld_debug_verbosity > (v)) __libc_format_log(5-(v), "linker", x); \
} while (0)
#else /* !LINKER_DEBUG_TO_LOG */
#define _PRINTVF(v, x...) \
do { \
if (g_ld_debug_verbosity > (v)) { __libc_format_fd(1, x); write(1, "\n", 1); } \
} while (0)
#endif /* !LINKER_DEBUG_TO_LOG */
如果LINKER_DEBUG_TO_LOG 为非零值,则输出到logcat 否则输出到stdout
但是android 的stdout 基本上被重定向到了/dev/null里面,所以这里基本是无效的
注意,这里面还有个变量
g_ld_debug_verbosity 这个值在linker_debug.h中有声明,定义在了linker.cpp里面
默认值为0 也就是说默认只有PRINT这个宏是可以输出的
Linker 初始化这个 g_ld_debug_verbosity值用的是如下代码
// Get a few environment variables.
const char* LD_DEBUG = getenv("LD_DEBUG");
if (LD_DEBUG != nullptr) {
g_ld_debug_verbosity = atoi(LD_DEBUG);
}
这个设置应该需要在
这里添加 aosp/system/core/rootdir/init.environ.rc.in
然后刷systemimge
这样的代价显然太大
最简单的方法是使用如下的修改,直接push /system/bin/linker /system/bin/link64到机器上即可,需要adb reboot 重启机器以让改动生效
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 573bcf8..be1d175 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1595,6 +1595,8 @@ static int open_library(android_namespace_t* ns,
const char* name, soinfo *needed_by,
off64_t* file_offset, std::string* realpath) {
TRACE("[ opening %s ]", name);
+ INFO("[ opening %s ]", name);
+ PRINT("[ opening %s ]", name);
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
@@ -4216,6 +4218,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
if (LD_DEBUG != nullptr) {
g_ld_debug_verbosity = atoi(LD_DEBUG);
}
+ g_ld_debug_verbosity = 1;
#if defined(__LP64__)
INFO("[ Android dynamic linker (64-bit) ]");
注意不建议把g_ld_debug_verbosity修改为2,这样的话会很久都无法启动机器,因为一直在打印
也就意味着如果不使用重定向到文件,基本上无法实现TRACE调试
init 是一个不使用linker的程序
使用linker的子进程都会执行__linker_init
可能静态链接的就不需要了?
readelf -h objfile
type | 是否需要linker |
---|---|
DYN (共享目标文件) | 是 |
EXEC (可执行文件) | 否 |