首页 > 其他分享 >linker.ld在链接阶段的行为

linker.ld在链接阶段的行为

时间:2024-11-15 17:56:53浏览次数:1  
标签:ld start text linker AM nemu build riscv32 链接

抽出编译AM程序中的“打包用户程序am-test到ELF”步骤,看看链接脚本abstract-machine/scripts/linker.ld如何将库函数和用户程序链接起来的。

首先看下链接命令:

echo + LD "->" build/amtest-riscv32-nemu.elf
($CROSS_COMPILE)ld -z noexecstack -melf64lriscv
-T /abstract-machine/scripts/linker.ld
  --defsym=_pmem_start=0x80000000
  --defsym=_entry_offset=0x0
  --gc-sections
  -e _start
  -melf32lriscv
-o $AM_TEST/build/amtest-riscv32-nemu.elf
    --start-group
    $AM_TEST/build/riscv32-nemu/src/main.o
    $AM_TEST/build/riscv32-nemu/src/tests/video.o
    $AM_TEST/build/riscv32-nemu/src/tests/mp.o
    $AM_TEST/build/riscv32-nemu/src/tests/hello.o
    $AM_TEST/build/riscv32-nemu/src/tests/devscan.o
    $AM_TEST/build/riscv32-nemu/src/tests/audio/audio-data.o
    $AM_TEST/build/riscv32-nemu/src/tests/audio.o
    $AM_TEST/build/riscv32-nemu/src/tests/keyboard.o
    $AM_TEST/build/riscv32-nemu/src/tests/intr.o
    $AM_TEST/build/riscv32-nemu/src/tests/rtc.o
    $AM_TEST/build/riscv32-nemu/src/tests/vm.o
    /abstract-machine/am/build/am-riscv32-nemu.a
    /abstract-machine/klib/build/klib-riscv32-nemu.a
    --end-group

这里蕴含几个关键信息:

  • linker.ld作为链接的自定义脚本
  • 设置符号(symbol)_pmem_start的值为0x80000000,_entry_offset为0。
  • 设置程序的入口地址为_start

接下来我们转移到链接脚本abstract-machine/scripts/linker.ld的具体实现:

ENTRY(_start)
PHDRS { text PT_LOAD; data PT_LOAD; }

SECTIONS {
  /* _pmem_start and _entry_offset are defined in LDFLAGS */
  . = _pmem_start + _entry_offset;
  .text : {		
    *(entry)	/* 引用与符号 entry 相关的所有内容*/
    *(.text*)	/* 将所有文件的 .text 段的内容合并到当前段*/
  } : text		/* 指定 .text 段被加载到名为 text 的内存区域中*/
  etext = .;
  _etext = .;
  .rodata : {
    *(.rodata*)
  }
  .data : {
    *(.data)
  } : data
  edata = .;
  _data = .;
  .bss : {
	_bss_start = .;
    *(.bss*)
    *(.sbss*)
    *(.scommon)
  }
  _stack_top = ALIGN(0x1000);
  . = _stack_top + 0x8000;
  _stack_pointer = .;
  end = .;
  _end = .;
  _heap_start = ALIGN(0x1000);
}

linker.ld的链接内容:

  • 设置_start作为程序的入口点:ENTRY(_start)

  • 加载.text.data 段到内存中:PHDRS { text PT_LOAD; data PT_LOAD; }PT_LOAD是Program Header的类型

  • 设置当前地址_pmem_start + _entry_offset. 表示当前地址,_pmem_start + _entry_offset 就是定义当前地址的位置。这里的地址就是0x80000000

  • 设置.text.rodata.data.bss段。其中拿出.text段的处理

      .text : {		
        *(entry)	/* 引用与符号 entry 相关的所有内容*/
        *(.text*)	/* 将所有文件的 .text 段的内容合并到当前段*/
      } : text		/* 指定 .text 段被加载到名为 text 的内存区域中*/
    
  • 设置栈和堆的布局

    • _stack_top = ALIGN(0x1000); 确保栈从 4KB 对齐的位置开始。
    • . = _stack_top + 0x8000; 设置栈的初始位置,分配了 32KB 的栈空间。
    • stack_pointer = .; 设置 _stack_pointer 符号,指示栈指针的位置
  • 设置结束符号:end_end

  • 设置堆的起始地址,并确保堆从 4KB 对齐的位置开始 _heap_start = ALIGN(0x1000)

而其中符号entry是在abstract-machine/am/src/riscv/nemu/start.S中定义的

.section entry, "ax"
.globl _start
.type _start, @function

_start:
  mv s0, zero				# 清零s0寄存器
  la sp, _stack_pointer		# 将标签 _stack_pointer 的地址加载到栈指针 sp 中,符号在linker.ld中定义。
  jal _trm_init				# 这条指令会跳转到 _trm_init 标签,并将当前指令地址(即 jal 的下一条指令的地址)压入栈中
  							# _trm_init就是trm初始化函数

