address-space.sgml 5.05 KB
Newer Older
1 2 3 4
<chapter id="address-space">
  <title> Address space management </title>

  <para>
5 6 7
    A good understanding of memory layout in Unix and Windows is
    required before reading the next section (<xref
      linkend="arch-mem"> gives some basic insight).  
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
  </para>

  <sect1>
    <title> Laying out the address space </title>

    <para>
      Up until about the start of 2004, the Linux address space very much resembled the Windows 9x
      layout: the kernel sat in the top gigabyte, the bottom pages were unmapped to catch null
      pointer dereferences, and the rest was free. The kernels mmap algorithm was predictable: it
      would start by mapping files at low addresses and work up from there.
    </para>

    <para>
      The development of a series of new low level patches violated many of these assumptions, and
      resulted in Wine needing to force the Win32 address space layout upon the system. This
      section looks at why and how this is done.
    </para>

    <para>
      The exec-shield patch increases security by randomizing the kernels mmap algorithms. Rather
      than consistently choosing the same addresses given the same sequence of requests, the kernel
      will now choose randomized addresses. Because the Linux dynamic linker (ld-linux.so.2) loads
      DSOs into memory by using mmap, this means that DSOs are no longer loaded at predictable
      addresses, so making it harder to attack software by using buffer overflows. It also attempts
      to relocate certain binaries into a special low area of memory known as the ASCII armor so
      making it harder to jump into them when using string based attacks.
    </para>

    <para>
      Prelink is a technology that enhances startup times by precalculating ELF global offset
      tables then saving the results inside the native binaries themselves. By grid fitting each
      DSO into the address space, the dynamic linker does not have to perform as many relocations
      so allowing applications that heavily rely on dynamic linkage to be loaded into memory much
      quicker. Complex C++ applications such as Mozilla, OpenOffice and KDE can especially benefit
      from this technique.
    </para>

    <para>
      The 4G VM split patch was developed by Ingo Molnar. It gives the Linux kernel its own address
      space, thereby allowing processes to access the maximum addressable amount of memory on a
      32-bit machine: 4 gigabytes. It allows people with lots of RAM to fully utilise that in any
49 50
      given process at the cost of performance: the reason behind
      giving the kernel a part of each processes address space was to avoid the overhead of switching on
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
      each syscall.
    </para>

    <para>
      Each of these changes alter the address space in a way incompatible with Windows. Prelink and
      exec-shield mean that the libraries Wine uses can be placed at any point in the address
      space: typically this meant that a library was sitting in the region that the EXE you wanted
      to run had to be loaded (remember that unlike DLLs, EXE files cannot be moved around in
      memory). The 4G VM split means that programs could receive pointers to the top gigabyte of
      address space which some are not prepared for (they may store extra information in the high
      bits of a pointer, for instance). In particular, in combination with exec-shield this one is
      especially deadly as it's possible the process heap could be allocated beyond
      ADDRESS_SPACE_LIMIT which causes Wine initialization to fail. 
    </para>

    <para>
      The solution to these problems is for Wine to reserve particular parts of the address space
      so that areas that we don't want the system to use will be avoided. We later on
      (re/de)allocate those areas as needed. One problem is that some of these mappings are put in
      place automatically by the dynamic linker: for instance any libraries that Wine
      is linked to (like libc, libwine, libpthread etc) will be mapped into memory before Wine even
      gets control. In order to solve that, Wine overrides the default ELF initialization sequence
      at a low level and reserves the needed areas by using direct syscalls into the kernel (ie
      without linking against any other code to do it) before restarting the standard
      initialization and letting the dynamic linker continue. This is referred to as the
      preloader and is found in loader/preloader.c.
    </para>

    <para>
      Once the usual ELF boot sequence has been completed, some native libraries may well have been
      mapped above the 3gig limit: however, this doesn't matter as 3G is a Windows limit, not a
      Linux limit. We still have to prevent the system from allocating anything else above there
      (like the heap or other DLLs) though so Wine performs a binary search over the upper gig of
      address space in order to iteratively fill in the holes with MAP_NORESERVE mappings so the
      address space is allocated but the memory to actually back it is not. This code can be found
      in libs/wine/mmap.c:reserve_area.
    </para>
    
  </sect1>
  
</chapter>