首页 > 其他分享 >LD 文件理解

LD 文件理解

时间:2023-04-20 17:46:22浏览次数:33  
标签:__ 文件 LD end text KEEP 理解 array data

参考:https://www.404bugs.com/index.php/details/1084978780534788096

在介绍SECTIONS的用法之前,我们先对之前提到的LMA和VMA进行说明:每个output section都有一个LMA和一个VMA,LMA是其存储地址(即.data数据存储在fls中的地址),而VMA是其运行时地址(加载到ram中的地址),例如将全局变量g_Data所在数据段.data的LMA设为0x80000020(属于ROM地址),VMA设为0xD0004000(属于RAM地址),那么g_Data的值将存储在ROM中的0x80000020处,而程序运行时,用到g_Data的程序会到RAM中的0xD0004000处寻找它。

 

ENTRY(Reset_Handler) //设置入口地址,ENTRY是 LD文件的关键字

HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400; //设置堆大小 ;DEFINED是 LD文件的关键字,类似ifdef
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400; //设置栈大小 ;DEFINED是 LD文件的关键字

MEMORY //定义链接地址空间
{
  /*定义只读空间m_interrupts ,起始地址0x00000000, 大小0x00000400 */,这里是对存储空间的命名,这里定义了4片空间,取了4个名字
  m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
  /*定义只读空间m_text,起始地址0x00000400, 大小0x0001FC00*/
  m_text (RX) : ORIGIN = 0x00000400, LENGTH = 0x0001FC00
  /*定义读写空间m_data,起始地址0x20000000, 大小0x00020000*/
  m_data (RW) : ORIGIN = 0x20000000, LENGTH = 0x00020000
  /*定义读写空间m_data2s ,起始地址0x20200000, 大小0x00000400*/
  m_data2 (RW) : ORIGIN = 0x20200000, LENGTH = 0x00040000
}

