Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actualcr88192

Posted 29 July 2013 - 06:44 PM

a stack overflow is little different in essence from an array overrun.

 

a thread stack may be located anywhere in the address space, likewise with parts of the heap (typically, the memory allocator will grab chunks of address space from the OS via "VirtualAlloc" or "mmap" as needed, then divide them up and commit pages and similar as needed, and grab more chunks when this space runs out, ...).

 

so, it is not like they are placed at opposite ends and grow towards each other or something.

 

typically, the space allocated for thread-stacks is fixed-size, and if the bottom end is hit, an exception will be thrown (typically resulting in a crash).

 

granted, some targets, namely Linux + GCC, have started experimentally using segmented stacks, where the initial stack is much smaller, but memory will be allocated elsewhere as the need arises (the stack-frame will essentially jump-ship to a new stack as-needed).

(this may require more looking into, I am not sure its current status...).

 

 

(note, from memory, may contain errors).

 

in general usually the memory map (for something like a Win32 virtual-address space, *3) ends up looking something like:

0x00000000-0x00400000: usually the main thread stack (and some free space, *1).

0x00400000+: main program EXE, followed directly by static application DLLs, ...

0x01000000-0x70000000 (approximate): used mostly for heap, thread-stacks, and dynamically loaded app DLLs;

0x70000000-0x80000000 (approximate): used mostly for OS DLLs (*4);

0x80000000-0xC0000000: free space for large-address-aware apps (used for more heap/...), otherwise inaccessible (*2).

0xC0000000-0xFFFFFFFF: inaccessible by userland processes, used by the OS itself.

 

 

*1: in the Win9x line, the low 4MB was apparently shared between applications and basically contained the real-mode MS-DOS address space, and various Win16 related data (corrected).

