Linux:如何获取刚刚从构造函数加载的共享对象的全名?

发布于 2024-08-09 02:29:05 字数 619 浏览 2 评论 0原文

在 Windows 上,有几个参数传递给 DllMain 构造函数:

BOOL WINAPI DllMain(  
  __in  HINSTANCE hinstDLL,  
  __in  DWORD fdwReason,  
  __in  LPVOID lpvReserved  
);

从 hinstDLL 我可以使用 GetModuleFileName() 获取 DLL 本身的完全限定文件名:

LPTSTR str = new TCHAR[256];  
int libNameLength = GetModuleFileName(hinstDLL, str, 256);  
delete[] str;  

在上面的示例中,str 现在包含刚刚加载的 DLL 的全名,例如, C:\Windows\System32\MyFile.dll。

在 Linux 上,没有参数传递给共享对象构造函数:

void `__attribute__` ((constructor)) on_load(void);

在这种情况下如何获取 DLL 的全名?如果您的解决方案也适用于 Mac,则额外加分。 :-)

On Windows, several arguments are passed to the DllMain constructor:

BOOL WINAPI DllMain(  
  __in  HINSTANCE hinstDLL,  
  __in  DWORD fdwReason,  
  __in  LPVOID lpvReserved  
);

From hinstDLL I can get the fully qualified file name of the DLL itself using GetModuleFileName():

LPTSTR str = new TCHAR[256];  
int libNameLength = GetModuleFileName(hinstDLL, str, 256);  
delete[] str;  

In the example above, str now contains the full name of the DLL just loaded, e.g., C:\Windows\System32\MyFile.dll.

On Linux, no arguments are passed to the shared object constructor:

void `__attribute__` ((constructor)) on_load(void);

How do I get the full name of the DLL in this case? Extra credit if your solution works on Mac, too. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为人所爱 2024-08-16 02:29:06

一种极其丑陋和可怕的方法是查看 /proc/pid/maps 并查找包含正在执行的 on_load 函数地址的映射。

One supremely ugly and horrible way to do this is to look through /proc/pid/maps and look for the mapping that encompasses the address of the on_load function being executed.

黑凤梨 2024-08-16 02:29:05

我认为 dladdr 函数可能会满足您的需求。从手册页:

函数 dladdr() 接受一个函数指针并尝试解析
名称及其所在文件。信息存储在
Dl_info结构:

typedef 结构 {
    const char *dli_fname; /* 共享对象的路径名
                               包含地址*/
    无效*dli_fbase; /* 共享对象的地址
                               已加载*/
    const char *dli_sname; /* 带有地址的最近符号的名称
                               低于地址 */
    无效*dli_saddr; /* 名为的符号的确切地址
                               在 dli_sname 中 */
} Dl_info;

如果找不到与 addr 匹配的符号,则 dli_sname
dli_saddr 设置为 NULL

dladdr() 出错时返回 0,成功时返回非零。

因此,您只需给它一个函数指针(如构造函数本身的地址),它就会为您提供文件名和一堆其他信息。下面是一些示例代码:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

__attribute__((constructor))
void on_load(void) {
    Dl_info dl_info;
    dladdr(on_load, &dl_info);
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}

编辑:看起来这个函数也存在于 OS X 上,具有相同的语义。

I think the dladdr function might do what you want. From the man page:

The function dladdr() takes a function pointer and tries to resolve
name and file where it is located. Information is stored in the
Dl_info structure:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that
                               contains address */
    void       *dli_fbase;  /* Address at which shared object
                               is loaded */
    const char *dli_sname;  /* Name of nearest symbol with address
                               lower than addr */
    void       *dli_saddr;  /* Exact address of symbol named
                               in dli_sname */
} Dl_info;

If no symbol matching addr could be found, then dli_sname and
dli_saddr are set to NULL.

dladdr() returns 0 on error, and non-zero on success.

So you just give it a function pointer (like the address of the constructor itself), and it will give you the filename and a bunch of other information. Here's some sample code:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

__attribute__((constructor))
void on_load(void) {
    Dl_info dl_info;
    dladdr(on_load, &dl_info);
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}

EDIT: It looks like this function exists on OS X, too, with the same semantics.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文