2003-05-30 22:59:18

by Carl Spalletta

[permalink] [raw]
Subject: Cute kernel trick, or communistic ploy?

Output of program to simulate a /proc file in a stopped kernel,
using the same kernel function(s) used to generate the actual file
when the kernel is up:

(gdb) source ./proc-uptime
$3 = (void *) 0xa1aec000
$4 = (void *) 0xa1da48d4
$5 = (void *) 0xa1da4384
$6 = (void *) 0xa1da48ac
$7 = 0
"remember to 'call(kfree($page))' when finished
"4080219633.89 395.85
(gdb)

This program works fine in the um arch but I was wondering what
the pitfalls are in an approach like this. This is a trivial example,
but other /proc files do very complicated bookkeeping and formatting;
and this method should be equally applicable to those.


GDB program 'proc-uptime' (18 lines):

set $gfp_atomic=0x20
call(kmalloc(4096,$gfp_atomic))
set $page=$
call(kmalloc(32,$gfp_atomic))
set $zero=(int *)$
set *$zero=(int)0
call(kmalloc(32,$gfp_atomic))
set $start=(int **)$
set *$start=$zero
call(kmalloc(32,$gfp_atomic))
set $eof=(int *)$
set *$eof=1
call(uptime_read_proc((char *)$page,(char **)$start,(off_t)0,\
0,$eof,(void *)$zero))
call(kfree($zero))
call(kfree($eof))
call(kfree($start))
echo "remember to 'call(kfree($page))' before continuing\n"
printf "%s\n",$page




2003-05-31 01:20:43

by Werner Almesberger

[permalink] [raw]
Subject: Re: Cute kernel trick, or communistic ploy?

Carl Spalletta wrote:
> This program works fine in the um arch but I was wondering what
> the pitfalls are in an approach like this.

You mean calling functions from a debugger ? By and large, this
should be okay. I'm doing it all the time in umlsim :-)

You have to make sure you're really allowed to call these functions
from the point where you've stopped the kernel, i.e.

- that they don't change data structures protected by a common
spinlock (which may be absent on UP)
- that they don't sleep

Besides that, you may run into problems if gdb doesn't understand
the calling convention. So far, I haven't found a case where this
happens. (But then, I'm working directly from the DWARF2 data, so
I wouldn't notice bugs in gdb, only wrong or incomplete debugging
information. And I haven't tried FASTCALL functions yet.)

Also, you probably can't call inline functions from gdb. You can
probably work around this by adding a file somewhere to the kernel
that includes all the headers with inline functions you want, and
then compile it with -fkeep-inline-functions -Wno-unused-function.
Depending on what you include, you may also need to

void __this_fixmap_does_not_exist(void)
{
panic("__this_fixmap_does_not_exist called\n");
}

Oh, and when you explore further, be warned that accessing local
variables can be messy, particularly when inline functions are
involved.

I ran your example with umlsim. Here's what it looks like:

#define GFP_ATOMIC 0x20
$uml = $run_uml("A","no-such-script",1);
$page = (char *) kmalloc(4096,GFP_ATOMIC);
$start = (char **) kmalloc(4,GFP_ATOMIC);
$eof = (int *) kmalloc(4,GFP_ATOMIC);
$data = kmalloc(1,GFP_ATOMIC);
uptime_read_proc($page,$start,0,0,$eof,$data);
kfree((void *) $eof);
kfree((void *) $start);
kfree((void *) $data);
printk(*$start);
kfree((void *) $page);

(I shouldn't need to kmalloc $data or the casts in kfree.
Two more things to fix ...)

If you don't like the printk, umlsim could also copy the
data to the simulator and print it from there, but the
syntax is a bit ugly:

print (char ["umlsim_inline.c".strlen(*$start)+1]) *$start;

By the way, it may also matter how you stop your process. I
normally use breakpoints (INT3), and things work fine. I'm
still experimenting with SIGSTOP.

- Werner

--
_________________________________________________________________________
/ Werner Almesberger, Buenos Aires, Argentina [email protected] /
/_http://www.almesberger.net/____________________________________________/

2003-05-31 03:44:36

by Werner Almesberger

[permalink] [raw]
Subject: Re: Cute kernel trick, or communistic ploy?

I wrote:
> (I shouldn't need to kmalloc $data or the casts in kfree.
> Two more things to fix ...)

Ancient history. With the current version
http://umlsim.sourceforge.net/umlsim-37.tar.gz
it can be written as

#define GFP_ATOMIC 0x20
$uml = $run_uml("A","no-such-script",1);
$page = (char *) kmalloc(4096,GFP_ATOMIC);
$start = (char **) kmalloc(4,GFP_ATOMIC);
$eof = (int *) kmalloc(4,GFP_ATOMIC);
uptime_read_proc($page,$start,0,0,$eof,0);
kfree($eof);
printk(*$start);
kfree($start);
kfree($page);

- Werner

--
_________________________________________________________________________
/ Werner Almesberger, Buenos Aires, Argentina [email protected] /
/_http://www.almesberger.net/____________________________________________/