Windows memory layout changes on each build.

For Windows XP/Vista, on a Intel chip, using Visual Studio 2005, I've been trying to write a function that will compute a checksum over a range of instructions during runtime. First I build the application and run it, putting a breakpoint on the checksum comparision( the breakpoint is outside of the range of the checksumming instructions, so the breakpoint isn't mucking up the checksum ). Once I get the sum value, I place that value in the comparision check, recompile, and run it. It runs fine, passing the checksum comparision check every time. If, however, I do a clean solution and rebuild( so delete all the objs basically ), the checksum value is different. How can that be, if NO code has changed? Can anyone explain this to me?
mhorsley99Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
>>How can that be, if NO code has changed?

The compiler/linker embeds a time stamp in the image header each build, that's the reason.
0
jkrCommented:
BTW, see also http://msdn.microsoft.com/msdnmag/issues/02/02/PE/ ("An In-Depth Look into the Win32 Portable Executable File Format") and the IMAGE_FILE_HEADER structure in particular (http://msdn.microsoft.com/msdnmag/issues/02/02/PE/figures.asp#fig3):

WORD
 Machine
 The target CPU for this executable. Common values are:
IMAGE_FILE_MACHINE_I386    0x014c // Intel 386
IMAGE_FILE_MACHINE_IA64    0x0200 // Intel 64

 
WORD
 NumberOfSections
 Indicates how many sections are in the section table. The section table immediately follows the IMAGE_NT_HEADERS.
 
DWORD
 TimeDateStamp <---------------
 Indicates the time when the file was created. This value is the number of seconds since January 1, 1970, Greenwich Mean Time (GMT). This value is a more accurate indicator of when the file was created than is the file system date/time. An easy way to translate this value into a human-readable string is with the _ctime function (which is time-zone-sensitive!). Another useful function for working with this field is gmtime.
 
0
mhorsley99Author Commented:
Thanks jkr. I guess I don't understand the build process well enough to fully understand your answer. Wouldn't the timestamp change when I simply change the checksum value comparision and then rebuild? The file is changed, so it rebuilds, the app links, then I run it and its fine( the checksum comparison works ).

On the other hand, after all this I delete the object files and then rebuild again, the app runs but the checksum fails. No code has changed. So I can accept it has to be something to do with the image header. I've only done console programming, so I'm alittle new to windows.
0
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

jkrCommented:
Well, the timestamt change just results in a different checksum, in both cases. Maybe that diccerence stems from the "inclremental" and "full" builds the linker performs. What happens if you use a "Rebuild All" in both of the above scenarios?
0
mhorsley99Author Commented:
Ah, I understand the problem now. I didn't state the problem correctly. The checksumming isn't done over the entire executable. It is a checksum that is done at runtime, every update of the main loop. The checksum is computing the sum of the instructions between instruction A through instruction B( where A and B are asm labels ).
static unsigned int addressStart;
static unsigned int addressEnd;
_asm mov eax,GUARD_1_BEGIN
_asm mov ebx,GUARD_1_END
_asm mov addressStart,eax
_asm mov addressEnd,ebx
unsigned int a = addressStart;
unsigned int sum = 0;
while (a <= addressEnd) {
	unsigned rawVal = *(unsigned int*)(a);
	rawVal &= 0xffff;
	sum += rawVal;
	a += 4;
}
cout << x << " checksum=" << sum << endl;
if ( sum != 0x001252b3) {
	//return 0;
	cout << " checksum=bad" << endl;
}

Open in new window

0
jkrCommented:
Hm, what are the GUARD_1_BEGIN and GUARD_1_END addresses?
0
mhorsley99Author Commented:
GUARD_1_BEGIN and GUARD_1_END are asm labels defined elsewhere in the application. Basically, there will be multiple checksums going on, each checksum responsible for different memory areas of the application to guard.
0
jkrCommented:
Err, you know that the Windows loader will assign module base addresses not the same way necessarily? Yet I'd expect to find your code at the same location, but it is still unclear what you exactly are trying to achieve and which modules you checksum.
0
grg99Commented:
The loader may align code at 16 or 256 byte boundaries.  There's no telling if it fills the holes with anything deterministic.

0
mhorsley99Author Commented:
Hi grg99,
   Thanks for you help. What I don't understand is how it seems to work fine, EVERYTIME I RUN IT. I've run it 4 or 5 times in a row, loaded firefox/IE/Office before,after/during the process to try and get a different memory layout on my windows machine. The checksum passes with flying colors. Without changing code, I simply delete the object files and recompile. Now, instead of the checksum summing up to 0x001252b3, its an entirely different value. Is the loader determining the byte boundaries when I compile/link the app? I thought the loader did its work when I actually ran the application. What's going on when I recompile so that the checksum changes? obviously its got something to do with memory, and how windows places my application in main memory. I just can't seem to understand how its different just by recompiling code that hasn't changed.
0
Infinity08Commented:
Object files are the compiled versions of the code. They contain what will ultimately end up in memory when you run the application. The linker merely combines object files into an executable. Once an executable is combined, the instruction memory contents will be the same no matter how many times you run the application.

However, when you re-compile the object files, they might not be the same byte-for-byte. Timestamps might be different as jkr said, unused space might contain different random data like grg99 said, possibly different compiler flags might trigger different optimizations (although that's probably not the case here), etc.
The linker will then again combine these new object files into an executable, but this time when you run it, the instruction memory contents might be different (because the object files might be different).
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
grg99Commented:
The linker combines the object files into an .exe.    It might not clear memory first, so there may be random stuff in the holes between subroutines.

0
mhorsley99Author Commented:
Thanks for all your help. I didn't realize unused space might contain random data.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.