ubuntu 内核调试(ubuntu切换内核)

大家好,今天小编来为大家解答以下的问题,关于ubuntu 内核调试,ubuntu切换内核这个很多人还不知道,现在让我们一起来看看吧!

盘点Linux内核debug绝招之一:GDB调试器

本文是"降龙十八掌"系列的第一招——GNU DeBuger(GDB)调试器,适用于Linux系统,以Ubuntu 18.04和gdb v8.1.1为例。本文将深入探讨GDB的底层原理和在Linux内核调试中的应用。

首先,GDB底层实现始于gdbserver的main函数,该函数实际上通过captured_main函数完成初始化,包括解析用户指令、初始化核心服务并启动事件循环。核心服务初始化时,会通过ptrace和调试core文件,确保功能可用。例如,创建子进程,设置追踪状态,以及插入断点等操作都在这个过程中完成。

插入断点的实现涉及gdb的breakpoint.c和infrun.c,通过initialize_breakpoint_ops创建断点,然后调用相应函数,如insert_memory_breakpoint,将断点指令插入目标地址。

此外,文章还分享了如何利用GDB调试实际的内核代码,如在qemu中的arm64 Linux,通过交叉编译和gdb-server实现远程调试。通过模拟异常,如动态加载模块时的越界错误,展示了如何通过GDB一步步追踪到问题所在。

深入学习GDB,可参考官方文档,如sourceware.org/gdb/current/和sourceware.org/gdb/wiki/,以及一些实用的命令集合。最后,文章推荐了其他与Linux内核编程相关的技术资源,供读者进一步探索。

Linux内核调试--Kdump的原理以及配置

virtualBox+ 18.04.1-Ubuntu

kdump是一种先进的基于 kexec的内核崩溃转储机制,其目的是在内核崩溃时捕获产生的crash dump。当内核出现错误时,kdump会将内存导出为vmcore格式并保存到磁盘。

Kdump包含两个主要组件:Kexec和 Kdump。

kexec可从当前运行的内核直接跳转到新内核,其工作原理如下:

主要用于分析Linux系统崩溃问题;需要注意的是,在系统无法热启动的情况下,Kdump是不适宜使用的,例如,硬件异常导致CPU宕机的情况,这种情况下只能通过重新开启电源才能启动系统。

当系统崩溃时,kdump会使用 kexec启动到第二个内核。这个第二个内核通常被称为捕获内核,它以极小的内存启动以捕获转储镜像。第一个内核启动时会保留一段内存给 kdump使用。一旦内存信息收集完成,系统将自动重启。

Kexec可以快速启动一个新的内核(捕获内核),它会跳过 BIOS或 Bootloader等引导程序的初始化阶段。这个特性可以让系统在崩溃时快速切换到捕获内核,从而保留生产内核的内存。捕获内核启动后,会像一般内核一样,去运行为它创建的 ramdisk上的 init程序。各种转储机制都可以事先在 init中实现。为了在生产内核崩溃时能顺利启动捕获内核,捕获内核以及它的 ramdisk是事先放到生产内核的内存中的(保留内存)。

Ubuntu配置的内核已经使能了 Kdump的支持,仅需要安装 linux-crashdump包即可,运行命令如下:

sudo apt install linux-crashdump

该软件包包含 crash,kdump-tools,grub等相关依赖,安装过程中选择默认启动,选择是即可安装。安装过程中会修改 kernel cmdline以预留 kdump转储内核内存空间,默认为 192M。可以通过修改/etc/default/grub.d/kdump-tools.cfg文件来修改保留内存的大小。

配置完成后更新 grub(sudo update-grub),重启操作系统(reboot)。执行 kdump-config show命令查看 kdump配置信息。

在命令窗口执行以下命令:

echo c>/proc/sysrq-trigger

如果 Kdump配置正确,上述命令会让系统快速重启并启动捕获内核进行转储,转储完成后会自动切换为生产内核。在进入生产内核的操作系统后,查看/var/crash目录中是否有根据年月日时分命名的文件夹。

