linux反汇编调试

反汇编有有以下几种方法:
1.使用gcc -S test.c 或者gcc -S test.c>out.txt
2.使用gdb调试,在调试中输入disass 函数名 就可以
3.objdump -D test 一般常用1,2两种,
~~~~~C语言代码example.c
int triangle( int width, int height)
{
int arr{0,1,2,3,4};
int area;
area = width * height /2;
return (area);
}
void main()
{
triangle(5,4);

}

~~~~~gdb反汇编代码
$ gdb example
(gdb) disass main
Dump of assembler code for function main:
0x080483f6 <+0>:    push   %ebp
0x080483f7 <+1>:    mov    %esp,%ebp
0x080483f9 <+3>:    sub    $0x8,%esp


目标码格式列表
--demangle
-C 将底层的符号名解码成用户级名字,除了去掉所有开头的下划线之外,还使得C++函数名以可理解的方式显示出来。

—disassemble或者-d 反汇编可执行段

.—dissassemble-all或者-D 反汇编所有段

--debugging显示调试信息。企图解析保存在文件中的调试信息并以C语言的语法显示出来。仅仅支持某些类型的调试信息。

--prefix-addresses反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式。显示效果并不理想,但可能会用到其中的某些显示,自己可以对比。

--disassemble-zeroes  一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编

-EB -EL  指定字节序  --endian={big|little}这个选项将影响反汇编出来的指令。little-endian就是我们当年在dos下玩汇编的时候常说的高位在高地址,x86都是这种。

--file-headers或者  -f 显示objfile中每个文件的整体头部摘要信息。

--section-headers;--headers 或者-h 显示目标文件各个section的头部摘要信息。

--info或者-i 显示对于 -b 或者 -m 选项可用的架构和目标格式列表。显示支持的目标文件格式和CPU架构


--section=name或者-j name 仅仅显示指定section的信息

--line-numbers或者-l 用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求编译时使用了-g之  类的调试编译选项。

--architecture=machine 或者-m machine指定反汇编目标文件时使用的架构,当待反汇编文件本身没有描述架构信息的时候(比如S-records),这个选项很有用。可以用-i选项列出这里能够指定的架构
--reloc或者-r 显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇编后的格式显示出来。

--dynamic-reloc    -R 显示文件的动态重定位入口,仅仅对于动态目标文件有意义,比如某些共享库。

--full-contents  -s 显示指定section的完整内容。

objdump --section=.text -s inet.o | more
--source    -S 尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,效果比较明显。隐含了-d参数。
--show-raw-insn反汇编的时候,显示每条汇编指令对应的机器码,除非指定了--prefix-addresses,这将是缺省选项。

--no-show-raw-insn


-S 尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,

   效果比较明显。隐含了-d参数。

-l 用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用

  使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求

  编译时使用了-g之类的调试编译选项。

-j name 仅仅显示指定section的信息


如何使用linux下objdump命令对任意一个二进制文件进行反汇编?

可以使用如下命令:

objdump -D -b binary -m i386 a.bin

-D表示对全部文件进行反汇编,-b表示二进制,-m表示指令集架构,a.bin就是我们要反汇编的二进制文件

objdump -m可以查看更多支持的指令集架构,如i386:x86-64,i8086等

另外上面的所有objdump命令的参数同样适用于arm-linux-objdump。

同时我们也可以指定big-endian或little-endian(-EB或-EL),我们可以指定从某一个位置开始反汇编等。


objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它还有其他作用,下面以ELF格式可执行文件test为例详细介绍:

objdump -f test  显示test的文件头信息

objdump -d test  反汇编test中的需要执行指令的那些section

objdump -D test  与-d类似,但反汇编test中的所有section

objdump -h test  显示test的Section Header信息

objdump -x test  显示test的全部Header信息

objdump -s test  除了显示test的全部Header信息,还显示他们对应的十六进制文件代码



使用arm-linux 工具链里面的arm-linux-objdump 就能反汇编

cd到bin文件所在的目录, 在命令行下输入:

arm-linux-objdump -D -b binary -m arm xxx.bin > xxx.asm

参数:

-D 反编译所有代码

-m 主机类型, arm

-b 文件格式, binary

对于ELF格式的文件只要一个-D参数即可

就可以把xxx.bin反汇编到xxx.asm文件


Arm-linux-objdump –D elf_file > dis_file 或者

Arm-linux-objdump –D –b binary –m arm bin_file > dis_file


内存地址反向查找出问题的程序:

<1>.通过汇编去查找.
Linux 平台:
  1. 在程序信号处理部分, 加入代码捕捉引起错误点的地址,简单来说,方法就是在注册自己的信号处理函数,在这个函数中加入获取内存错误地址的代码,并把结果写到一个日志文件中。
  2. 编译 DEBUG 版本 程序 (compile 时用 -g , 生成可执行文件后不用 strip 去掉symbol 信息)
  3. 在程序出问题时, 查看日志记录, 得到错误点的地址.
  4. 用objdump -S 导出Debug 版本的汇编代码, 查找错误地址, 则得出那条语句出错.
