6.1 u-boot.lds  链接脚本分析

  uboot 编译出来的第一个链接脚本就是执行 u-boot.lds 链接脚本,去掉里面无用的和没有定义的,进行分析。

  1. /* 配置头文件,自动生成的,包含芯片SOC 相关的头文件 */
  2. #include <config.h>
  3. /* 主要是做一些 32位 和64 位的适配定义 */
  4. #include <asm/psci.h>
  5. /* 输出格式为 elf32-littlearm, */
  6. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  7. OUTPUT_ARCH(arm) /* 输出架构为 ARM */
  8. /* 用来指定整个程序的入口地址,所谓入口地址就是整个程序的开头地址,可以认为就是整个程序的第一句指令。有点像C语言中的main。 */
  9. ENTRY(_start) /* _start 就是汇编的起始函数 */
  10. /* SECTIONS 就是整个链接脚本的指定 */
  11. SECTIONS
  12. {
  13. /* 指定程序的链接地址有2种方法:一种是在Makefile中ld的flags用-Ttext 0x20000000来指定;
  14. 第二种是在链接脚本的SECTIONS开头用.=0x20000000来指定。
  15. 两种都可以实现相同效果。这两种技巧是可以共同配合使用的,也就是说既在链接脚本中指定也在ld flags中用-Ttext来指定。两个都指定以后以-Ttext指定的为准。
  16. uboot的最终链接起始地址就是在Makefile中用-Ttext 来指定的,注意 TEXT_BASE 变量。最终来源是 Makefile 中配置对应的命令中,在make xxx_config时得到的。
  17. 若没有配置,则由此处指定*/
  18. . = 0x00000000;
  19. . = ALIGN(); /* 4字节对齐 */
  20. /* 代码段 */
  21. /* 在代码段中,必须注意文件的排列顺序,这些顺序会影响编译的时候这些 .o 文件在生成的u-boot.bin 中的排列顺序 */
  22. /* 指定必须放在前面部分的那些文件就是那些必须安排在前4KB内的文件,这些文件中的函数在前4KB会被调用。在后面第二部分(4KB之后)中调用的程序,前后顺序就无所谓了。 */
  23. .text :
  24. {
  25. /* 映像文件赋值起始地址,它在文件 arch/arm/lib/sections.c 中定义:
  26. * char __image_copy_start[0] __attribute__((section(".__image_copy_start")));*/
  27. *(.__image_copy_start)
  28. /* arch/arm/lib/vectors.S 里有一句:.section ".vectors" */
  29. /* 这里的 vectors 是让 vector.S 链接的二进制文件的开头部分 */
  30. *(.vectors)
  31. CPUDIR/start.o (.text*) /* 执行 start.S */
  32. *(.text*) /* 其他代码 */
  33. }
  34. . = ALIGN();
  35. .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } /* 只读数据段 */
  36. . = ALIGN();
  37. .data : { /* 普通数据段,即可读写数据段 */
  38. *(.data*)
  39. }
  40. . = ALIGN();
  41. . = .;
  42. /* 在u-boot的linker_list.h中通过宏定义,让编译器在编译阶段生成了一些顺序链表.u_boot_list*,链接阶段顺序存放到这个.u_boot_list节中。 */
  43. /* u-boot启动过程中,会从这个节读取模块驱动,命令行支持的命令等。 */
  44. . = ALIGN();
  45. .u_boot_list : {
  46. KEEP(*(SORT(.u_boot_list*)));
  47. }
  48. . = ALIGN();
  49. /* UEFI 段 */
  50. .__efi_runtime_start : {
  51. *(.__efi_runtime_start)
  52. }
  53. .efi_runtime : {
  54. *(efi_runtime_text)
  55. *(efi_runtime_data)
  56. }
  57. .__efi_runtime_stop : {
  58. *(.__efi_runtime_stop)
  59. }
  60. .efi_runtime_rel_start :
  61. {
  62. *(.__efi_runtime_rel_start)
  63. }
  64. .efi_runtime_rel : {
  65. *(.relefi_runtime_text)
  66. *(.relefi_runtime_data)
  67. }
  68. .efi_runtime_rel_stop :
  69. {
  70. *(.__efi_runtime_rel_stop)
  71. }
  72. /* UEFI 段结束地方 */
  73. . = ALIGN();
  74. .image_copy_end :
  75. {
  76. *(.__image_copy_end)
  77. }
  78. /* .rel_dyn* 段 */
  79. /* .rel_dyn_start,.rel.dyn和.rel_dyn_end提供了程序的重定位支持 */
  80. /* 重定位:
  81.     在老的uboot中,如果我们想要uboot启动后把自己拷贝到内存中的某个地方,只要把要拷贝的地址写给TEXT_BASE即可,
  82.     然后boot启动后就会把自己拷贝到TEXT_BASE内的地址处运行,在拷贝之前的代码都是相对的,不能出现绝对的跳转,否则会跑飞。
  83.     在新版的uboot里,TEXT_BASE的含义改变了。它表示用户要把这段代码加载到哪里,通常是通过串口等工具。
  84.     然后搬移的时候由uboot自己计算一个地址来进行搬移。
  85.     新版的uboot采用了动态链接技术,在lds文件中有__rel_dyn_start和__rel_dyn_end,这两个符号之间的区域存放着动态链接符号,
  86.     只要给这里面的符号加上一定的偏移,拷贝到内存中代码的后面相应的位置处,就可以在绝对跳转中找到正确的函数。*/
  87. .rel_dyn_start :
  88. {
  89. *(.__rel_dyn_start)
  90. }
  91. .rel.dyn : {
  92. *(.rel*)
  93. }
  94. .rel_dyn_end :
  95. {
  96. *(.__rel_dyn_end)
  97. }
  98. .end :
  99. {
  100. *(.__end)
  101. }
  102. _image_binary_end = .;
  103. /*
  104. * Deprecated: this MMU section is used by pxa at present but
  105. * should not be used by new boards/CPUs.
  106. */
  107. /* MMU 表项 */
  108. . = ALIGN();
  109. .mmutable : {
  110. *(.mmutable)
  111. }
  112. /*
  113. * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
  114. * __bss_base and __bss_limit are for linker only (overlay ordering)
  115. */
  116. /* bss 段,.bss节包含了程序中所有未初始化的全局变量 */
  117. /* 由链接指令(OVERLAY)可见,.bss_start与__rel_dyn_start,.bss与__bss_base,.bss_end与__bss_limit是重叠的。*/
  118. .bss_start __rel_dyn_start (OVERLAY) : {
  119. KEEP(*(.__bss_start));
  120. __bss_base = .;
  121. }
  122. .bss __bss_base (OVERLAY) : {
  123. *(.bss*)
  124. . = ALIGN();
  125. __bss_limit = .;
  126. }
  127. .bss_end __bss_limit (OVERLAY) : {
  128. KEEP(*(.__bss_end));
  129. }
  130. /* 其他段,这些节都是在编译链接时自动生成的,主要用于动态链接或调试使用: */
  131. .dynsym _image_binary_end : { *(.dynsym) } /* 动态符号表`dynamic symbol`,但与`.symtab`不同,`.dynsym`只保存动态链接相关的符号,而`.symtab`通常保存了所有的符号; */
  132. .dynbss : { *(.dynbss) } /* 动态未初始化数据表`dynamic bss`; */
  133. .dynstr : { *(.dynstr*) } /* 动态字符串表`dynamic string`,用于保存符号名的字符串表; */
  134. .dynamic : { *(.dynamic*) } /* 保存了动态链接所需要的基本信息,例如依赖哪些共享对象,动态链接符号表的位置,动态链接重定位表的位置,共享对象初始化代码的地址等; */
  135. .plt : { *(.plt*) } /* 程序连接表`Procddure Linkage Table`,是实现动态链接的必要数据; */
  136. .interp : { *(.interp*) } /* 解释器`interpreter`的缩写 */
  137. .gnu.hash : { *(.gnu.hash) }
  138. .gnu : { *(.gnu*) }
  139. .ARM.exidx : { *(.ARM.exidx*) }
  140. .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
  141. /*.gnu.hash .gnu .ARM.exidx`和`.gnu.linkonce.armexidx`是针对`arm`体系专门生成的段,用于调试时函数调用的`backtrace`,如果不需要调试,则可以不用这两段。 */
  142. }

