The MSVC linker generates range extensions for these thunks when needed.
This commit inlines the range extension into the thunk, making it both
slightly more optimal and easier to implement in LLD.
* Don't call raw_string_ostream::flush(), which is essentially a no-op.
* Strip calls to raw_string_ostream::str(), to avoid excess layer of indirection.
These thunks can be accessed using `__impchk_*` symbols, though they
are typically not called directly. Instead, they are used to populate the
auxiliary IAT. When the imported function is x86_64 (or an ARM64EC
function with a patched export thunk), the thunk is used to call it.
Otherwise, the OS may replace the thunk at runtime with a direct
pointer to the ARM64EC function to avoid the overhead.
Thunks themselves are the same as regular ARM64 thunks; they just need
to report the correct machine type. When processing the code, we also
need to use the current chunk's machine type instead of the global one:
we don't want to treat x86_64 thunks as ARM64EC, and we need to report
the correct machine type in hybrid binaries.
This is part of CHPE metadata containing a sorted list of x86_64 export
thunks RVAs and RVAs of ARM64EC functions associated with them. It's
stored in a dedicated .a64xrm section.
This implements Fast-Forward Sequences documented in ARM64EC
ABI https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi.
There are two conditions when linker should generate such thunks:
- For each exported ARM64EC functions.
It applies only to ARM64EC functions (we may also have pure x64
functions, for which no thunk is needed). MSVC linker creates
`EXP+<mangled export name>` symbol in those cases that points to the
thunk and uses that symbol for the export. It's observable from the
module: it's possible to reference such symbols as I did in the test.
Note that it uses export name, not name of the symbol that's exported
(as in `foo` in `/EXPORT:foo=bar`). This implies that if the same
function is exported multiple times, it will have multiple thunks. I
followed this MSVC behavior.
- For hybrid_patchable functions.
The linker tries to generate a thunk for each undefined `EXP+*` symbol
(and such symbols are created by the compiler as a target of weak alias
from the demangled name). MSVC linker tries to find corresponding
`*$hp_target` symbol and if fails to do so, it outputs a cryptic error
like `LINK : fatal error LNK1000: Internal error during
IMAGE::BuildImage`. I just skip generating the thunk in such case (which
causes undefined reference error). MSVC linker additionally checks that
the symbol complex type is a function (see also #102898). We generally
don't do such checks in LLD, so I made it less strict. It should be
fine: if it's some data symbol, it will not have `$hp_target` symbol, so
we will skip it anyway.
For x86_64 callable functions, ARM64EC requires an entry thunk generated
by the compiler. The linker interprets .hybmp sections to associate
function chunks with their entry points and writes an offset to thunks
preceding function section contents.
Additionally, ICF needs to be aware of entry thunks to not consider
chunks to be equal when they have different entry thunks, and GC needs
to mark entry thunks together with function chunks.
I used a new SectionChunkEC class instead of storing entry thunks in
SectionChunk, following the guideline to keep SectionChunk as compact as
possible. This way, there is no memory usage increase on non-EC targets.
When doing GC, we normally won't have dangling references, because such
a reference would keep the other section alive, keeping it from being
eliminated.
However, references within DWARF sections are ignored for the purposes
of GC (because otherwise, they would essentially keep everything alive,
defeating the point of the GC), see
c579a5b1d9 for more context.
Therefore, dangling relocations against discarded symbols are ignored
within DWARF sections (see maybeReportRelocationToDiscarded in
Chunks.cpp). Consequently, we also shouldn't create any pseudo
relocations for these cases, as we run into a null pointer dereference
when trying to generate the pseudo relocation info for it.
This fixes the downstream bug
https://github.com/mstorsjo/llvm-mingw/issues/418, fixing crashes on
combinations with -ffunction-sections, -fdata-sections,
-Wl,--gc-sections and debug info.
In 64 bit mode, any references to symbols that might end up autoimported
must be made via full 64 bit pointers (usually in .refptr stubs
generated by the compiler).
If referenced via e.g. a 32 bit rip relative offset, it might work
as long as DLLs are loaded close together in the 64 bit address
space, but will fail surprisingly later if they happen to be loaded
further apart. Any cases of that happening is usually a toolchain
error, and the sooner we can warn about it, the easier it is to diagnose.
Differential Revision: https://reviews.llvm.org/D154777
In preparation for removing the `#include "llvm/ADT/StringExtras.h"`
from the header to source file of `llvm/Support/Error.h`, first add in
all the missing includes that were previously included transitively
through this header.
This adds very minimal support for ARM64EC/ARM64X targets,
just enough for interesting test cases. Next patches in the
series extend llvm-objdump and llvm-readobj to provide
better tests. Those will also be useful for testing further
ARM64EC LLD support.
Differential Revision: https://reviews.llvm.org/D149086
By using emplace_back, as well as converting some loops to for-each, we can do more efficient vectorization.
Make copy constructor for TemporaryFile noexcept.
Reviewed By: #lld-macho, int3
Differential Revision: https://reviews.llvm.org/D139552
Similar to how `makeArrayRef` is deprecated in favor of deduction guides, do the
same for `makeMutableArrayRef`.
Once all of the places in-tree are using the deduction guides for
`MutableArrayRef`, we can mark `makeMutableArrayRef` as deprecated.
Differential Revision: https://reviews.llvm.org/D141814
This reverts commit 7370ff624d.
(and 47fb8ae2f9).
This commit broke the symbol type in import libraries generated
for mingw autoexported symbols, when the source files were built
with LTO. I'll commit a testcase that showcases this issue after
the revert.
LLVM contains a helpful function for getting the size of a C-style
array: `llvm::array_lengthof`. This is useful prior to C++17, but not as
helpful for C++17 or later: `std::size` already has support for C-style
arrays.
Differential Revision: https://reviews.llvm.org/D133598
llvm::sort is beneficial even when we use the iterator-based overload,
since it can optionally shuffle the elements (to detect
non-determinism). However llvm::sort is not usable everywhere, for
example, in compiler-rt.
Reviewed By: nhaehnle
Differential Revision: https://reviews.llvm.org/D130406
This reverts commit ef82063207.
- It conflicts with the existing llvm::size in STLExtras, which will now
never be called.
- Calling it without llvm:: breaks C++17 compat
Move all variables at file-scope or function-static-scope into a hosting structure (lld::CommonLinkerContext) that lives at lldMain()-scope. Drivers will inherit from this structure and add their own global state, in the same way as for the existing COFFLinkerContext.
See discussion in https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html
Differential Revision: https://reviews.llvm.org/D108850
lld-link used to consistently print all /verbose output to stdout, and that was
an intentional decision: https://reviews.llvm.org/rG4bce7bcc88f3https://reviews.llvm.org/rGe6e206d4b4814 added message() and log(),
and back then `log()` morally was just `if (verbose) message(...)`
and message() wrote to stdout.
So that change moved most /verbose-induced writes to outs() to
log(). Except for the one in printDiscardedMessage(), since
the check for `verbose` for that one is in the caller, in
Writer::createSections():
if (config->verbose)
sc->printDiscardedMessage();
Later, https://reviews.llvm.org/D41033 changed log() to write to
stderr. That moved lld-link from writing all its /verbose output
to stdout to writing almost all of its /verbose output to stderr --
except for printDiscardedMessage() output.
This change moves printDiscardedMessage() to call log() as well,
so that all /verbose output once again consistently goes to the same
stream.
Differential Revision: https://reviews.llvm.org/D116667
Original commit description:
[LLD] Remove global state in lld/COFF
This patch removes globals from the lldCOFF library, by moving globals
into a context class (COFFLinkingContext) and passing it around wherever
it's needed.
See https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html for
context about removing globals from LLD.
I also haven't moved the `driver` or `config` variables yet.
Differential Revision: https://reviews.llvm.org/D109634
This reverts commit a2fd05ada9.
Original commits were b4fa71eed3
and e03c7e367a.
This patch removes globals from the lldCOFF library, by moving globals
into a context class (COFFLinkingContext) and passing it around wherever
it's needed.
See https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html for
context about removing globals from LLD.
I also haven't moved the `driver` or `config` variables yet.
Differential Revision: https://reviews.llvm.org/D109634
The COFF driver produces an ABSOLUTE relocation base for an ADDR32
relocation type and the system is 64 bits (machine=AMD64). The
relocation information won't be added in the output and could
produce an incorrect address access during run-time. This change
set checks if the relocation type is IMAGE_REL_AMD64_ADDR32 and
if so, adds the relocated symbol as IMAGE_REL_BASED_HIGHLOW base.
Differential Revision: https://reviews.llvm.org/D96619
This is a different approach from D98993 that should achieve most of the
same benefit. The two changes are:
1. Sort the list of associated child sections by section name
2. Do not consider associated sections to have children themselves
This fixes the main issue, which was that we sometimes considered an
.xdata section to have a child .pdata section. That lead to slow links
and larger binaries (less xdata folding).
Otherwise, this should be NFC: we go back to ignoring .debug/.gljmp and
other metadata sections rather than only looking at pdata/xdata. We
discovered that we do care about other associated sections, like ASan
global registration metadata.
This reverts commit bacf9cf2c5 and
reinstates commit 1a9bd5b813.
Reverting this commit did not appear to make the problem go away, so we
can go ahead and reland it.
This reverts commit 5b7aef6eb4 and relands
6529d7c5a4.
The ASan error was debugged and determined to be the fault of an invalid
object file input in our test suite, which was fixed by my last change.
LLD's project policy is that it assumes input objects are valid, so I
have added a comment about this assumption to the relocation bounds
check.