/proc/xx/maps命令

本文通过解析/proc/pid/maps,详细介绍了Linux进程中虚拟空间布局,包括各段内存的属性、映射范围及对应文件,有助于理解Linux内核中内存管理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

          最近学习一下linux内核相关的,利用/proc/pid/maps可以查看进程的虚拟空间布局,从而获知当前使用内存的具体分布情况。

[root@localhost ~]# cat /proc/728/maps
556217d91000-556217dcd000 r-xp 00000000 fd:00 559540                     /usr/sbin/chronyd
556217fcd000-556217fce000 r--p 0003c000 fd:00 559540                     /usr/sbin/chronyd
556217fce000-556217fcf000 rw-p 0003d000 fd:00 559540                     /usr/sbin/chronyd
556217fcf000-556217fd0000 rw-p 00000000 00:00 0 
5562182b2000-5562182d3000 rw-p 00000000 00:00 0                          [heap]
7fd860000000-7fd860021000 rw-p 00000000 00:00 0 
7fd860021000-7fd864000000 ---p 00000000 00:00 0 
7fd865761000-7fd865770000 r-xp 00000000 fd:00 88597                      /usr/lib64/libbz2.so.1.0.6
7fd865770000-7fd86596f000 ---p 0000f000 fd:00 88597                      /usr/lib64/libbz2.so.1.0.6
7fd86596f000-7fd865970000 r--p 0000e000 fd:00 88597                      /usr/lib64/libbz2.so.1.0.6
7fd865970000-7fd865971000 rw-p 0000f000 fd:00 88597                      /usr/lib64/libbz2.so.1.0.6

以第一行为例:

556217d91000-556217dcd000 :虚拟地址空间的起始地址和结束地址

 r-xp :此段地址空间的属性,r表示可读,x表示可执行,p表示私有段(s表示共享段)

00000000 :针对有名映射,指本段映射地址在文件中的偏移;对匿名映射,为vm_area_struct->vm_start

fd:00 :所映射的文件所属设备的设备号,其中fd为主设备号,00为次设备号

559540  :文件的索引节点号

/usr/sbin/chronyd :所映射的文件名。有有名映射而言,是映射的文件名。对匿名映射来说,是此段内存在进程中的作用

 

 

 

 

 

 

学习地址:https://blog.youkuaiyun.com/lijzheng/article/details/23618365

