这次更新第7章习题。

参考资料:

7.6

代码:

extern int buf[];

int *bufp0 = &buf[0];
static int *bufp1;

static void incr()
{
	static int count = 0;
	
	count++;
}

void swap()
{
	int temp;
	
	incr();
	bufp1 = &buf[1];
	temp = *bufp0;
	*bufp0 =*bufp1;
	*bufp1 = temp;
}

表格:

符号 swap.o.symtab条目? 符号类型 定义符号的模块
buf 外部 m.o .data
bufp0 全局 swap.o .data
bufp1 局部 swap.o .bss
swap 全局 swap.o .text
temp
incr 局部 swap.o .text
count 局部 swap.o .bss

7.7

将double x设置为static变量。

bar5.c:

/* $begin bar5 */
/* bar5.c */ 
static double x; 
 
void f()  
{ 
    x = -0.0; 
} 
/* $end bar5 */

foo5.c:

/* $begin foo5 */
/* foo5.c */ 
#include <stdio.h>
void f(void);

int y = 15212; 
int x = 15213; 
 
int main()  
{ 
    f(); 
    printf("x = 0x%x y = 0x%x \n", 
	   x, y); 
    printf("x = %d y = %d \n", 
	   x, y); 
    return 0;
} 
/* $end foo5 */

编译:

gcc -Wall -Og -o foobar5 foo5.c bar5.c

运行:

x = 0x3b6d y = 0x3b6c 
x = 15213 y = 15212

7.8

A

代码:

/* Module 1 */
int main()
{
}

/* Module 2*/
static int main = 1;
int p2()
{
}
  • REF(main.1)->DEF(main.1)
  • REF(main.2)->DEF(main.1)

原因:

main.1是强符号,main.2是弱符号。

B

代码:

/* Module 1 */
int x;
void main()
{
}

/* Module 2*/
double x;
int p2()
{
}
  • REF(x.1)->未知
  • REF(x.2)->未知

原因:

x.1和x.2都是弱符号。

C
/* Module 1 */
int x = 1;
void main()
{
}

/* Module 2*/
double x = 1.0;
int p2()
{
}
  • REF(x.1)->错误
  • REF(x.2)->错误

原因:

x.1和x.2都是弱符号。

7.9

根据规则2,如果有一个强符号和多个弱符号同名,那么选择强符号;此处main在foo6.c中已经定义为强符号。

编译:

gcc -Wall -Og -o foobar6 foo6.c bar6.c

运行结果:

$ ./foobar6
0x48

7.10

思路:保证文件的相对依赖顺序即可。

A
gcc p.o libx.a
B
gcc libx.a liby.a libx.a
C
gcc p.o libx.a liby.a libx.a libz.a

7.11

.bss段或者对齐。

7.12

R_X86_64_PC32

A

给定:

ADDR(s) = ADDR(.text) = 0x4004e0
ADDR(r.symbol) = ADDR(swap) = 0x4004f8

可得:

refaddr = ADDR(s) + r.offset
        = 0x4004e0 + 0xa
        = 0x4004ea
*refptr = (unsigned) (ADDR(r.symbol) + r.addend - refaddr)
        = (unsigned) (0x4004f8       + (-4)     - 0x4004ea)
        = (unsigned) (0xa)

所以引用的值为0xa。

B

给定:

ADDR(s) = ADDR(.text) = 0x4004d0
ADDR(r.symbol) = ADDR(swap) = 0x400500

可得:

refaddr = ADDR(s) + r.offset
        = 0x4004d0 + 0xa
        = 0x4004da
*refptr = (unsigned) (ADDR(r.symbol) + r.addend - refaddr)
        = (unsigned) (0x400500       + (-4)     - 0x4004da)
        = (unsigned) (0x22)

所以引用的值为0x22。

7.13

参考资料:

https://www.runoob.com/linux/linux-comm-ar.html

A

libm.a:

$ whereis libm.a
libm: /usr/lib/x86_64-linux-gnu/libm.a /usr/lib/x86_64-linux-gnu/libm.so

$ ar t /usr/lib/x86_64-linux-gnu/libm.so
ar: /usr/lib/x86_64-linux-gnu/libm.so: File format not recognized

lib.c:

$ whereis lib.c
lib: /usr/local/lib /mnt/c/Program Files/Racket/lib
B

编译:

gcc -Og -o main1.out main.c
gcc -Og -g -o main2.out main.c

反汇编:

$ objdump -d main1.out > main1ass
$ objdump -d main2.out > main2ass

比较结果:

$ diff main1ass main2ass 
2c2
< main1.out:     file format elf64-x86-64
---
> main2.out:     file format elf64-x86-64

所以对于此例,内容相同。

C
ldd main1.out
        linux-vdso.so.1 (0x00007ffc905eb000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fac69405000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fac699f8000