[问题] ld 连结 object file

楼主: gn00618777 (非常念旧)   2021-02-06 11:59:39
我在阅读一本书,里面给一个静态连结的范例
a.c:
extern int shared;
int main() {
int a = 100;
swap(&a, &shared);
return 0;
}
b.c:
int shared = 1;
void swap(int *a, int *b){
*a ^= *b ^= *a ^= *b;
}
编译指令:
gcc -c a.c -fno-stack-protector
gcc -c b.c -fno-stack-protector
连结指令:
ld a.o b.o -e main -o ab
执行时:
./ab 出现 segmentation fault(core dump)
请问有人知道这什么状况吗? 谢谢
我GCC 版本 gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
ld 版本 GNU ld (GNU Binutils for Ubuntu) 2.34
作者: Lipraxde (Lipraxde)   2021-02-06 13:52:00
为什么你要下 -e?环境比较特殊吗?你这样直接用 ld 编译出来的程式,会直接用 main 当 entry point,不会经过 c runtime,所以stack 上的 return address 是无效的,当执行到 return 0 的时候就会 segmentation fault
作者: Schottky (顺风相送)   2021-02-06 14:52:00
所以正确的编译方法应该是这样:gcc -c b.c -o b.ogcc a.c b.o -o abgcc 才会正确把 C runtime 连结进来
楼主: gn00618777 (非常念旧)   2021-02-06 16:21:00
请问经过 c runtime 是什么概念?我在网络上看到和同事讨论知道要用gcc 连结,但我不解ld 为何就不行,书上这样写我照刻下 -e 他entry point 就会是_start ,这是ld默认
作者: Schottky (顺风相送)   2021-02-06 16:46:00
C runtime 就是你还需要连结 crt0.o 的意思虽然你应该找不出这个 crt0.o 藏在哪个 library 里C 语言写的程式,在呼叫 main 前还需要做一点事前准备
作者: Lipraxde (Lipraxde)   2021-02-06 16:56:00
gcc ... -v 可以看到比较详细的编译过程,实际上会发现link 阶段不是只把你自己写的那些程式 link 起来而已,还需要像是 c runtime、std lib 等东西
作者: LPH66 (-6.2598534e+18f)   2021-02-06 20:54:00
你知道不设 -e 的默认进入点是 _start, 这个标签就是在crt0.o 里面, 它包含一些在进你的 main 之前要执行的东西以及在你的 main 结束后帮你清理东西的程式也在里面这些东西就是上面推文提到的 C runtime
作者: descent (“雄辩是银,沉默是金”)   2021-02-06 21:22:00
是那一本书的内容呢?
楼主: gn00618777 (非常念旧)   2021-02-09 18:29:00
"程式设计师的自我修养" 这本书原来有这么多没提到的...,我再好好整理一下,谢谢大家
作者: SonyF800 (索尼F800)   2021-02-10 18:02:00
那是因为你还在章节 4 ,章节 11 有大概讲一下书上这边说的意思是,没给 -e main 的话默认会是 _start
楼主: gn00618777 (非常念旧)   2021-02-11 11:59:00
我往后翻章节4有CRT概念带出了,不过要是我没发问我肯定只是唸过带过不会留意

Links booklink

Contact Us: admin [ a t ] ucptt.com