当前位置: 首页 > 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.xdnf.cn/news/1265959.html

相关文章:

  • 2022 RoboCom 世界机器人开发者大赛-本科组(国赛)
  • 前端工程化:从构建工具到性能监控的全流程实践
  • 2G内存的服务器用宝塔安装php的fileinfo拓展时总是卡死无法安装成功的解决办法
  • Ubuntu下搭建LVGL模拟器
  • 【第2.1话:基础知识】基于Ubuntu的ROS环境搭建与车辆可视化编程实践:初学者指南及RVIZ应用(含作业及代码)
  • Ubuntu Server 22 虚拟机空间扩容
  • ubuntu dpkg命令使用指南
  • 从零玩转Linux云主机:免费申请、连接终端、命令速查表
  • 【SQL进阶】用EXPLAIN看透SQL执行计划:从“盲写“到“精准优化“
  • 【JavaEE】(11) 前端基础三件套
  • 比亚迪第五代DM技术:AI能耗管理的深度解析与实测验证
  • 数学与应用数学:到底有啥区别?
  • Kafka学习记录
  • 建筑物实例分割数据集-9,700 张图片 城市规划与发展 灾害评估与应急响应 房地产市场分析 智慧城市管理 地理信息系统(GIS) 环境影响评估
  • Java安全-组件安全
  • 关于灰度图像相似度的损失函数(笔记)
  • C++安全异常设计
  • 华为交换机进阶功能和场景化配置
  • Javaweb - 14.1 - 前端工程化
  • day16 - CSS3新增属性
  • 利用whisper api实现若无字幕则自动下载音频并用 whisper 转写,再用 LLM 总结。
  • Blender 快捷键速查表 (Cheat Sheet)
  • 数据结构(9)——排序
  • 202506 电子学会青少年等级考试机器人二级理论综合真题
  • 本文章分享一个本地录音和实时传输录音给app的功能(杰理)
  • java10学习笔记
  • IntelliJ IDEA 新手全方位使用指南
  • 服务机器人选择屏幕的逻辑
  • 7、docker |其余命令
  • spring.config.import 不存在