windows 下c 语言调试
  1. release 版编译/连接选项, 把"generate debug info/" 打钩选择
  2.dumpbin /DISASM /OUT:dump.out.txt.1 prep.exe 可反编译exe文件
  3.得到程序非法地址(可从管理工具-》事件查看器里得到),与汇编比较。


对目标文件:***.o:

arm-none-Linux-gnueabi-objdump -D  ./kernel/sched.o > sched.S


对可执行文件***.bin:

arm-linux-objdump -D -b binary -m arm xxx.bin > xxx.asm


为了运行ARM汇编代码,需要使用交叉编译器arm-linux-gcc对ARM汇编代码进行编译。下载交叉编译器安装完毕后,对ARM汇编代码进行编译。

arm-linux-gcc main.s -o main -nostdlib

编译选项“-nostdlib”表示不使用任何运行时库文件,编译生成的可执行文件main只能在ARM体系结构的系统上运行。

通常认为,产生异常的地址是lr寄存器的值,从上面的异常信息可以看到[lr]的值是c01a4e30。

接下来,我们可以通过内核镜像文件反汇编来找到这个地址。内核编译完成后,会在内核代码根目录下生成vmlinux文件,我们可以通过以下命令来反汇编:

arm-none-eabi-objdump -Dz -S vmlinux >linux.dump

值得注意的是,arm-none-eabi-objdump的参数-S表示尽可能的把原来的代码和反汇编出来的代码一起呈现出来,-S参数需要结合 arm-linux-gcc编译参数-g,才能达到反汇编时同时输出原来的代码。所以,我在linux内核代码根目录的Makefile中增加-g编译参 数:

KBUILD_CFLAGS   := -g -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
     -fno-strict-aliasing -fno-common \
     -Werror-implicit-function-declaration \
     -Wno-format-security \
     -fno-delete-null-pointer-checks

修改Makefile后,重新编译内核,在根目录中生成的vmlinux文件就会包含了原来的代码信息,因此,该文件的大小也比原来大一倍!

最后执行“arm-none-eabi-objdump -Dz-S vmlinux >linux.dump”,由于加入了-g编译参数,执行这个反汇编命令需要很长时间(本人在虚拟机上执行,花了近6个小时!),反汇编出来的linux.dump文件也比原来的44MB增大到惊人的503MB。

(博主加:这里有一点要注意,如果是ko模块文件,反汇编时如果想看到ko文件的某函数反汇编代码,该函数不能加static关键字修饰,而且module_init修饰的入口函数,其名字即为module_init)

接下来可以用UltraEdit打开linux.dump文件,查找“c01a4e30”字符串。

最后定位到的信息是:

==================================================================================================================

/*
 * tasklet handling tty stuff outside the interrupt handler.
 */
