linux之vmlinux、vmlinuz、System.map和/proc/kallsyms简介


前言

由于最近经常装系统,经常看到 vmlinux、vmlinuz,便总结起来,顺便记录一下System.map和/proc/kallsyms的知识。

一、vmlinux与vmlinuz

1.1 vmlinux

我以我之前编译的5.0.0内核为例:ubuntu 18.04.6 使用内核源码安装内核

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。


在这里插入图片描述


vmlinux(“vm”代表的“virtual memory”)是一个包括linux kernel的静态链接的可运行文件,编译内核源码得到的最原始的内核文件,未压缩,比较大,是elf格式的文件。

file vmlinux

在这里插入图片描述

readelf -h vmlinux

在这里插入图片描述


从elf头中我们可以看到:
程序头表(program headers)中的表项的数目为5

readelf -l vmlinux

在这里插入图片描述

节头表(section headers)中的表项的数目为78

readelf -S vmlinux

在这里插入图片描述


在这里插入图片描述

1.2 vmlinuz

vmlinuz是可引导的,经过压缩的linux内核。vmlinuz是vmlinux经过gzip和objcopy制作出来的压缩文件。

vmlinuz是一个统称,有两种详细的表现形式:zImage和bzImage。它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有 gzip解压缩代码。

(1)bzImage是vmlinux经过gzip压缩后的文件,适用于大内核(bzImage是x86 linux常用的一种压缩镜像文件 )。
(2)zImage是vmlinux经过gzip压缩后的文件,适用于小内核( zImage是ARM linux常用的一种压缩镜像文件)。

备注: bz表示big zImage,其格式与zImage类似,但采用了不同的压缩算法,bzImage的压缩率更高。

我这里是X86_64 ,vmlinuz是bzImage类型的文件.

在这里插入图片描述

1.3 extract-vmlinux

在内核源码下 /scripts目录下有一个 extract-vmlinux 脚本文件:

在这里插入图片描述


将vmlinuz解压缩还原成vmliunx:

./extract-vmlinux vmlinuz-5.0.0 > vmlinux

在这里插入图片描述

 strings vmlinux | grep "\<sbin\>"

sbin(system binary):用于系统管理的程序(以及其他仅限root用户的命令)存储在/sbin、/usr/sbin和/usr/local/sbin中。除/bin中的二进制文件外,/sbin还包含引导、恢复、恢复和/或修复系统所需的二进制文件。

在挂载/usr 之后执行的系统管理程序通常放在/usr/sbin 中。 本地安装的系统管理程序应该放在 /usr/local/sbin。

在这里插入图片描述

脚本内容:

#!/bin/sh
# ----------------------------------------------------------------------
# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
# ----------------------------------------------------------------------

check_vmlinux()
{
	# Use readelf to check if it's a valid ELF
	# TODO: find a better to way to check that it's really vmlinux
	#       and not just an elf
	readelf -h $1 > /dev/null 2>&1 || return 1

	cat $1
	exit 0
}

try_decompress()
{
	# The obscure use of the "tr" filter is to work around older versions of
	# "grep" that report the byte offset of the line instead of the pattern.

	# Try to find the header ($1) and decompress from here
	for	pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
	do
		pos=${pos%%:*}
		tail -c+$pos "$img" | $3 > $tmp 2> /dev/null
		check_vmlinux $tmp
	done
}

