Subject: Re: multi-thread debugging
From: [email-masked] (root)

6 Nov 1996 15:50:56 -0800
Sender: [email-masked]
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Content-Type: text
Original-To: [email-masked] (Michel Dagenais)
Original-Cc: [email-masked]
In-Reply-To: <[email-masked]> from "Michel Dagenais" at Nov 6, 96 09:23:17 am
Content-Length: 2952      
Original-Sender: [email-masked]

I am still writing my debugger, and in this context, I just do that for each
thread: When I receive the event that a thread starts, I store the
info to be able to switch to the good context later. This looks very easy
to say, but not so easy to do... If it is not done in gdb is because of that
I suppose... You have to handle thread termination and do the cleanup too of
course.

In this 'context', I would like to know how gdb solves the problem of a trap in 
ntdll.dll for instance. Problem is, ebp (the frame pointer) is used in that
dll as a normal register, and can have values that do not point to the current
stack frame at all, mainly because there is no stack frame! it has been optimized
in hand-written assembly! I haven't found any solution for this problem.

One solution is obviously to read the whole stack in, and see which values
(in a vector that can be 4-5 thousand integers long) 'look' like pointers to
return addresses, look at those return addresses in the code, see if there is a 
call instruction before, and working from there, etc etc. Is this at all
possible?

For the time being my debugger is happy to tell you that your program crashed
in ntdll.dll, and disassemble a bit of it. Then you have to mannually look
for sequences like
pop esi
pop edi
pop ebp
ret 5
and position the ordinal counter (eip) at the desired assembly instruction
where you want to resume execution. Then you go on, crossing fingers... This
is not very user-friendly (a good knowledge of assembly is essential) and 
doesn't always work, because you can trash esp, and then all is dead, even
the debugger...

Another solution would be that the debugger pokes around in the import
table and plants a breakpoint at each call to a dll. I would save the context
away before jumping into system code. If there is a trap I would have all
context previously saved. Problem is, this would slow things down drastically,
just look at the speed of bchkw from nu-mega when it runs a windows program:
it will make a 8088 from a pentium!

Of course bchkw makes much more than just plant a breakpoint, checking all
arguments to the dll call. Maybe what I intend to do is feasible... Any
comments?

How did gdb solve that?

Thanks in advance for any info.

P.S. re-reading the message, I think I should state more clearly my problem:

Given a trap in the system code, my debugger receives an address from the
system telling it where it crashed. How do I rebuild the stack frames to get
to the last user-level instruction that called the dll? Please consider that 
I can be several levels down in nested dll calls, and that the contents of
ebp can be bogus...  ESP is right of course but I suspect that the stack that
the system uses is different from the normal stack of the program being
debugged.

What an idea to write a debugger!

-- 
Jacob Navia	Logiciels/Informatique
41 rue Maurice Ravel			Tel (1) 48.23.51.44
93430 Villetaneuse 			Fax (1) 48.23.95.39
France
-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".