【发布时间】:2018-05-05 05:35:45
【问题描述】:
假设您有以下汇编文件:
.file "print.s"
.intel_syntax noprefix
.text
.globl _start
.type _start, @function
_start:
mov rax, 1
mov rdi, 1
lea rsi, hello_string
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
.size _start, .-_start
和
.file "string.s"
.intel_syntax noprefix
.data
.globl hello_string
.type hello_string, @object
hello_string:
.string "Hello, world!\n"
.size hello_string, 14
如果你运行as string.s -o string.o、as print.s -o print.o,然后运行ld *.o -o hello.elf,你会得到一个打印Hello, world!的可执行文件。现在假设您将 print.s 中的 _start 标签更改为 print,并且您有以下 C 文件:
// main.c
void print(void);
int main (void) {
print();
return 0;
}
我想运行 gcc -o main.elf main.c string.s print.s 之类的东西来获取我的两个汇编文件并将它们链接到标准 C 运行时。所写的这个命令不起作用。我收到以下错误消息:
/usr/bin/ld: /tmp/ccc1yRif.o: relocation R_X86_64_32S against symbol `hello_string' can not be used when making a shared object; recompile with -fPIC
我不知道如何正确使用 -fPIC 标志来使事情正常进行。我什至不确定这是否是我应该做的。我可以尝试使用内联汇编器来执行此操作,但对于我的实际用例,这将非常烦人,我更愿意学习如何将汇编块正确链接到我的 C 程序中。我无法在网上找到很多关于此的信息。
问题:如何正确使用 GNU 链接器将汇编文件链接到 C 运行时?
编辑:在How to link a C object file with a Assembly Language object file? 中,OP 询问如何仅使用ld 来解决类似的链接问题。我想使用gcc,这是链接问题中推荐的解决方案,但我什至无法让它工作。
【问题讨论】:
-
@RobinGreen:嗨,罗宾,这个问题有点不同。 OP 询问如何仅使用
ld进行链接。我想使用gcc,这是他们推荐的答案,但它对我不起作用,我不明白为什么 -
但是您的称呼方式与推荐答案中的方式不同。显然,您可以省略
-m32,因为您正在编写 64 位代码,但看起来您应该输出.o而不是.elf。 -
我明白你在说什么。也许我应该首先从我的 c 文件生成一个目标文件,然后将三个目标文件与 gcc 组合在一起。但是,当我尝试使用
gcc main2.c -o main2.o准确编译 OPs C 文件main2.c时,链接器出错并抱怨对strlength的未定义引用 -
@RobinGreen:你知道如何让 gcc 输出一个可重定位的目标文件吗?我在手册中看不到它的标志。 -o 输出一个elf 文件,opsys 可以直接加载该文件。这是不可重定位的,所以不能再链接了