SECTIONS //定义输出段
{
  __NCACHE_REGION_START = ORIGIN(m_data2); //将m_data2的起始地址赋值给__NCACHE_REGION_START, ORIGIN是LD文件的关键字,取原始值之意; = 就是赋值语句
  __NCACHE_REGION_SIZE = 0;//__NCACHE_REGION_SIZE赋值0

  .interrupts : //输出段描述,表示这一段是中断向量表,就是一个名字,大家可以自己取,是其下{}内所有内容的别名
  {
    __VECTOR_TABLE = .; //把当前位置计数器的值赋值给__VECTOR_TABLE ,位置计数器的值一开始默认为0
    __Vectors = .;//把当前位置计数器的值赋值给__VECTOR_TABLE ,位置计数器的值一开始默认为0
    . = ALIGN(4); //这句话不是再给位置计数器赋值,而是给它增加限制条件,表示其增加一次增加4,在内存中的表现即为4字节对齐
    KEEP(*(.isr_vector))//放置所有文件中的.isr_vector section,*是通配符,表示所有,就跟我们搜索文件使用*时一样的。使用KEEP的意思就是告诉编译器这段数据非常重要,不要把它当成垃圾优化掉了
    . = ALIGN(4);
  } > m_interrupts //将这一输出段链接至m_interrupts区域处,所以中断向量表的链接地址就是m_interrupts的起始地址,m_interrupts是上面MEMORY定义的空间名称之一

  // > m_interrupts 只有这个表示 LMA 和VMA是一个地址,不需要从fls搬到ram,如果是 > m_interrupts  AT > m_data 的形式就表示LMA 和 VMA不是一个地址,VMA位于m_interrupts中,LMA位于m_data中

  .text : //定义输出段,就是一个名字,大家可以自己取
  {
    . = ALIGN(4); //4字节对齐
    *(.text) /*放置所有文件的.text段(code) */
    *(.text*) /*放置所有文件的.text*段(code) */
    *(.rodata) /*放置所有文件的.rodata段(constants, strings, etc.) */
    *(.rodata*) /*放置所有文件的.rodata*段(constants, strings, etc.) */
    *(.glue_7) /*同上*/
    *(.glue_7t) /*同上*/
    *(.eh_frame) /*同上*/
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
  } > m_text //将这一输出段链接至m_text区域处

  .ARM.extab : //定义输出段,就是一个名字,大家可以自己取
  {
    *(.ARM.extab* .gnu.linkonce.armextab.*) //
  } > m_text //将这一输出段链接至m_text区域处

  .ARM : //定义输出段,就是一个名字,大家可以自己取
  {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } > m_text //将这一输出段链接至m_text区域处

  .ctors : //定义输出段,就是一个名字,大家可以自己取
  {
    __CTOR_LIST__ = .;
    KEEP (*crtbegin.o(.ctors)) //放置*crtbegin.o中的.ctors段,并保证不被优化
    KEEP (*crtbegin?.o(.ctors)) //同上

    /*下面的语句中出现了EXCLUDE_FILE函数,这个函数的意思就是把括号里面的除外,
    意思就是说放置所有文件除了*crtend?.o *crtend.o文件的 .ctors段,
    因为在上面已经放置过了*/
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors))
    /*下面的语句中出现了SPORT函数,SOPT是SORT_BY_NAME的别名,
    意思是放置.ctors.*段的时候,按照名字的排列顺序来放置*/
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    __CTOR_END__ = .;
  } > m_text //将这一输出段链接至m_text区域处

  .dtors : //定义输出段,就是一个名字,大家可以自己取
  {
    __DTOR_LIST__ = .;
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    __DTOR_END__ = .;
  } > m_text

  .preinit_array : //定义输出段,就是一个名字,大家可以自己取
  {
    /*下面的出现了PROVIDE_HIDDEN, 意思就是后面的这个符号__preinit_array_start 只能在
    链接器中被使用,外部文件是不能调用的,与它相反的还有PROVIDE, PROVIDE表示这个符号可以
    被外部调用,而且如果外部文件也定义了同样的符号也不会发生冲突,优先使用外部定义值,
    后面会出现很多PROVIDE*/
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } > m_text

  .init_array : //定义输出段,就是一个名字,大家可以自己取
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
  PROVIDE_HIDDEN (__init_array_end = .);
  } > m_text

  .fini_array : //定义输出段,就是一个名字,大家可以自己取
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } > m_text

  __etext = .;
  __DATA_ROM = .;

  __VECTOR_RAM = ORIGIN(m_interrupts);
  __RAM_VECTOR_TABLE_SIZE_BYTES = 0x0;

  .data : AT(__DATA_ROM) //AT的作用就是给当前输出段指定加载地址
  {
    . = ALIGN(4);
    __DATA_RAM = .;
    __data_start__ = .;
    *(m_usb_dma_init_data)
    *(.data)
    *(.data*)
    KEEP(*(.jcr*))
    . = ALIGN(4);
    __data_end__ = .;
  } > m_data
  __NDATA_ROM = __DATA_ROM + (__data_end__ - __data_start__);
  .ncache.init : AT(__NDATA_ROM)
  {
    __noncachedata_start__ = .;
    *(NonCacheable.init)
    . = ALIGN(4);
    __noncachedata_init_end__ = .;
  } > m_data
  . = __noncachedata_init_end__;
  .ncache :
  {
    *(NonCacheable)
    . = ALIGN(4);
    __noncachedata_end__ = .;
  } > m_data

  __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
  text_end = ORIGIN(m_text) + LENGTH(m_text);
  ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")

  /* Uninitialized data section */
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    . = ALIGN(4);
    __START_BSS = .;
    __bss_start__ = .;
    *(m_usb_dma_noninit_data)
    *(.bss)
    *(.bss*)
    /*放置COMMON块,关于COMMON块是链接器为弱符号所制定的编译解决方案,
    本质上其实就是bass段,感兴趣的小伙伴可以自行去搜一搜*/
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
    __END_BSS = .;
  } > m_data

  .heap :
  {
    . = ALIGN(8);
    __end__ = .;
    PROVIDE(end = .);
    __HeapBase = .;
    . += HEAP_SIZE;
    __HeapLimit = .;
    __heap_limit = .;
  } > m_data

  .stack :
  {
    . = ALIGN(8);
    . += STACK_SIZE;
  } > m_data

  __StackTop = ORIGIN(m_data) + LENGTH(m_data);
  __StackLimit = __StackTop - STACK_SIZE;
  PROVIDE(__stack = __StackTop);

  .ARM.attributes 0 : { *(.ARM.attributes) }

  /*ASSERT表示断言,跟C中的assert功能是一摸一样的*/
  ASSERT(__StackLimit >= __HeapLimit, "region m_data overflowed with stack and heap")
}

