首页 > 解决方案 > 获取库本身内动态库的文件名

问题描述

我正在做一个动态库(loader.so)并希望根据库的名称打开一个文件。这个想法是复制/符号链接库以打开不同的文件。

是否可以从库中找到使用 dlopen() 打开的库的文件名?我需要在运行时进行。

编辑:更多上下文:该库作为插件加载并充当 Python 插件的包装器。这意味着该库被同一个进程多次加载。因此,查找符号的方法失败了。(搜索匹配第一个实例,所以我得到相同的名称返回给所有库实例。)

Program -> loader_plugin1.so -> plugin1.py
        -> loader_another_plugin.so -> another_plugin.py

标签: clinuxdynamic-library

解决方案


你可以用dl_iterate_phdr.

示例脚本(用于构建示例项目;在空目录中运行):

#!/bin/sh -eu
cat > main.c <<EOF
void pr_libnm(void);
int main()
{
    pr_libnm();
    return 0;
}
EOF
cat > pr_libnm.c <<'EOF'
#define _GNU_SOURCE
#include  <link.h>
#include  <stdio.h>
#include  <stdint.h>
static int cb_(struct dl_phdr_info *Info, size_t Sz, void *Data)
{
    //printf("Name=%s\n",Info->dlpi_name);
    uintptr_t a = (uintptr_t)cb_;

    //for each elf-header, iterate thru program headers
    for(size_t i=0; i<Info->dlpi_phnum; i++){
        // [b,e) is the corresponding segment
        uintptr_t b = Info->dlpi_addr + Info->dlpi_phdr[i].p_paddr;
        uintptr_t e = b + Info->dlpi_phdr[i].p_memsz;
        if(a>=b && a<e){
            //if this is cb_'s segment, we're done
            printf("NAME=%s\n", Info->dlpi_name);
            //nonzero signals end of iteration
            return 1;
        }

    }
    return 0;
}
void pr_libnm(void)
{
    //iterate thru elf-headers
    dl_iterate_phdr(cb_ ,(void*)0);
}
EOF
: ${CC:=gcc}
for c in *.c; do $CC -fpic -c $c; done
$CC -shared -o libpr.so pr_libnm.o
$CC main.o $PWD/libpr.so
./a.out #prints NAME=$PWD/libpr.so

(当然,在 Unix 上,一个文件可以有多个名称。您将只获得用于映射它的共享对象的名称。)

dl_iterate_phdr遍历映射对象的 elf 标头。每个 elf 标头都包含一个指向对象名称的指针。

程序遍历每个 elf 对象的段,当它找到调用共享对象的函数映射到的段时,它从 elf 标头打印名称并退出迭代。


推荐阅读