如何在 GAS 中设置一个 .global 符号?
How to .set a .globl symbol in GAS?
我在一个文件 (original_fun.c
) 中定义了一个函数 original_fun
,我需要在文件 use_alias.c
中将其引用为 global_alias
。我尝试了以下方法:
# 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;
}
但是没有导出符号global_alias
:
$ 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)
和objdump
报告:
$ 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
(有启发性的例子是 original_fun
是一个损坏的 C++ 名称,我想以更清晰的名称导出它,以便它可以很容易地从汇编程序中使用。)
GAS 手册 (https://sourceware.org/binutils/docs/as/Set.html) 规定如下:
If you .set a global symbol, the value stored in the object file is the last value stored into it.
这可能与我的问题有关,但我不确定我是否理解正确。
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.
作为替代答案,更简洁的解决方案可能是使用 extern "C"
:
extern "C" {
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
}
这不仅需要更少的源文件,而且据我所知,它还可以在不同的 C++ 编译器之间移植。
If you .set a global symbol, the value stored in the object file is
the last value stored into it.
阅读本文我相信这意味着您正在尝试将别名设置为无法完成的变量,我会尝试使用但我现在无法测试!
const auto& new_fn_name = old_fn_name;
您尝试做的事情不起作用的基本原因是因为 gas
不知道 original_fun
的 "value",因为它是一个外部符号.组装对 original_fun
的引用时,它只能发出重定位指令,这与发出它的实际值不同。
.set
然后在本地使 global_alias
成为 original_fun
的一种软别名,因此它的工作方式与它类似。发生的情况是,在同一文件中每次使用 global_alias
都会发出重定位到 original_fun
。然而,这样的机制无法作为 global_alias
的实际值有意义地导出,因为在 ELF 中无法表达该想法。 (我不知道是否有一些目标文件格式能够将一个符号表示为另一个符号的别名,我也不知道 gas
在组装成该格式时是否会支持该功能。)
如果您想让 global_alias
像您描述的那样工作,.set
指令需要与 original_fun
的实际定义位于同一汇编单元中。从技术上讲,如果您使用 GCC,那么您可以使用顶级内联汇编来执行此操作:
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
asm(".set global_alias, original_fun");
但是,这显然不能移植到不同的编译器。
我在一个文件 (original_fun.c
) 中定义了一个函数 original_fun
,我需要在文件 use_alias.c
中将其引用为 global_alias
。我尝试了以下方法:
# 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;
}
但是没有导出符号global_alias
:
$ 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)
和objdump
报告:
$ 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
(有启发性的例子是 original_fun
是一个损坏的 C++ 名称,我想以更清晰的名称导出它,以便它可以很容易地从汇编程序中使用。)
GAS 手册 (https://sourceware.org/binutils/docs/as/Set.html) 规定如下:
If you .set a global symbol, the value stored in the object file is the last value stored into it.
这可能与我的问题有关,但我不确定我是否理解正确。
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.
作为替代答案,更简洁的解决方案可能是使用 extern "C"
:
extern "C" {
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
}
这不仅需要更少的源文件,而且据我所知,它还可以在不同的 C++ 编译器之间移植。
If you .set a global symbol, the value stored in the object file is the last value stored into it.
阅读本文我相信这意味着您正在尝试将别名设置为无法完成的变量,我会尝试使用但我现在无法测试!
const auto& new_fn_name = old_fn_name;
您尝试做的事情不起作用的基本原因是因为 gas
不知道 original_fun
的 "value",因为它是一个外部符号.组装对 original_fun
的引用时,它只能发出重定位指令,这与发出它的实际值不同。
.set
然后在本地使 global_alias
成为 original_fun
的一种软别名,因此它的工作方式与它类似。发生的情况是,在同一文件中每次使用 global_alias
都会发出重定位到 original_fun
。然而,这样的机制无法作为 global_alias
的实际值有意义地导出,因为在 ELF 中无法表达该想法。 (我不知道是否有一些目标文件格式能够将一个符号表示为另一个符号的别名,我也不知道 gas
在组装成该格式时是否会支持该功能。)
如果您想让 global_alias
像您描述的那样工作,.set
指令需要与 original_fun
的实际定义位于同一汇编单元中。从技术上讲,如果您使用 GCC,那么您可以使用顶级内联汇编来执行此操作:
void original_fun(int x)
{
printf("original_fun(%d)\n", x);
}
asm(".set global_alias, original_fun");
但是,这显然不能移植到不同的编译器。