此程序设置了程序的入口点_start,并且将符号 _start 声明为一个函数类型。

至此,linker.d的行为就分析完了。

标签:ld,start,text,linker,AM,nemu,build,riscv32,链接
From: https://www.cnblogs.com/shangshankandashu/p/18548419

相关文章

  • 一文掌握:java编译器:跑通helloworld并了解核心原理
    本文旨在详细介绍Java编译器的工作原理及其在Windows系统下的具体使用方法,包括安装步骤、常用命令介绍以及大致原理。通过本文,你可以全面掌握从编写代码到生成可执行文件的全过程,为Java开发奠定坚实的基础。Windows下Java环境的搭建与程序编译为了在Windows环境下运行Jav......
  • 安装鸿蒙的开发工具DevEco Studio并跑一下hello world
    去此网站下载开发工具https://developer.huawei.com/consumer/cn/download/1.按照教程安装,并启用中文,下载git(软件内置一个"下载并安装"按钮,安完后会自动识别安装目录下的git.exe,之前已安装的,填写已安装的git.exe路径)2.按照教程创建示例项目3.创建完毕后,右边小铃铛提示windowsD......
  • thinkphp升级后报错Declaration of think\app\Url::build() must be compatible wit
    ​将源码中的thinkphp升级后,发现了错误:Declarationofthink\app\Url::build()mustbecompatiblewiththink\route\Url::build():string出现这个错误的原因是,你通过命令“composerupdatetopthink/framework”只升级了框架,没有更新多应用扩展模块。只需要composer运行下面......
  • C# read json file throw exception: Could not load file or assembly 'System.Runti
    Couldnotloadfileorassembly'System.Runtime.CompilerServices.Unsafe,Version=4.0.4.1,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a'oroneofitsdependencies.Thelocatedassembly'smanifestdefinitiondoesnotmatchtheassemblyr......
  • 前端开发中怎么把链接转为二维码并展示?
    前言:把一个链接生成一个二维码图片,这是我们前端非常常见的一个需求。那么我们应该如何做呢?查看往期文章:五分钟一百行代码,手写一个vue项目全局通用的toast提示组件十五分钟两百行代码,手写一个vue项目全局通用的弹框第一步:下载Qrcode库npminstall--saveqrcode第二步:准......
  • C++builder中的人工智能(29):如何在Windows项目中导入FANN库
    这篇文章旨在使用由SteffenNissen开发的FANN库实现人工神经网络。FANN库支持20多种编程语言,包括Delphi和C++Builder。您可以在FANN的官方网站上找到完整信息和文档,并下载FANN的源文件。步骤:下载FANN库:从Nissen的官方网站下载FANN库包(http://leenissen.dk),包含二进制文......
  • C++builder中的人工智能(27):如何将 GPT-3 API 集成到 C++ 中
    人工智能软件和硬件技术正在迅速发展。我们每天都能看到新的进步。其中一个巨大的飞跃是我们拥有更多基于自然语言处理(NLP)和深度学习(DL)机制的逻辑性更强的AI聊天应用。有许多AI工具可以用来开发由C、C++、Delphi、Python等编程语言驱动的AI。本文将解释如何在C++Builder中使用......
  • C++builder中的人工智能(28):FANN: Fast Artificial Neural Networks快速人工神经网络(ANN
    这篇文章全面介绍了快速人工神经网络(ANNs)的世界,探讨了它们在现代计算智能中的重要地位、核心特点、应用领域以及未来发展。快速人工神经网络库(FastArtificialNeuralNetworkLibrary,简称FANN)是一个免费的开源神经网络库,它使用C语言实现了多层人工神经网络,并支持全连接和稀疏......
  • 呼叫中心开源系统FreeIPCC最新链接
    开源呼叫中心系统FreeIPCC最新链接作者:开源呼叫中心系统FreeIPCC,Github地址:https://github.com/lihaiya/freeipcc用户手册,登录系统查看即可!2024.11.11,最新链接、账户名、密码,enjoy!   话务/在线客服:(demo123/demo123@Abc) FreeIpcchttp://118.25.192.13:8822/cc......
  • jenkins打包报错Build step 'Execute shell' marked build as failure Finished: FA
    1、jenkins打包报错  处理方式1、在步骤“Executeshell”命令最上面添加(还是报错)#!/bin/bash2、设置全局配置,添加键和值(还是报错)键:LANG值:zh.CH.UTF-83、设置全局配置,添加键和值(还是报错)键:JAVA_TOOL_OPTIONS值:-Dfile.encoding=UTF-84、cat /usr/lib/systemd/sys......