I'm working on the 4.9 Linux kernel on a aarch64 machine, specifically mm/memory.c and a custom platform device driver. My goal is to have my device driver communicate some information to hardware that originates in functions in memory.c.
At first, I tried the same approach I always use for communicating across (platform) device drivers:
EXPORT_SYMBOLfor the respective function in driver A- Defining the symbol as extern in driver B and accessing
Usually works like a charm, but this time I came across the following error when linking, with the platform driver EXPORTing and memory.c using extern:
mm/memory.c:164:(.text+0x2a874): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against undefined symbol `my_func'
However, if I do the opposite, that is:
- Define and
EXPORT_SYMBOLa function pointer inmemory.c - Assign a pointer to the platform driver function to the exported symbol
... it works!
Specifically...
Platform Driver:
void my_func(args){ ... };
EXPORT_SYMBOL(my_func);
memory.c:
extern void my_func(args);
... causes the linker error described above.
But ...
Platform Driver:
extern void (*funcptr)(args);
driver_probe() {
...
funcptr = &my_func;
....
}
memory.c:
void (*funcptr)(args) = NULL;
EXPORT_SYMBOL(funcptr);
... works !
A quick google search hinted that the linker error is concerned with the gcc options PIC/PIE, but I couldn't find a definitive answer.
It works now ... but WHY? :-)
