dlsym 是如何工作的?
How does the dlsym work?
很容易找到如何使用 dlsym() 和该系列的其他函数,但它在内部是如何工作的?是否可以自己编写简单的 dlsym() 实现?
我想知道是否有可能实现类似的行为,但是没有 与 -ldl 链接(假设我不能这样做)。
how does it work internally?
正如 this answer 所解释的,在 GLIBC 中第一个参数实际上是指向 struct link_map
的指针,它包含足够的信息来定位共享库的动态符号 table。一旦找到符号 table 和 DT_HASH
或 DT_GNU_HASH
,dlsym
使用一个或另一个散列 table 来查找给定的符号名称。
Is it possible to write own, easy implementation of dlsym()?
是的。如果你不关心查找速度,你可以简单地对动态符号table进行线性搜索。这样做的代码非常简单,特别是如果共享库有(可选)部分 header:您需要做的就是在内存中找到 .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.
很容易找到如何使用 dlsym() 和该系列的其他函数,但它在内部是如何工作的?是否可以自己编写简单的 dlsym() 实现?
我想知道是否有可能实现类似的行为,但是没有 与 -ldl 链接(假设我不能这样做)。
how does it work internally?
正如 this answer 所解释的,在 GLIBC 中第一个参数实际上是指向 struct link_map
的指针,它包含足够的信息来定位共享库的动态符号 table。一旦找到符号 table 和 DT_HASH
或 DT_GNU_HASH
,dlsym
使用一个或另一个散列 table 来查找给定的符号名称。
Is it possible to write own, easy implementation of dlsym()?
是的。如果你不关心查找速度,你可以简单地对动态符号table进行线性搜索。这样做的代码非常简单,特别是如果共享库有(可选)部分 header:您需要做的就是在内存中找到 .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.