这次更新第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