Hi I'm doing homework about operating system using Pintos. I was asked to find the faulting instruction in one test. The testing framework expected Pintos to output “do-nothing: exit(162)”. This is the standard message that Pintos prints when a process exits. However, Pintos did not output this message; instead, the do-nothing program crashed in userspace due to a memory access violation (a segmentation fault).
#include "tests/lib.h"
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
I looked into the result of this test,
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
The questions :
- What virtual address did the program try to access from userspace that caused it to crash? A: From the result file, I think it's 0xc000008
- What is the virtual address of the instruction that resulted in the crash? A: eip = 0x8048757, it's the virtual address of the instruction.
- To investigate, disassemble the do-nothing binary using objdump. What is the name of the function the program was in when it crashed? Copy the disassembled code for that function onto Gradescope, and identify the instruction at which the program crashed.
I have no idea about how to find the answer of 3. question, the output with "objdump -S do-nothing.o" is really simple :
Disassembly of section .text:
00000000 <main>:
int
main (int argc UNUSED, char *argv[] UNUSED)
{
return 162;
}
0: b8 a2 00 00 00 mov $0xa2,%eax
5: c3 ret
A:
void
_start (int argc, char *argv[])
{
8048754: 83 ec 1c sub $0x1c,%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>
- Find the C code for the function you identified above. For each instruction in the disassembled function in #3, explain in a few words why it’s necessary and/or what it’s trying to do.
#include <syscall.h>
int main (int, char *[]);
void _start (int argc, char *argv[]);
void
_start (int argc, char *argv[])
{
exit (main (argc, argv));
}
- Why did the instruction you identified in #3 try to access memory at the virtual address you identified in #1? Don’t explain this in terms of the values of registers; we’re looking for a higher level explanation. A: I found the faulting instruction but I'm even more confused,
8048757: 8b 44 24 24 mov 0x24(%esp),%eax
**why would this instruction lead to segmentation fault? **
sub $0x1c,%esp
mov 0x24(%esp),%eax
Firstly it allocated some stack space (0x1c), then move the argument argv at 0x24(%esp) [which was 0x8 before stack pointer changed] to %eax, why would this simple instruction lead to segmentation fault?