【发布时间】:2021-08-25 07:47:48
【问题描述】:
我在下面有一个代码。它是一个动态共享库的一部分,由 qemu 程序(一个 C 程序)使用 dlopen 加载。
extern "C" {
extern uint64_t host_virt_offset;
}
int Driver::CallSetBareMetalMode( uint64_t * args_ptr)
{
dbg_enter();
(... some codes ..)
baremetal_axpu_es = (struct es_t *)(args_ptr[0] + host_virt_offset); // line a
baremetal_axpu_regs = (struct reg_csr_t *)(args_ptr[1] + host_virt_offset); // line b
dbg_leave();
return 0;
}
因为变量host_virt_offset是在qemu(一个C程序)中定义的,所以我认为它可以在这个共享库中使用没有问题。但是当我运行它时,会发生错误,当我使用调试器检查它时,我发现代码正在寻找Driver::host_virt_offset,而不是全局(和外部)变量host_virt_offset。我从下面那条线附近知道这一点。
(gdb) print host_virt_offset
Missing ELF symbol "AXPU::host_virt_offset".
我尝试在 a、b 行中使用 ::host_virt_offset,但它无法编译。应该如何声明和使用变量host_virt_offset?
添加:(我有一段时间无法连接到 stackoverflow)我制作了一个可重现的程序。在这里使用我使用的方法可以正常工作。所以还有别的东西。 '
>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uint64_t var_from_qemu = 0x12345678;
int main(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
bar();
return 0;
}
>
#include <stdint.h>
#include <stdio.h>
extern "C" {
extern uint64_t var_from_qemu;
}
class BC;
class BC {
public:
void bar(void);
BC();
~BC();
};
BC::BC()
{
}
BC::~BC()
{
}
void BC::bar(void)
{
printf("class function : var_from_qemu = %lx\n", var_from_qemu);
}
extern "C" {
void bar(void)
{
printf("global function : var_from_qemu = %lx\n", var_from_qemu);
BC tmp;
tmp.bar();
}
}
>
$ g++ bar.cpp -Wall -fpic -shared -g -o libbar.so
$ gcc main.c -o main -g -ldl -rdynamic
$ main
global function : var_from_qemu = 12345678
class function : var_from_qemu = 12345678
【问题讨论】:
-
请发布完整且未经编辑的编译器错误消息。
-
问题一定与您的可重现示例和真实代码之间的差异有关。请尝试使您的可重现示例逐渐更像真实代码,直到您遇到同样的失败。我建议您首先仔细查看
Driver类的定义——编译器将host_virt_offset解析为Driver::host_virt_offset一定是有原因的,这就是原因所在。 -
您可以提供的其他有用信息:运行
nm --dynamic --no-demangle your_real_plugin.so | grep host_virt_offset并发布完整且未经编辑的输出。 -
继续努力。问题的根本原因在于您认为不相关的代码。这是调试时常见的认知陷阱,所以不要难过,但要重新审视你的假设。
标签: c++ c gcc linker shared-libraries