dxe: page fault when derefencing an exported pointer variable
The project in question is libmikmod along with its mikmod player: https://github.com/sezero/mikmod
The libmikmod library exports many functions and variables, only
one of those variables is a pointer: https://github.com/sezero/mikmod/blob/master/libmikmod/playercode/mdriver.c#L51
The 'normal' vars don't seem to have a problem, but dereferencing
that particular pointer results in a page fault: https://github.com/sezero/mikmod/blob/master/mikmod/src/display.c#L338-L339
At time of dereferencing the pointer is not actually NULL, because
if I write an accessor returning that pointer and export and use it
then things work. (Yes, the library and its api are a mess, I know)
Using dxe3gen from CVS -- can give instructions to reproduce / test
if requested.
Anyone has an insight, please?
The 'normal' vars don't seem to have a problem, but dereferencing
that particular pointer results in a page fault:
Well, I was very very wrong:
I added some debug printf() statements to a simple program, so that
it prints the values of certain variables exported by the library :
UBYTE md_volume : 233 (0xe9) --- should have been 128
UBYTE md_musicvolume : 233 (0xe9) --- should have been 128
UBYTE md_sndfxvolume : 233 (0xe9) --- should have been 128
UBYTE md_reverb : 233 (0xe9) --- should have been 0
UBYTE md_pansep : 233 (0xe9) --- should have been 128
UWORD md_mixfreq : 44100
UWORD md_mode : 63977 (0xf9e9) --- should have been 0x110F
UWORD md_device : 9705 (0x25e9) --- should have been ???
MDRIVER* md_driver : 0xcea27e9
CHAR* md_driver->Name: [crash...]
Note that all of those values have 0xe9 - except for md_mixfreq to
which I do assign 44100. 0xe9 (i.e.: jmp) seems to be coming from dlstatbind(): https://www.delorie.com/bin/cvsweb.cgi/djgpp/src/libc/dxe/dxe3stat.c?rev=1.1
Looks like exported variables support in import libraries is very
much broken?
I believe this is because of how variables are exported (as opposed to functions).
Things are quite foggy after all those years, but for COFF, you are actually getting a _pointer_ to a variable. That is, in your case a _pointer_ to the desired pointer (that's why having a getter for the pointer solves it). I know this is *not* how it works when you are compiling statically, but it is a limitation of the executable format. I also think this limitation applies to the original DXE (as designed by Charles W Sandmann) not only for my
DXE3. BTW, the COFF used by DJGPP is not even Windows COFF.
TL;DR: you have to dereference that pointer twice. I am not sure it can be handled transparently as long as DJGPP was COFF-based.
That's why I "invented" DJELF back then. The ELF executable format has a special kind of relocation (perhaps it was called R_<arch>_COPY or something like that) which would solve this issue magically, but then you are restricted to ELF.
-dborca
The 'normal' vars don't seem to have a problem, but dereferencing
that particular pointer results in a page fault:
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 431 |
Nodes: | 16 (3 / 13) |
Uptime: | 156:41:48 |
Calls: | 9,071 |
Calls today: | 1 |
Files: | 13,402 |
Messages: | 6,020,581 |