[commit: ghc] master: Fix incorrect calculated relocations on Windows x86_64 (b40e1b4)

git at git.haskell.org git at git.haskell.org
Sun Jun 12 11:39:53 UTC 2016


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/b40e1b4c6746bdc34e6a53548a3925d309201c4d/ghc

>---------------------------------------------------------------

commit b40e1b4c6746bdc34e6a53548a3925d309201c4d
Author: Tamar Christina <tamar at zhox.com>
Date:   Sat Jun 11 10:18:19 2016 +0200

    Fix incorrect calculated relocations on Windows x86_64
    
    Summary:
    See #12031 for analysis, but essentially what happens is:
    
    To sum up the issue, the reason this seems to go wrong is because
    of how we initialize the `.bss` section for Windows in the runtime linker.
    
    The first issue is where we calculate the zero space for the section:
    
    ```
    zspace = stgCallocBytes(1, bss_sz, "ocGetNames_PEi386(anonymous bss)");
    sectab_i->PointerToRawData = ((UChar*)zspace) - ((UChar*)(oc->image));
    ```
    
    Where
    ```
    UInt32 PointerToRawData;
    ```
    
    This means we're stuffing a `64-bit` value into a `32-bit` one. Also `zspace`
    can be larger than `oc->image`. In which case it'll overflow and
    then get truncated in the cast.
    
    The address of a value in the `.bss` section is then calculated as:
    
    ```
    addr = ((UChar*)(oc->image))
         + (sectabent->PointerToRawData
         + symtab_i->Value);
    ```
    
    If it does truncate then this calculation won't be correct (which is what is happening).
    
    We then later use the value of `addr` as the `S` (Symbol) value for the relocations
    
    ```
    S = (size_t) lookupSymbol_( (char*)symbol );
    ```
    
    Now the majority of the relocations are `R_X86_64_PC32` etc.
    e.g. They are guaranteed to fit in a `32-bit` value.
    
    The `R_X86_64_64` introduced for these pseudo-relocations so they can use
    the full `48-bit` addressing space isn't as lucky.
    As for why it sometimes work has to do on whether the value is truncated or not.
    
    `PointerToRawData` can't be changed because it's size is fixed by the PE specification.
    
    Instead just like with the other platforms, we now use `section` on Windows as well.
    This gives us a `start` parameter of type `void*` which solves the issue.
    
    This refactors the code to use `section.start` and to fix the issues.
    
    Test Plan: ./validate and new test added T12031
    
    Reviewers: RyanGlScott, erikd, bgamari, austin, simonmar
    
    Reviewed By: simonmar
    
    Subscribers: thomie, #ghc_windows_task_force
    
    Differential Revision: https://phabricator.haskell.org/D2316
    
    GHC Trac Issues: #12031, #11317


>---------------------------------------------------------------

b40e1b4c6746bdc34e6a53548a3925d309201c4d
 rts/Linker.c                             | 73 ++++++++++++++++++--------------
 rts/LinkerInternals.h                    |  4 +-
 testsuite/tests/rts/T12031/ExternBug.hs  |  9 ++++
 testsuite/tests/rts/T12031/Makefile      |  8 ++++
 testsuite/tests/rts/T12031/T12031.stdout |  1 +
 testsuite/tests/rts/T12031/all.T         |  4 ++
 testsuite/tests/rts/T12031/bar.c         | 11 +++++
 testsuite/tests/rts/T12031/baz.c         |  9 ++++
 testsuite/tests/rts/T12031/foo.h         | 11 +++++
 9 files changed, 97 insertions(+), 33 deletions(-)

Diff suppressed because of size. To see it, use:

    git diff-tree --root --patch-with-stat --no-color --find-copies-harder --ignore-space-at-eol --cc b40e1b4c6746bdc34e6a53548a3925d309201c4d


More information about the ghc-commits mailing list