Log in

View Full Version : Question about memory mapping


Kayaker
January 28th, 2001, 03:40
Hi All,

I've developed a curiosity as to the exact process that occurs when a program first starts up, specifically what determines what sections are mapped into memory at the Program Entry Point.

It's sort of like exploring the precise moment of the Big Bang - what exactly happens when you load a file in SoftIce Loader and press that first F8?


Take Notepad as an example. Here are the sections and their Virtual Sizes:

.text :00401000 00003E9C
.data :00405000 0000084C
.idata :00406000 00000DE8
.rsrc :00407000 00004FB8
.reloc :0040C000 00000A9C

At the Program Entry Point of 4010CC, the only sections that are committed to memory are the 1st 1000 bytes of the .text section, the full .idata section, and the 1st 1000 bytes of the .rsrc section. As you step through the program you can find where the other bits and pieces are memory mapped by monitoring the Data Window.

Now I can live with the .text, or code, section being mapped piecemeal 1000 bytes at a time, but I'd like to know what determines which sections and how much of each is mapped into memory in that very first instance at the Program Entry Point. I've been burning up various PE documentations for clues, but nothing seems to jump out at me. Are all sections treated equally? Could you force a program to load the WHOLE of its .text section upon startup, irrespective of any later code which might be involved in doing this?


For Notepad the Program Entry Point and register values are below. What information is here concerning what's to be mapped into memory as soon as you F8 over that first magic PUSH EBP? Are the values in ECX, EDX and ESI significant?


EAX=004010CC EBX=00000000 ECX=8171B660 EDX=8171B6A0 ESI=8171B640
EDI=00000000 EBP=0063FF78 ESP=0063FE38 EIP=004010CD

0167:004010CA 0000 ADD [EAX],AL
0167:004010CC 55 PUSH EBP
0167:004010CD 8BEC MOV EBP,ESP
0167:004010CF 83EC44 SUB ESP,44
0167:004010D2 56 PUSH ESI
0167:004010D3 FF15E0634000 CALL [KERNEL32!GetCommandLineA]


You may rightly wonder why I ask such strange questions. Specifically, I have a packed program which, during the unpacking process every section is mapped into memory in the regular program address space, and then it jumps to the OEP and the program runs fine. Unpack the program and partway through the code there's a Runtime error because part of the .text section is not mapped into memory yet! Hence my interest in committing the entire .text section to memory on program startup, but this is as a general interest question as well.

Any light shed on this mystery of Windows is appreciated ;-)

Regards,

Kayaker

carpathia
January 28th, 2001, 05:51
This question is more to do with paging, than the loader itself.
If you take another look, you'll notice that the committed blocks are not 1000 bytes in size, but actually 4096.

When a request is made to read a certain virtual address of the image, the kernel consults the paging directory to see if the page contained by that address is in physical RAM. When it finds that it cant be found in ram, a page fault occurs.

VMM32 handles this page fault, loads the 4k page from disk into memory, and then re-executes the instruction which caused the page fault. Second time round of course, the page is present, and no page fault occurs. All this is totally transparent to the process itself.

Kayaker
January 28th, 2001, 14:48
According to The Portable Executable File Format from Top to Bottom by Randy Kath, the heap and stack sizes are controlled by

"SizeOfStackReserve, SizeOfStackCommit, SizeOfHeapReserve, SizeOfHeapCommit. These fields control the amount of address space to reserve and commit for the stack and default heap. Both the stack and heap have default values of 1 page committed and 16 pages reserved. These values are set with the linker switches -STACKSIZE: and -HEAPSIZE:."

I tried changing the sizes of SizeOfStackCommit and SizeOfHeapCommit in the Optional Header from the default of 1 page (4096 = 1000h bytes), but it had no effect on how much of each section was actually loaded on startup.

Luevelsmeyer seems to indicate that the stack will grow in pages no matter what these PE settings are. So as you mention, it may be VMM32 controlling this.

"The 'reserved' amounts are address space (not real RAM) that is reserved
for the specific purpose; at program startup, the 'committed' amount is
actually allocated in RAM. The 'committed' value is also the amount by
which the committed stack or heap grows if necessary. (Other sources
claim that the stack will grow in pages, regardless of the
'SizeOfStackCommit' value. I didn't check this.)
So, as an example, if a program has a reserved heap of 1 MB and a
committed heap of 64 KB, the heap will start out at 64 KB and is
guaranteed to be enlargeable up to 1 MB. The heap will grow in
64-KB-chunks."

Iceman
January 28th, 2001, 16:18
It seems that you confuse some things ....
In the first place what "comitted" memory means.
When the PE loader maps a PE image into memory
(the process is not quite simple so I wont describe it here in detail) it will commit the entire address range occupied for image . Whatever
the memory will be actualy present or paged out ,
thats another issue. (Softice will dispaly ?? ?? ?? ?? for paged out memory too , not only for reserved memory ).
Second , that heap and stack size has nothing to do with how the image is mapped in memory .
They control exactly what their name suggest:
stack and heap .
If you are really interest in what happens in detail , I can explain it for you providing you have a basic knowledge of protected mode and paging.
And read a good article about virtual memory management on NT to clean up what "commited" ,
"reserved" , paged-out memory means.

Kayaker
January 28th, 2001, 18:16
Thanks Iceman and Carpathia. I am no doubt confused by this aspect of program operation ^_^

I am interested in understanding this, so I'll do a little research and get back to clarify things with a more informed background.

Cheers,
Kayaker