当前位置: 首页 > news >正文

[Linux]学习笔记系列 -- [arm][lds]

文章目录

  • include/asm-generic/vmlinux.lds.h
  • arch/arm/Makefile
    • 生成vmlinux.lds
    • CONFIG_CPU_BIG_ENDIAN
  • arch/arm/include/asm/vmlinux.lds.h
    • ARM_CPU_DISCARD ARM_CPU_KEEP 热插拔CPU时需要保持或丢弃的段
      • CONFIG_HOTPLUG_CPU 热插拔CPU
    • ARM_EXIT_KEEP ARM_EXIT_DISCARD
      • CONFIG_SMP_ON_UP 在单处理器系统上启用SMP
      • CONFIG_JUMP_LABEL 启用跳转标签优化,以减少条件分支的开销
    • ARM_DISCARD arm丢弃的段
  • 解压部分代码的lds
    • arch/arm/boot/compressed/vmlinux.lds.S
      • CONFIG_CPU_ENDIAN_BE8 大端模式
      • SANITIZER_DISCARDS 无害丢弃
      • PATCHABLE_DISCARDS 可修补的丢弃
        • CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE 控制动态函数跟踪(ftrace)功能的行为
      • COMMON_DISCARDS 公共丢弃
  • 内核的lds
    • arch/arm/kernel/vmlinux.lds.S
      • CONFIG_XIP_KERNEL 选择不同的lds.s文件
      • jiffies 取低32位使用

在这里插入图片描述

https://github.com/wdfk-prog/linux-study

include/asm-generic/vmlinux.lds.h

arch/arm/Makefile

