Commit Graph

32 Commits

Author SHA1 Message Date
Peter Collingbourne 79a5e6b1b7 COFF: New symbol table design.
This ports the ELF linker's symbol table design, introduced in r268178,
to the COFF linker.

Differential Revision: http://reviews.llvm.org/D21166

llvm-svn: 289280
2016-12-09 21:55:24 +00:00
Rui Ueyama 489a806965 Update for LLVM function name change.
llvm-svn: 257801
2016-01-14 20:53:50 +00:00
Rui Ueyama 84425d7289 COFF: Implement DLL symbol forwarding.
DLL export tables usually contain dllexport'ed symbol RVAs so that
applications which use the DLLs can find symbols from the DLLs.
However, there's a minor feature to "forward" DLL symbols to other
DLLs.

If you set an RVA to a string whose form is "<dllname>.<symbolname>"
(e.g. "KERNEL32.ExitProcess") instead of symbol RVA to the export
table, the loader interprets that as a forwarder symbol, and resolve
that symbol from the specified DLL.

This patch implements that feature.

llvm-svn: 257243
2016-01-09 01:22:00 +00:00
Rui Ueyama dba6b576cf COFF: Rename RoundUpToAlignment -> align.
llvm-svn: 257220
2016-01-08 22:24:26 +00:00
Rui Ueyama 63bbe84b27 COFF: Make Chunk::writeTo() const. NFC.
This should improve code readability especially because this function
is called inside parallel_for_each.

llvm-svn: 248103
2015-09-19 23:28:57 +00:00
Rui Ueyama 27e9e6540c Remove unused #includes.
llvm-svn: 248081
2015-09-19 02:28:32 +00:00
Rui Ueyama bfbd277a1c COFF: Preserve original spelling of DLL file name.
This patch fixes a subtle incompatibility with MSVC linker.
MSVC linker preserves the original spelling of a DLL in the
import descriptor table. LLD previously converted all
characters to lowercase. Usually this difference is benign,
but if a program explicitly checks for DLL file names, the
program could fail.

llvm-svn: 246620
2015-09-02 07:27:31 +00:00
Rui Ueyama f10a32014d COFF: Improve dllexported name mangling compatibility.
The rules for dllexported symbols are overly complicated due to
x86 name decoration, fuzzy symbol resolution, and the fact that
one symbol can be resolved by so many different names. The rules
are probably intended to be "intuitive", so that users don't have
to understand the name mangling schemes, but it seems that it can
lead to unintended symbol exports.

To make it clear what I'm trying to do with this patch, let me
write how the export rules are subtle and complicated.

 - x86 name decoration: If machine type is i386 and export name
   is given by a command line option, like /export:foo, the
   real symbol name the linker has to search for is _foo because
   all symbols are decorated with "_" prefixes. This doesn't happen
   on non-x86 machines. This automatic name decoration happens only
   when the name is not C++ mangled.

   However, the symbol name exported from DLLs are ones without "_"
   on all platforms.

   Moreover, if the option is given via .drectve section, no
   symbol decoration is done (the reason being that the .drectve
   section is created by a compiler and the compiler should always
   know the exact name of the symbol, I guess).

 - Fuzzy symbol resolution: In addition to x86 name decoration,
   the linker has to look for cdecl or C++ mangled symbols
   for a given /export. For example, it searches for not only
   _foo but also _foo@<number> or ??foo@... for /export:foo.

Previous implementation didn't get it right. I'm trying to make
it as compatible with MSVC linker as possible with this patch
however the rules are. The new code looks a bit messy to me, but
I don't think it can be simpler due to the ad-hoc-ness of the rules.

llvm-svn: 246424
2015-08-31 08:43:21 +00:00
Rui Ueyama d157088adb COFF: Fix the order of the DLL import entry.
There are some DLLs whose initializers depends on other DLLs'
initializers. The initialization order matters for them.

MSVC linker uses the order of the libraries from the command line.
LLD used ASCII-betical order. So they were incompatible.
This patch makes LLD compatible with MSVC.