<think>我们正在讨论的问题是:调试信息没有基地址为什么可以加载到正在运行的程序,以及为什么放在/usr/lib/debug下就能被识别。首先,我们需要理解调试信息是如何与运行中的程序关联的。调试信息通常是以分离的方式存储的,即与可执行文件或库文件分开存放。在Linux系统中,常见的做法是将调试信息放在/usr/lib/debug目录下。关键点在于,调试信息并不是通过基地址来关联的,而是通过构建ID(Build ID)或调试链接(debuglink)来关联。1.**构建ID(Build ID)**:-现代编译工具链(如GCC)在生成二进制文件时,会在二进制文件中嵌入一个唯一的构建ID。这个构建ID是一个哈希值(通常为SHA-1),存储在ELF文件的.note.gnu.build-id节中。-调试信息文件(通常是一个.debug文件)也会包含相同的构建ID。-调试器(如GDB)在加载二进制文件时,会读取其构建ID,然后在特定的目录(如/usr/lib/debug/.build-id/)下查找对应的调试信息文件。例如,构建ID为abcdef1234...,那么调试信息文件可能位于/usr/lib/debug/.build-id/ab/cdef1234...debug。 2. **调试链接(debuglink)**:-如果二进制文件没有构建ID,也可以使用调试链接。调试链接是在二进制文件中添加一个.gnu_debuglink节,其中包含调试信息文件的文件名和一个CRC校验值。-调试器会根据这个文件名在特定的路径中查找调试信息文件,包括当前目录、二进制文件所在目录以及/usr/lib/debug目录等。同时,CRC校验值用于验证找到的调试信息文件是否匹配。因此,调试信息不需要基地址,因为关联是通过唯一的构建ID或文件名+CRC来实现的。关于为什么放在/usr/lib/debug下就能被识别:-调试器(如GDB)有一个默认的调试文件搜索路径,其中就包括/usr/lib/debug。可以通过GDB命令`showdebug-file-directory`查看。 -系统规范(如FHS)指定了/usr/lib/debug作为存放调试信息的标准位置,因此调试器会默认在该目录下查找。此外,引用[1]中提到了dmesg输出中包含了发生段错误时的详细信息,其中就包括加载的库的路径(如libc-2.10.1.so)以及内存地址。这些信息对于调试是有用的,但调试信息的加载并不依赖于这些地址。总结:-调试信息通过构建ID或调试链接与运行中的程序关联,不需要基地址。- /usr/lib/debug是系统默认的调试信息存放目录,调试器会在此目录下查找。相关问题: 1.如何查看一个二进制文件的构建ID? 2.如何为程序生成分离的调试信息并安装到/usr/lib/debug目录下?3.调试链接和构建ID有什么区别?哪种方式更好? 4.如果调试信息不在默认路径,如何让GDB找到它?</think>### 调试信息无需基地址即可加载的原理分析 调试信息能在没有基地址的情况下加载到运行中的程序,主要依赖以下机制: #### 1. **构建 ID(Build ID)唯一标识机制** [^1] - **唯一哈希标识**: 编译时编译器会在 ELF 文件的 `.note.gnu.build-id` 节中嵌入唯一的 SHA-1 哈希值(如 `ab/cdef1234`),该值与调试信息文件完全对应。 ```bash $ readelf -n /bin/ls | grep Build.ID # 输出示例:Build ID: abcd1234ef56... ``` - **路径映射规则**: 调试器通过固定规则将构建 ID 映射到 `/usr/lib/debug/.build-id/ab/cdef1234.debug` 路径,无需基地址信息。 #### 2. **调试链接(Debug Link)机制** [^1] - **文件名+CRC 校验**: 当二进制文件通过 `objcopy --add-gnu-debuglink` 添加调试链接时: ```bash objcopy --add-gnu-debuglink=program.debug program ``` 会在 ELF 文件中生成 `.gnu_debuglink` 节,包含: - 调试信息文件名(如 `program.debug`) - CRC32 校验值(用于验证文件匹配性) #### 3. **标准化路径识别机制** - **系统级默认路径**: Linux 调试器(GDB)默认配置了调试信息搜索路径: ```bash (gdb) show debug-file-directory # 输出:/usr/lib/debug ``` - **路径解析规则**: 当加载 `/usr/lib/libc.so.6` 时,调试器自动查找: ``` /usr/lib/debug/usr/lib/libc-2.31.so.debug ``` #### 4. **运行时地址重定位** [^1] - **动态重定位支持**: 调试信息中的地址都是**相对偏移量**而非绝对地址。当程序加载时: 1. 调试器获取模块的实际加载基地址(通过 `/proc/<pid>/maps`) 2. 动态计算:`符号地址 = 基地址 + 符号偏移` 3. 实现符号与运行时内存地址的匹配 ### 为何 `/usr/lib/debug` 能被识别 | 机制 | 说明 | |---------------------|----------------------------------------------------------------------| | **FHS 标准规范** | Linux 文件系统层次标准(FHS)指定 `/usr/lib/debug` 为调试信息默认目录 | | **调试器硬编码路径** | GDB/LLDB 等调试器在代码中硬编码此路径作为默认搜索位置 | | **构建系统约定** | 编译工具链(gcc/clang)生成的调试信息默认指向此路径 | | **包管理器支持** | RPM/Deb 等包管理器安装 `-debuginfo` 包时自动部署到此目录 | ```mermaid graph TD A[运行中的程序] --> B(通过/proc/pid/maps获取基地址) B --> C[查询ELF的.note.gnu.build-id节] C --> D{构建ID是否存在?} D -->|是| E[在/usr/lib/debug/.build-id/xx/yy.debug加载符号] D -->|否| F[检查.gnu_debuglink节] F --> G[按文件名在/usr/lib/debug查找] G --> H[用CRC32校验文件] H --> I[动态重定位符号地址] ``` ### 关键结论 1. **无需基地址**:调试信息通过**构建ID/调试链接**关联,通过**运行时重定位**解决地址映射问题 2. **路径可识别**:`/usr/lib/debug` 是Linux生态的**标准化基础设施**,被工具链、调试器和包管理系统共同遵守 3. **位置无关性**:调试信息文件本身是**位置无关的**(仅包含相对偏移),加载时动态绑定内存地址 > 示例:当程序崩溃时,`dmesg` 输出的 `ip 00d2906a` 等地址信息[^1],调试器会结合运行时基地址和调试信息中的偏移量解析出具体符号名。 --- ### 相关问题 1. 如何查看 ELF 文件的构建 ID 和调试链接信息? 2. 调试信息中的相对偏移量如何与运行时内存地址映射? 3. 当程序使用 ASLR 时,调试信息加载是否会失效? 4. 如何为自定义编译的程序生成符合规范的调试信息文件? 5. 调试信息加载失败时有哪些诊断步骤? [^1]: 调试信息通过构建 ID 和调试链接实现与运行程序的关联,无需基地址即可加载 [^2]: 系统库路径(如 `/lib64`)与调试信息路径存在对应关系 [^3]: 头文件中的二进制数据(如开机画面数组)调试时依赖符号偏移量 [^4]: 本地仓库配置(如 `baseurl=file://...`)原理类似调试信息的路径解析
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼盼编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值