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?
 
Infinity08Connect With a Mentor Commented:
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
 
jkrConnect With a Mentor Commented:
>>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
 
jkrConnect With a Mentor Commented:
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
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
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
 
jkrConnect With a Mentor Commented:
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
 
jkrConnect With a Mentor Commented:
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
 
jkrConnect With a Mentor Commented:
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
 
grg99Connect With a Mentor Commented:
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
 
grg99Connect With a Mentor Commented:
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
All Courses

From novice to tech pro — start learning today.