llvm-svn: 245201
2015-08-17 08:30:31 +00:00
Rafael Espindola 5c546a1437 COFF: In chunks, store the offset from the start of the output section. NFC.
This is more convenient than the offset from the start of the file as we
don't have to worry about it changing when we move the output section.

This is a port of r245008 from ELF.

llvm-svn: 245018
2015-08-14 03:30:59 +00:00
Rui Ueyama 857b30356f Move file-local classes to an anonymous namespace. NFC.
llvm-svn: 244525
2015-08-10 23:02:57 +00:00
Rui Ueyama 9420dee328 COFF: Fix export symbol names for x86.
I don't fully understand the rationale behind the name mangling
scheme used for the DLL export table and the import library.
Why only leading "_" is dropped for the import library while
both "_" and "@" are dropped from DLL symbol table? But this seems
to be what MSVC linker does.

llvm-svn: 243490
2015-07-28 22:34:24 +00:00
Rui Ueyama 7e387a68de COFF: Fix 32-bit delay-import address table.
The address table entry is 32-bit wide on 32-bit and 64-bit on 64-bit.
Previously, it was 64-bit even on 32-bit.

llvm-svn: 243372
2015-07-28 02:54:18 +00:00
Rui Ueyama 5e706b3ee3 COFF: Use short identifiers. NFC.
llvm-svn: 243229
2015-07-25 21:54:50 +00:00
Rui Ueyama 3afd5bfd7b COFF: Handle base relocation as a tuple of relocation type and RVA. NFC.
On x64 and x86, we use only one base relocation type, so we handled
base relocations just as a list of RVAs. That doesn't work well for
ARM becuase we have to handle two types of base relocations on ARM.
This patch changes the type of base relocation from uint32_t to
{reltype, uint32_t} to make it easy to port this code to ARM.

llvm-svn: 243197
2015-07-25 01:44:32 +00:00
Rui Ueyama 35ccb0f7d4 COFF: Don't assume !is64() means i386.
In many places we assumed that is64() means AMD64 and i386 otherwise.
This assumption is not sound because Windows also supports ARM.
The linker doesn't support ARM yet, but this is a first step.

llvm-svn: 243188
2015-07-25 00:20:06 +00:00
Rui Ueyama 3cb895c930 COFF: Fix __ImageBase symbol relocation.
__ImageBase is a special symbol whose value is the image base address.
Previously, we handled __ImageBase symbol as an absolute symbol.

Absolute symbols point to specific locations in memory and the locations
never change even if an image is base-relocated. That means that we
don't have base relocation entries for absolute symbols.

This is not a case for __ImageBase. If an image is base-relocated, its
base address changes, and __ImageBase needs to be shifted as well.
So we have to have base relocations for __ImageBase. That means that
__ImageBase is not really an absolute symbol but a different kind of
symbol.

In this patch, I introduced a new type of symbol -- DefinedRelative.
DefinedRelative is similar to DefinedAbsolute, but it has not a VA but RVA
and is a subject of base relocation. Currently only __ImageBase is of
the new symbol type.

llvm-svn: 243176
2015-07-24 22:58:44 +00:00
Rui Ueyama 759c8aa9a0 COFF: Fix offset in x86 delay-load thunks.
llvm-svn: 242353
2015-07-15 23:01:36 +00:00
Rui Ueyama ef0e647581 COFF: Implement x86 delay-load thunks.
llvm-svn: 242343
2015-07-15 22:26:57 +00:00
Rui Ueyama 25522f5d4a COFF: Support 32-bit x86 DLL import table.
llvm-svn: 241767
2015-07-09 00:45:50 +00:00
Rui Ueyama d8111f2c2e COFF: Fix ordinal-only delay-imported symbols.
DLLs can export symbols only by ordinal, and DLLs are also able to be
delay-loaded. The combination of the two is valid. I didn't expect
that combination. This patch implements that feature.

With this patch, LLD is now able to link a working executable of Chrome
for 64-bit debug build. The browser seemed to be working fine. Chrome is
good for testing because of its variety and size. It contains various
open-source libraries written by various people. The largest file in
Chrome is chrome.dll whose size is 496MB. LLD can link it in 24 seconds.
MSVC linker takes 48 seconds. So it is exactly 2x faster. (I measured
that with debug info and ICF being turned off.)

