Linux内核链接器学习
时间:2007-05-05 来源:andersma
[init.h] |
[Linux内核的Makefile] vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ --start-group \ $(CORE_FILES) \ $(DRIVERS) \ $(NETWORKS) \ $(LIBS) \ --end-group \ -o vmlinux |
LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
vmlinux.lds
/* ld script to make i386 Linux kernel
* Written by Martin Mares <[email protected]>;
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0xC0000000 + 0x100000;
_text = .; /* Text and read-only data */
.text : {
*(.text)
*(.fixup)
*(.gnu.warning)
} = 0x9090
_etext = .; /* End of text section */
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
__start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
.data : { /* Data */
*(.data)
CONSTRUCTORS
}
_edata = .; /* End of data section */
. = ALIGN(8192); /* init_task */
.data.init_task : { *(.data.init_task) }
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
. = ALIGN(16);
__setup_start = .;
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
.initcall.init : { *(.initcall.init) }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }
. = ALIGN(32);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
__bss_start = .; /* BSS */
.bss : {
*(.bss)
}
_end = . ;
/* Sections to be discarded */
/DISCARD/ : {
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
上面是Linux ld(链接器)所使用的脚本,也就是在链接linux内核时所参照的文件,ENTRY界定了程序的入口点,这里面时__start,也就是bootsect.S中的其实地址,执行copy内核到指定内存功能,然后用SECTION定义了生成内核文件的分块结构,__setup_start = .;这句话很有意思,在linux内核里面定义了__setup_start这个变量,但就是没有赋值过,嘿嘿,其实赋值在这里呢,"."代表输出文件(内核image)当前链接位置,之前我还疑惑,linux为何有时候定一变量,却没看到初始化,果不其然,原来在这里。通过链接文件的配合,一个符合开发者所规划的linux内核image就产生了。