This change implements support for the /stub flag to align with MS
link.exe. This option is useful when a program needs to optimize the DOS
program that executes when the PE runs on DOS, avoiding the traditional
hardcoded DOS program in LLD.
This refactor prepares for further ARM64X hybrid support, where these
helpers will need to work with either the native or EC symbol table
based on context.
Move `LinkerDriver::addUndefined` to` SymbolTable` to allow its use with
both symbol tables on ARM64X and rename it to `addGCRoot` to clarify its
distinct role compared to the existing `SymbolTable::addUndefined`.
Command-line `-include` arguments now apply to the EC symbol table, with
`mainSymtab` introduced in `linkerMain`. There will be more similar
cases. For `.drectve` sections, the corresponding symbol table is used
based on the context.
cg_profile in object is from CGProfilePass and it is often inaccurate.
While call-graph-ordering-file is provided by user. It is weird to
aggregate them together especially when call-graph-ordering-file is
accurate enough.
The addFile implementation does not rely on the SymbolTable object. With
#119294, the symbol table for input files is determined during the
construction of the objects representing them. To clarify that
relationship, this change moves the implementation from the SymbolTable
class to the LinkerDriver class.
Previously, we'd collect all input files in Driver::filePaths, and then
write filePaths after all other flags in
createResponseFile(). This meant that `-start-lib foo.obj -end-lib`
would be written as `-start-lib -end-lib foo.obj`, changing semantics.
Instead, remove Driver::filePaths, and handle things that fed into it
directly:
* OPT_INPUT is now handled in the same way as other flags, so that we
now get `-start-lib foo.obj -end-lib` in response.txt as desired. Add a
test for -start-lib / -end-lib and /reproduce:.
* OPT_wholearchive_file needs explicit handling now -- but before, this
was buggy as well: We'd put the flag without a rewritten path in
response.txt, but also the rewritten input file without wholearchive
semantics via filePaths. So this commit makes --whole-archive work with
/reproduce: too, and adds test coverage.
* /defaultlib:foo is now written as /defaultlib:foo into response.txt,
instead of writing the resolved path previously. While response.txt
looks slightly differently, both should have the same semantics, and
this should be mostly a no-op. (It does require updating a test.)
* /defaultlib: from .drectve sections are no longer recorded in
response.txt. This seems like a progression -- in the non-repro case
they come from .obj files, so they should come (only) from there in the
repro case too. This adds test coverage for this case.
Makes createResponseFile() look more like the versions in the ELF and
MachO ports too.
On hybrid ARM64X targets, ARM64 and ARM64EC input files operate in
separate namespaces and cannot reference each other. This change
introduces separate `SymbolTable` instances and associates each
`InputFile` with the appropriate table to reflect this behavior.
This change prepares for hybrid ARM64X support, which requires two
`SymbolTable` instances: one for native symbols and one for EC symbols.
In such cases, `config.machine` will remain ARM64X, while the
`SymbolTable` instances will store ARM64 and ARM64EC machine types.
This change prepares for the introduction of separate hybrid namespaces.
Hybrid images will require two `SymbolTable` instances, making it
necessary to associate `InputFile` objects with the relevant one.
Similar to #112319 for ELF. While there is some initial boilerplate, it
can simplify some call sites that use Twine, especially when a printed
element uses `ctx` or toString.
Since these symbols cannot be mangled or demangled, there is no symbol
to check for conflicts in `checkLazyECPair`, nor is there an alias to
create in `addUndefined`. Attempting to create an import library with
such symbols results in an error; the patch includes a test to ensure
the error is handled correctly.
This is a follow-up to #115567.
On ARM64EC, a symbol may be defined in either its mangled or demangled
form (or both). To ensure consistent linking for entry points and
exports, define an anti-dependency symbol that binds both forms, similar
to how compiler-generated code references external functions.
Co-authored-by: Billy Laws <blaws05@gmail.com>
Anti-dependency symbols are allowed to be duplicated, with the first
definition taking precedence. If a regular weak alias is present, it is
preferred over an anti-dependency definition. Chaining anti-dependencies
is not allowed.
The assumption that a symbol is either `Defined` or `Undefined` is not
always true for some cases. For example, `mangleMaybe` may create a weak
alias to a lazy archive symbol.
__arm64x_native_entrypoint and __guard_check_icall_a64n_fptr are
relevant only for hybrid ARM64X images, we need support for separate
namespaces before we can support them.
__hybrid_image_info_bitfield is 0 in MSVC linker in all tests I tried.
Fill the regular delay-load IAT with x86_64 delay-load thunks. Similarly
to regular imports, create an auxiliary IAT and its copy for ARM64EC
calls. These are filled with the same `__impchk_` thunks used for
regular imports, which perform an indirect call with
`__icall_helper_arm64ec` on the regular delay-load IAT. These auxiliary
IATs are exposed via CHPE metadata starting from version 2.
The MSVC linker creates one more copy of the auxiliary IAT. `__imp_func`
symbols refer to that hidden IAT, while the `#func` thunk performs a
call with the public auxiliary IAT. If the public auxiliary IAT is fine
for `#func`, it should be fine for calls using the `__imp_func` symbol
as well. Therefore, I made `__imp_func` refer to that IAT too.
In addition to the auxiliary IAT, ARM64EC modules also contain a copy of
it. At runtime, the auxiliary IAT is filled with the addresses of actual
ARM64EC functions when possible. If patching is detected, the OS may use
the IAT copy to revert the auxiliary IAT, ensuring that the call checker
is used for calls to imported functions.