6.2 其他

  在 u-boot 的编译过程中会生成 3 个符号表文件:

  • u-boot.map
  • u-boot.sym
  • System.map

  可以通过查看 .uboot.cmd 显示 uboot 编译链接的数据:

  1. cmd_u-boot := arm-linux-ld.bfd -pie --gc-sections -Bstatic --no-dynamic-linker -Ttext 0x0 -o u-boot
  2. -T u-boot.lds arch/arm/cpu/arm920t/start.o --start-group
  3. arch/arm/cpu/built-in.o
  4. arch/arm/cpu/arm920t/built-in.o
  5. arch/arm/lib/built-in.o
  6. board/samsung/common/built-in.o
  7. board/samsung/jz2440/built-in.o
  8. cmd/built-in.o common/built-in.o
  9. disk/built-in.o drivers/built-in.o
  10. drivers/dma/built-in.o
  11. drivers/gpio/built-in.o
  12. drivers/i2c/built-in.o
  13. drivers/mtd/built-in.o
  14. drivers/mtd/nand/built-in.o
  15. drivers/mtd/onenand/built-in.o
  16. drivers/mtd/spi/built-in.o
  17. drivers/net/built-in.o
  18. drivers/net/phy/built-in.o
  19. drivers/pci/built-in.o
  20. drivers/power/built-in.o
  21. drivers/power/battery/built-in.o
  22. drivers/power/domain/built-in.o
  23. drivers/power/fuel_gauge/built-in.o
  24. drivers/power/mfd/built-in.o
  25. drivers/power/pmic/built-in.o
  26. drivers/power/regulator/built-in.o
  27. drivers/serial/built-in.o
  28. drivers/spi/built-in.o
  29. drivers/usb/common/built-in.o
  30. drivers/usb/dwc3/built-in.o
  31. drivers/usb/emul/built-in.o
  32. drivers/usb/eth/built-in.o
  33. drivers/usb/gadget/built-in.o
  34. drivers/usb/gadget/udc/built-in.o
  35. drivers/usb/host/built-in.o
  36. drivers/usb/musb-new/built-in.o
  37. drivers/usb/musb/built-in.o
  38. drivers/usb/phy/built-in.o
  39. drivers/usb/ulpi/built-in.o
  40. env/built-in.o
  41. fs/built-in.o
  42. lib/built-in.o
  43. net/built-in.o
  44. test/built-in.o
  45. test/dm/built-in.o
  46. --end-group arch/arm/lib/eabi_compat.o arch/arm/lib/lib.a -Map u-boot.map;
  47. true

  -pic-pie ,一个用于动态库的位置无关,一个用于动态可执行文件的位置无关。

  -Ttext 用于指定指定链接的起始地址

  -T u-boot.lds指定了链接使用的脚本文件,实际上,在这个脚本文件的.text节开始前同样也指定了起始地址:

  

