Why are some error messages in executable binary - windows

Answering another question about how const string data was stored in an executable a question occured: Why are run time error messages stored in the executable rather than generated by the OS?
!This program cannot be run in DOS mode.
Seems reasonable, DOS can't be expected to detect a newer Windows app and generate an appropriate error message. Some others about stack frame corrupted might also occur when your program is in a state where it can't reliably communicate with an OS function
But some make no sense:
- Attempt to use MSIL code from this assembly during native code initialization...etc..
If I was trying to call a .Net assembly (which I don't - this is pure C++ code) surely the .Net or OS runtime could manage to generate the error message itself.
And the file system error messages are also in the exe. Surely I want these errors to be generated by the OS at run time - if the app is being run on a non-english version of Windows don't I want system errors to reflect that language rather than the one I used to compile it?
Just a Friday afternoon sort of question but there doesn't seem to be anything about it on Raymond Chen's site

The examples I know of are stubs that are placed specifically because there isn't a good way for the OS or some runtime to produce the error. Also, they are fundamental problems with the implementation, not the types of errors a user should ever see.
The DOS one is a perfect example. There's no way for DOS to recognize a Windows program and produce a reasonable error, so the stub code is included in Windows programs.
Your MSIL one is very similar. How can the runtime produce this error if the runtime isn't actually loaded (because the program is still initializing)?
Another example I can think of are "Pure virtual function called" in C++ programs. The abstract base class vtables are filled with stubs that emit this message. I suppose they could be stubs that make an OS call to produce the same message, but that seems like overkill for something that's never supposed to happen.
There's a similar problem if you try to call into the floating point library from a native C or C++ program that isn't actually linked against the floating point library. This is essentially a floating-point implementation detail of the language runtime library (in cooperation with the compiler and the linker). It's not an OS-level issue (in the sense that something like "file not found" is).

It's so you can globalise your application.
E.g
Ivan can have the error messages in Russian even though it's running on a French OS.

I'm guessing this is code pulled in by the CRT, try compiling a test application that does not link with the default libraries and use mainCRTstartup as the entry point, then the only string should be the error message in the DOS stub.

Related

Error Bad Calling Convention when debugging vb6 program

I have a standard VB 6 exe (mailviewer).
This program has a "link" to a cobol DLL:
Declare Sub InkMvwMail Lib "inkvwm" Alias "INKMVWMAIL" ...
When starting the normal exe from windows,
EVERYTHING WORKS FINE,
but when I want to debug the call to the cobol DLL entry point in Visual Studio 6.0 (SP6) (on windows xp), I get
"Error 49, Bad Calling Convention"
Thanks for any help in advance
Wolfgang
EVERYTHING WORKS FINE,
No, it only looks that way. Everything is not fine, that Cobol function was designed to be called from a C program. It has the wrong calling convention, cdecl instead of stdcall. The stack imbalance that's caused by this can cause extremely hard to diagnose runtime failure, like local variables mysteriously having the wrong value and includes the hard crash for which this site is named.
When you run from the IDE, the debugger performs an extra check to verify that the stack pointer is properly restored across the function call. It is not, thus generating the error 49 diagnostic.
You'll need to follow the guidance in this KB article. It cannot be solved in VB6, this requires writing a little helper function in another language that can make cdecl calls, like C or C++. The KB article shows what such a function could look like, although they intentionally gave it the wrong convention to demonstrate the problem.

Change in display languages to Turkish results in "80070002" errors in COM Interop

I'm utterly stumped, so what I'm looking for is a body of speculation. Or maybe someone actually knows what's going on.
I have a program written in VB6 which has had every user interface element font set to "MS Sans Serif, 7 point", in an effort to create an English/Turkish localization. The localized strings are compiled into the VB6 EXE, and there is custom code to do the hot-switching between languages.
The program reaches through COM to a .NET DLL assembly which carries a "tr" satellite assembly with it, so that is also in the mix.
With a clean test system set with the display language (NOT the non-unicode setting, the other, more general one) to "English" the software runs without problems.
When it is set to Turkish, the .NET Interop system returns "Run-time error '-2147024894 (80070002)' -- Automation error -- The system cannot find the file specified." as soon as (it appears) the .NET DLL is called. (EDIT: This may not be the .NET DLL. I've opened an incident with Microsoft for more information from a deep trace.)
Because this is a clean-system test, there were no diagnostic tools installed, but a trace with Sysinternals ProcMon failed to show me something I could recognize.
The question becomes: Is that the right tool to go tracing my obscure little "file not found" error? Are there better tools? What should I be looking for?
But most fundamentally, does anyone know what changes when the display language changes, that would cause either a VB6 EXE or an Interop DLL to fail?
(EDIT) -- I have now tested this with five different display languages; only Turkish is failing.
I bet you have an I (i) in there!
I don't know how you are loading your DLLs, or if you've changed just the UI Thread or the worker threads' culture to Turkish, so I might be off a little, BUT...
Double check any file loads, any paths, and strings of importance etc. If they have an i, I in them, and you are using case operations (to lower, to upper) it will all go wrong with Turkish language.
We had a similar issue with our .net app and it's a pain to fix and go round using a specific culture for some things, but you can't trust to upper or to lower and the turkish language!
good luck.
I cannot account for the source of this error. Instead, after removing an "AMUS" directive from the installer, the error no longer occurs after installation. According to Microsoft's summary of the problem after I did some testing and couldn't reproduce it any longer:
The theory is there was something wrong with your install package (MSI
packaged using InstallShield). You were using the “REINSTALL=AMUS”
install setting which is a dangerous setting because it allows for
‘file downgrades’. Newer files can be overwritten with older versions.
Likely there was a overwritten file with the wrong version and it
failed to load because the dependency was for a newer version.
So... I'm gonna mark this one as answered with this answer, and add a Windows Installer key to the question. Steer clear of "AMUS" when calling Windows Installer...

Customer getting R6002 runtime error when using our app

We have an application built with Visual C++ 2005, and one customer has reported that he's getting this runtime error:
Microsoft Visual C++ Runtime Library
Runtime Error!
Program: [path to our application]
R6002
- floating point support not loaded
According to Microsoft (on this page), the possible reasons for this are:
the machine does not have an FPU (not in this case: the customer has an Intel Core 2 Duo CPU and I haven't seen a machine without FPU since the 486SX)
printf or scanf is used with a floating-point format specification but there are no FP variables in the program (our app contains FP variables but I'm pretty sure we never use printf or scanf with FP formats)
Something to do with FORTRAN (no FORTRAN code in our app)
Also, the error is occurring while they're using our application (specifically, just after they select a file to be processed), not when the application starts up.
I realise this is a long shot, but has anyone seen anything like this anywhere before? Google was pretty unhelpful (there were lots of unsupported claims that it was a symptom of some kind of virus infection but very little apart from that).
Any suggestions gratefully received :-)
Are you linking a static version of the CRT? If so, you need to have floating point variables in the binary that calls printf(). And these variables have to be really used (i.e not optimized out by the comppiler).
Another possibility is a race between the CRT initialization and the code that uses these FP routines, but that would be hard to produce.
R6002 can be caused by printf trying to print a string that contains a percent-sign.
Most likely root cause of such printf failure is a program that manipulates arbitrary files and prints their names. Amazing to me, there really ARE people who put percent-signs in file names! (Yes, I realize that is technically legal.)
printf("%f\n", (float)rand() / RAND_MAX);
I experienced the same runtime error in a program compiled with VS2010 command line cl.
The reported error occurred without the (float) cast and disappeared when I added it.

how to obtain VC++ compiler-style help on GCC G++ compile/link errors (on linux)

I'm using VC++ as professional developer for more than 10 years and it has been good to me, now I'm trying to broaden my horizons and learn C++ development on Linux.
On Windows things are simple, VC++ does it all (editing, project management, help, debugging), but on linux things are different, you have assemble your development environment from different tools.
I'm still trying to tie things together, and one thing I still haven't figured out is how to decipher GCC (G++) errors when compiling/linking C++ apps on Linux (although I realize GCC is multi-platform, I'll refer to my linux experience here only).
In VC++, things are very clear: If during compilation VC++'s compiler encounters error in program, it will create new entry in 'output' window with the 'compiler error ID'. Example:
c:\projectA\fileB.cpp(38) : error C2228: left of '.cout' must have class/struct/union
From here, you can click on the line in question in 'output' window, press F1, and 'Microsoft Document Browser' app will start (if it wasn't started already), which will load MSDN help file describing compile error connected to the compiler error ID (in example it's C2228), usually with sample you can check out to figure out what's wrong with your code. If you don't have MDB installed, you can always search on the web for C2228 and get the same help page, optionally finding other people's web pages describing their experience with this error.
The same thing is with linking, you'll get 'linker error ID' (e.g. LNK1123), which you can use to find help either locally or on web.
Try as I might, I can't find this kind of functionality in GCC's G++. All I can see is bunch of less experienced GCC developers asking another bunch of more experienced GCC developers to analyze their code based on descriptive compiler/linker errors with no associated error IDs.
Is there tool(set) that provides VC++ compiler-style help on GCC G++ compile/link errors for linux?
You may try to use qtcreator. At least it can show the errors in a more comprehensive way comparable to the VC++, that is, it can locate the error position and highlight the error line and variables.
If you can an alternative might be to use Clang instead. It gives much better error messages than g++. It compiles most code these days (but it still a work in progress). Highly recommended.
Alternatively (as another poster has mentioned) you could use an IDE such as Eclipse to capture the error messages, though I don't think that adds anything beyond taking you to the line number on double-click.

Lua compiled scripts on Mac OS X - Intel vs PPC

Been using Lua 5.0 in a Mac OS X universal binary app for some years. Lua scripts are compiled using luac and the compiled scripts are bundled with the app. They have worked properly in Tiger and Leopard, Intel or PPC.
To avoid library problems at the time, I simply added the Lua src tree to my Xcode project and compiled as is, with no problems.
It was time to update to a more modern version of Lua so I replaced my source tree with that of 5.1.4. I rebuilt luac using make macosx (machine is running Leopard on Intel).
Uncompiled scripts work properly in Tiger and Leopard, Intel and PPC, as always.
However, now compiled scripts fail to load on PPC machines.
So I rebuilt luac with the 'ansi' flag, and recompiled my scripts. Same error. Similarly, a build flag of 'generic' produced no joy.
Can anyone please advise on what I can do next?
Lua's compiled scripts are pretty much the raw bytecode dumped out after a short header. The header documents some of the properties of the platform used to compile the bytecode, but the loader only verifies that the current platform has the same properties.
Unfortunately, this creates problems when loading bytecode compiled on another platform, even if compiled by the very same version of Lua. Of course, scripts compiled by different versions of Lua cannot be expected to work, and since the version number of Lua is included in the bytecode header, the attempt to load them is caught by the core.
The simple answer is to just not compile scripts. If Lua compiles the script itself, you only have to worry about possible version mismatches between Lua cores in your various builds of your application, and that isn't hard to deal with.
Actually supporting a full cross compatibility for compiled bytecode is not easy. In that email, Mike Pall identified the following issues:
Endianess: swap on output as needed.
sizeof(size_t), affects huge string constants: check for overflow when
downgrading.
sizeof(int), affectsMAXARG_Bx and MAXARG_sBx: check for overflow when
downgrading.
typeof(lua_Number): easy in C, but only when the host and the target
follow the same FP standard; precision
loss when upgrading (rare case);
warn about non-integer numbers when
downgrading to int32.
From all the discussions that I've seen about this issue on the mailing list, I see two likely viable approaches, assuming that you are unwilling to consider just shipping the uncompiled Lua scripts.
The first would be to fix the byte order as the compiled scripts are loaded. That turns out to be easier to do than you'd expect, as it can be done by replacing the low-level function that reads the script file without recompiling the core itself. In fact, it can even be done in pure Lua, by supplying your own chunk reader function to lua_load(). This should work as long as the only compatibility issue over your platforms is byte order.
The second is to patch the core itself to use a common representation for compiled scripts on all platforms. This has been described as possible by Luiz Henrique de Figueiredo:
....
I'm convinced that the best route to
byte order or cross-compiling is
third-party dump/undump pairs. The
files ldump.c and lundump.c are
completely replaceable; they export a
single, well-defined, entry point. The
format of precompiled chunks is not
sacred at all; you can use any format,
as long as ldump.c and lundump.c agree
about it. (For instance, Rici Lake is
considering writing a text format for
precompiled chunks.)
....
Personally, I'd recommend giving serious consideration to not pre-compiling the scripts and thus avoid the platform portability issues entirely.
Edit: I've updated my description of the bytecode header thanks to lhf's comment. I hadn't read this part of the Lua source yet, and I probably should have checked it before being quite so assertive about what information is or is not present in the header.
Here is the fragment from lundump.c that forms a copy of the header matching the running platform for comparison to the bytecode being loaded. It is simply compared with memcmp() for an exact match to the header from the file, so any mismatch will cause the stock loader (luaU_undump()) to reject the file.
/*
* make header
*/
void luaU_header (char* h)
{
int x=1;
memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
h+=sizeof(LUA_SIGNATURE)-1;
*h++=(char)LUAC_VERSION;
*h++=(char)LUAC_FORMAT;
*h++=(char)*(char*)&x; /* endianness */
*h++=(char)sizeof(int);
*h++=(char)sizeof(size_t);
*h++=(char)sizeof(Instruction);
*h++=(char)sizeof(lua_Number);
*h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
}
As can be seen, the header is 12 bytes long and contains a signature (4 bytes, "<esc>Lua"), version and format codes, a flag byte for endianness, sizes of the types int, size_t, Instruction, and lua_Number, and a flag indicating whether lua_Number is an integral type.
This allows most platform distinctions to be caught, but doesn't attempt to catch every way in which platforms can differ.
I still stand by the recommendations made above: first, ship compilable sources; or second, customize ldump.c and lundump.c to store and load a common format, with the additional note that any custom format should redefine the LUAC_FORMAT byte of the header so as to not be confused with the stock bytecode format.
You may want to use a patched bytecode loader that supports different endianness.
See this.
I would have commented on RBerteig's post, but I apparently don't have enough reputation yet to be able to do so. In working on bringing LuaRPC up to speed with Lua 5.1.x AND making it work with embedded targets, I've been modifying the ldump.c and lundump.c sources to make them both a bit more flexible. The embedded Lua project (eLua) already had some of the patches you can find on the Lua list, but I've added a bit more to make lundump a little more friendly to scripts compiled on different architectures. There's also cross-compilation support provided so that you can build for targets differing from the host system (see luac.c in the same directory as the links below).
If you're interested in checking out the modifications, you can find them in the eLua source repository:
http://svn.berlios.de/wsvn/elua/trunk/src/lua/lundump.c
http://svn.berlios.de/wsvn/elua/trunk/src/lua/lundump.h
http://svn.berlios.de/wsvn/elua/trunk/src/lua/ldump.c
Standard Disclaimer:
I make no claim that the modifications are perfect or work in every situation. If you use it and find anything broken, I'd be glad to hear about it so that it can be fixed.
Lua bytecode is not portable. You should ship source scripts with your application.
If download size is a concern, they are generally shorter than the bytecode form.
If intellectual property is a concern, you can use a code obfuscator, and keep in mind that disassembling Lua bytecode is anything but difficult.
If loading time is a concern, you can precompile the sources locally in your installation script.
I conjecture that you compiled the scripts on an Intel box.
Compiled scripts are wildly unportable. If you really want to precompile scripts, you'll need to include two versions of each compiled script: one for Intel and one for PPC. Your app will have to interrogate which program it's running on and use the correct compiled script.
I don't have enough reputation to comment, so I have to provide this as an answer instead even though it's not an appropriate answer to the question asked. Sorry.
There is an Lua Obfuscator available here:
http://www.capprime.com/CapprimeLuaObfuscator/CapprimeLuaObfuscator.aspx
Full disclosure: I am the author of the obfuscator and I am aware it is not perfect. Feedback is welcome and encouraged (there is a feedback page available from the above page).

Resources