`
spartan1
  • 浏览: 360295 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ucore-project5: linker script

 
阅读更多

要对内核进行页映射,首先要知道内核在内存中的位置和内核的大小。内核在内存中的位置很好知道,因为是启动代码拷贝进去的,而内核的大小就不好知道了,只有最后将各个obj文件组合成内核文件的ld命令才知道。而ld命令的命令行参数很难定义参数告诉代码,此时就需要链接器脚本linker script了。ld使用命令-T指定链接器

 

linker script功能很强大,可以告诉链接器应该怎么干活儿,除了告诉链接器起始代码地址在哪里,是什么样的cpu机器类型外,最重要的是告诉链接器各个文件的各个section应该怎么组合:应该从哪个地址开始放,各个section以什么顺序放,分别怎么对齐等等,最终组成输出文件的各个section

 

除此之外,linker script还可以定义各种符号,放到最终生成的符号表中。符号表是一堆符号的列表,每个符号包含了符号名字,符号所引用的内存地址,以及其他一些属性信息。符号本身不占用程序的任何内存空间,实际上就是一个地址的符号表示。

 

在C语言中,当定义一个变量时,实际上是做了两件事:1. 定义一个符号,最终放到符号表中,为其关联一个地址;2. 为这个变量分配一块儿内存空间,可以对其进行访问。举例来说:

int a;
a = 10;
printf("%d\n", a);
int *pa = &a;

 

int a;定义了一个变量,首先在符号表中创建符号a,保存a对应的地址,然后在内存空间中给a预留了一个int大小的空间,空间的地址由符号表中a对应的地址指定。

 

第二行a=10;是为符号a所代表的地址指向的int大小的内存空间赋值为10,第三行是引用符号a所代表地址指向的int大小内存空间中的数据。

 

第四行&a是直接从符号表中取符号a所对应的地址的值,该值与内存中的实际数据无关,在编译链接期间就可确定(当然,本例中a是局部变量,其地址还是运行期确定的,静态变量和全局变量的地址编译器确定)。

 

linker script中定义的符号,只是符号表中的一个符号,其没有对应的内存空间,只是表示了一个地址值。因此,如果在linker script中如此定义了两个符号:

.text :
{
    _text_begin = .;
    *(.text)
    _text_end = .;
}

 在代码中如下访问是错误的:

extern int _begin_text, _end_text;

int a = _end_text - _begin_text;

 

上面引用_begin_text和_end_text的方式是采用变量的访问方式,直接访问变量所对应的内存中的值,实际上这些符号在内存中没有对应的值。如下访问是正确的:

extern int _begin_text, _end_text;

int a = &_end_text - &_begin_text;

 

另外,数组名字实际上就是一个符号值,可以直接拿来使用,如下访问也是正确的:

extern char _begin_text[], _end_text[];

int a = _end_text - _begin_text;

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics