链接

链接的概念

1.链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。

2.链接可以执行于编译、加载、运行时。

3.在现代系统中,链接由连接器自动执行。

具体操作

编译器驱动程序

测试代码1

//mismatch-main.c
#include <stdio.h>
long int x;  /* Weak symbol */
int main(int argc, char *argv[]) {
    printf("%ld\n", x);
    return 0;
}
//mismatch-variable.c
/* Global strong symbol */
double x = 3.14;

1.在Ubuntu终端输入 gcc -Og -o mismatch mismatch-main.c mismatch-variable.c 得到一个可执行目标文件mismatch,后输入 ./mismatch 即可得运行结果“461425307021498087”。

2.-o表示设定输出文件名,不加-o时默认a.out为可执行文件名。

3.在mismatch-main.c中定义了全局变量x(弱符号),mismatch-variable.c中定义了强符号x并赋值为3.14,依多重定义的符号名原则,Linux连接器选择强符号(即double x=3.14),又浮点数在计算机中按IEEE754标准存储表示,故输出结果为461425307021498087。

运行结果如下
在这里插入图片描述
测试代码2

//global.h
extern int g;
int f();
//global-c1.c
#include "global.h"
int f() {
    return g+1;
}
//global-c1.c
#include <stdio.h>
#include <stdlib.h>
#include "global.h"
int g = 0;
int main(int argc, char *argv[]) {
    if (argc >= 2) {
	g = atoi(argv[1]);
    }
    printf("g = %d.  f() = %d\n", g, f());
    return 0;
}

运行结果如下
在这里插入图片描述

静态链接

测试代码

/* addvec.c */
/* $begin addvec */
int addcnt = 0;
void addvec(int *x, int *y,int *z, int n){
    int i;
    addcnt++;
    for (i = 0; i < n; i++)
	z[i] = x[i] + y[i];
}
/* $end addvec */
/* multvec.c */
/* $begin multvec */
int multcnt = 0;
void multvec(int *x, int *y, int *z, int n) {
    int i;
    multcnt++;
    for (i = 0; i < n; i++)
	z[i] = x[i] * y[i];
}
/* $end multvec */
/* main2.c */
/* $begin main2 */
#include <stdio.h>
#include "vector.h"
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main() {
    addvec(x, y, z, 2);
    printf("z = [%d %d]\n", z[0], z[1]);
    return 0;
}
/* $end main2 */

1.在Ubuntu终端依次输入
gcc -c addvec.c multvec.c
ar rcs libvector.a addvec.o multvec.o
gcc -c main2.c
gcc -static -o prog2c main2.o ./libvector.a
./prog2c
五条命令即得运行结果z = [4 6]。

2.gcc -c addvec.c multvec.c、ar rcs libvector.a addvec.o multvec.o用于将addvec.c和multvec.c大包至libvector库函数中。main2.c中包含了vector.h的头文件,包含了addvec函数信息。

运行结果如下
在这里插入图片描述

可重定位目标文件

测试代码

//symbols.c
#include <stdio.h>
int time;
int foo(int a) {
    int b = a + 1;
    return b;
}
int main(int argc, char *argv[]){
    printf("%d\n", foo(5));
    return 0;
}

1.在Ubuntu终端依次输入
readelf -s symbols.o
readelf -S symbols.o
readelf -r symbols.o
objdump -d main.o

2.readelf -s symbols.o为查看符号信息(此处为小s)。输出结果为符号表。foo、main均为强符号(函数)。foo、time定义为int型,占4字节。time定义为未初始化的全局变量(由COM表示),所以为弱符号。printf无类型、未定义(UND)。

3.readelf -S symbols.o为显示节头信息,-r可查看重定位信息。

4.objdump -d main.o为反汇编。可通过 objdump -dx main.o 查看可用头信息(符号表等)。其中-x表示显示所有可用头信息。

5.由于文件为可重定位文件,因此起始地址为0。Size表示每个节所占的大小、File off表示每个节在ELF中的偏移地址。

运行结果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写这次日志的时候自己的电脑出了点问题,所以借用的别人的电脑,下次还会在自己的电脑上运行一遍。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值