生成vmlinux.lds

  1. 预处理

    • vmlinux.lds.S 文件首先会经过 C 预处理器(cpp)的处理。预处理器会处理文件中的宏定义、条件编译指令(如 #ifdef#include 等),并生成一个纯文本的链接脚本文件 vmlinux.lds
  2. 编译命令

    • 在内核构建过程中,Makefile 会调用 GCC 或 Clang 编译器来处理这个文件。具体的命令类似于:
      $(CC) -E -P -o vmlinux.lds vmlinux.lds.S
      
      其中:
      • $(CC) 是编译器命令(如 gccclang)。
      • -E 选项表示只运行预处理器,不进行编译。
      • -P 选项表示去掉预处理器生成的行号信息。
      • -o vmlinux.lds 指定输出文件名为 vmlinux.lds
      • vmlinux.lds.S 是输入文件。
  3. 生成 vmlinux.lds

    • 经过预处理后,vmlinux.lds.S 文件中的所有宏定义和条件编译指令都会被展开和处理,生成最终的 vmlinux.lds 文件。这个文件是一个纯文本文件,包含了链接器需要的所有指令,用于定义内核镜像的内存布局。
  4. 链接阶段

    • 最终,生成的 vmlinux.lds 文件会被传递给链接器(如 ld),用于链接内核各个部分,生成最终的内核镜像文件 vmlinux。

通过这种方式,vmlinux.lds.S 文件中的内容经过预处理后生成 vmlinux.lds,再由链接器使用这个链接脚本来生成最终的内核镜像。

CONFIG_CPU_BIG_ENDIAN

ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
KBUILD_CPPFLAGS	+= -mbig-endian
CHECKFLAGS	+= -D__ARMEB__
KBUILD_LDFLAGS	+= -EB
else
KBUILD_CPPFLAGS	+= -mlittle-endian
CHECKFLAGS	+= -D__ARMEL__
KBUILD_LDFLAGS	+= -EL
endif

arch/arm/include/asm/vmlinux.lds.h

ARM_CPU_DISCARD ARM_CPU_KEEP 热插拔CPU时需要保持或丢弃的段

#ifdef CONFIG_HOTPLUG_CPU
#define ARM_CPU_DISCARD(x)
#define ARM_CPU_KEEP(x)		x
#else
#define ARM_CPU_DISCARD(x)	x
#define ARM_CPU_KEEP(x)
#endif

CONFIG_HOTPLUG_CPU 热插拔CPU

  • CONFIG_HOTPLUG_CPU 是一个内核配置选项,用于启用或禁用 CPU 热插拔功能。热插拔允许在运行时添加或移除 CPU,而不需要重启系统。
  • 在 ARM 架构的 Linux 内核中,.ARM.exidx 和 .ARM.extab 段用于异常处理和栈回溯(unwinding)。这些段包含了异常索引表(exception index table)和异常表(exception table),它们对于处理异常和执行栈回溯是必需的。
  • 当启用 CONFIG_HOTPLUG_CPU 配置选项时,内核需要支持 CPU 的热插拔功能,这意味着在运行时可以动态地添加或移除 CPU。为了支持这种动态变化,内核必须确保在 CPU 被移除或添加时,异常处理和栈回溯机制能够正确工作。这就需要保留与 CPU 相关的异常处理信息。
  • 具体来说,.ARM.exidx.cpuexit.text 和 .ARM.extab.cpuexit.text 段包含了与 CPU 退出(cpuexit)相关的异常处理信息和栈回溯信息。当 CPU 被热插拔时,这些信息是必需的,以确保系统能够正确处理与该 CPU 相关的异常和栈回溯。因此,当启用 CONFIG_HOTPLUG_CPU 时,这些段不会被丢弃。

ARM_EXIT_KEEP ARM_EXIT_DISCARD

#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \defined(CONFIG_GENERIC_BUG) || defined(CONFIG_JUMP_LABEL)
#define ARM_EXIT_KEEP(x)	x
#define ARM_EXIT_DISCARD(x)
#else
#define ARM_EXIT_KEEP(x)
#define ARM_EXIT_DISCARD(x)	x
#endif

CONFIG_SMP_ON_UP 在单处理器系统上启用SMP

  • SMP 内核包含在非 SMP 处理器上失败的指令。启用此选项允许内核修改自身以使这些说明安全。 禁用它会允许大约 1K 的空间储蓄。

CONFIG_JUMP_LABEL 启用跳转标签优化,以减少条件分支的开销

  • 此选项启用透明分支优化,该优化创建某些几乎总是 true 或几乎总是 false 的分支条件甚至比在 kernel 中执行更便宜。
  • 某些对性能敏感的内核代码(如跟踪点、调度程序功能、网络代码和 KVM 都有这样的分支,并包含对此优化技术的支持。
  • 如果检测到编译器支持 “asm goto”,内核将仅使用 nop 编译此类分支指令。当 condition 标志切换为 true 时,nop 将转换为 jump 指令来执行条件指令块。
  • 此技术降低了分支预测的开销和压力的处理器,通常会使内核更快。更新的情况较慢,但这种情况总是非常罕见的。

ARM_DISCARD arm丢弃的段

  • ARM_DISCARD 是一个宏定义,用于在链接脚本中指定哪些段应该被丢弃或忽略。这个宏通常用于内核的链接脚本中,以确保某些不需要的段不会被包含在最终的内核映像中。
#define ARM_DISCARD							\*(.ARM.exidx.exit.text)					\*(.ARM.extab.exit.text)					\*(.ARM.exidx.text.exit)					\*(.ARM.extab.text.exit)					\ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))		\ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))		\ARM_EXIT_DISCARD(EXIT_TEXT)				\ARM_EXIT_DISCARD(EXIT_DATA)				\EXIT_CALL						\ARM_MMU_DISCARD(*(.text.fixup))				\ARM_MMU_DISCARD(*(__ex_table))				\COMMON_DISCARDS

解压部分代码的lds

arch/arm/boot/compressed/vmlinux.lds.S

CONFIG_CPU_ENDIAN_BE8 大端模式

  • 大端模式修改顺序
#ifdef CONFIG_CPU_ENDIAN_BE8
#define ZIMAGE_MAGIC(x) ( (((x) >> 24) & 0x000000ff) | \(((x) >>  8) & 0x0000ff00) | \(((x) <<  8) & 0x00ff0000) | \(((x) << 24) & 0xff000000) )
#else
#define ZIMAGE_MAGIC(x) (x)
#endif

SANITIZER_DISCARDS 无害丢弃

#if defined(CONFIG_GCOV_KERNEL) || defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN)
# ifdef CONFIG_CONSTRUCTORS
#  define SANITIZER_DISCARDS						\DISCARD_EH_FRAME
# else
#  define SANITIZER_DISCARDS						\*(.init_array) *(.init_array.*)					\DISCARD_EH_FRAME
# endif
#else
# define SANITIZER_DISCARDS
#endif

PATCHABLE_DISCARDS 可修补的丢弃

/* 实际配置决定了 init/exit 部分是否* 作为文本/数据处理,或者它们可以被丢弃(* 经常发生在运行时)*/
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE
#define KEEP_PATCHABLE		KEEP(*(__patchable_function_entries))
#define PATCHABLE_DISCARDS
#else
#define KEEP_PATCHABLE
#define PATCHABLE_DISCARDS	*(__patchable_function_entries)
#endif
CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE 控制动态函数跟踪(ftrace)功能的行为
  • 它决定了是否使用不可修补的函数条目。

COMMON_DISCARDS 公共丢弃

#define COMMON_DISCARDS							\SANITIZER_DISCARDS						\PATCHABLE_DISCARDS						\*(.discard)							\*(.discard.*)							\*(.export_symbol)						\*(.no_trim_symbol)						\*(.modinfo)							\/* ld.bfd warns about .gnu.version* even when not emitted */	\*(.gnu.version*)						\

内核的lds

arch/arm/kernel/vmlinux.lds.S

CONFIG_XIP_KERNEL 选择不同的lds.s文件

#ifdef CONFIG_XIP_KERNEL
#include "vmlinux-xip.lds.S"
#else
#endif

jiffies 取低32位使用

  • 这个定义在链接脚本中不会直接生成可见的输出段或内容,因为它只是定义了一个符号,并没有分配内存或生成代码段。因此,在最终生成的 vmlinux.lds 文件中,你不会看到显式的 jiffies 定义。
  • 链接脚本的主要作用是定义内核镜像的内存布局和各个段的排列方式,而符号定义(如 jiffies)通常用于在链接过程中为特定地址或变量提供别名或偏移量。这些符号在链接过程中会被解析和使用,但不会直接出现在最终的链接脚本输出中。
#ifndef __ARMEB__
jiffies = jiffies_64;
#else
jiffies = jiffies_64 + 4;
#endif
http://www.dtcms.com/a/323110.html

相关文章:

  • qt文件操作与qss基础
  • 3.5.2_1 随机访问介质访问控制
  • Docker容器部署Tomcat线上商城
  • 组件通信的方式
  • AI编程工具 | Trae介绍
  • [SC]高效地调试SystemC模型中的语法错误
  • 如何用OpenAI SDK调用Ollama LLM
  • 智慧养老场景跌倒检测准确率↑32%:陌讯多模态融合算法实战解析
  • GPT-5深度解析:革命性AI模型的全面报告与实战指南
  • windows10 ubuntu 24.04 双系统 安装教程
  • ubuntu dpkg命令使用指南
  • 【排序算法】②希尔排序
  • Delphi:TList/TObjectList 设计中的 Notify 设计范式
  • Day38--动态规划--322. 零钱兑换,279. 完全平方数,139. 单词拆分,56. 携带矿石资源(卡码网),背包问题总结
  • 10 分钟用 FastAPI 将机器学习模型上线为 REST API
  • day28 IPC通信机制
  • C++隐式转换的魔法与陷阱:explicit关键字的救赎
  • RecyclerView 缓存机制
  • centos 怎么将一些命令设置为快捷命令
  • 2025华数杯数学建模C题:可调控生物节律LED光源全解析
  • LLM表征的提取方式
  • 【Python 高频 API 速学 ⑥】
  • 【Mac】MLX:Lora微调工作流
  • 【排序算法】①直接插入排序
  • QT第二讲-信号和槽
  • uniapp实现的圆形滚盘组件模板
  • ThingsBoard配置邮件发送保姆级教程(新版qq邮箱)
  • SkyWalking-2--Java Agent是什么?
  • Qt与嵌入式设备中的字节序问题
  • 客服Agent革命:智能客服系统的技术实现与效果评估