[comp.sys.sun] ptrace

ant@batserver.cs.uq.OZ (10/09/89)

I am absolutely sure that the title of this article would have brought
back memories of some pretty terrible experiences to anyone who has had
the pleasure (err) of using the PTRACE system call.  As for those who
haven't, feel well assured that you are probably all the better for it.

Anyhow, jokes (I'm not laughing) aside, I DO have to use it, and not
surprisingly, I am having a spot of bother with it.

I am doing an honours project on Sun workstations, under SunOS 4.0.3.
Basically my problem is that I have to be able to save a processes state
and be able to restore it again later (controlled from another process).

So I use PTRACE_ATTACH, PTRACE_DUMP and PTRACE_DETACH to dump a core file.
No problem (only week or so).  Now come the tricky bit

	1> Positions of the information in the core file, and
	2> The addresses that they are to be restored to in the process.

1 took a little bit of time to find, but find it we did, despite the fact
that UNIX man entries are about as believe able as Snow White.  I will
list these, just in case I am wrong

1> The core file has a header of type "struct core" (hereby called pcore).

2> The data segment starts at pcore.c_len.  What exactly is in the core
file between sizeof(core) and pcore.c_len ? 

3> The data segment is pcore.c_dsize bytes long (a multiple of 8192).

4> Using the getrlimit system call, get rlim for the stack (RLIMIT_STACK).


5> The size of the stack (actually used) is then ; rlim.rlim_max -
pcore.c_regs.r_areg[7]	/* A7 being the stack pointer */

6> This means that the location of the stack in the core file is ;
pcore.c_len + pcore.c_dsize + pcore.d_size - stacksize.  ie seek back
stacksize from eof.

Now the real tricky bit is to find out where to put it back into the
processes

	1> Registers, no problem.  PTRACE_SETREGS, no address required.
	2> Stack, no problem.  You know the stack pointer and its size.
	3> Ha ha, sounds easy so far doesn't it, but now comes THE DATA SEGMENT.
	   This is how I viewed a process ;
			+-------------------------------+<--0
			|	Some process info	|
			|	PTRACE cannot get	|
			|	into here.		|<--8191
			+-------------------------------+ A
			|	The Code or Text	| |
			|	Segment			| | Some multiple (n) of 
			|				| V      8192
			+-------------------------------+<-- (n+1)*8192
			|	The Data Segment	|
			|				|
			|				|
			|				|
			|				|
			|				|
			|	A  A  A  A		|
			|	|  |  |  |		|
			|	The Stack		|
			+-------------------------------+ Some Humungous value.

4> BUT, this is not so, the data segment does not start after the text
segment at all.  I have absolutely no idea what is actually in there.


5> The only way I can think of, to find the address of the data segment is
to have the process take the address of some global variable, say "me" and
then (((int)&me) div 8192) * 8192 should give the address (I think).

Obviously, this is not a nice way of doing it, and there must be a better
way (dbx could not do this as it requires the cooperation of the process).

Why is it that PTRACE has to use such an grotty scheme.  I would have
thought it would be much easier to access each of the segments from a base
address of 0, and have the call map it into the correct physical/virtual
address.

If you know of any information that could point me towards sanity, then
please mail your experience to me.  I will colate the replies I get and
post them.

thanx in advance
| \o/        Anthony Murdoch             ant@batserver.cs.uq.oz
| -O- ant    Dept of Computer Science    "It's great to be young and insane"
| /0\        University of Queensland     - Dream Team

steve@mullian.ee.mu.oz.au (Steve Mabbs) (10/12/89)

I'm using ptrace(2) to trace memory references on a sun4 during program
execution.  Ptrace allows you to read the registers into a structure,
which is defined in reg.h, as follows:

	#include machine/reg.h
	struct regs registers;
	ptrace(GETREGS, pid, &registers);

	etc.....

It seems, though, (looking at reg.h) that only the global registers and
the 'out' registers of the current window can be read by this ptrace call.
I need to be able to look at all the registers to form the effective
addresses of the memory load/stores.  Is there any easy way of examining
the contents of the 'ins' and 'locals' either by using ptrace(GETREGS) or
ptrace(PEEKDATA)?

(There is already a structure called rwindow defined in reg.h, but there
is no mention of this in the ptrace manual page.  Also, gdb declares a
structure (local_and_ins) as rwindow in sparc-dep.c, but doesn't seem to
use it anywhere)

Stephen A. Mabbs
Dept of Electrical and Electronic Engineering
University of Melbourne	
PARKVILLE VIC 3052
AUSTRALIA		INTERNET/ARPANET: steve@mullian.ee.mu.OZ.AU

paulm@Solbourne.COM (Paul Maybee) (10/17/89)

>(There is already a structure called rwindow defined in reg.h, but there
>is no mention of this in the ptrace manual page.  Also, gdb declares a
>structure (local_and_ins) as rwindow in sparc-dep.c, but doesn't seem to
>use it anywhere)

The top of the stack contains the current ins and outs in structure
rwindow. If you read this using PTRACE PEEKDATA or READDATA you should
have all the regsiters for the outermost stack frame.

-paul maybee