U-Boot GOT表分析和u-boot.lds解读

时间:2022-09-07 19:09:06

转自:http://blog.sina.com.cn/s/blog_70dd16910100zab6.html

u-boot-2010.09/arch/powerpc/cpu/mpc86xx/start.S文件中的创建GOT段的代码片段如下:

// Set up GOT: Global Offset Table

// Use r12 to access the GOT

START_GOT

GOT_ENTRY(_GOT2_TABLE_)

GOT_ENTRY(_FIXUP_TABLE_)

GOT_ENTRY(_start)

GOT_ENTRY(_start_of_vectors)

GOT_ENTRY(_end_of_vectors)

GOT_ENTRY(transfer_to_handler)

GOT_ENTRY(__init_end)

GOT_ENTRY(_end)

GOT_ENTRY(__bss_start)

END_GOT

操作GOT表的函数在u-boot-2010.09/include/ppc_asm.tmpl文件中,相关代码如下:

// These definitions simplify the ugly declarations necessary for GOT

// definitions.

// Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, paubert@iram.es

// Uses r12 to access the GOT

#define START_GOT                 \

.section  ".got2","aw";      \

.LCTOC1 = .+32768                                 <1>

#define END_GOT                            \

.text                                      <2>

#define GET_GOT                            \      <3>

bl    1f           ;      \

.text       2            ;      \

0:    .long       .LCTOC1-1f  ;      \

.text                     ;      \

1:    mflr              r12         ;      \

lwz  r0,0b-1b(r12) ;      \

add  r12,r0,r12      ;

#define GOT_ENTRY(NAME)    .L_ ## NAME = . - .LCTOC1 ; .long NAME     <4>

#define GOT(NAME)          .L_ ## NAME (r12)                          <5>

分析:

<1>: START_GOT定义了段“got2”,属性为“allocatable and writable”,并定义了变量.LCTOC1,.LCTOC1的值是表的最高地址;如果设表的起始地址为TABLE_START,则.LCTOC1的值为TABLE_START+0x8000;

<2>:END_GOT定义为子节.text 的起始处;

<3>:

GET_GOT用于初始化GOT表。首先程序跳转到标号为“1”的地址处(bl 1f),然后将lr的值赋值给r12(此时lr的值为“1:”的地址值)。然后令r0 = 0b - 1b(r12),0b为“0:”处的地址值,1b为“1:”处的地址值。这样r0就等于“0:”处的值,也就是.LCTOC1-1f。最后r12 = r0 + r12 = .LCTOC1 - 1f + 1f = .LCTOC1,也就是等于GOT表的最高地址。

<4>:

GOT_ENTRY定义了变量.L_NAME,其值为当前表项的地址(.)-.LCTOC1。如果设NAME的表项偏移地址为NAME_OFFSET,那么.L_NAME = . - .LCTOC1 = TABLE_START + NAME_OFFSET – (TABLE_START + 0x8000)= NAME_OFFSET - 0x8000。之后将名字为NAME的offset值写入当前表项,这些offset值是在编译的时候确定的。

备注:##是字符串连接符,比如L_##TOM其实就是字符串L_TOM

<5>:

GOT(NAME)的值定义为.L_NAME(r12),这里面r12的值为表的最高地址,也就是.LCTOC1的值。

这样GOT(NAME) = .L_NAME + r12= .L_NAME + .LCTOC1 = NAME_OFFSET - 0x8000 + TABLE_START + 0x8000 = NAME_OFFSET + TABLE_START,也就是NAME所在表项的地址。这样,通过查表,就可以找到当初存储在表中的名字为NAME的offset值。

小结:

START_GOT用于定义表的开始,END_GOT用于定义表的结束,GOT_ENTRY用于将offset写入表中,GOT用于从表中读出 offset,GET_GOT用于将表进行初始化

动态库要解决的一个问题是代码/变量地址在编译时不能确定,GOT就是用来解决这个问题的技术。 u-boot运行时要从Flash搬到RAM高端,RAM大小是运行时检测出来的,编译时不能确定,这和动态库面对的问题相同,正好可以用GOT技术解决

参考资料:

http://blog.csdn.net/foriner/article/details/5847501

关于GOT表的机制可以参考我的一篇博文:

http://blog.sina.com.cn/s/blog_70dd16910100r1gi.html

第二部分 u-boot.lds解读

2.1:board/freescale/mpc8641hpcn/目录下有两个文件:u-boot.lds和config.mk

u-boot.lds定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置,从中可以找到u-boot的函数入口。config.mk文件用于设置TEXT_BASE的地址,该地址就是代码运行的链接地址。

下面我们来分析u-boot.lds和config.mk文件。

备注:我分析的U-Boot版本为:u-boot-2010.09.tar.bz2

2.2:具体分析及注解如下

OUTPUT_ARCH(powerpc)

//指定输出的可执行文件的平台为powerpc

SECTIONS

