I have a function original_fun
defined in one file (original_fun.c
), and I need to refer to it as global_alias
in file use_alias.c
. I tried the following:
# set_alias.s
.globl global_alias
.set global_alias, original_fun
// original_fun.c
#include <stdio.h>
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
// use_alias.c
extern void global_alias(int x);
int main()
{
global_alias(42);
return 0;
}
But the symbol global_alias
is not exported:
$ as set_alias.s -o set_alias.o
$ clang original_fun.c -c -o original_fun.o
$ clang use_alias.c -c -o use_alias.o
$ clang set_alias.o original_fun.o use_alias.o -o result
use_alias.o: In function `main':
use_alias.c:(.text+0x1d): undefined reference to `global_alias'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
And objdump
reports:
$ objdump -rt set_alias.o
set_alias.o: file format elf32-i386
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 *UND* 00000000 original_fun
(The motivating example is that original_fun
is a mangled C++ name, and I would like to export it under a cleaner name, so that it can be easily used from assembler.)
The GAS manual (https://sourceware.org/binutils/docs/as/Set.html) states the following:
If you .set a global symbol, the value stored in the object file is the last value stored into it.
This might be related to my problem, but I am not sure I understand this correctly.
The basic reason why what you're trying to do doesn't work is because gas
doesn't know the "value" of original_fun
, as it is an external symbol. When assembling references to original_fun
, it can only emit relocation directives, which is different from emitting the actual value of it.
What .set
then does instead is to locally make global_alias
a kind-of soft alias for original_fun
, so that it works similar to it. What happens is that every use of global_alias
in the same file emits a relocation to original_fun
instead. However, such a mechanic cannot meaningfully be exported as the actual value of global_alias
, as there is no way to express that idea in ELF. (I don't know if there may some object file-format that is capable of expressing a symbol as being an alias for another symbol, nor do I know if gas
would support that feature when assembling to that format.)
If you want to make global_alias
work as you describe it, the .set
directive would need to be in the same assembly unit as the actual definition of original_fun
. Technically, if you use GCC, then you could do this with top-level inline assembly:
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
asm(".set global_alias, original_fun");
That is clearly not portable to different compilers, however.