# Check invocation:
me=${0##*/}
img=$1
if	[ $# -ne 1 -o ! -s "$img" ]
then
	echo "Usage: $me <kernel-image>" >&2
	exit 2
fi

# Prepare temp files:
tmp=$(mktemp /tmp/vmlinux-XXX)
trap "rm -f $tmp" 0

# That didn't work, so retry after decompression.
try_decompress '\037\213\010' xy    gunzip
try_decompress '\3757zXZ\000' abcde unxz
try_decompress 'BZh'          xy    bunzip2
try_decompress '\135\0\0\0'   xxx   unlzma
try_decompress '\211\114\132' xy    'lzop -d'
try_decompress '\002!L\030'   xxx   'lz4 -d'
try_decompress '(\265/\375'   xxx   unzstd

# Finally check for uncompressed images or objects:
check_vmlinux $img

# Bail out:
echo "$me: Cannot find vmlinux." >&2

用file、odjdump和readelf命令进行查看:

file vmlinux
objdump -d vmlinux | more
readelf -h vmlinux

在这里插入图片描述


在这里插入图片描述


可以看到提取出来的vmlinux 的 节头表(section headers)中的表项的数目只有34项。

在这里插入图片描述

1.4 vmlinux 对比

这里将编译出来的原始内核vmlinux与通过extract-vmlinux提取出来的vmlinux做对比:

(1)编译出来的原始内核vmlinux

在这里插入图片描述


with debug_info,not stripped 代表没有去除调试信息,所以编译出来的内核很大,当然也可以在编译内核时配置不带有调试信息的vmlinux。

 size --format=SysV vmlinux

在这里插入图片描述

sudo nm vmlinux | more

nm:list symbols from object files,查看vmlinux的符号信息

在这里插入图片描述

(2)extract-vmlinux提取出来的vmlinux

在这里插入图片描述


stripped 代表去除掉了调试信息。

在这里插入图片描述


用nm查看符号信息:显示没有符号,提取出来的镜像没有符号信息。

在这里插入图片描述

二、System.map与 /proc/kallsyms

2.1 System.map

System.map是编译内核时产生的一个文件,存放着内核符号表信息。每次编译一次内核,就会产生一个新的System.map文件。符号表是所有内核符号及其对应地址的一个列表,如下图所示:
左边是符号地址(默认为十六进制),中间是符号的类型,右边是内核符号。

在这里插入图片描述


备注:System.map是一个磁盘上的文件。可以由nm vmlinux经过重定向到文件中获得。
输出重定向:将命令的输出发送的一个文件中,终端输出的内容会被保存到输出文件中

bash shell : >    输出的内容会覆盖已有文件的内容
bash shell : >>   输出的内容追加到已有的文件中

在这里插入图片描述


选择一个符号将System.map和 nm vmlinux重定向后的文件 进行内容对比,结果一致。

在这里插入图片描述

2.2 /proc/kallsyms

/proc/kallsyms也是内核提供的一个符号表,包含了动态加载的内核模块的符号,可以在模块加载时动态扩展其长度,给出了所有内核符号及其对应地址的一个列表:
左边是符号地址(默认为十六进制),中间是符号的类型,右边是内核符号。

在这里插入图片描述

2.3 两者区别

(1)
/proc/kallsysms 具有动态加载模块的符号以及静态代码(kernel image)的符号表。
system.map 仅是静态代码(kernel image)的符号表。

正在运行的内核可能和System.map不匹配,所以/proc/kallsyms才是内核符号参考的主要来源,我们应该通过/proc/kallsyms获得符号的地址。

(2)
System.map 是文件系统上的实际文件。 每次内核编译都会生成一个新的 System.map。

/proc/kallsyms 是内核启动时动态创建的“proc 文件”。 实际上,它并不是真正的磁盘文件。 它是内核数据的表示,已经加载到内存中。因此,对于当前正在运行的内核,它总是正确的。

(3)
因此我们要获取一个内核符号的地址,要通过/proc/kallsyms来获取,比如:
T代表位于代码段,一个全局的符号地址。

在这里插入图片描述

2.4 符号表类型

符号类型指明符号位于目标文件的哪个区或其属性。
如果是小写,符号通常是局部的; 如果是大写,则符号是全局的(外部的)。

type meaning
“A” The symbol’s value is absolute,and will not be changed by further linking.
“B/b” The symbol is in the BSS data section. This section typically contains zero-initialized or uninitialized data,although the exact behavior is system dependent.
“C” The symbol is common. Common symbols are uninitialized data. When linking,multiple common symbols may appear with the same name. If the symbol is defined anywhere,the common symbols are treated as undefined references.
“D/d” The symbol is in the initialized data section.
“G/g” The symbol is in an initialized data section for small objects. Some object file formats permit more efficient access to small data objects,such as a global int variable as opposed to a large global array.
“i” For ELF format files this indicates that the symbol is an indirect function. This is a GNU extension to the standard set of ELF symbol types. It indicates a symbol which if referenced by a relocation does not evaluate to its address,but instead must be invoked at runtime. The runtime execution will then return the value to be used in the relocation.
“I” The symbol is an indirect reference to another symbol.
“N” The symbol is a debugging symbol
“p” The symbols is in a stack unwind section
“R/r” The symbol is in a read only data section
“S/s” The symbol is in an uninitialized or zero-initialized data section for small objects.
“T/t” The symbol is in the text (code) section.
“U” The symbol is undefined.
“u” The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.
“V/v” The symbol is a weak object. When a weak defined symbol is linked with a normal defined symbol,the normal defined symbol is used with no error. When a weak undefined symbol is linked and the symbol is not defined,the value of the weak symbol becomes zero with no error. On some systems,uppercase indicates that a default value has been specified
“W/w” The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. When a weak defined symbol is linked with a normal defined symbol,the value of the symbol is determined in a system-specific manner without error. On some systems,uppercase indicates that a default value has been specified
“-” The symbol is a stabs symbol in an a.out object file. In this case,the next values printed are the stabs other field,the stabs desc field,and the stab type. Stabs symbols are used to hold debugging information.
“?” The symbol type is unknown,or object file format specific.

总结

这篇文章主要介绍了linux 中 vmlinux、vmlinuz、System.map和/proc/kallsyms方面的知识。

参考资料

https://blog.51cto.com/u_1472521/4253215
https://www.dingmos.com/index.php/archives/17/
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s16.html
https://www.cnblogs.com/Oude/articles/12039025.html

原文地址:https://blog.csdn.net/weixin_45030965

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读2.3k次,点赞4次,收藏22次。最近安装了CARLA预编译版,总体过程感觉还是挺简单的,但是由于在网上找的参考资料并没有和自己遇到的情况完全一样的,所以把自己的安装过程记录下来,方便和自己一样的后来人进行安装,同时也自己作个记录留作备忘。其实预编译版的CARLA本身几乎不用什么命令行进行安装,主要步骤只有解压缩和拷贝文件,和极少的命令行安装操作。但是相关依赖以及其它的CARLA所使用的一些工具需要一起安装好,下面一起来看看安装步骤吧。_ubuntu22.04安装carla
文章浏览阅读6.3k次,点赞5次,收藏15次。在清华镜像中下载Ubuntu 20 安装包_ubuntu20下载
文章浏览阅读5k次。linux环境, python3.7.问题描述: 安装rally, pip3 install -r requirements.txt 时提示如下: 说明openssl 已安装。解决:1. pip3 install --upgrade pip , 结果输出如下 ..._error: command '/usr/bin/gcc' failed with exit code 1
文章浏览阅读1.1k次。自己刚踩坑装好的W11 WSL2 miniconda_wsl2 cuda
文章浏览阅读4.2k次,点赞4次,收藏17次。要安装这个 standalone的,会有一点区别(不识别 下面的 -localhost no)上面的命令会在~/.vnc/目录下生成一个 passwd文件。具体端口号,可以查看vncserver -list返回结果中的RFB PROT。作用是vncserver启动的时候运行这些命令,把桌面程序启动起来。如果希望用某个用户比如 demo登录,就用su切换到这个用户。桌面版默认就已安装,服务器版需要手动安装,并启动。关闭某个会话可以用下面的命令。远程地址输入ip:port。查看全部的vnc会话。_ubuntu vncserver
文章浏览阅读894次,点赞51次,收藏31次。在安卓使用vscode主要是连接一个远程的code-server服务,code-server服务安装在什么系统,调用的就是什么系统的环境,如这里使用ubuntu进行安装code-server,那使用的就是ubuntu环境,如需要go,python,java开发,需要在Ubuntu安装相关环境,创建的文件夹和项目也是在Ubuntu里面.这种方式其实在访问vscode的时候利于可以随时随地进行连接使用,且不受设备影响。
安装Ubuntu上超好用的终端Terminator。通过添加软件源、更新源、安装Terminator等步骤完成。
文章浏览阅读1.1k次,点赞83次,收藏74次。不要嫌弃Ubuntu的单调的终端界面啦,快来试试这些有意思的命令_ubuntu系统有趣的玩法
文章浏览阅读2.5k次。在ubuntu系统中,swap空间就是虚拟内存,所以考虑在磁盘空间富余的目录下设置虚拟内存swap文件,用来缓解内存不足的问题。通过上面的信息可以看到,/dev/vda2 目录下还剩余45G,那么就可以把swap文件生成在/dev/vda2目录下。在系统监控中发现,当数据库服务程序启动后,占用了大量内存空间,导致系统的剩余的内存往往只有几十MB。# bs 为块的大小,count 创建多少个块。# 执行命令后,删除创建的swap目录即可。#把生成的文件转换成 Swap 文件。2、创建一个swap文件。_ubuntu20修改swap大小
文章浏览阅读2.9k次,点赞2次,收藏10次。记录RV1126的SDK编译错误,以及解决处理_command exited with non-zero status 1
文章浏览阅读1.1w次,点赞22次,收藏101次。【记录】ubuntu20.04安装nvidia显卡驱动_ubuntu20.04安装nvidia显卡驱动
文章浏览阅读727次,点赞6次,收藏27次。在嵌入式Linux开发过程中,可能遇到uboot无法通过nfs服务从Ubuntu下载系统镜像(TTTTTT)的问题。如果你使用的是较新版本的Ubuntu,那么其**默认内核将不支持nfs2**!而**uboot仅支持到nfs2**,因此我们需要修改系统内核以及nfs配置文件,开启nfs2服务。**此问题非常棘手**,因为问题出现的时间太近,并且使用的人少。由于是2023年后才出现的问题,**chatgpt也无法解答**!本文参考网络上多篇博客资料,是解决此问题的最新办法。
ubuntu系统下安装软件的方法有多种,包括使用apt工具、deb软件包安装、源码编译安装以及通过软件中心安装。还有一种以 .run 后缀的软件包也可以在ubuntu系统下安装。具体的安装方法可以通过百度搜索来获取。
文章浏览阅读814次。本篇目的:Xubuntu如何安装pkg-configpkg-config是一个计算机软件包,用于帮助开发人员查找、定位和使用依赖库。它通常用于构建软件时,开发人员需要指定程序所依赖的外部库的位置和版本信息。使用pkg-config,开发人员可以很容易地查找、检索和导出这些依赖库的信息,从而简化了软件的构建过程。_ubuntu中怎么下载pkg-config
文章浏览阅读2k次。ubuntu创建共享文件夹_ubuntu20.04共享文件夹
文章浏览阅读2.9k次,点赞74次,收藏73次。对于有长期远程桌面需求的用户,建议将cpolar套餐升级到专业套餐,支持配置固定的公网TCP端口,且带宽也会相应的增大,支持更高效便捷的远程桌面连接Ubuntu系统。【cpolar内网穿透支持http/https/tcp协议,支持永久免费使用,不限制流量,无需公网IP,也不用进入路由器设置,操作简单。隧道创建成功后,点击左侧仪表盘的状态——在线隧道列表,查看xrdp隧道的所生成的公网TCP端口地址,复制下来。,使用cpolar内网穿透映射3389端口,生成公网TCP端口地址,实现在公网环境下,_ubuntu 局域网桌面
文章浏览阅读3.2k次。而在linux的ubuntu版本中,又多出两类用户:安装ubuntu系统的源用户xxx,其与root具有相同权限,仅在执行命令时,前面加sudo。在ubuntu中,用命令deluser username可以直接删除用户账号及家目录,而用centos7中的命令userdel -r username才能达到同样目的。在ubuntu中,没有moduser命令,centos7中的usermod修改用户信息的命令,同样可以用在ubuntu中。在系统中,创建新的用户或称为账号,一般需要多步操作。_ubuntu创建一个新用户
文章浏览阅读1.6w次,点赞4次,收藏23次。系统的许多日志文件都存储在 /var/log 目录中。你可以使用 ls /var/log 命令来列出可用的日志文件。/var/log/Xorg.0.log:包含 X 服务器的日志信息(图形界面)。打开DASH,搜索日志或者log,打开app,这个是/var/log的界面版。这将显示系统日志的末尾,并提供有关系统崩溃和错误的信息。/var/log/kern.log:包含内核日志信息。/var/log/dmesg:包含开机时的日志信息。/var/log/syslog:包含系统日志信息。_ubuntu查看系统日志
文章浏览阅读857次。首先将source.list复制为source.list.bak备份,然后将source.list内容改为需要的镜像源列表即可。Ubuntu采用apt作为软件安装工具,其镜像源列表记录在/etc/apt/source.list文件中。本节均为 Ubuntu 20.04 的镜像源列表。若为其他版本,将所有focal更改为其他版本代号即可。_apt 国内源