很容易找到如何使用 dlsym()以及此系列中的其他功能,但内部如何工作?是否有可能编写自己的,易于实现的dlsym()?
我想知道是否有可能实现类似的行为,但没有链接-ldl(假设我不能这样做)。
答案 0 :(得分:10)
它在内部如何运作?
正如this answer所解释的那样,在GLIBC中,第一个参数实际上是指向struct link_map
的指针,它包含足够的信息来定位共享库的动态符号表。找到符号表DT_HASH
或DT_GNU_HASH
后,dlsym
会使用一个或另一个哈希表来查找给定的符号名称。
是否有可能编写自己的,易于实现的dlsym()?
是。如果您不关心查找速度,则可以简单地对动态符号表进行线性搜索。这样做的代码非常简单,特别是如果共享库有(可选)部分标题:您需要做的就是在内存中找到.dynsym
和.dynstr
部分的位置,然后(假设您正在寻找符号"foo"
)
const char *strtab = ... /* locate .dynstr */
const ElfW(Sym) *sym = ... /* locate .dynsym */
for (; sym < end_of_dynsym; ++sym) {
if (strcmp(strtab + sym->st_name, "foo") == 0) {
/* found it */
return load_address + sym->st_value;
}
}
/* symbol not found */
return NULL;
如果您确实关心查找速度(dlsym
当然可以),则需要解码.hash
或.gnu_hash
,这有点复杂。你可以开始here。