* [uml-devel] "Stracing" guest from gdb on the host and examining its memory.
@ 2007-03-30 15:54 Blaisorblade
0 siblings, 0 replies; only message in thread
From: Blaisorblade @ 2007-03-30 15:54 UTC (permalink / raw)
To: user-mode-linux-devel
Today I ran -mm as UML.
To debug some hard problems (in the end that udev on Dapper doesn't like -mm
kernels, while the one on Breezy does - so /dev/tty* doesn't get created and
getty never starts), I found an efficient enough way to strace system calls
from the guest.
Note that YMMV - below I reference various concept which are explained
elsewhere without links, and it took me some time to learn how to debug UML
efficiently and address the various quirks of gdb.
It's a personal note to remember, but may be useful to motivated hackers.
Probably I should put this inside Documentation/ ...
Btw, I discovered recently that when you boot UML inside gdb, it's the first
break call to confuse gdb: breakpoints set before cease working when that
call is done, i.e. very early (I remember that was in init_aio).
The basic idea is to break at handle_syscall, to intercept all syscall, have
some nice gdb displays for parameters, and display which is the syscall.
First, let's get some parameters; we want to be able to access current.
1) CONFIG_KERNEL_STACK_ORDER is normally 2, so the stack is 16K wide. Since
This means that struct thread_info* current_thread_info() is given by this:
((struct thread_info*)((long)$rsp & 0xffffc000))
As a check, current_thread_info() == current_thread_info()->task->thread_info
is always true, so you can verify whether
((struct thread_info*)((long)$rsp & 0xffffc000))->task->thread_info ==
((struct thread_info*)((long)$rsp & 0xffffc000))
After this, I can create a display for the pid and name of the current
executing process:
display ((struct thread_info*)((long)$rsp & 0xffffc000))->task->pid
display ((struct thread_info*)((long)$rsp & 0xffffc000))->task->comm
(there is some garbage in comm after the first NULL, that's normal).
That's for x86_64; on i386 replace $rsp with $esp.
2) I want at times to print the process IP.
I compile with O=$OUT, i.e. using KBUILD_OUTPUT ($OUT points to a folder), to
place object files elsewhere than sources.
So to get HOST_IP I can do:
$ grep -r HOST_IP $OUT/arch/um/
Currently it is in user_constants, so I can do:
$ grep HOST_IP $OUT/arch/um/include/user_constants.h
(if you build without O=, use the following:)
$ grep HOST_IP arch/um/include/user_constants.h
I get
#define HOST_IP 16 /* RIP # */
3) now I break on handle_syscall.
The best for me was to break on "result = EXECUTE_SYSCALL(syscall, regs);".
Here, union uml_pt_regs * r represents the registers of the userspace process.
To print the current syscall, you can do:
(gdb) print r->skas->syscall
to get the syscall number, but
(gdb) print sys_call_table[r->skas->syscall]
prints the associated function, and that's clearer.
Finally, the IP is r->skas->regs[HOST_IP], but HOST_IP is a macro, so we need
the actual value we got earlier:
display r->skas->regs[16]
And we have all! By stepping into EXECUTE_SYSCALL, we can also debug the
syscall execution and see the parameters (most times you must wait for
copy_from_user to see parameters value, if just a pointer is passed).
We can also look at the guest memory - that was thought me by Jeff years ago.
While the given guest process is stopped inside UML:
1) get the pid of the host process representing the guest process. That's
print userspace_pid[$CPU], where $CPU must always be 0 for now (until SMP will
be implemented).
Let that be $PID
2) The child memory is mapped from a deleted temp file, named
$TEMP/vm_file-XXXXXX. We must look to the page table, and that's simple
through the host. Suppose we want to look at 0x405ac012 (because that's the
IP where a process gets a SIGSEGV and dies); first let's split this into page
address and offset, getting 0x405ac012 == 0x405ac000 + 0x12.
cat /proc/$PID/maps will show this, like (sample row):
405ac000-405ad000 rwxs 03fb4000 00:13
85912 /tmp/vm_file-IUCpfE (deleted)
The first column is the range mapped with mmap(), the third is the offset
inside the file. So 0x405ac012 is located at 0x03fb4000 + 0x12 in that file.
How to look at it, since it's deleted? Uml has mapped the whole of it,
starting from the address stored in uml_physmem onwards.
So in gdb I must just look (with the 'x' or 'disassemble' command) to
uml_physmem + 0x03fb4000 + 0x12.
These are the basic ideas, very condensed.
--
Inform me of my mistakes, so I can add them to my list!
Paolo Giarrusso, aka Blaisorblade
http://www.user-mode-linux.org/~blaisorblade
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-03-30 15:54 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-30 15:54 [uml-devel] "Stracing" guest from gdb on the host and examining its memory Blaisorblade
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox