以linux內核啟動地址破解30008000由來之謎
出處:互聯網 發(fā)布于:2011-09-02 22:54:47
關于Linux
Linux是一類Unix計算機操作系統(tǒng)的統(tǒng)稱。Linux操作系統(tǒng)的內核的名字也是“Linux”。Linux操作系統(tǒng)也是自由軟件和開放源代碼發(fā)展中著名的例子。嚴格來講,Linux這個詞本身只表示Linux內核,但在實際上人們已經習慣了用Linux來形容整個基于Linux內核,并且使用GNU 工程各種工具和數據庫的操作系統(tǒng)。Linux得名于計算機業(yè)余愛好者Linus Torvalds。
內核概念解說
在Linux的術語中被稱為“內核”,也可以稱為“”。Linux內核的主要模塊(或組件)分以下幾個部分:存儲管理、CPU和進程管理、文件系統(tǒng)、設備管理和驅動、網絡通信,以及系統(tǒng)的初始化(引導)、系統(tǒng)調用等。Linux 內核實現了很多重要的體系結構屬性。在或高或低的層次上,內核被劃分為多個子系統(tǒng)。Linux 也可以看作是一個整體,因為它會將所有這些基本服務都集成到內核中。這與微內核的體系結構不同,后者會提供一些基本的服務,例如通信、I/O、內存和進程管理,更具體的服務都是插入到微內核層中的。
內核啟動地址的分析過程:
內核編譯鏈接過程是依靠vmlinux.lds文件,以arm為例vmlinux.lds文件位于kernel/arch/arm/vmlinux.lds,
vmlinux-armv.lds的生成過程在kernel/arch/arm/Makefile中
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0xC0008000
LDSCRIPT = arch/arm/vmlinux-armv.lds.in
endif
arch/arm/vmlinux.lds: $(LDSCRIPT) dummy
@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@
查看arch/arm/vmlinux.lds 中
OUTPUT_ARCH(arm)
ENTRY(stext)
SECTIONS
{
. = 0xC0008000;
.init : { /* Init code and data */
_stext = .;
__init_begin = .;
*(。text.init)
__proc_info_begin = .;
*(。proc.info)
__proc_info_end = .;
__arch_info_begin = .;
*(。arch.info)
__arch_info_end = .;
__tagtable_begin = .;
*(。taglist)
__tagtable_end = .;
*(。data.init)
. = ALIGN(16);
__setup_start = .;
*(。setup.init)
__setup_end = .;
__initcall_start = .;
*(。initcall.init)
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
}
/DISCARD/ : { /* Exit code and data */
*(。text.exit)
*(。data.exit)
*(。exitcall.exit)
}
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(。text)
*(。fixup)
*(。gnu.warning)
*(。rodata)
*(。rodata.*)
*(。glue_7)
*(。glue_7t)
*(。got) /* Global offset table */
_etext = .; /* End of text section */
}
.kstrtab : { *(。kstrtab) }
. = ALIGN(16);
__ex_table : { /* Exception table */
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}
__ksymtab : { /* Kernel symbol table */
__start___ksymtab = .;
*(__ksymtab)
__stop___ksymtab = .;
}
. = ALIGN(8192);
.data : {
/*
* fIRst, the init task union, aligned
* to an 8192 byte boundary.
*/
*(。init.task)
/*
* then the cacheline aligned data
*/
. = ALIGN(32);
*(。data.cacheline_aligned)
/*
* and the usual data section
*/
*(。data)
CONSTRUCTORS
_edata = .;
}
.bss : {
__bss_start = .; /* BSS */
*(。bss)
*(COMMON)
_end = . ;
}
/* 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) }
}
arch/arm/Makefile中:
vmlinux: arch/arm/vmlinux.lds
arch/arm/vmlinux.lds: $(LDSCRIPT) dummy
@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
bzImage zImage zinstall Image bootpImage install: vmlinux
@$(MAKEBOOT) $@
但在kernel/arch/arm/boot/Makefile
ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
zImage: $(CONFIGURE) compressed/vmlinux
$(OBJCOPY) -O binary -R .note -R .comment -S compressed/vmlinux $@
compressed/vmlinux: $(TOPDIR)/vmlinux dep
@$(MAKE) -C compressed vmlinux
在compressed目錄下的Makefile中
ZLDFLAGS = -p -X -T vmlinux.lds
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
all: vmlinux
vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds
$(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux
vmlinux.lds: vmlinux.lds.in Makefile $(TOPDIR)/arch/$(ARCH)/boot/Makefile $(TOPDIR)/.config
@sed "$(SEDFLAGS)" < vmlinux.lds.in > $@
vmlinux-armv.lds.in文件的內容:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = LOAD_ADDR;
_load_addr = .;
. = TEXT_START;
_text = .;
.text : {
_start = .;
*(。start)
*(。text)
*(。fixup)
*(。gnu.warning)
*(。rodata)
*(。rodata.*)
*(。glue_7)
*(。glue_7t)
input_data = .;
piggy.o
input_data_end = .;
. = ALIGN(4);
}
_etext = .;
_got_start = .;
.got : { *(。got) }
_got_end = .;
.got.plt : { *(。got.plt) }
.data : { *(。data) }
_edata = .;
. = BSS_START;
__bss_start = .;
.bss : { *(。bss) }
_end = .;
.stack (NOLOAD) : { *(。stack) }
.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) }
}
vmlinux.lds內容為
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x30008000;
_load_addr = .;
. = 0;
_text = .;
.text : {
_start = .;
*(。start)
*(。text)
*(。fixup)
*(。gnu.warning)
*(。rodata)
*(。rodata.*)
*(。glue_7)
*(。glue_7t)
input_data = .;
piggy.o
input_data_end = .;
. = ALIGN(4);
}
_etext = .;
_got_start = .;
.got : { *(。got) }
_got_end = .;
.got.plt : { *(。got.plt) }
.data : { *(。data) }
_edata = .;
. = ALIGN(4);
__bss_start = .;
.bss : { *(。bss) }
_end = .;
.stack (NOLOAD) : { *(。stack) }
.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) }
}
一般情況下都在生成vmlinux后,再對內核進行壓縮成為zImage,壓縮的目錄是kernel/arch/arm/boot。
到flash中的是壓縮后的zImage文件,zImage是由壓縮后的vmlinux和解壓縮程序組成,如下圖所示:
|-----------------|\ |-----------------|
| | \ | |
| | \ | decompress code |
| vmlinux | \ |-----------------| zImage
| | \| |
| | | |
| | | |
| | | |
| | /|-----------------|
| | /
| | /
| | /
|-----------------|/
zImage鏈接腳本也叫做vmlinux.lds,位于kernel/arch/arm/boot/compressed。
是由同一目錄下的vmlinux.lds.in文件生成的
在kernel/arch/arm/boot/Makefile文件中定義了:
ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
ZTEXTADDR就是解壓縮代碼的ram偏移地址,ZRELADDR是內核ram啟動的偏移地址,這里看到指定ZTEXTADDR的地址為30008000,
總結內核啟動地址的設置:
設置kernel/arch/arm/boot/Makefile文件中的
ifeq ($(CONFIG_ARCH_S3C2410),y)
ZTEXTADDR = 0x30008000
ZRELADDR = 0x30008000
endif
# We now have a PIC decompressor implementation. Decompressors running
# from RAM should not define ZTEXTADDR. Decompressors running directly
# from ROM or Flash must define ZTEXTADDR (preferably via the config)
#
查看2410的datasheet ,發(fā)現內存映射的基址是0x3000 0000 ,那么 0x30008000又是如何來的呢?
在內核文檔kernel/Document/arm/Booting 文件中有:
Calling the kernel image
Existing boot loaders: MANDATORY
New boot loaders: MANDATORY
There are two options for calling the kernel zImage. If the zImage is stored in flash, and is linked correctly to be run from flash, then it is legal for the boot loader to call the zImage in flash directly.
The zImage may also be placed in system RAM (at any location) and called there. Note that the kernel uses 16K of RAM below the image to store page tables. The recommended placement is 32KiB into RAM.
看來在image下面用了32K(0x8000)的空間存放內核頁表,
0x30008000就是2410的內核在RAM中的啟動地址,這個地址就是這么來的。
版權與免責聲明
凡本網注明“出處:維庫電子市場網”的所有作品,版權均屬于維庫電子市場網,轉載請必須注明維庫電子市場網,http://hbjingang.com,違反者本網將追究相關法律責任。
本網轉載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網贊同其觀點或證實其內容的真實性,不承擔此類作品侵權行為的直接責任及連帶責任。其他媒體、網站或個人從本網轉載時,必須保留本網注明的作品出處,并自負版權等法律責任。
如涉及作品內容、版權等問題,請在作品發(fā)表之日起一周內與本網聯系,否則視為放棄相關權利。
- ARM技術架構與應用開發(fā)實踐指南2026/1/6 10:40:19
- 嵌入式實時操作系統(tǒng)(RTOS)選型與移植技術指南2025/12/31 10:42:31
- 工業(yè)嵌入式系統(tǒng):通信接口技術選型與抗干擾設計實踐2025/12/15 14:36:53
- 深入解析嵌入式 OPENAMP 框架:開啟異核通信新時代2025/7/22 16:27:29
- 一文快速了解OPENWRT基礎知識2025/7/14 16:59:04