With this achievement, I think I can say that the new COFF linker is
now mostly feature complete for x86-64 Windows. I believe there are
still many lingering bugs, though.

llvm-svn: 241318
2015-07-03 04:32:49 +00:00
Rui Ueyama 0744e87fad COFF: Rename getReplacement -> repl.
The previous name was too long to my taste.

llvm-svn: 241215
2015-07-02 00:21:11 +00:00
Rui Ueyama 6bf638e688 COFF: Simplify and rename findMangle. NFC.
Occasionally we have to resolve an undefined symbol to its
mangled symbol. Previously, we did that on calling side of
findMangle by explicitly updating SymbolBody.
In this patch, mangled symbols are handled as weak aliases
for undefined symbols.

llvm-svn: 241213
2015-07-02 00:04:14 +00:00
Rui Ueyama f5313b3498 COFF: Allow mangled symbols as arguments for /export.
Usually dllexported symbols are defined with 'extern "C"',
so identifying them is easy. We can just do hash table lookup
to look up exported symbols.

However, C++ non-member functions are also allowed to be exported,
and they can be specified with unmangled name. So, if /export:foo
is given, we need to look up not only "foo" but also its all
mangled names. In MSVC mangling scheme, that means that we need to
look up any symbol which starts with "?foo@@Y".

In this patch, we scan the entire symbol table to search for
a mangled symbol. The symbol table is a DenseMap, and that doesn't
support table lookup by string prefix. This is of course very
inefficient. But that should be probably OK because the user
should always add 'extern "C"' to dllexported symbols.

llvm-svn: 240919
2015-06-28 22:16:41 +00:00
Rui Ueyama 810551a694 COFF: Add base relocation for delay-import table.
Because the address table of the delay-import table contains
absolute address, it needs to be added to the base relocation
table.

llvm-svn: 240844
2015-06-26 22:05:32 +00:00
Rui Ueyama 382dc96e29 COFF: Fix delay-import tables.
There were a few issues with the previous delay-import tables.

 - "Attribute" field should have been 1 instead of 0.
   (I don't know the meaning of this field, though.)
 - LEA and CALL operands had wrong addresses.
 - Address tables are in .didat (which is read-only).
   They should have been in .data.

llvm-svn: 240837
2015-06-26 21:40:15 +00:00
Rui Ueyama 610962061f Fix typo.
llvm-svn: 240298
2015-06-22 17:26:27 +00:00
Rui Ueyama a77336bd5d COFF: Support delay-load import tables.
DLLs are usually resolved at process startup, but you can
delay-load them by passing /delayload option to the linker.

If a /delayload is specified, the linker has to create data
which is similar to regular import table.
One notable difference is that the pointers in a delay-load
import table are originally pointing to thunks that resolves
themselves. Each thunk loads a DLL, resolve its name, and then
overwrites the pointer with the result so that subsequent
function calls directly call a desired function. The linker
has to emit thunks.

llvm-svn: 240250
2015-06-21 22:31:52 +00:00
Rui Ueyama 97dff9ee3a COFF: Support creating DLLs.
DLL files are in the same format as executables but they have export tables.
The format of the export table is described in PE/COFF spec section 5.3.

A new class, EdataContents, takes care of creating chunks for export tables.
What we need to do is to parse command line flags for dllexports, and then
instantiate the class to create chunks. For the writer, export table chunks
are opaque data -- it just add chunks to .edata section.

llvm-svn: 239869
2015-06-17 00:16:33 +00:00
Rui Ueyama c6b87363a1 COFF: Use named constants instead of sizeof().
llvm-svn: 239267
2015-06-07 22:00:28 +00:00
Rui Ueyama 94df713199 COFF: Make local variables local.
llvm-svn: 239244
2015-06-07 03:55:28 +00:00
Rui Ueyama 4b22fa7437 COFF: Move Windows-specific code from Chunk.{cpp,h} to DLL.{cpp,h}.
llvm-svn: 239239
2015-06-07 01:15:04 +00:00