{

//指定各个段内容,只读的各个节(section)均放到代码段(text)中

.interp : { *(.interp) }

//定义 .interp段,该段由所有代码的.interp段共同组成

.hash          : { *(.hash)           }

//.hash段: 由所有代码的.hash段共同组成,hash表允许在不对全表元素进行线性搜索的情况下快速访问所有的符合表项。

.dynsym     : { *(.dynsym)    }

.dynstr      : { *(.dynstr)             }

.rel.text      : { *(.rel.text)     }

.rela.text     : { *(.rela.text)    }

.rel.data      : { *(.rel.data)    }

.rela.data     : { *(.rela.data)   }

.rel.rodata    : { *(.rel.rodata) }

.rela.rodata   : { *(.rela.rodata)       }

.rel.got       : { *(.rel.got)     }

.rela.got      : { *(.rela.got)   }

.rel.ctors     : { *(.rel.ctors)   }

.rela.ctors    : { *(.rela.ctors) }

.rel.dtors     : { *(.rel.dtors)   }

.rela.dtors    : { *(.rela.dtors) }

.rel.bss       : { *(.rel.bss)           }

.rela.bss      : { *(.rela.bss)          }

.rel.plt       : { *(.rel.plt)              }

.rela.plt      : { *(.rela.plt)            }

.init          : { *(.init)  }

.plt : { *(.plt) }

.text      :

//定义文本段

{

arch/powerpc/cpu/mpc86xx/start.o      (.text)

//文本段的第一部分start.S,后跟其他做文本段

arch/powerpc/cpu/mpc86xx/traps.o (.text)

arch/powerpc/cpu/mpc86xx/interrupts.o (.text)

arch/powerpc/cpu/mpc86xx/cpu_init.o (.text)

arch/powerpc/cpu/mpc86xx/cpu.o (.text)

arch/powerpc/cpu/mpc86xx/speed.o (.text)

common/dlmalloc.o (.text)

lib/crc32.o (.text)

arch/powerpc/lib/extable.o (.text)

lib/zlib.o (.text)

drivers/bios_emulator/atibios.o (.text)

*(.text)

*(.got1)

}

_etext = .;

PROVIDE (etext = .);

.rodata    :

{

*(.eh_frame)

*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))

}

.fini      : { *(.fini)    } =0

.ctors     : { *(.ctors)   }

.dtors     : { *(.dtors)   }

. = (. + 0x00FF) & 0xFFFFFF00;

//地址对齐(地址低8位为0)

_erotext = .;

PROVIDE (erotext = .);

.reloc   :

//从定位段.reloc的组成

{

*(.got)   // got段

_GOT2_TABLE_ = .;

//_GOT2_TABLE_值为当前地址,同时也是.got段结束地址,另外也是.got2段起始地址

*(.got2)  // got2段

_FIXUP_TABLE_ = .;

//_FIXUP_TABLE_值为当前地址,同时也是.got2段结束地址;另外也是.fixup段起始地

*(.fixup)

}

__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;

//__got2_entries符号定义,其值为GOT表项个数,每个表项占4字节

__fixup_entries = (. - _FIXUP_TABLE_) >> 2;

//__fixup_entries值为.fixup的字个数

.data    :    //数据段

{

*(.data)

*(.data1)

*(.sdata)

*(.sdata2)

*(.dynamic)

CONSTRUCTORS

}

_edata  =  .;  //数据段结束

PROVIDE (edata = .);

. = .;

__u_boot_cmd_start = .; //定义u-boot命令起始地址,board_init_r中有调用

.u_boot_cmd : { *(.u_boot_cmd) }  //u_boot_cmd段

__u_boot_cmd_end = .; //定义u-boot命令结束地址

. = .;

__start___ex_table = .;

__ex_table : { *(__ex_table) }

__stop___ex_table = .;

. = ALIGN(256);   //256个字节对齐

__init_begin = .;

.text.init : { *(.text.init) }

.data.init : { *(.data.init) }

. = ALIGN(256);

__init_end = .;

// start.S中relocate_code函数计算u-boot镜像text长度,利用了__init_end,后面不再搬运,直接清零clear_bss

__bss_start = .;  // bss代码段起始地址

.bss (NOLOAD)       :

{

*(.sbss) *(.scommon)

*(.dynbss)

*(.bss)

*(COMMON)

. = ALIGN(4);

}

_end = . ;   //_end 符号定义 bss代码段结束地址,u-boot镜像结束地址

PROVIDE (end = .);

}// SECTIONS 对各段定义完毕

同时在board/freescale/mpc8641hpcn/ config.mk文件中U-Boot在RAM中的程序入口地址,具体内容如下:

#

# mpc8641hpcn board

# default CCSRBAR is at 0xff700000

# assume U-Boot is less than 0.5MB

#

TEXT_BASE = 0xeff00000

解释:TEXT_BASE是U-Boot在RAM中的程序入口地址,U-Boot启动以后,在RAM中就运行在这个地址往上的空间。这个地址是U-Boot的指令最开始的地址(对很多PowerPC,例如我们的MPC8641HPCN,一般在这个地址开始的一个0x100字节的偏移处)。在Flash中启动的话,这个地址就在Flash中。