static void atmel_tasklet_func(unsigned long data)
{
c01a4e20: e92d45f0  push {r4, r5, r6, r7, r8, sl, lr}
c01a4e24: e24dd01c  sub sp, sp, #28 ; 0x1c
c01a4e28: e1a04000  mov r4, r0
 /* The interrupt handler does not take the lock */
 spin_lock(&port->lock);

 if (atmel_use_pdc_tx(port))
  atmel_tx_pdc(port);
 else if (atmel_use_dma_tx(port))
c01a4e2c: ebfffda1  bl c01a44b8 <atmel_use_dma_tx>
c01a4e30: e3500000  cmp r0, #0 ; 0x0
c01a4e34: e5943034  ldr r3, [r4, #52]
c01a4e38: 0a00007b  beq c01a502c <atmel_tasklet_func+0x20c>

==================================================================================================================

可以看出来,异常的产生位于atmel_tasklet_func函数的 else if (atmel_use_dma_tx(port))一行

估计atmel_use_dma_tx(port)的“port”参数为空指针所致!






<think>好的,我现在需要帮助用户解决关于如何对vmlinux进行反汇编以生成ko文件的问题。首先,我需要仔细理解用户的需求。用户提到“vmlinux反汇编生成ko文件”,这可能有些混淆,因为vmlinux是内核镜像文件,而.ko文件是内核模块。通常,反汇编是将可执行文件转换为汇编代码,而生成.ko文件需要编译源代码,而不是反汇编。不过,用户可能是在遇到内核或模块崩溃时,希望通过反汇编vmlinux来分析问题,比如在调试oops信息时使用反汇编来跟踪堆栈。 接下来,我需要回顾用户提供的引用内容。引用[1]、[2]、[3]、[4]都提到了使用arm-linux-objdump或类似的工具来反汇编vmlinux或.ko文件,生成.dis或.dump文件。例如,引用[1]中的命令是arm-linux-objdump -D xxx.ko > xxx.dis,而引用[3]也使用了类似的命令。用户可能误解了反汇编和生成.ko的关系,但实际需求可能是如何通过反汇编来辅助调试内核模块的错误。 用户的问题可能涉及两个部分:一是如何反汇编vmlinux,二是如何生成或分析.ko文件。但根据引用内容,生成.ko文件通常是通过编译源代码,而不是反汇编。因此,正确的步骤应该是使用objdump工具对已有的vmlinux或.ko文件进行反汇编,生成汇编代码,以便分析问题。 接下来,我需要整理出具体的步骤。首先,确认工具链的路径,如引用[1]和[3]中提到的arm-linux-objdump路径。然后,使用正确的命令对vmlinux进行反汇编,例如arm-linux-objdump -D vmlinux > vmlinux.dis。对于.ko文件,同样使用objdump工具,如arm-linux-objdump -D module.ko > module.dis。 另外,引用[2]提到使用-g参数编译以保留调试信息,这样反汇编时会有更多符号信息,但生成的文件会很大。这可能对用户有帮助,尤其是在需要符号信息进行调试的情况下。此外,引用[4]提到使用crash工具分析dump文件,这可能是在系统崩溃后分析vmcore,结合vmlinux的符号信息。 用户可能需要的是如何结合反汇编结果和调试信息来定位问题,比如在oops日志中找到出错的地址,然后在反汇编文件中查找对应的代码位置。这需要将地址与反汇编代码中的符号对应起来,可能需要addr2line工具的帮助,如引用[3]中的路径示例。 总结来说,用户的真实需求可能是如何通过反汇编vmlinux和.ko文件来调试内核或模块的问题,而不是直接生成.ko文件。因此,回答应该指导用户正确使用objdump工具进行反汇编,并解释如何利用生成的.dis文件进行调试分析,同时提到相关的注意事项,比如工具链的选择、调试符号的重要性,以及如何结合崩溃日志进行地址解析。 最后,生成相关问题需要考虑用户可能的后续需求,比如如何处理反汇编后的文件、如何优化调试过程,或者常见的错误及解决方法。例如,用户可能遇到工具链不匹配的问题,或者反汇编文件过大的问题,因此相关问题可以围绕这些潜在问题展开。</think>### 分步解答:如何对vmlinux和内核模块进行反汇编分析 #### 1. 工具选择与基本命令 - **核心工具**:使用`arm-linux-objdump`或`objdump`(根据架构选择,如x86平台用`objdump`)进行反汇编。 - **反汇编vmlinux**: ```bash arm-linux-objdump -D vmlinux > vmlinux.dis # ARM架构示例[^1][^3] ``` - **反汇编.ko文件**: ```bash arm-linux-objdump -D module.ko > module.dis # 驱动模块示例[^1][^3] ``` #### 2. 关键注意事项 - **工具链匹配**:必须使用与编译内核或模块时相同的交叉编译工具链(如`arm-linux-objdump`用于ARM架构内核)[^1][^3]。 - **调试符号**:编译时需添加`-g`选项保留调试信息,反汇编结果会包含源代码与汇编的对应关系: ```bash make CFLAGS="-g" # 编译时保留调试符号[^2] ``` 反汇编后可通过地址定位具体代码行(需结合`addr2line`工具): ```bash arm-linux-addr2line -e vmlinux 0xc0123456 # 解析地址对应的代码位置[^3] ``` #### 3. 典型应用场景 - **调试内核崩溃(Oops日志)**: 1. 从Oops日志中获取崩溃地址(如`PC: [<c0123456>]`)。 2. 在反汇编文件中搜索`c0123456`,找到对应的汇编代码段。 3. 结合源码和汇编逻辑分析崩溃原因[^1][^4]。 - **验证代码逻辑**: 检查反汇编后的指令是否符合预期,例如: ```assembly c0123456: e1a00000 nop ; (mov r0, r0) c012345a: e12fff1e bx lr ``` #### 4. 性能与存储优化 - **分块反汇编**:若反汇编文件过大(如超过500MB[^2]),可针对特定段操作: ```bash arm-linux-objdump -D -j .text vmlinux > vmlinux_text.dis # 仅反汇编代码段 ``` - **并行处理**:使用`split`分割文件后并行分析。 #### 5. 完整操作流程示例 ```bash # 1. 编译内核时保留调试信息 make menuconfig # 确保开启CONFIG_DEBUG_INFO make -j4 # 2. 反汇编vmlinux arm-linux-objdump -D vmlinux > vmlinux.dis # 3. 解析Oops日志中的地址 grep "PC" /var/log/messages # 示例输出:PC: [<c0123456>] arm-linux-addr2line -e vmlinux c0123456 # 输出:/kernel/sched.c:123 # 4. 在反汇编文件中定位 grep -n "c0123456" vmlinux.dis # 定位到具体汇编行 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值