/var/crash$ ls-a

ls-al后根据日期可以看到哪个捕获内核产生

启动捕获内核为 linux-image-5.4.0-150-generic-202403011016.crash

进入该日期的文件夹 202403011016(年月日时分来创建文件夹的)。目录包含 dmesg文件和 dump文件,文件后缀为内核崩溃的时间,其中 dmesg是生产内核发生崩溃时生成的内核日志信息,dump是捕获内核转储的文件。

cat dmesg.202403011016

发现一段 log,其中 sysrq: Trigger a crash是我模拟触发的内核崩溃

对于 dump.202403011016这个文件需要使用 Crash工具去打开分析

crash [dump] [vmlinux]

Crash需要指定两个文件:

dump:转储的内核文件,通常在/var/crash目录下;

vmlinux:带调试内核符号信息的内核映像。

crash dump.202403011016 vmlinux

注意,Ubuntu系统默认不包含 vmlinux文件,笔者已经对 Ubuntu系统的内核进行了更换,更换过程中生成了带调试符号的 vmlinux文件,具体步骤可以关注《话说 Linux》订阅号,查看文章《Ubuntu下的系统内核更换》下具体是

crash启动 dump文件

crash常用命令

help命令用于在线查看 crash命令的帮助,在 crash命令行中输入 help命令可以查看 crash支持的所有子命令。

crash dump.202403011016 vmlinux后输入 crash的命令,例如,dis function_name将显示 function_name函数的汇编代码。

参考文章:

一文解决内核调试之 Kdump的原理及配置-知乎(zhihu.com)

Kdump配置及使用(详细)总结(二)- CSDN博客

如何使用qemu调试freebsd/linux内核

无人知晓:qemu搭建arm64 linux kernel调试环境

在深入讲解如何单步调试内核之前,我们需要先了解配置qemu启动环境的步骤和方法。本次实验以基于ARM64架构的环境为例。为了方便调试,我们需要准备一个host=x86,target= arm64版本的gdb。有三种方式可以选择:使用sudo apt安装gdb-multiarch,下载ARM官网提供的交叉编译工具链(其中包含gdb),或自行下载gdb源码并编译。不同安装方式可能在特性支持上有所差异,使用apt安装的gdb在某些老版本的Ubuntu上可能存在部分特性不支持的情况,如ARMv8.5的PAC和BTI特性。需要注意的是,使用ARM官网提供的gdb启动时可能会遇到缺少库文件或python3.8的依赖问题,需要通过相应的解决步骤进行处理。

进行内核调试,我们可以遵循以下步骤:首先,使用qemu启动内核并暂停等待,同时建立网络端口以备gdb连接。其次,启动gdb并加载对应kernel Image的vmlinux文件,然后通过attach到指定端口完成连接。如果内核启动时已暂停,直接设置断点即可开始调试。若未选择启动时暂停,可使用ctrl+ c触发挂起状态,之后进行常规断点设置。

在进行qemu启动内核的调试时,需要确保正确处理KASLR问题。KASLR(Kernel Address Space Layout Randomization)是在内核启动时添加的随机地址保护机制,导致实际运行地址与vmlinux文件中的地址存在随机偏移。为解决这一问题,可以采取以下两种方式:一是重新编译内核,修改arch/arm64/configs/defconfig中的CONFIG_RANDOMIZE_BASE参数,将其更改为CONFIG_RANDOMIZE_BASE=n,以关闭KASLR功能。二是通过qemu启动的cmdline参数增加nokaslr,以关闭内核的KASLR功能。经过上述处理,断点设置将能正确生效,并显示正确的调用栈信息。

总结而言,在使用qemu进行内核调试时,需要注意关闭KASLR功能,确保qemu启动脚本的正确性和gdb的兼容性。调试过程中,对于KASLR原理的相关知识有兴趣的伙伴,可以参考专门的文章进行深入了解。

阅读剩余
THE END