Fix incorrect calculated relocations on Windows x86_64
authorTamar Christina <tamar@zhox.com>
Sat, 11 Jun 2016 08:18:19 +0000 (10:18 +0200)
committerTamar Christina <tamar@zhox.com>
Sun, 12 Jun 2016 11:43:32 +0000 (13:43 +0200)
commitb40e1b4c6746bdc34e6a53548a3925d309201c4d
tree8db58488f701c2dc944714406ebf5fc9a4bbcf6f
parent913086797af8060808973e8f6a11a3702afffe14
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
rts/Linker.c
rts/LinkerInternals.h
testsuite/tests/rts/T12031/ExternBug.hs [new file with mode: 0644]
testsuite/tests/rts/T12031/Makefile [new file with mode: 0644]
testsuite/tests/rts/T12031/T12031.stdout [new file with mode: 0644]
testsuite/tests/rts/T12031/all.T [new file with mode: 0644]
testsuite/tests/rts/T12031/bar.c [new file with mode: 0644]
testsuite/tests/rts/T12031/baz.c [new file with mode: 0644]
testsuite/tests/rts/T12031/foo.h [new file with mode: 0644]