this shared space did not exist in the NT line (WinNT/2K, also WinXP and newer), and so is available for application use (ADD: hence the OS putting the main thread's stack there).

 

*2: in Win9x, this area was owned by the OS but accessible and shared between processes. this was generally used for inter-process communication, as well as for data shared between processes and the OS.

 

in the NT line, it was basically reserved for the OS and unused (resources were shared with the OS via alternative means, namely the OS could directly access memory located anywhere within the process, and so didn't need some dedicated shared/global area). this was later made available for applications (WinXP and Server 2003), via a special linker flag.

 

address regions are generally allocated at the lowest address for which sufficient free pages can be found, unless a flag is given in which case it will start at a high address and work downwards.

 

*3: each application process will have its own local address space layout, but some general patterns apply (as imposed by the OS)

*4: the OS prefers to map DLLs to the same location in every process when possible so that more pages can be shared between processes.

 

 

the 32-bit Linux memory map is simpler, more like:

0x00000000-0xC0000000: application binaries/heap/libraries/stack, spread around fairly haphazardly;

0xC0000000-0xFFFFFFFF: inaccessible by userland processes, used by the OS itself.

 

*: some builds of RedHat (and possibly other) leave a full 4GB for the user-land process, at the cost of more expensive system calls (making a syscall requires changing to a different address space).

 

 

in 64-bit Windows, it is more like:

0x00000000'00000000-...: application code/data/...

...-0x0000007F'FFFFFFFF: OS DLLs/...

 

typically, memory is allocated from low addresses and works upwards.

 

 

the OS's address space is then generally located at negative addresses...

or, seen alternatively, in the space just below:

0xFFFFFFFF'FFFFFFFF

 

 

Linux is basically similar, except once again the spread is fairly haphazardly.

 

memory address ranges are also normally allocated in an apparently more-or-less pseudo-random order.

 

 

or such...


#4cr88192

Posted 29 July 2013 - 06:33 PM

a stack overflow is little different in essence from an array overrun.

 

a thread stack may be located anywhere in the address space, likewise with parts of the heap (typically, the memory allocator will grab chunks of address space from the OS via "VirtualAlloc" or "mmap" as needed, then divide them up and commit pages and similar as needed, and grab more chunks when this space runs out, ...).

 

so, it is not like they are placed at opposite ends and grow towards each other or something.

 

typically, the space allocated for thread-stacks is fixed-size, and if the bottom end is hit, an exception will be thrown.

 

granted, some targets, namely Linux + GCC, have started experimentally using segmented stacks, where the initial stack is much smaller, but memory will be allocated elsewhere as the need arises (the stack-frame will essentially jump-ship to a new stack as-needed).

(this may require more looking into, I am not sure its current status...).

 

 

(note, from memory, may contain errors):

 

in general usually the memory map (for something like a Win32 virtual-address space) ends up looking something like:

0x00000000-0x00400000: usually the main thread stack (and some free space, *1).

0x00400000+: main program EXE, followed directly by static application DLLs, ...

0x01000000-0x70000000 (approximate): used mostly for heap, thread-stacks, and dynamically loaded app DLLs;

0x70000000-0x80000000 (approximate): used mostly for OS DLLs;

0x80000000-0xC0000000: free space for large-address-aware apps (used for more heap/...), otherwise inaccessible (*2).

0xC0000000-0xFFFFFFFF: inaccessible by userland processes, used by the OS itself.

 

 

*1: in the Win9x line, the low 4MB was apparently shared between applications and basically contained the real-mode MS-DOS address space, and various Win16 related data (corrected).

this shared space did not exist in the NT line (WinNT/2K, also WinXP and newer), and so is available for application use (ADD: hence the OS putting the main thread's stack there).

 

*2: in Win9x, this area was owned by the OS but accessible and shared between processes. this was generally used for inter-process communication, as well as for data shared between processes and the OS.

 

in the NT line, it was basically reserved for the OS and unused (resources were shared with the OS via alternative means, namely the OS could directly access memory located anywhere within the process, and so didn't need some dedicated shared/global area). this was later made available for applications (WinXP and Server 2003), via a special linker flag.

 

address regions are generally allocated at the lowest address for which sufficient free pages can be found, unless a flag is given in which case it will start at a high address and work downwards.

 

 

the 32-bit Linux memory map is simpler, more like:

0x00000000-0xC0000000: application binaries/heap/libraries/stack, spread around fairly haphazardly;

0xC0000000-0xFFFFFFFF: inaccessible by userland processes, used by the OS itself.

 

*: some builds of RedHat (and possibly other) leave a full 4GB for the user-land process, at the cost of more expensive system calls (making a syscall requires changing to a different address space).

 

 

in 64-bit Windows, it is more like:

0x00000000'00000000-...: application code/data/...

...-0x0000007F'FFFFFFFF: OS DLLs/...

 

typically, memory is allocated from low addresses and works upwards.

 

 

the OS's address space is then generally located at negative addresses...

or, seen alternatively, in the space just below:

0xFFFFFFFF'FFFFFFFF

 

 

Linux is basically similar, except once again the spread is fairly haphazardly.

 

memory address ranges are also normally allocated in an apparently more-or-less pseudo-random order.

 

 

or such...


#3cr88192

Posted 29 July 2013 - 05:02 PM

a stack overflow is little different in essence from an array overrun.

 

a thread stack may be located anywhere in the address space, likewise with parts of the heap (typically, the memory allocator will grab chunks of address space via "VirtualAlloc" or "mmap" as needed, then divide them up and commit pages and similar as needed, and grab more chunks when this space runs out, ...).

 

so, it is not like they are placed at opposite ends and grow towards each other or something.

 

typically, the space allocated for thread-stacks is fixed-size, and if the bottom end is hit, an exception will be thrown.

 

granted, some targets, namely Linux + GCC, have started experimentally using segmented stacks, where the initial stack is much smaller, but memory will be allocated elsewhere as the need arises (the stack-frame will essentially jump-ship to a new stack as-needed).

(this may require more looking into, I am not sure its current status...).

 

 

(note, from memory, may contain errors):

 

in general usually the memory map (for something like a Win32 virtual-address space) ends up looking something like:

0x00000000-0x00400000: usually the main thread stack (and some free space, *1).

0x00400000+: main program EXE, followed directly by static application DLLs, ...

0x01000000-0x70000000 (approximate): used mostly for heap, thread-stacks, and dynamically loaded app DLLs;

0x70000000-0x80000000 (approximate): used mostly for OS DLLs;

0x80000000-0xC0000000: free space for large-address-aware apps (used for more heap/...), otherwise inaccessible (*2).

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

 

*1: in the Win9x line, the low 1MB was apparently shared between applications and basically contained the real-mode MS-DOS address space.

then the main-thread's stack would be placed between the MS-DOS space, and the start of the main program binary.

this shared DOS-space did not exist in the NT line (WinNT/2K, also WinXP and newer), and so is available for application use.

 

*2: in Win9x, this area was owned by the OS but accessible and shared between processes. this was generally used for inter-application communication, as well as for data shared between applications and the OS.

 

in the NT line, it was basically reserved for the OS and unused (resources were shared with the OS via alternative means, namely the OS could directly access memory located anywhere within the process, and so didn't need some dedicated shared/global area). this was later made available for applications, via a special linker flag.

 

address regions are generally allocated at the lowest address for which sufficient free pages can be found, unless a flag is given in which case it will start at a high address and work downwards.

 

 

the 32-bit Linux memory map is simpler, more like:

0x00000000-0xC0000000: application binaries/heap/libraries/stack, spread around fairly haphazardly;

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

*: some builds of RedHat (and possibly other) leave a full 4GB for the user-land process, at the cost of more expensive system calls (making a syscall requires changing to a different address space).

 

 

in 64-bit Windows, it is more like:

0x00000000'00000000-...: application code/data/...

...-0x0000007F'FFFFFFFF: OS DLLs/...

 

typically, memory is allocated from low addresses and works upwards.

 

 

the OS's address space is then generally located at negative addresses...

or, seen alternatively, in the space just below:

0xFFFFFFFF'FFFFFFFF

 

 

Linux is basically similar, except once again the spread is fairly haphazardly.

 

memory address ranges are also normally allocated in an apparently more-or-less pseudo-random order.

 

 

or such...


#2cr88192

Posted 29 July 2013 - 05:01 PM

a stack overflow is little different in essence from an array overrun.

 

a thread stack may be located anywhere in the address space, likewise with parts of the heap (typically, the memory allocator will grab chunks of address space via "VirtualAlloc" or "mmap" as needed, then divide them up and commit pages and similar as needed, and grab more chunks when this space runs out, ...).

 

so, it is not like they are placed at opposite ends and grow towards each other or something.

 

typically, the space allocated for thread-stacks is fixed-size, and if the bottom end is hit, an exception will be thrown.

 

granted, some targets, namely Linux + GCC, have started experimentally using segmented stacks, where the initial stack is much smaller, but memory will be allocated elsewhere as the need arises (the stack-frame will essentially jump-ship to a new stack as-needed).

(this may require more looking into, I am not sure its current status...).

 

 

(note, from memory, may contain errors):

 

in general usually the memory map (for something like a Win32 virtual-address space) ends up looking something like:

0x00000000-0x00400000: usually the main thread stack (and some free space, *1).

0x00400000+: main program EXE, followed directly by static application DLLs, ...

0x01000000-0x70000000 (approximate): used mostly for heap, thread-stacks, and dynamically loaded app DLLs;

0x70000000-0x80000000 (approximate): used mostly for OS DLLs;

0x80000000-0xC0000000: free space for large-address-aware apps (used for more heap/...), otherwise inaccessible (*2).

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

 

*1: in the Win9x line, the low 1MB was apparently shared between applications and basically contained the real-mode MS-DOS address space.

then the main-thread's stack would be placed between the MS-DOS space, and the start of the main program binary.

this shared DOS-space did not exist in the NT line (WinNT/2K, also WinXP and newer), and so is available for application use.

 

*2: in Win9x, this area was owned by the OS but accessible and shared between processes. this was generally used for inter-application communication, as well as for data shared between applications and the OS.

 

in the NT line, it was basically reserved for the OS and unused (resources were shared with the OS via alternative means, namely the OS could directly access memory located anywhere within the process, and so didn't need some dedicated shared/global area). this was later made available for applications, via a special linker flag.

 

memory regions are generally allocated at the lowest address for which sufficient free pages can be found, unless a flag is given in which case it will start at a high address and work downwards.

 

 

the 32-bit Linux memory map is simpler, more like:

0x00000000-0xC0000000: application binaries/heap/libraries/stack, spread around fairly haphazardly;

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

*: some builds of RedHat (and possibly other) leave a full 4GB for the user-land process, at the cost of more expensive system calls (making a syscall requires changing to a different address space).

 

 

in 64-bit Windows, it is more like:

0x00000000'00000000-...: application code/data/...

...-0x0000007F'FFFFFFFF: OS DLLs/...

 

typically, memory is allocated from low addresses and works upwards.

 

 

the OS's address space is then generally located at negative addresses...

or, seen alternatively, in the space just below:

0xFFFFFFFF'FFFFFFFF

 

 

Linux is basically similar, except once again the spread is fairly haphazardly.

 

memory address ranges are also normally allocated in an apparently more-or-less pseudo-random order.

 

 

or such...


#1cr88192

Posted 29 July 2013 - 01:50 PM

a stack overflow is little different in essence from an array overrun.

 

a thread stack may be located anywhere in the address space, likewise with parts of the heap (typically, the memory allocator will grab chunks of address space via "VirtualAlloc" or "mmap" as needed, then divide them up and commit pages and similar as needed, and grab more chunks when this space runs out, ...).

 

so, it is not like they are placed at opposite ends and grow towards each other or something.

 

typically, the space allocated for thread-stacks is fixed-size, and if the bottom end is hit, an exception will be thrown.

 

granted, some targets, namely Linux + GCC, have started experimentally using segmented stacks, where the initial stack is much smaller, but memory will be allocated elsewhere as the need arises (the stack-frame will essentially jump-ship to a new stack as-needed).

(this may require more looking into, I am not sure its current status...).

 

 

(note, from memory, may contain errors):

 

in general usually the memory map (for something like Win32) ends up looking something like:

0x00000000-0x00400000: usually the main thread stack (and some free space, *1).

0x00400000+: main program EXE, followed directly by static application DLLs, ...

0x01000000-0x70000000 (approximate): used mostly for heap, thread-stacks, and dynamically loaded app DLLs;

0x70000000-0x80000000 (approximate): used mostly for OS DLLs;

0x80000000-0xC0000000: free space for large-address-aware apps (used for more heap/...), otherwise inaccessible (*2).

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

 

*1: in the Win9x line, the low 1MB was apparently shared between applications and basically contained the real-mode MS-DOS address space.

then the main-thread's stack would be placed between the MS-DOS space, and the start of the main program binary.

this shared DOS-space did not exist in the NT line (WinNT/2K, also WinXP and newer).

 

*2: in Win9x, this area was owned by the OS but accessible and shared between processes. this was generally used for inter-application communication, as well as for data shared between applications and the OS.

in the NT line, it was basically reserved for the OS and unused (resources were shared with the OS via alternative means, namely the OS could directly access memory located anywhere within the process, and so didn't need some dedicated shared/global area).

 

memory regions are generally allocated at the lowest address for which sufficient free pages can be found, unless a flag is given in which case it will start at a high address and work downwards.

 

 

the 32-bit Linux memory map is simpler, more like:

0x00000000-0xC0000000: binaries/heap/libraries/stack, spread around fairly haphazardly;

0xC0000000-0xFFFFFFFF: inaccessible, used by the OS itself.

 

 

in 64-bit Windows, it is more like:

0x00000000'00000000-...: application code/data/...

...-0x0000007F'FFFFFFFF: OS DLLs/...

 

typically, memory is allocated from low addresses and works upwards.

 

 

the OS's address space is then generally located at negative addresses...

or, seen alternatively, in the space just below:

0xFFFFFFFF'FFFFFFFF

 

 

Linux is basically similar, except once again the spread is fairly haphazardly.

 

memory address ranges are also normally allocated in an apparently more-or-less pseudo-random order.

 

 

or such...


PARTNERS