注意的是:TEXT_BASE是链接地址,UBoot第一个阶段的初始化运行的时间地址,有时候会和这一地址不一致,但是MMU开启之后,所用的地址均是链接地址了。

U-Boot GOT表分析和u-boot.lds解读的更多相关文章

  1. Spring Boot 启动原理分析

    https://yq.aliyun.com/articles/6056 转 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启 ...

  2. Spring Boot 入门详细分析

    推荐阅读: 我们为什么要学习 Spring Boot 我们搭建 Spring Boot 项目,可以使用 Spring 为我们提供的初始化网站,那个可能不太方便,今天呢,我们就来说说如何使用 IDEA ...

  3. Spring Boot源码分析

    1.核心: SpringApplication.run(SpringbootdemoApplication.class, args); 内部 2.初始化: new SpringApplication( ...

  4. Spring Boot Jpa 表名小写转大写

    今天在使用SpringBoot整合Hibernate后创建表,表名为小写,而在linux下,mysql的表名是区分大小写的,因此在我的数据表中,就出现了两个一样的表 act_id_user 和  AC ...

  5. 【Spring Boot源码分析】&commat;EnableAutoConfiguration注解(一)&commat;AutoConfigurationImportSelector注解的处理

    Java及Spring Boot新手,首次尝试源码分析,欢迎指正! 一.概述 @EnableAutoConfiguration注解是Spring Boot中配置自动装载的总开关.本文将从@Enable ...

  6. Spring Boot源码分析-配置文件加载原理

    在Spring Boot源码分析-启动过程中我们进行了启动源码的分析,大致了解了整个Spring Boot的启动过程,具体细节这里不再赘述,感兴趣的同学可以自行阅读.今天让我们继续阅读源码,了解配置文 ...

  7. Spring Boot源码分析-启动过程

    Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...

  8. 精尽Spring Boot源码分析 - 序言

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  9. 精尽Spring Boot源码分析 - Jar 包的启动实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  10. 精尽Spring Boot源码分析 - 文章导读

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

随机推荐

  1. jQuery插件中文乱码解决办法

    修改jQuery插件源代码的时候,中文字符有时候会显示乱码,通常这个插件是老外写的,默认文件的编码格式ANSI格式,源代码写中文字符的时候就会显示乱码,解决方法就是将文件编码格式换成UTF-8格式 保 ...

  2. 重新启动 Apache 以加载上面安装的模块

    尽管Ubuntu 是一种新兴的Linux分支,但Ubuntu 组织却为Apache提供了丰富的支持软件,这些软件都可以从发行版的光盘获取,也可以从官方站点轻松下载.所以,Ubuntu非常适合作为Web ...

  3. Java高级之内存模型分析

    博客出自:http://blog.csdn.net/liuxian13183,转载注明出处! All Rights Reserved ! 下文是博主感悟,请带着怀疑性的态度阅读! 需要了解基本变量所占 ...

  4. 一款jQuery满屏自适应焦点图切换特效

    一款jQuery满屏自适应焦点图切换特效 ,自适应当前浏览器的宽度,可以作为网站整个大背景的却换效果,很不错的一款不jquery特效. 兼容性没的说直接秒杀了IE6.适用浏览器:IE6.IE7.IE8 ...

  5. WOSA&sol;XFS及SP综述

    转自  http://blog.csdn.net/andyhou/article/details/6888416 前言:         写给ATM硬件和软件人员的无言歌.         希望对工作 ...

  6. swift3&period;0 coredata 的使用

    //swift3.0在语法上有很大的改变,以简单的增删改查为例,如下: //User类如下: import Foundation import CoreData extension User { @n ...

  7. 使用多线程完成Socket

    public class Service { //服务器 public static void main(String[] args) { ServerSocket serverSocket=null ...

  8. js版贪吃蛇

    之前没有写博客的习惯,这是我的第一个博客,有些的不好的地方,希望大家多多提意见 js版的贪吃蛇相对比较简单,废话不多说直接上代码,有需要注意的地方我会标红,github源码地址https://gith ...

  9. 转载 【&period;NET基础】--委托、事件、线程(1) https&colon;&sol;&sol;www&period;cnblogs&period;com&sol;chengzish&sol;p&sol;4559268&period;html

    [.NET基础]--委托.事件.线程(1)   1,委托 是存放方法的指针的清单,也就是装方法的容器 A, 新建winform项目[01委托],项目中添加dg_SayHi.cs 委托类 用于存储方法 ...

  10. 潭州课堂25班:Ph201805201 爬虫高级 第四课 sclapy 框架 crawispider类 &lpar;课堂笔记)

    以上内容以 spider 类 获取 start_urls 里面的网页 在这里平时只写一个,是个入口,之后 通过 xpath 生成 url,继续请求, crawispider 中 多了个  rules  ...