push OFFSET MyHandler ;New handler
push fs:[0] ;Previous handler
mov fs:[0],esp ;Install new
<exception cause goes here>
pop fs:0 ;Restore previous
add esp,4 ;Clean stack
Even if I do nothing at all in MyHandler (besides
remove the cause of the exception or adjust EIP to
skip it on return), the same crash happens under
Vista64 only.
I haven't been able to find info on the CONTEXT
structure in Wow64, but just in case it is
different I tried removing the cause of the
exception by rewriting the opcode instead of
trying to adjust registers in the CONTEXT.
It occurs to me that this might not be a 64-bit
problem, so much as a case of Vista64 getting more
aggressive about security than Vista32, and
perhaps enforcing pre-registration of the handler
(SafeSEH). I haven't needed that before, so I'm
still looking into how to do that in assembler.
Any ideas or info would be greatly appreciated!
Best regards,
Bob Masta
DAQARTA v4.51
Data AcQuisition And Real-Time Analysis
www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
FREE Signal Generator
Science with your sound card!
Hi Bob,
I don't "do Windows" and know nothing about it, but I note an item in
the Nasm manual on the subject:
<http://www.nasm.us/doc/nasmdoc7.html#section-7.6.2>
After "completely different matter", I don't understand a word it
says... but maybe would give you some clue(?).
Best,
Frank
Frank, I think that "completely different matter"
section pertains only to Win64 code, not Win32
code running under Win64 (Wow64). At least, other
things I have found imply that Win32 code should
run OK on Win64 as long as SafeSEH is used.
I've found enough info on the Web to be ready to
try SafeSEH. My problem now is that my project is
written in MASM32, which uses old versions of
ml.exe and link.exe that don't support SafeSEH.
Since my EXE is large (over 300k), I'm not
inclined to try converting to NASM or something
else at this late stage.
I actually have the latest versions of ml.exe and
link.exe from the Vista SDK, but they no longer
work from the command line... apparently they need
to be run from within the VC IDE. I don't know if
that is also in the SDK, but even if it is I
suspect that there would be plenty of conversion
problems pertaining to doing things the VC way
regarding headers, includes, decoration, etc.
I'm *almost* willing to add the needed SafeSEH
section to the PE myself... but I don't even have
an example to copy, let alone the new PE format
specs. So for now I am seriously thinking of
abandoning SEH entirely, unless some miraculous
breakthrough arrives in the next week or so. <g>
> I'm *almost* willing to add the needed SafeSEH
> section to the PE myself... but I don't even have
> an example to copy, let alone the new PE format
> specs. =A0So for now I am seriously thinking of
> abandoning SEH entirely, unless some miraculous
> breakthrough arrives in the next week or so. =A0<g>
You can try out JWasm v2.0 (http://www.japheth.de/JWasm.html)
I probably wouldn't try to compile your whole project with JWasm, but
AFAIK all what's needed is a small "stub" which must be assembled and
added to the link step:
;----------------------------------
.386
.model flat,stdcall
extern mysehhandler1:proc
extern mysehhandler2:proc
.safeseh mysehhandler1
.safeseh mysehhandler2
end
;----------------------------------
@echo off
call "%ProgramFiles%\Microsoft Visual Studio 9.0\vc\vcvarsall.bat" x86
"%ProgramFiles%\Microsoft Visual Studio 9.0\vc\bin\ml.exe" %1 %2 %3 %4 %5 %6
%7 %8 %9
Put it in a file called ml.bat or ml.cmd and assuming you use the same paths
as me it should work.
Thanks for this. Is "vcvarsall.bat" something
that I also need to create?
Can I use a similar approach to operate link.exe
from a bat file?
Thanks again, and best regards,
Thank you. This is a great point... I don't
really need to reassemble all my code, just the
SafeSEH handler.
I still need a linker that can handle SafeSEH.
Any recommendations?
Not sure what version that is. I've got from ml.exe from a 2003
DDK. There's a setenv.bat file dated 2005 which probably came
with that DDK. Not sure we can trust the year for the version,
though as the date on the ml.exe file is 2005 too. For some odd
reason I placed it inside a folder named 2003.
ml.exe is located in an x86 folder and reports:
03/24/2005 04:25 PM 413,696 ml.exe
<snip>
Microsoft (R) Macro Assembler Version 7.10.4035
Copyright (C) Microsoft Corporation. All rights reserved.
usage: ML [ options ] filelist [ /link linkoptions]
Run "ML /help" or "ML /?" for more info
</snip>
I'll attach the setenv.bat file.
"Bob Masta" <N0S...@daqarta.com> wrote...
: Can I use a similar approach to operate link.exe
: from a bat file?
:
: Thanks again, and best regards,
The link.exe with this particular version provides:
03/24/2005 04:25 PM 647,168 link.exe
Microsoft (R) Incremental Linker Version 7.10.4035
Copyright (C) Microsoft Corporation. All rights reserved.
usage: LINK [options] [files] [@commandfile]
IF you want a copy of this version of the DDK let me know.
It came with a number of batch files. Some set paths based upon
the target system, for instance you compile for wxp, w2k, w64 or
wnet. It may have been the last version with a lib16 folder for
support for 16-bit applications.
It appears to be the same version of the compiler that came with
WKMDF 1.1?
Microsoft (R) Macro Assembler Version 7.10.4035
Copyright (C) Microsoft Corporation. All rights reserved.
03/24/2005 05:25 PM 413,696 ml.exe
Comparing files ml.exe and ML.EXE
FC: no differences encountered
Comparing files link.exe and LINK.EXE
FC: no differences encountered
Don't know if any of that helps you at all with SEH.
As far as Vista goes, the extra security seems to involve
preventing files from registering themselves. As for getting
such a thing done, in the past we used regsvr32.exe to do it.
I have not messed with VISTA yet, so someone else needs to provide
some comments on that. Some suggestions and/or details about such
things would help me and I look forward to reading comments on it.
Registering those types of files tends to mean .ocx (ActiveX). The
.ocx files get placed in directories all over the place, and thus
the registration of that file identifies where the file resides as
well as identifying that funny 64-bit(?) key that gets tied to it.
Unfortunately, because I do not mess with VISTA systems, that's
about as far as I go.
I might be able to find MS links to the KMDF (Kernel Mode Driver
Framework 1.1 - a DDK) or the 2005 DDK.
--
Jim Carlock
North Carolina Swimming Pool Contractors
http://www.aquaticcreationsnc.com/
<snip>
The following was taken from the KMDF/DDK Documentation (to run
this help from the command-line, you need the HTML Help compiler
{hh.exe} and the name of the help file is (winddk.col).Search for
exception, as searching for SEH only turns up one link, the link
below.
x64 Compiler Limitations
The compiler for x64-based processors has the following known
limitations:
* No support for the /clr switch. The compiler for x64-based
processors only generates native code.
* No support for MMX intrinsic functions.
* No support for run-time checks using the /RTC switch.
* No support for security checks using the /GS switch.
* The _frnd function does not work with arguments whose absolute
values are greater than MAX_INT.
* Inlining into SEH filters can result in invalid code if you
use the GetExceptionCode or GetExceptionInfo functions. The
symptom could be an executable file that terminates without a
dialog box.
//Avoid using GetExceptionInfo() for this structure
__inline void funca(DWORD);
__try {
...
} except(funca(GetExceptionCode()))
{
...
}
//Instead use the compiler switch /Ob0 to disable inlining or use:
__declspec(noinline)
// On a class member function if there is a problem
* Two special cases of the va_start usage and one special case
of va_arg usage are not currently supported.
Define class string as follows:
class String1 {
public:
String1 (const String1 &);
...
};
class String2 {
...
};
Note that String1 has a copy constructor, and String2 could
be any class. The following two cases of va_start are not
supported:
<any type> foo1(const String1 last_parameter_with_known_type, ...)
{
va_list arg_list;
va_start(arg_list, last_parameter_with_known_type);
...
}
<any type> foo2(const String2 &last_parameter_with_known_type, ...)
{
va_list arg_list;
va_start(arg_list, last_parameter_with_known_type);
...
}
va_start calls are not supported if:
* Last parameter with known type is an object of class with
default copy constructor (the constructor is called to create
a copy of object to pass the copy to function foo1).
* Last parameter with known type is an object passed by
reference.
The following case of va_arg usage is not supported (see
the previous String1 definition):
<any type> foo3(<any type> last_parameter_with_known_type, ...)
<any type> foo4( )
{
String1 q;
foo3(last_parameter_with_known_type, q);
}
The passing of an object of class with default copy
constructor in the "..." part of parameters is not supported.
It does not matter in the previous example if q is a local,
global, or temporary variable.
The fourth case is not supported with object passed by
reference in "...", because there are no language-supported
ways to do that. The only proposed workaround is to change
specifications of foo1, foo2, foo3, and so on to those ones
that accept pointers to objects instead.
* Fatal error C1128: <func:#> object file format limit
exceeded: more than 64-KB sections can occur if a file
contains many functions. Remove -Gy or split up the file so
it contains fewer functions. Removing -Zi or -Z7 also
removes a lot of sections, because if -Gy is applied,
-Zi forces emission of a .debug$S section for each .text
section included.
* _asm is not supported for x64-based compilers. All assembly
code must be written in a separate file, or intrinsic
functions must be used.
</snip>
vcvarsall.bat should already exists (I only have the free VC 2008 express
edition so I can't confirm). For assembling 64-bit code supply it with x64
instead of x86.
For link.exe just make another .bat file called link.bat and replace ml.exe
in it with link.exe. Put the bach files in the windows\system32 directory
and you can run them from anywhere.
Ps. .bat files are executed after .exe files so if link.bat doesn't execute
check if you have a link.exe in one of the %path% folders. You can check
what's in %path% by writing "path" on the command line. Search order is from
the first folder to the last, so for instance if link.exe is in the same or
in a folder before link.bat then link.bat won't execute.
Good luck.
Bob,
If that were true, tons of legacy applications would fail under WOW64.
They do not. Therefore, there has got to be a simpler reason why your
code would crash.
If you install Visual C++ Express 2008 SP1 it will install
MASM 9 and provide you with an already configured command
prompt which allows you to use MASM from the command line
and thus avoid any problems associated with doing things through
the IDE.
Well, this *is* a "legacy application" as far as
WOW64 goes, and runs fine under all 32-bit
versions from Win95 through Vista32. If I leave in
the legacy SEH as shown in my initial post, WOW64
crashes... even if modified so the SEH doesn't do
anything (other than prevent the exception from
happening again on return).
I haven't tested under XP-64.
Lack of SafeSEH is the only thing I can think of,
but I would certainly welcome other ideas!
Follow-up:
1) I was mistaken about the ml.exe and link.exe
versions in the Vista SDK not working from the
command line... they work fine, on the Vista
machine where they were installed, just not when
moved to my XP development system. There, I get
"Windows can not run this program". I had read on
the Web something about ml.exe v7.xx and later
only running in the IDE, and assumed that's what
it was. (The Vista SDK version is 8.xx.)
2) I used the code Japeth provided (thanks!) and
it assembled OK.
3) Linking was another issue. The MASM32 libs
were not compatible with SAFESEH, so I modified
all the includelib lines in my main code to use
the SDK libs, and the linker was happy with those.
4) Alas, the linker was *not* happy with my main
code... said it was "unsafe for SAFESEH". No
explanation, but I suspect that the problem is my
using a combined code and data section linked with
ERW privileges. I use this to allow
self-modification. (No, this does not run afoul
of hardware DEP.)
So, I'm throwing in the towel on SafeSEH for now.
If anyone has any insights on how to run under
WOW64 without SafeSEH (assuming that's the problem
here), I'd be delighted to hear.
Thanks to everyone for the help, and best regards.
I still don't see why that _should_ be the problem. There are gazillions
of legacy applications using SEH, and whose creators didn't even know
how to _spell_ "SafeSEH".
And they all work fine in WOW64.
What am I missing?
....Or what am *I* missing? <g> However, I recall
that when XP-64 first came out, a colleague asked
if I had any ideas why Win32 apps wouldn't work on
XP-64... seems one of his clients just *had* to
have the latest and greatest OS, and the result
was that many of his existing apps wouldn't run on
it. I suggested driver problems, but he seemed to
think that was not the explanation. Never did
hear the final outcome.
Also, I don't know how many apps actually use SEH
in the first place. I suspect that for the vast
majority, it's not used at all. In most cases
it's easy enough to pre-check for divide overflow,
etc, and it actually makes for a better app to do
so, IMHO. After all, if you wait and catch this
as an exception, it's a lot harder to handle.
I'd really like to know what percentage of apps
use SEH. It may be that those that actually
needed it made the switch to SafeSEH back when
XP-64 came out.
Best regards,
Odd. I have the Vista SDK right here (October 2006), and all of the tools
(including ml.exe and link.exe) work just fine on my XP SP3 machines.
The Win 7 SDK doesn't include the compiler tools, but the other tools also
run fine on XP SP3.
It IS true that XP checks the operating system version in the PE header,
and will refuse to run an exe that is marked with a version greater than 5,
but that's not the case with the SDK tools.
>I had read on
>the Web something about ml.exe v7.xx and later
>only running in the IDE, and assumed that's what
>it was. (The Vista SDK version is 8.xx.)
8.00.50727.42 in mine. Is that the same one?
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.
>
>N0S...@daqarta.com (Bob Masta) wrote:
>>
>>Follow-up:
>>
>>1) I was mistaken about the ml.exe and link.exe
>>versions in the Vista SDK not working from the
>>command line... they work fine, on the Vista
>>machine where they were installed, just not when
>>moved to my XP development system. There, I get
>>"Windows can not run this program".
>
>Odd. I have the Vista SDK right here (October 2006), and all of the tools
>(including ml.exe and link.exe) work just fine on my XP SP3 machines.
Hmm, did you install the SDK on the XP machine?
In my case, I installed on the Vista machine and
just copied ml.exe and link.exe to XP. Maybe
there were some configuration files or registry
settings that were also needed.
>The Win 7 SDK doesn't include the compiler tools, but the other tools also
>run fine on XP SP3.
>
>It IS true that XP checks the operating system version in the PE header,
>and will refuse to run an exe that is marked with a version greater than 5,
>but that's not the case with the SDK tools.
>
>>I had read on
>>the Web something about ml.exe v7.xx and later
>>only running in the IDE, and assumed that's what
>>it was. (The Vista SDK version is 8.xx.)
>
>8.00.50727.42 in mine. Is that the same one?
>--
That's the one!
Best regards,
I'm pretty sure this is your problem. Since VS 2005, MS uses the
manifest in the exe to specify a specific C runtime version that it
will use. If it can't find that *exact* version, you will get the
error message you are seeing. (See http://blog.koroirc.com/2008/06/visual-c=
pp-woes
). The easiest way around this is to install the SDK on your XP
machine. This will install the correct runtime as part of the install.
--
Paul Carter
OK, I have another hypothesis about existing Win32
apps that use SEH and run under WOW64: I'll bet
that very close to *none* of those apps were
written is assembly, setting SEH by direct
manipulation of the thread area at FS:0. Instead,
they were almost certainly written in an HLL that
used the approved API calls.
The API surely does more than mess with FS:0.
Seems plausible that apps that use the API would
continue to work under WOW64, whereas those using
the unapproved FS:0 trick no longer work.
Someday I may even try using the approved APIs for
this! <g>
Any compiler generated code I've seen so far has this implemented as
direct reads/writes to fs:[0], for decades already.
It might be worth while checking your exception handler code. Just in
case that there _might_ be some flaw inside, which merely didn't strike
in pure Win32.
Legacy SEH in WOW64 is fine, really!
I would *love* this to be a problem with my code,
since then I'd just have to fix that! But I've
run out of places to look...
As I mentioned in my initial post, I get a WOW64
crash even with a trivial handler that does
nothing more than remove the cause of the
exception before returning. My first thought was
that maybe WOW64 put the register images in
different locations in FS:0, which would have
explained why adjusting EIP to skip the exception
instruction, or adjusting (say) EAX to prevent a
DIV overflow, would have failed. So just to be
absolutely sure, I tried a modified handler that
simply overwrote the exception instruction (INT3)
with NOP, avoiding all need to mess with register
images at FS:0. The handler was just:
mov Do_INT3,90h
xor eax,eax
ret
where Do_INT3 is the location of the INT3 opcode.
Same failure on WOW64, no problem on XP or
Vista32. Doesn't seem to be much room for a bug
to hide in there, but if you can find one, I'm all
ears!
Another thought: Maybe legacy SEH in WOW64 only
works in "normal" separate data and code sections,
which I suppose all that legacy code uses. Maybe
it only gags on combined code and data, which I
use. Grasping at straws here...