五、u-boot 启动流程---u-boot.lds的更多相关文章

  1. Spring Boot启动流程分析

    引言 早在15年的时候就开始用spring boot进行开发了,然而一直就只是用用,并没有深入去了解spring boot是以什么原理怎样工作的,说来也惭愧.今天让我们从spring boot启动开始 ...

  2. Spring Boot启动流程详解(一)

    环境 本文基于Spring Boot版本1.3.3, 使用了spring-boot-starter-web. 配置完成后,编写了代码如下: @SpringBootApplication public ...

  3. Spring Boot启动流程详解

    注:本文转自http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow 环境 本文基于Spring Boot版本1.3.3, 使用了sp ...

  4. activiti自定义流程之整合(五):启动流程时获取自定义表单

    流程定义部署之后,自然就是流程定义列表了,但和前一节一样的是,这里也是和之前单独的activiti没什么区别,因此也不多说.我们先看看列表页面以及对应的代码,然后在一步步说明点击启动按钮时如何调用自定 ...

  5. activiti自己定义流程之整合(五):启动流程时获取自己定义表单

    流程定义部署之后,自然就是流程定义列表了,但和前一节一样的是,这里也是和之前单独的activiti没什么差别.因此也不多说.我们先看看列表页面以及相应的代码,然后在一步步说明点击启动button时怎样 ...

  6. Spring Boot -- 启动流程分析之ApplicationContext 中

    上一节我们已经分析到AbsractApplicationContext类refresh方法中的postProcessBeanFactory方法,在分析registerBeanPostProcessor ...

  7. Spring Boot(三):Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)

    前言:在讲述内容之前 希望大家对设计模式有所了解 即使你学会了本片的内容 也不知道什么时候去使用 或者为什么要这样去用 观察者模式: 观察者模式是一种对象行为模式.它定义对象间的一种一对多的依赖关系, ...

  8. Spring Boot启动流程

    基础准备 1,BeanPostProcessor:这个接口的作用在于对于新构造的实例可以做一些自定义的修改.比如如何构造.属性值的修改.构造器的选择等等 2,BeanFactoryPostProces ...

  9. 头秃了,二十三张图带你从源码了解Spring Boot 的启动流程~

    持续原创输出,点击上方蓝字关注我 目录 前言 源码版本 从哪入手? 源码如何切分? 如何创建SpringApplication? 设置应用类型 设置初始化器(Initializer) 设置监听器(Li ...

随机推荐

  1. Laravel之路由 Route::get/post/any、路由参数、过滤器、命名、子域名、前缀、与模型绑定、抛出 404 错误、控制器

    基本路由 应用中的大多数路都会定义在 app/routes.php 文件中.最简单的Laravel路由由URI和闭包回调函数组成. 基本 GET 路由 代码如下: Route::get('/', fu ...

  2. python数据统计量分析

    #-*- coding: utf-8 -*- #餐饮销量数据统计量分析 from __future__ import print_function import pandas as pd cateri ...

  3. ComboBox中如何嵌套TreeView控件

      在ComboBox中嵌套TreeView控件,有时候我们在设计界面的时候,由于界面设计的需要,我们需要将TreeView控件嵌套在ComboBox中,因为TreeView控件实在是太占用地方了,要 ...

  4. SpringMVC @RequestBody的使用

    @RequestBody的作用 @RequestBody用于读取Request请求的body数据,然后利用SpringMVC配置的HttpMessageConverter对数据进行转换,最后把转换后的 ...

  5. BZOJ2006[NOI2010]超级钢琴——堆+主席树

    题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...

  6. 19 Zabbix web监控实例

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 9 Zabbix web监控实例 通过前面的介绍你已经了解Web scenario的配置,下面我们 ...

  7. 【BZOJ4555】求和(多种解法混合版本)

    [BZOJ4555]求和(多种解法混合版本) 题面 BZOJ 给定\(n\),求 \[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}S(i,j)\times 2^j \times ...

  8. BZOJ 2929: [Poi1999]洞穴攀行

    2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 351  Solved: 195[Submit][Status][ ...

  9. luogu1970 花匠(dp)

    设f1[i]表示以1..i中某个合法序列的长度,而且最后一位是较大的 f2[i]表示以1..i中某个合法序列的长度,而且最后一位是较小的 那么就有$f1[i]=max\{f2[j]+1\},(j< ...

  10. sklearn 的train_test_split

    train_test_split函数用于将矩阵随机划分为训练子集和测试子集,并返回划分好的训练集测试集样本和训练集测试集标签. 格式: from sklearn.model_selection imp ...