Linux ld命令教程:如何成功连接处理目标文件(附实例详解和注意事项)

Linux ld命令教程:如何成功连接处理目标文件(附实例详解和注意事项)

Linux ld命令介绍

ld(link editor)是一个链接器,用来将多个编译后的对象文件和库文件合并成一个输出文件,通常是可执行文件或共享库。ld可以处理不同的目标文件格式,如ELF、COFF、PE等,也可以支持不同的架构,如x86、ARM、MIPS等。ld是GNU binutils套件的一部分,通常不需要直接调用,而是由编译器如gcc或g++来调用。ld支持很多命令行选项,但在实际使用中,只有少数几个是常用的。

Linux ld命令适用的Linux版本

ld命令适用于大多数Linux发行版,如Ubuntu、Debian、Fedora、CentOS等。如果某些Linux系统没有安装ld,可以通过包管理器来安装。例如,在Ubuntu或Debian上,可以使用以下命令来安装ld:

[linux@bashcommandnotfound.cn ~]$ sudo apt-get install binutils

在CentOS 7上,可以使用以下命令来安装ld:

[linux@bashcommandnotfound.cn ~]$ sudo yum install binutils

在CentOS 8上,可以使用以下命令来安装ld:

[linux@bashcommandnotfound.cn ~]$ sudo dnf install binutils

Linux ld命令的基本语法

ld命令的基本语法如下:

ld [options] file...

其中,options是一些可选的参数,用来控制ld的行为,如指定输出文件名、搜索路径、符号表等。file是一个或多个输入文件,通常是对象文件或库文件。如果没有指定输出文件名,ld会默认生成一个名为a.out的文件。

Linux ld命令的常用选项或参数说明

ld命令有很多选项或参数,可以通过man ld或ld --help来查看完整的列表。这里列举一些常用的选项或参数,以及它们的作用:

选项或参数作用-o file指定输出文件名为file-l library搜索名为liblibrary.so或liblibrary.a的库文件,并链接到输出文件-L directory添加directory到库文件的搜索路径-r生成可重定位的输出文件,而不是可执行文件或共享库-s删除输出文件中的所有符号信息,减小输出文件的大小-static使用静态链接,不链接任何共享库-shared生成共享库,而不是可执行文件-soname name指定共享库的名称为name-T script使用script作为链接脚本,控制输出文件的布局和符号解析-v显示ld的版本信息-V显示ld支持的目标文件格式和架构--trace显示ld搜索和打开的输入文件--trace-symbol symbol显示ld如何解析符号symbol--verbose显示ld的详细信息,包括链接脚本和符号表

Linux ld命令的实例

下面是一些使用ld命令的实例,展示了ld命令的常见用法。

实例1:链接一个简单的C程序

假设有一个名为hello.c的C程序,内容如下:

#include

int main(void) {

printf("Hello, world!\n");

return 0;

}

要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为hello.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c hello.c

然后,使用ld命令来链接这个对象文件,生成一个名为hello的可执行文件:

[linux@bashcommandnotfound.cn ~]$ ld -o hello /lib/crt1.o /lib/crti.o hello.o -lc /lib/crtn.o

这里,需要指定一些库文件,如/lib/crt1.o,/lib/crti.o,/lib/crtn.o和-lc,这些库文件包含了一些C程序运行所需的初始化和终止代码,以及C标准库的函数。

最后,可以运行这个可执行文件,输出Hello, world!:

[linux@bashcommandnotfound.cn ~]$ ./hello

Hello, world!

实例2:链接一个静态库

假设有一个名为math.c的C程序,内容如下:

#include

int add(int a, int b) {

return a + b;

}

int sub(int a, int b) {

return a - b;

}

int mul(int a, int b) {

return a * b;

}

int div(int a, int b) {

return a / b;

}

这个程序定义了四个简单的数学函数,分别是加、减、乘、除。要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为math.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c math.c

然后,使用ar命令来将这个对象文件打包成一个名为libmath.a的静态库:

[linux@bashcommandnotfound.cn ~]$ ar rcs libmath.a math.o

接着,假设有另一个名为test.c的C程序,内容如下:

#include

int add(int a, int b);

int sub(int a, int b);

int mul(int a, int b);

int div(int a, int b);

int main(void) {

int a = 10;

int b = 5;

printf("%d + %d = %d\n", a, b, add(a, b));

printf("%d - %d = %d\n", a, b, sub(a, b));

printf("%d * %d = %d\n", a, b, mul(a, b));

printf("%d / %d = %d\n", a, b, div(a, b));

return 0;

}

这个程序调用了math.c中定义的四个数学函数,并输出结果。要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为test.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c test.c

然后,使用ld命令来链接这个对象文件和libmath.a静态库,生成一个名为test的可执行文件:

[linux@bashcommandnotfound.cn ~]$ ld -o test /lib/crt1.o /lib/crti.o test.o -L. -lmath -lc /lib/crtn.o

这里,需要使用-L.来指定当前目录为静态库的搜索路径,使用-lmath来链接libmath.a静态库。⁵

最后,可以运行这个可执行文件,输出结果:

[linux@bashcommandnotfound.cn ~]$ ./test

10 + 5 = 15

10 - 5 = 5

10 * 5 = 50

10 / 5 = 2

实例3:链接一个共享库

假设有一个名为math.c的C程序,内容如下:

#include

int add(int a, int b) {

return a + b;

}

int sub(int a, int b) {

return a - b;

}

int mul(int a, int b) {

return a * b;

}

int div(int a, int b) {

return a / b;

}

这个程序定义了四个简单的数学函数,分别是加、减、乘、除。要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为math.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c -fPIC math.c

这里,需要使用-fPIC选项来生成位置无关的代码,这是生成共享库所必需的。

然后,使用ld命令来链接这个对象文件,生成一个名为libmath.so的共享库:

[linux@bashcommandnotfound.cn ~]$ ld -shared -o libmath.so math.o

这里,需要使用-shared选项来指定生成共享库,使用-o选项来指定输出文件名为libmath.so。

接着,假设有另一个名为test.c的C程序,内容如下:

#include

int add(int a, int b);

int sub(int a, int b);

int mul(int a, int b);

int div(int a, int b);

int main(void) {

int a = 10;

int b = 5;

printf("%d + %d = %d\n", a, b, add(a, b));

printf("%d - %d = %d\n", a, b, sub(a, b));

printf("%d * %d = %d\n", a, b, mul(a, b));

printf("%d / %d = %d\n", a, b, div(a, b));

return 0;

}

这个程序调用了math.c中定义的四个数学函数,并输出结果。要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为test.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c test.c

然后,使用ld命令来链接这个对象文件和libmath.so共享库,生成一个名为test的可执行文件:

[linux@bashcommandnotfound.cn ~]$ ld -o test /lib/crt1.o /lib/crti.o test.o -L. -lmath -lc /lib/crtn.o

这里,需要使用-L.来指定当前目录为共享库的搜索路径,使用-lmath来链接libmath.so共享库。

最后,可以运行这个可执行文件,输出结果:

[linux@bashcommandnotfound.cn ~]$ ./test

10 + 5 = 15

10 - 5 = 5

10 * 5 = 50

10 / 5 = 2

实例4:使用链接脚本

链接脚本是一种控制ld的行为的文本文件,可以指定输出文件的布局和符号解析的规则。链接脚本的语法比较复杂,这里只给出一个简单的例子,展示如何使用链接脚本来修改输出文件的入口点。

假设有一个名为hello.c的C程序,内容如下:

#include

void foo(void) {

printf("Hello, world!\n");

}

int main(void) {

foo();

return 0;

}

这个程序定义了一个名为foo的函数,用来输出Hello, world!,并在main函数中调用它。要使用ld命令来链接这个程序,首先需要使用gcc或其他编译器来编译这个程序,生成一个名为hello.o的对象文件:

[linux@bashcommandnotfound.cn ~]$ gcc -c hello.c

然后,使用ld命令来链接这个对象文件,生成一个名为hello的可执行文件:

[linux@bashcommandnotfound.cn ~]$ ld -o hello /lib/crt1.o /lib/crti.o hello.o -lc /lib/crtn.o

这里,需要指定一些库文件,如/lib/crt1.o,/lib/crti.o,/lib/crtn.o和-lc,这些库文件包含了一些C程序运行所需的初始化和终止代码,以及C标准库的函数。

最后,可以运行这个可执行文件,输出Hello, world!:

[linux@bashcommandnotfound.cn ~]$ ./hello

Hello, world!

现在,假设有一个名为script.ld的链接脚本,内容如下:

ENTRY(foo)

这个链接脚本只有一行,用来指定输出文件的入口点为foo函数,而不是默认的_start符号。

要使用ld命令来链接这个程序,并使用这个链接脚本,可以使用以下命令:

[linux@bashcommandnotfound.cn ~]$ ld -o hello -T script.ld /lib/crt1.o /lib/crti.o hello.o -lc /lib/crtn.o

这里,需要使用-T选项来指定链接脚本为script.ld。

最后,可以运行这个可执行文件,输出Hello, world!,并立即退出,不会执行main函数:

[linux@bashcommandnotfound.cn ~]$ ./hello

Hello, world!

Linux ld命令的注意事项

使用ld命令时,需要注意以下几点:

ld命令通常不需要直接调用,而是由编译器如gcc或g++来调用,这样可以简化链接过程,避免一些错误和警告。

ld命令需要根据不同的目标文件格式和架构来选择合适的选项和参数,否则可能会出现不兼容或不支持的情况。

ld命令需要指定一些库文件,如/lib/crt1.o,/lib/crti.o,/lib/crtn.o和-lc,这些库文件包含了一些C程序运行所需的初始化和终止代码,以及C标准库的函数。如果没有指定这些库文件,可能会出现undefined reference to _start或undefined reference to printf等错误。

ld命令需要注意输入文件的顺序,因为ld会按照输入文件的顺序来解析符号,如果某个符号在后面的输入文件中定义,而在前面的输入文件中引用,可能会出现undefined reference to symbol的错误。

ld命令需要注意输出文件的入口点,如果没有指定入口点,ld会默认使用_start符号作为入口点,这个符号通常在/lib/crt1.o库文件中定义,用来调用main函数。如果要修改入口点,可以使用链接脚本来指定,如ENTRY(symbol)。

如果在使用ld命令时,出现bash: ld: command not found的错误,说明系统没有安装ld,可以按照上面的方法来安装ld,根据不同的Linux发行版,使用不同的包管理器来安装binutils套件。

Linux ld相关命令

以下是一些与ld命令相关的命令,以及它们的作用:

ar命令:创建、修改和提取静态库

as命令:汇编器,将汇编代码转换为目标文件

❈ ❈ ❈

相关文章

✧ ✧ ✧
电脑中的DNS服务是什么?如何手动设置电脑DNS服务器地址
速收藏!看中医还是西医?一目了然…
www.bet3365.com

速收藏!看中医还是西医?一目了然…

📅 07-19 👁️ 5198
[世界杯]马拉多纳观看世界杯 深情亲吻梅西球衣
365bet官方网站

[世界杯]马拉多纳观看世界杯 深情亲吻梅西球衣

📅 07-11 👁️ 8245