Mail Archives: djgpp-workers/2001/03/22/01:15:02
Hello.
I've recently begun work on a core dumping facility for DJGPP. This would
allow DJGPP users to do post-mortem debugging of their programs. This is
particularly useful for debugging programs that use Allegro or other
graphics-based programs with GDB.
I've been discussing this with Eli and, with his guidance, I've been
working on it for about three weeks now. He also pointed out an old post by
George Foot about post-mortem debugging on the DJGPP mailing-list archives.
George had already written the core dumping facility along with a primitive
(yet functional) command-line debugger. However, his work was a bit
incomplete. He was kind enough to provide me with his sources and let me
work on improving it.
I did not attach those sources (with some changes I made) because the 26K
zip file might annoy some of you here, but if you want I can send it to you
in a separate post.
Anyway, here's what GF's code does:
It is a module that you link with your program, assuming you also compiled
it with debugging info. In your program, you call a function that will hook
your specified signal with the core dumper. The core dumper properly chains
to an existing signal handler if you want it to. For example, you can hook
SIGSEGV to the core dumper and tell it to chain to the old handler. If the
old handler is __djgpp_traceback_exit(), it will call that handler after
the core is dumped. This allows one to see a traceback screen, as usual,
and get a core dump as well.
As for the core file and the way it's laid out, here's an excerpt from GF's
Readme.txt:
Core files start with a six-byte ID string (`pmdbcd', for
"post mortem debugger core dump"). This is followed by a
two-byte version number (major, minor).
After that header the file is divided into sections. Each
has a four-character ID string, followed by a 32-bit size
value, then that number of data bytes.
All multi-byte numbers are little-endian.
The sections currently used are:
file: Stores the filename of the executable (from
argv[0]). It's not NULL-terminated.
sgnl: Information about the signal that was raised.
Three 32-bit numbers. The first is the signal
as passed to the handler. The second is the
__signum field of the exception state variable;
this gives more information about the error in
some cases. The third is the __sigmask field;
I'm not sure what it's for.
regs: Register contents -- 32 bits each for eax, ebx,
ecx, edx, esi, edi, ebp, esp. I'll add some
others too sometime.
sels: Selector details -- handles, base addresses and
limits for cs, ds, es, fs, gs and ss. All 32-bit,
stored in that order (i.e. cs handle, cs address,
cs limit, ds handle, ...).
cftb: Call frame traceback. This is just a list of
32-bit offsets.
blks: DPMI memory block information. For each memory
block, the base address, size (guessed) and chunk
count are stored as 32-bit numbers. The chunk
count is the number of 64K chunks of this block
which were dumped to the `data' section.
data: Memory dump. This is just a big block of data.
It holds the first DPMI memory block's chunks
first, then the second's, etc.
end.: This has zero data size, and just marks the end
of the file.
What's missing in the regs section is the value of eip. I've looked into
dpmiexcp.c to see how __djgpp_traceback_exit() does this, and this is what
I've written:
if (__djgpp_exception_state == fake_exception
&& __djgpp_exception_state -> __cs == _my_cs()
&& (unsigned)__djgpp_exception_state -> __ebp
>= __djgpp_exception_state -> __esp
&& (unsigned *)__djgpp_exception_state -> __ebp >= &end
&& (unsigned *)__djgpp_exception_state -> __ebp
< (unsigned *)__djgpp_selector_limit)
_writei4 (corefile, *((unsigned *)__djgpp_exception_state -> __ebp + 1));
else
_writei4 (corefile, __djgpp_exception_state -> __eip);
which is basically what the code in dpmiexcp does, except the value of eip
is written to an open file. The eip is correctly written for signals other
than the fake signal SIGABRT (well for SIGSEGV anyway, eip is correctly
written). I also noticed discrepancies in the values of the registers eax,
ecx, edx, esi, edi, ebp, and esp. There's a big difference between the ones
generated by the traceback and the ones stored in the core file, this
apparently happens for fake signal SIGABRT, doesn't seem to happen for
SIGSEGV.
This is one of the test program's results:
DJGPP traceback
----- cut here -----
Exiting due to signal SIGABRT
Raised at eip=00004e96
eax=00090224 ebx=00000120 ecx=0000047c edx=0000d568 esi=00000007 edi=00000018
ebp=000902d0 esp=00090220 program=C:\STUFF\PROJECTS\PMDB\COREDUMP\ABRT.EXE
cs: sel=00f7 base=83744000 limit=0009ffff
ds: sel=00ff base=83744000 limit=0009ffff
es: sel=00ff base=83744000 limit=0009ffff
fs: sel=00d7 base=0000de20 limit=0000ffff
gs: sel=010f base=00000000 limit=0010ffff
ss: sel=00ff base=83744000 limit=0009ffff
App stack: [0009046c..0001046c] Exceptn stack: [000103cc..0000e48c]
Call frame traceback EIPs:
0x00004db4
0x00004e96
0x00002756
0x00004e9b
0x0000410b
0x0000157b
0x0000158f
0x0000159f
0x000015c1
0x00003d02
----- cut here -----
This is the output from pmdb (GF's pm debugger), given the `i' command:
----- cut here -----
reading exe file `C:\STUFF\PROJECTS\PMDB\COREDUMP\ABRT.EXE'...
For help use the `h'elp command.
pmdb command: i
Signal:
@ eip = 4e91
sig = 0120 SIGABRT
num = 007b
error = 00ff
Registers:
eax: 00090334 ebx: 00000120 ecx: 00000000 edx: 0000de20
esi: 00000054 edi: 0001046c ebp: 000903e0 esp: 000902e8
Selectors:
cs: 00f7 (base = 83744000, limit = 0009ffff)
ds: 00ff (base = 83744000, limit = 0009ffff)
es: 00ff (base = 83744000, limit = 0009ffff)
fs: 00d7 (base = 0000de20, limit = 0000ffff)
gs: 010f (base = 00000000, limit = 0010ffff)
ss: 00ff (base = 83744000, limit = 0009ffff)
pmdb command:
----- cut here -----
In it's current state, the code works fine for SIGSEGV and SIGFPE. The
values of the regs are correct. The core file now also includes the
environment variables inherited by the running program. I just dump the
``invisible'' DJGPP global `environ'.
Again, if you need the sources, I'll be more than happy to send them to you.
Thanks for reading this.
nimrod_a_abing
--------------
+========================================+
| Home page: www.geocities.com/n_abing |
+========================================+
"Tinimbang ka ngunit kulang."
If you understand that phrase, i-email mo'ko. ;-)
- Raw text -