From: Blaisorblade <blaisorblade@yahoo.it>
To: user-mode-linux-devel@lists.sourceforge.net
Subject: [uml-devel] "Stracing" guest from gdb on the host and examining its memory.
Date: Fri, 30 Mar 2007 17:54:27 +0200 [thread overview]
Message-ID: <200703301754.27335.blaisorblade@yahoo.it> (raw)
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
reply other threads:[~2007-03-30 15:54 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200703301754.27335.blaisorblade@yahoo.it \
--to=blaisorblade@yahoo.it \
--cc=user-mode-linux-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox