C EXPORT_符号导致一个方向上的引用未定义,但另一个方向上的引用未定义(重定位截断)

C EXPORT_符号导致一个方向上的引用未定义,但另一个方向上的引用未定义(重定位截断),c,gcc,linux-kernel,linux-device-driver,arm64,C,Gcc,Linux Kernel,Linux Device Driver,Arm64,我正在aarch64机器上开发4.9Linux内核,特别是mm/memory.c和一个定制的平台设备驱动程序。我的目标是让我的设备驱动程序与源于memory.c中函数的硬件通信一些信息 首先,我尝试了我一直用于跨(平台)设备驱动程序通信的相同方法: 导出驱动程序A中相应功能的\u符号 在驱动程序B中将符号定义为外部并访问 通常工作起来很有魅力,但这次我在使用平台驱动程序导出和内存.c使用外部进行链接时遇到了以下错误: mm/memory.c:164:(.text+0x2a874): relo

我正在aarch64机器上开发4.9Linux内核,特别是mm/memory.c和一个定制的平台设备驱动程序。我的目标是让我的设备驱动程序与源于memory.c中函数的硬件通信一些信息

首先,我尝试了我一直用于跨(平台)设备驱动程序通信的相同方法:

  • 导出驱动程序A中相应功能的\u符号
  • 在驱动程序B中将符号定义为外部并访问
通常工作起来很有魅力,但这次我在使用平台驱动程序导出
内存.c
使用外部进行链接时遇到了以下错误:

mm/memory.c:164:(.text+0x2a874): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against undefined symbol `my_func'
然而,如果我做相反的事情,那就是:

  • memory.c
  • 将指向平台驱动程序功能的指针指定给导出的符号
。。。它起作用了

具体地说

平台驱动程序:

void my_func(args){ ... };
EXPORT_SYMBOL(my_func);
extern void (*funcptr)(args);

driver_probe() {
...
funcptr = &my_func;
....
}
记忆c:

extern void my_func(args);
void (*funcptr)(args) = NULL;
EXPORT_SYMBOL(funcptr);
。。。导致上述链接器错误

但是

平台驱动程序:

void my_func(args){ ... };
EXPORT_SYMBOL(my_func);
extern void (*funcptr)(args);

driver_probe() {
...
funcptr = &my_func;
....
}
记忆c:

extern void my_func(args);
void (*funcptr)(args) = NULL;
EXPORT_SYMBOL(funcptr);
。。。工作

谷歌快速搜索暗示链接器错误与gcc选项PIC/PIE有关,但我找不到确切的答案


它现在起作用了。。。但是为什么呢?:-)

我认为给出的图片将澄清这里的错误。内核不能使用模块导出的符号。首先,内核不会在您遇到链接器错误时构建


我是否正确理解,
mm/memory.c
是内核内核中的一个文件(直接编译到内核映像中),您将驱动程序构建为一个模块(打算在运行时加载)?如果是这样,那么
mm/memory.c
只能使用内核核心中定义的函数,不能使用模块中声明的函数。最初,我将驱动程序作为一个模块,但在添加符号时,我已经在内核配置中将其从M切换到Y。如果所有涉及的代码都作为内核核心的一部分进行编译,那么
EXPORT\u SYMBOL
与您的问题无关-此宏仅影响内核模块中符号的使用。