赞
踩
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,本文图片来源于唐佐林老师课程PPT,只用于个人笔记学习
实验1 : 自定义的链接脚本中自己指定的 代码段和数据段的地址没有遵循linux平台对应用程序的规定。
test.c
#include <stdio.h>
int s1;
int main()
{
printf("&s1 = %p\n", &s1);
return 0;
}
test.lds
SECTIONS { .text 0x3000000: { *(.text) } .data 0x4000000: { *(.data) } .bss : { *(.bss) } }
以默认的方式进行编译,然后运行:
mhr@ubuntu:~/work$ gcc -o test.out test.c
mhr@ubuntu:~/work$ ./test.out
&s1 = 0x60103c
mhr@ubuntu:~/work$
使用自定义链接脚本进行编译
使用链接脚本编译运行后提示段错误,因为我们自定义的链接脚本中自己指定的 代码段和数据段的地址没有遵循linux平台对应用程序的规定。
实验2 :链接脚本中指定全局变量地址
test.c
#include <stdio.h>
int s1;
int main()
{
printf("&s1 = %p\n", &s1);
return 0;
}
test.lds
SECTIONS { .text 0x08048400: 说明:符合平台规定 { *(.text) } . = 0x01000000; 说明:将当前位置指针 . 的值改变为 0x01000000 s1 = .; 显示的重定位 s1这个标识符,即s1就是 0x01000000 地址的别名,即s1这个全局变量的地址位于 0x01000000 .data 0x0804a800: 说明:符合平台规定 { *(.data) } .bss : { *(.bss) } }
使用自定义链接脚本编译并且运行
mhr@ubuntu:~/work$ gcc -o test-lds.out test.c test.lds
mhr@ubuntu:~/work$ ./test-lds.out
&s1 = 0x1000000
mhr@ubuntu:~/work$
果然s1这个全局变量的地址就是链接脚本中指定的 地址 0x1000000
实验3 :在链接脚本中定义标识符,,并且在源码中使用
test.c
#include <stdio.h>
int s1;
extern int s2;//使用标识符s2 在链接脚本中定义
int main()
{
printf("&s1 = %p\n", &s1);
printf("&s2 = %p\n", &s2);
return 0;
}
test.lds
SECTIONS { .text 0x08048400: { *(.text) } . = 0x01000000; s1 = .; . += 4; 重新指定当前位置指针.的值 s2 = .; 用改变后的当前位置指针的值来重定位s2这个标识符,即s2是 0x1000004地址的别名 .data 0x0804a800: { *(.data) } .bss : { *(.bss) } }
使用自定义链接脚本编译并且运行
mhr@ubuntu:~/work$
mhr@ubuntu:~/work$ gcc -o test-lds.out test.c test.lds
mhr@ubuntu:~/work$ ./test-lds.out
&s1 = 0x1000000
&s2 = 0x1000004
mhr@ubuntu:~/work$
自从有了MMU内存管理单元之后,编译,链接的时候所面的都是虚存地址,具体的存储区域在内存的什么地方是由mmu决定的,所以链接器就认为这些事情全部由mmu做就可以了,自己在链接的时候只需要给一个合法的重定位地址就可以了。虚存地址,就是逻辑上的一个非常大的存储空间,在桌面应用中,链接器这个认为大多数是对的,但是对于嵌入式环境而言,就有可能不存在mmu,直接基于物理存储空间开发,此时如果存在多个存储空间…
嵌入式环境的链接方式,在链接脚本中,通过memory 指令 指定 代码段放在只读属性的flash中直接运行,数据段放在Ram中。
通过链接脚本指定应用程序的入口函数
实验4 :通过链接脚本指定应用程序的入口函数
test.c
#include <stdio.h>
#include <stdlib.h>
int program()
{
printf("D.T.Software\n");
exit(0);
}
test.lds : 链接器根据平台规范来确认其他段的信息,此处之编写代码段的信息,并且显示的重定位代码段到地址 0x08048400
ENTRY(program)
SECTIONS
{
.text 0x08048400:
{
*(.text)
}
}
编译链接运行
mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ gcc -o test.o -c test.c mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ gcc -nostartfiles test.o -o test-lds.out test.lds mhr@ubuntu:~/work$ ./test-lds.out D.T.Software mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ nm test-lds.out 0000000008249028 D __bss_start 0000000008248ec0 d _DYNAMIC 0000000008249028 D _edata 0000000008249028 D _end U exit@@GLIBC_2.2.5 0000000008249000 d _GLOBAL_OFFSET_TABLE_ 0000000008048428 r __GNU_EH_FRAME_HDR 0000000008048400 T program //program 函数的地址 0000000008048400 U puts@@GLIBC_2.2.5 U _start mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ mhr@ubuntu:~/work$ objdump -h test-lds.out test-lds.out: file format elf64-x86-64 Sections: Idx Name Size VMA LMA File off Algn ... //所以 grogram确实被指定成了 代码段的入口函数 9 .text 00000018 0000000008048400 0000000008048400 00048400 2**0 CONTENTS, ALLOC, LOAD, READONLY, CODE ... mhr@ubuntu:~/work$ mhr@ubuntu:~/work$
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。