From: root AT jacob DOT remcomp DOT fr (root) Subject: Re: multi-thread debugging 6 Nov 1996 15:50:56 -0800 Sender: daemon AT cygnus DOT com Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: Content-Type: text Original-To: dagenais AT vlsi DOT polymtl DOT ca (Michel Dagenais) Original-Cc: gnu-win32 AT cygnus DOT com In-Reply-To: <9611061423.AA21688@gutrune.vlsi.polymtl.ca> from "Michel Dagenais" at Nov 6, 96 09:23:17 am Content-Length: 2952 Original-Sender: owner-gnu-win32 AT cygnus DOT com 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 "gnu-win32-request AT cygnus DOT com" with one line of text: "help".