标签:__,文件,LD,end,text,KEEP,理解,array,data
From: https://www.cnblogs.com/lance9527/p/17337691.html

相关文章

  • python-ldap模块
    文章目录模块作用模块安装代码示例参考文档模块作用python操作ldap的库,可以对ldap的数据进行增删改查,官方文档地址:https://www.python-ldap.org/en/latest/index.html模块安装pipinstallpython-ldap代码示例不断完善中……#!/usr/bin/envpython#-*-coding:utf-8-*-#......
  • 编辑pcap文件
    1、使用tshark编辑pcap文件//过滤掉不是tcp的数据包tshark-rsichuandianli.pcap-wtcp_output.pcap-Y"tcp"//过滤掉消息长度大于1500字节的数据包tshark-routcap.pcap-Y"frame.len<=1500"-wout_filter.pcap//过滤掉消息长度大于1500字节和不是tcp的数据包ts......
  • 10 文件与异常
    从文件中读取数据一次性读取#file_reader.pywithopen('pi_digits.txt')asfile_object:contents=file_object.read()print(contents.rstrip())#因为read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行#要删除多出来的空行,可在pr......
  • Python中保存字典类型数据到文件
    三种方法:1、在Python中使用pickle模块的dump函数将字典保存到文件中importpicklemy_dict={'Apple':4,'Banana':2,'Orange':6,'Grapes':11}#保存文件withopen("myDictionary.pkl","wb")astf:pickle.dump(my_dict,tf......
  • Dell R730 raid1换盘后不自动Rebuild
    一台R730raid1坏了一块盘,更换后发现没有rebuild。在linux系统下查看如下:/opt/MegaRAID/MegaCli/MegaCli64-PDList-aALL|grepstate查看有问题硬盘是0号槽位,信怎如下:/opt/MegaRAID/MegaCli/MegaCli64-PDList-aALLAdapter#0EnclosureDeviceID:32SlotNumber:0Driv......
  • Linux解压缩文件乱码的解决
    Linux解压缩文件乱码的解决使用unzip软件提供了-O参数(以及-I参数),可以指定编码。-OCHARSET为DOS,Windows和OS/2归档文件指定字符编码-ICHARSET为UNIX和其他归档文件指定字符编码 例子:解压缩example.zip文件到当前目录,使用归档管理器打开为乱码。example.zip为windows环......
  • 系统文件管理工具:Path Finder 中文激活版
    PathFinder是一款Mac平台上的文件管理和操作工具,提供了比Finder更丰富的功能和更直观的用户界面。它可以帮助用户更高效地浏览、复制、移动、删除和管理文件,以及进行各种高级操作。PathFinder的主要功能包括:-文件浏览:可以快速浏览文件夹、文件和磁盘,并支持多标签页和侧边栏视图......
  • Python pth 文件写入 getshell 或权限维持
    今天看到Y4er师傅写的文章,我这里简单学习了一下:https://y4er.com/posts/python-pth-file-write-getshell/概述python的site模块支持"Site-specificconfigurationhook"的功能,这个功能点本身是用来将特定路径加入模块搜索路径。该模块在初始化期间自动导入。sys.prefix......
  • VSCode,轻松提交文件到GitHub
    方法如下:在GitHub创建一个仓库来存放你的项目;2.在本地文件夹(可以是空文件夹,也可以是非空)内右键-GitBashHere进入命令行;3.输入如下命令,会看到一个名字为.git的隐藏文件,这说明该文件夹已经成为受控制的文件夹了;gitinit4.依次输入如下命令,将本地文件夹与远程仓库建立链接......
  • 文件上传漏洞
    基础知识上传文件,使用burp抓包,会出现如下两种情况:-①若burp抓到请求包: -则说明存在服务端检测, -可通过修改数据包中文件的content-type类型、修改filename为.htaccess、添加文件头GIF89a,等操作进行绕过。-②若burp未抓到请求包: -则说明存在前端检测, -需禁用浏览器......