CFA: pseudo-reloc v2

Charles Wilson cygwin@cwilson.fastmail.fm
Mon Oct 5 05:08:00 GMT 2009


Corinna wrote:
> Here's another idea.  At one point Brian Dessent proposed a patch to
> detect a missing DLL.  Hmm, yes, here's the checkin of your patch
> implementing that, back on 2008-03-26.
> 
> I was wondering if a similar technique could be used to print an error
> message in the parent process, if the relocation failed in the child
> process.  The idea would be to generate a specific status code which
> would then catched in status_exit, just like STATUS_DLL_NOT_FOUND.

There are three error cases under consideration:
#1)  invalid pseudo_reloc version number. Right now, this uses printf
(ick!).  If we go Corinna's route (with or without also using
WriteConsole) -- how about STATUS_ILLEGAL_DLL_RELOCATION?

#2) invalid address (we can't access the specified page), which is
currently checked by 'assert (VirtualQuery (addr, &b, sizeof(b)));'.

For this, how about STATUS_NOT_MAPPED_VIEW (0xC0000019, which needs to
be added to ntdll.h). Aocording to:
http://msdn.microsoft.com/en-us/library/cc704588(PROT.10).aspx
this code means "The address range to unmap is not a mapped view." (Ok,
we're not actually trying to unmap, but VirtualQuery doesn't set an
error number on 'error' -- it just returns 0. But the only way that
would happen, I think, is if the address itself isn't mapped --
hence...NOT_MAPPED_VIEW.

Unless we want to use STATUS_ILLEGAL_DLL_RELOCATION for this, too --
which might be the smarter way to go, since then we can catch both cases
with the same code in sigproc.c and pinfo.c.

#3) there's also a non-fatal DEBUG printf.



One downside of using WriteConsole[W] is that you'll never see the
message if you're running in a terminal other than cmd.exe, nor if
you're launching the app via a shortcut. The output will go to the
"invisible" console allocated by cygwin, right?

> I'm just not sure how to generate that specific status code...

Yeah, that...

cgf suggests ExitProcess. I tried that, but the process hangs when it
calls that function. I think this has to do with the fact that
ExitProcess goes back thru the loaded DLL list and tries to call the
entry points with DLL_PROCESS_DETACH. But, since the (current) DLL is
fubared...

Now, TerminateProcess seems to work -- but then NONE of the DLLs get
notified. Oh -- and it hangs if you strace within any terminal except
cmd.exe; the strace output is identical in the two cases, but the
non-cmd one has this extra line at the end:
29661   30435 [sig] crtest_v1 4692 wait_sig: entering ReadFile loop,
my_readsig 0x17C, my_sendsig 0x180
and then it hangs.

Wierd.

> Other than that, I have no problems to use WriteConsole.

So...maybe something like the following?  This is a diff against the
current mingw/pseudo-reloc.c.  The "normal" code path (that is, none of
the error conditions are hit) works fine.

The rest of this email is about the error cases.

I tested the error path by reversing the test at line 110. In an rxvt
window, I got the following behavior:

$ ./crtest_v2.exe
$ echo $?
0

In a cmd.exe window, this is what I observerd:

$ ./crtest_v2.exe
Relocation error: bad address specified 0x00401139.
$ echo $?
0

I also attempted to modify pinfo.cc and sigproc.cc bits following Dave's
suggestion, partly so that these reloc errors would result in a 127 exit
code, just like cgf/brian's mod for STATUS_DLL_NOT_FOUND.  But I
couldn't get it to "trigger" -- I didn't get the error message I
specified in pinfo.cc, and I still got an exit code 0, not 127.  Then, I
tried this:

--------------- foo.c -----------------
#include <stdio.h>
#include <windows.h>
#include <ntdef.h>

#define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xc0000269)
#define STATUS_DLL_NOT_FOUND          ((NTSTATUS) 0xc0000135)

int main(int argc, char* argv[])
{
  TerminateProcess (GetCurrentProcess(), STATUS_ILLEGAL_DLL_RELOCATION);
  exit (1);
}
---------------------------------------

With cygwin1.dll having the modified pinfo/sigproc, and launching this
test program from bash, I would *expect* to see the message from my
patched pinfo.cc: "foo.exe: error while loading shared libraries: ?:
cannot open shared object file: illegal relocation" (there's a '?'
because this silly test program doesn't have an 'unloaded DLL' name to
put there).

If I understand the pinfo code, it's actually the *parent* process that
receives the err code >= 0xc0000000, and prints the
DLL_NOT_FOUND/ILLEGAL_DLL_RELOCATION error message.  That is, bash.

However:
$ gcc -o foo.exe foo.c
$ ./foo.exe
$ echo $?
0
(NOT 127, and NOT 1 !)

But, if I use gcc-3 -mno-cygwin:
$ gcc-3 -mno-cygwin -o foo.exe  foo.c
$ ./foo.exe
/usr/src/devel/kernel/pseudo-reloc-tests/test-app/foo.exe: error while
loading shared libraries: ?: cannot open shared object file: illegal
relocation
$ echo $?
127

which is what I expected to see in all cases.  Just to verify that it is
not a gcc-3/gcc-4 thing:

$ gcc-3 -o foo.exe  foo.c
$ ./foo.exe
$ echo $?
0

So, it's a "cygwin" thing: if the child is a cygwin app, then the
pinfo::maybe_set_exit_code_from_windows --> status_exit() code path is
NOT hit at all.  That's just weird. Help?

--
Chuck

-------------- next part --------------
A non-text attachment was scrubbed...
Name: pseudo-reloc-2.patch
Type: application/x-patch
Size: 3666 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-developers/attachments/20091005/e6d16e4a/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: status_illegal_dll_reloc.patch
Type: application/x-patch
Size: 1338 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-developers/attachments/20091005/e6d16e4a/attachment-0001.bin>


More information about the Cygwin-developers mailing list