I am doing the Pintos project on the side to learn more about operating systems. I finished Project 1 and have started the second project. I already have setup stack verified and working (via hex_dump). Right now I am having issues getting the correct syscall arguments.
In user/syscall.c there are 4 assembly stubs(0 - 4 stubs) that the user syscall wrap.
#define syscall3(NUMBER, ARG0, ARG1, ARG2) \
({ \
int retval; \
asm volatile \
("pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; " \
"pushl %[number]; int $0x30; addl $16, %%esp" \
: "=a" (retval) \
: [number] "i" (NUMBER), \
[arg0] "g" (ARG0), \
[arg1] "g" (ARG1), \
[arg2] "g" (ARG2) \
: "memory"); \
retval; \
}) (this code is given to us)
I have some code inside of my syscall_handler that calls the correct function inside of the kernel.
static void syscall_handler (struct intr_frame *f) {
uint32_t *args = f->esp;
if (args[0] == SYS_WRITE) {
f->eax = write(args);
}
Inside of my write function I am printing out the FD and Size
int sysCallNumber = (int) args[0];
int fd = (int) args[1];
const char *buffer = (char *) args[2];
unsigned size = (unsigned) args[3];
printf("FD is %d\n", fd);
printf("Size is %d\n", size);
Running 'echo hello stack overflow 1 22 333' will yield the result below. Note I added the notes in parentheses. () <- Something is getting screwed up and FD is getting overridden with the size (including null terminator)
FD is 6 (hello)
Size is 6
FD is 6 (stack)
Size is 6
FD is 9 (overflow)
Size is 9
FD is 2 (1)
Size is 2
FD is 3 (22)
Size is 3
FD is 4 (333)
Size is 4
FD is 1 (this is from the printf("\n") in echo.c)
Size is 1
Ive ran this with GDB setting breakpoints and dumping frames and have not been able to figure it out. Has anyone encountered anything similar? If so how did you fix it?
Thanks!
I discovered a bug recently in
user/syscall.cthat could be affecting you. Try applying this patch touser/syscall.c:Here's the long story...
In the macro
syscall3for example, the expected assembly code to be generated looks something like thisThis should work as long as the stack looks exactly as expected just push the interrupt instruction. Here is what the disassembled
writefunction looks like in of the test programs (generated byobjdump -d pintos/src/userprog/build/tests/userprog/args-many):There is an enormous problem with these instructions. Because the arguments are being pushed onto the stack relative to the stack pointer
%esp, the wrong arguments are pushed onto the stack! This is because%espchanges after everypushlinstruction.After doing some digging on the extended asm syntax for gcc, I think I found the right fix. The
%espregister needs to be added to the Clobbers list in the extended asm instruction for eachsyscall*. This is because eachpushlinstruction modifies%espindirectly, so we need to inform gcc of that modification so that it does not use%espimproperly in the generated instructions.