如何使用objdump查找导致崩溃的指令
How to find the instruction causing crash using objdump
嗨,我正在做关于使用 Pintos 的操作系统的作业。
我被要求在一次测试中找出出错的指令。测试框架期望 Pintos 输出“do-nothing: exit(162)”。这是 Pintos 在进程退出时打印的标准消息。但是,Pintos 并没有输出这条信息;相反,什么都不做的程序
由于内存访问冲突(分段错误)在用户space 中崩溃。
#include "tests/lib.h"
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
我查看了这个测试的结果,
FAIL
Test output failed to match any acceptable form.
Acceptable output:
do-nothing: exit(162)
Differences in `diff -u' format:
- do-nothing: exit(162)
+ Page fault at 0xc0000008: rights violation error reading page in user context.
+ do-nothing: dying due to interrupt 0x0e (#PF Page-Fault Exception).
+ Interrupt 0x0e (#PF Page-Fault Exception) at eip=0x8048757
+ cr2=c0000008 error=00000005
+ eax=00000000 ebx=00000000 ecx=00000000 edx=00000000
+ esi=00000000 edi=00000000 esp=bfffffe4 ebp=00000000
+ cs=001b ds=0023 es=0023 ss=0023
问题:
- 程序试图从用户space 访问哪个虚拟地址导致它崩溃?
答:从结果文件来看,我认为是0xc000008
- 导致崩溃的指令的虚拟地址是什么?
A:eip = 0x8048757,是指令的虚拟地址
- 为了进行调查,请使用 objdump 反汇编不执行任何操作的二进制文件。程序崩溃时所在的函数的名称是什么?将该函数的反汇编代码复制到 Gradescope,并确定程序崩溃的指令。
我不知道如何找到问题3的答案,
“objdump -S do-nothing.o”的输出非常简单:
Disassembly of section .text:
00000000 <main>:
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
0: b8 a2 00 00 00 mov [=12=]xa2,%eax
5: c3 ret
甲:
void
_start (int argc, char *argv[])
{
8048754: 83 ec 1c sub [=13=]x1c,%esp
exit (main (argc, argv));
8048757: 8b 44 24 24 mov 0x24(%esp),%eax
804875b: 89 44 24 04 mov %eax,0x4(%esp)
804875f: 8b 44 24 20 mov 0x20(%esp),%eax
8048763: 89 04 24 mov %eax,(%esp)
8048766: e8 35 f9 ff ff call 80480a0 <main>
804876b: 89 04 24 mov %eax,(%esp)
804876e: e8 49 1b 00 00 call 804a2bc <exit>
- 找到您在上面确定的函数的 C 代码。对于#3中反汇编函数中的每条指令,用几句话解释
为什么它是必要的 and/or 它正在尝试做什么。
#include <syscall.h>
int main (int, char *[]);
void _start (int argc, char *argv[]);
void
_start (int argc, char *argv[])
{
exit (main (argc, argv));
}
- 为什么您在#3 中确定的指令尝试访问您指定的虚拟地址处的内存
在#1 中确定?不要用寄存器的值来解释这个;我们正在寻找更高的
水平解释。
答:我找到了错误的指令,但我更困惑了,
8048757: 8b 44 24 24 mov 0x24(%esp),%eax
**为什么这条指令会导致段错误? **
sub [=16=]x1c,%esp
mov 0x24(%esp),%eax
首先它分配了一些堆栈space (0x1c),然后将参数 argv 移动到 0x24(%esp) [在堆栈指针更改之前是 0x8] 到 %eax,为什么这个简单的指令导致分段错误?
我不是 PintOS 方面的专家,但我可以提供一些见解。您正在对目标文件 (.o
) 使用 OBJDUMP。这些是未链接的 ELF 对象文件,没有任何 VMA(虚拟内存地址)起点(也称为原点),并且不包含每个 PintOS 程序中的任何用户模式运行时代码。诸如设置用户模式应用程序并使用 argc
和 argv
参数在 main
处启动代码的 C 启动之类的东西。
您需要做的是使用正常的 PintOS 构建过程将目标文件构建到用户模式程序中。 userland 可执行文件与删除了 .o
的 .o
文件同名。 do-nothing
是可执行文件的名称,它们似乎可以在目录 pintos/src/userprog/build/tests/userprog/
中找到。 运行 此可执行文件上的 OBJDUMP,搜索地址 0x8048757。您应该能够轻松找到函数名称和它的所有代码。有了这些信息,您应该能够回答第三个问题。您对问题 1 和问题 2 的回答是正确的。
嗨,我正在做关于使用 Pintos 的操作系统的作业。 我被要求在一次测试中找出出错的指令。测试框架期望 Pintos 输出“do-nothing: exit(162)”。这是 Pintos 在进程退出时打印的标准消息。但是,Pintos 并没有输出这条信息;相反,什么都不做的程序 由于内存访问冲突(分段错误)在用户space 中崩溃。
#include "tests/lib.h"
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
我查看了这个测试的结果,
FAIL
Test output failed to match any acceptable form.
Acceptable output:
do-nothing: exit(162)
Differences in `diff -u' format:
- do-nothing: exit(162)
+ Page fault at 0xc0000008: rights violation error reading page in user context.
+ do-nothing: dying due to interrupt 0x0e (#PF Page-Fault Exception).
+ Interrupt 0x0e (#PF Page-Fault Exception) at eip=0x8048757
+ cr2=c0000008 error=00000005
+ eax=00000000 ebx=00000000 ecx=00000000 edx=00000000
+ esi=00000000 edi=00000000 esp=bfffffe4 ebp=00000000
+ cs=001b ds=0023 es=0023 ss=0023
问题:
- 程序试图从用户space 访问哪个虚拟地址导致它崩溃? 答:从结果文件来看,我认为是0xc000008
- 导致崩溃的指令的虚拟地址是什么? A:eip = 0x8048757,是指令的虚拟地址
- 为了进行调查,请使用 objdump 反汇编不执行任何操作的二进制文件。程序崩溃时所在的函数的名称是什么?将该函数的反汇编代码复制到 Gradescope,并确定程序崩溃的指令。
我不知道如何找到问题3的答案, “objdump -S do-nothing.o”的输出非常简单:
Disassembly of section .text:
00000000 <main>:
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
0: b8 a2 00 00 00 mov [=12=]xa2,%eax
5: c3 ret
甲:
void
_start (int argc, char *argv[])
{
8048754: 83 ec 1c sub [=13=]x1c,%esp
exit (main (argc, argv));
8048757: 8b 44 24 24 mov 0x24(%esp),%eax
804875b: 89 44 24 04 mov %eax,0x4(%esp)
804875f: 8b 44 24 20 mov 0x20(%esp),%eax
8048763: 89 04 24 mov %eax,(%esp)
8048766: e8 35 f9 ff ff call 80480a0 <main>
804876b: 89 04 24 mov %eax,(%esp)
804876e: e8 49 1b 00 00 call 804a2bc <exit>
- 找到您在上面确定的函数的 C 代码。对于#3中反汇编函数中的每条指令,用几句话解释 为什么它是必要的 and/or 它正在尝试做什么。
#include <syscall.h>
int main (int, char *[]);
void _start (int argc, char *argv[]);
void
_start (int argc, char *argv[])
{
exit (main (argc, argv));
}
- 为什么您在#3 中确定的指令尝试访问您指定的虚拟地址处的内存 在#1 中确定?不要用寄存器的值来解释这个;我们正在寻找更高的 水平解释。 答:我找到了错误的指令,但我更困惑了,
8048757: 8b 44 24 24 mov 0x24(%esp),%eax
**为什么这条指令会导致段错误? **
sub [=16=]x1c,%esp
mov 0x24(%esp),%eax
首先它分配了一些堆栈space (0x1c),然后将参数 argv 移动到 0x24(%esp) [在堆栈指针更改之前是 0x8] 到 %eax,为什么这个简单的指令导致分段错误?
我不是 PintOS 方面的专家,但我可以提供一些见解。您正在对目标文件 (.o
) 使用 OBJDUMP。这些是未链接的 ELF 对象文件,没有任何 VMA(虚拟内存地址)起点(也称为原点),并且不包含每个 PintOS 程序中的任何用户模式运行时代码。诸如设置用户模式应用程序并使用 argc
和 argv
参数在 main
处启动代码的 C 启动之类的东西。
您需要做的是使用正常的 PintOS 构建过程将目标文件构建到用户模式程序中。 userland 可执行文件与删除了 .o
的 .o
文件同名。 do-nothing
是可执行文件的名称,它们似乎可以在目录 pintos/src/userprog/build/tests/userprog/
中找到。 运行 此可执行文件上的 OBJDUMP,搜索地址 0x8048757。您应该能够轻松找到函数名称和它的所有代码。有了这些信息,您应该能够回答第三个问题。您对问题 1 和问题 2 的回答是正确的。