wasm sections sizes are specified as u32s, and thus can be as large as
4GB. wasm-ld currently stores the offset into a section as an int32_t
which overflows on large sections and results in a crash. This change
makes it a int64_t to accommodate any valid wasm section and allow
catching even larger sections instead of wrapping around.
This PR fixes the issue by storing the offset as a int64_t, as well as
adding extra checks to handle un-encodeable sections to fail instead of
producing garbage wasm binaries, and also adds lit tests to make sure it
works. I confirmed the test fails on `main` but passes with this fix.
Fixes: #178286
This change adds initial support to libObject for reading compact
imports and support for writing compact imports in the linker.
There is minimal testing here since to tools like lllvm-readobj, and
obj2yaml don't currently report compact imports any differently.
See https://github.com/WebAssembly/compact-import-section
When merging `.bss` into a code section (e.g., `/MERGE:.bss=.text`), the
INT3 gap-filling loop in `writeSections()` would write past the output
buffer. This happens because `.bss` chunks have `hasData=false`, so they
contribute to `VirtualSize` but not `SizeOfRawData`. The loop was using
chunk RVAs without checking if they exceeded the raw data region.
This caused a crash on Windows with `/FILEALIGN:1` (access violation
0xC0000005). The tight alignment leaves no slack in the mapped buffer,
so the overflow immediately hits unmapped memory.
The fix bounds all memset operations to `rawSize` and exits early when
encountering chunks beyond the raw data boundary.
Fixes#180406
findMaskR11() was missing handling for duplex instructions. This caused
incorrect encoding when R_HEX_TPREL_11_X relocations were applied to
duplex instructions with large TLS offsets.
For duplex instructions, the immediate bits are located at positions
20-25 (mask 0x03f00000), not in the standard positions used for
non-duplex instructions.
This fix adds the isDuplex() check to findMaskR11() to return the
correct mask for duplex instruction encodings.
This was added in 94317878d826 ("LLD Support for Basic Block Sections")
and was only ever used for getRelocTargetVA. It was always redundant
even back then, as it was always the same as is.file, and so passing it
separately made it confusing and less obvious which file it was
referring to, but 2b5cb1bf628f ("[ELF] getRelocTargetVA: pass Ctx and
Relocation. NFC") removed that one use so it is now completely unused.
Remove it, and if anyone ever finds a need for it, they can just use
is.file like should have been done in the first place.
Commit a94060ca0c87 ("[ELF] Pass Ctx & to Relocations") swapped the
InputSectionBase &c argument for an InputSectionBase *sec member, and so
"c." was replaced with "sec->". However, this must have done in such a
way that "Local-Exec." was transformed to "Local-Exesec->" and
"RISCV::relocateAlloc." to "RISCV::relocateAllosec->", i.e. without the
use of something like clangd, and without appropriate word boundaries in
a regex.
In corner cases, it is profitable to move an llvm::SmallString instead
of copying it.
It is almost always profitable to move an std::vector
Changes suggested by performance-use-std-move from
https://github.com/llvm/llvm-project/pull/179467
We checked twice of size is equal to zero. This is not necessary and
makes the code a little bit less readable.
Reviewers: MaskRay, tmsri
Pull Request: https://github.com/llvm/llvm-project/pull/180304
Merge eh-frame-value-format{1..9}.s into eh-frame-fde-encoding.s
(encoding is the DWARF term) using split-file. Add .eh_frame and
.eh_frame_hdr content verification for absptr, udata2, sdata4, udata4.
Move error test (9) to eh-frame-invalid-fde-encoding.s.
They have multiple `not ld.lld` commands or they test multiple error
messages. Add --implicit-check-not=error: to catch unexpected errors.
While updating them, use directory isolation pattern and simplify
filenames where appropriate.
Rename abs-conflict.s to conflict-abs.s to be consistent with other
conflict*.s tests.
Currently, both GNU ld and lld only support
`table_enc = DW_EH_PE_datarel | DW_EH_PE_sdata4` for .eh_frame_hdr.
When a table entry exceeds the 32-bit range, we can use
`DW_EH_PE_sdata8` instead of reporting an error
(https://reviews.llvm.org/D49607 introduced the "PC offset is too large"
error). This is useful for certain large executables.
This patch auto-detects when 64-bit encoding is needed and upgrades
the encoding accordingly. We use DW_EH_PE_sdata8 when either a table
entry or eh_frame_ptr exceeds the 32-bit range.
Technically, eh_frame_ptr could remain sdata4 when only table entries
require sdata8, but there is little value in this flexibility since
.eh_frame/.eh_frame_hdr distance is a much less strict constraint than
.text/.eh_frame_hdr distance.
The implementation caches FDE data in EhFrameHeader during
updateAllocSize and reuses it in writeTo.
Previously, `EhFrameSection::getFdePc` was used to read the
`initial_location` value from .eh_frame FDEs. Since the value equals the
relocated symbol's VA for all cases that matter, we now obtain the value
directly and simplify the implementation.
Also update the outdated comment about sorting the FDE list; the ICF
case mentioned there no longer applies after
https://reviews.llvm.org/D116093.
In the new test eh-frame-hdr-sdata8.s, 3.lds is carefully crafted to
ensure that .eh_frame_hdr size requires fixed-point iteration (to test
`updateAllocSize`). This is also groundwork for compact unwind support
similar to Mach-O `__unwind_info`.
Close#172777
When a branch relocation has a non-zero addend (e.g., `bl _func+16`),
the linker was incorrectly computing `stub_address + addend` instead of
`function_address + addend`. This caused the branch to land in the wrong
location (past the stub section) rather than at the intended interior
point of the function.
The fix checks for non-zero addends on branch relocations and uses the
actual symbol VA in those cases. This makes sense semantically—branching
to an interior offset implies reliance on the original function's
layout, which an interposed replacement wouldn't preserve anyway.
Added test `arm64-branch-addend-stubs.s` that verifies the correct
behavior using `-flat_namespace` (which makes local symbols interposable
and thus routed through stubs).
[Assisted-by](https://t.ly/Dkjjk): Cursor IDE + claude-opus-4.5-high
Adopt modern test patterns for relocation overflow and alignment error
tests:
* Use `rm -rf %t && mkdir %t && cd %t` pattern for isolation. Use simple
filenames (32.o, 64.o, out.32) instead of %t-prefixed names
* Use `--defsym` instead of external input files where possible
* Omit `-o /dev/null` for negative tests (implicit when errors occur)
* Add `--implicit-check-not=error:` to catch unexpected errors
Update tests to include proper `error:` or `warning:` prefixes and
file/section information in CHECK patterns. Add
--implicit-check-not=error: to ensure no unexpected errors are produced.
Update tests to use the canonical error message format with `error:`
prefix and file:section information. Add `--implicit-check-not=error:`
to ensure no unexpected errors are produced.
This commit focuses on "out of range" and "not aligned" errors.
For a non-preemptible ifunc, `handleNonPreemptibleIfunc` creates a
cloned
symbol (`directSym`) to compute the addend of the IRELATIVE dynamic
relocation.
This cloned symbol wasn't tracked by `initSymbolAnchors`, so its value
wasn't adjusted during RISC-V/LoongArch linker relaxation.
This caused IRELATIVE addends to point to pre-relaxation addresses.
Fix this by:
- Tracking cloned IRELATIVE symbols in `ctx.irelativeSyms`
- Adding these symbols to `relaxAux->anchors` in `initSymbolAnchors`
This allows R_AARCH64_AUTH_ABS64 to follow R_AARCH64_ABS64's flow rather
than being implemented on the side in the place that is normally for
symbolic relocations.
Note that this has one implementation change: the RelExpr passed to
relaDyn is now RE_AARCH64_AUTH rather than R_ABS, but the two are
handled identically by InputSectionbase::getRelocTargetVA, and it was
inconsistent with relrAuthDyn which was passed RE_AARCH64_AUTH.
Reviewers: kovdan01
Pull Request: https://github.com/llvm/llvm-project/pull/171180
Currently, R_AARCH64_AUTH_ABS64 against a tagged global just ignores the
tagging and so, if out of the symbol's bounds, does not write the
negated original addend for the loader to determine which granule's tag
to use for it. Handle the composition of the two.
Note that R_AARCH64_AUTH_ABS64/RELATIVE encode the signing schema in the
upper 32 bits of the value at the relocation target, and so only the
lower 32 bits are available for use as an addend, including for Memtag's
disambiguation, and so if a wildly out-of-bounds PAuth relocation
against a tagged global is used we have no choice but to error out with
the current ABI.
Reviewers: MaskRay, kovdan01, smithp35, asl
Reviewed By: smithp35
Pull Request: https://github.com/llvm/llvm-project/pull/173291
Support both decimal and hexadecimal formats for cstring hashes in
the order file. Hex values must use the 0x prefix (case insensitive).
Examples:
CSTR;1234567890 (decimal)
CSTR;0x499602D2 (hex)
Co-authored-by: Sharon Xu <sharonxu@fb.com>
When linking PIC code as non-PIC we internally define `__memory_base`
and `__table_base`. However we were defining these incorrectly as data
symbols and not global symbols (as in Wasm globals).
This happened to work incidentally as long as there was a live reference
to the symbol. This is because the live reference would cause a GOT
entry to be created for these symbol and then they could be referenced
via via `R_WASM_GLOBAL_INDEX_LEB` or `R_WASM_GLOBAL_INDEX_I32`. However,
when no live reference existed there could still be references from
debug sections, and in that case the relocation code was crashing.
Fixes: #174676
This change renames `setImportAttributes` to `updateExistingUndefined`
which better defines what it does. We also now call this function for
all different symbol types.
In addition we preserve the `NO_STRIP` symbol attribute if any undefined
reference is tagged as such.
This is partial fix for #174676, although there seems to be anther crash
that occurs after this issue is fixed.
Splitting the VA / addend calculations between build and writeTo means
having to keep them in sync and duplicating some of the logic. Move all
such calculations into build, mirroring how the normal non-MIPS code in
Relocations.cpp ensures the addend and initial memory contents are set.
Fills unused parts of code segments with trap instructions instead of
zeroes. This is especially useful on x86-64 since 0x00 0x00 is a
two-byte instruction that performs a memory access. Benefits:
- Provides an explicit trap when executing invalid code.
- Required for security reasons when targeting LFI.
- Makes disassembling easier, especially without symbol information.
Previously an odd number of zero bytes between sections could cause a
disassembler to incorrectly disassemble the remainder of the program.
We already have code to extract bitcode files from archives so they can
be distributed. Extend this code to extract bitcode from FatLTO objects
too, which otherwise cannot be used with DTLTO.
DTLTO emits temporary files to allow distribution of archive member
inputs.
It also emits temporary files from the ThinLTO backend, such as the
index files needed for each distributed ThinLTO backend compilation.
This change brings archive member temporary files into line with those
produced by the ThinLTO backend. They are now emitted in the same
location, warnings are emitted if they cannot be deleted, and they are
cleaned up on abnormal exit (e.g. Ctrl-C). All temporary files are
preserved when --save-temps is specified.
The existing signal-handling test has been extended to cover the full
set of DTLTO temporary files, and a new test has been added to exercise
temporary file handling in normal operation. Additionally, a minimal
test has been added to show the COFF behaviour.
SIE Internal tracker: TOOLCHAIN-21022
When all undefined references to a version are weak, set vna_flags to
VER_FLG_WEAK in the .gnu.version_r section. This enables glibc ld.so to
report a warning instead of an error when the required version is not
found at runtime, supporting optional dependencies.
Per https://sourceware.org/bugzilla/show_bug.cgi?id=24718#c20 ,
glibc rtld since 2.30 (BZ #24741) tolerates missing versioned symbols
when the runtime shared object defines the required version. With this
vna_flags VER_FLG_WEAK change, rtld can also tolerate a completely
missing version, printing a message like:
```
% LD_PRELOAD=c2.so ./a
./a: /tmp/t/v2/c2.so: weak version `v1' not found (required by /tmp/t/v2/b.so)
a
```
instead of a fatal error.
In addition, add a comment about `vn.vernaxus.size() == 1`.
Symbols of empty names can be matched by `--why-live='*'`, which are
generally not useful.
* The first entry in a symbol table (STB_LOCAL and undefined)
* `STT_SECTION` symbols (emitted by LLVM integrated assembler when
needed by relocations). These input section symbols will be demoted by
`demoteAndCopyLocalSymbols`, so technically not really live.
In addition, such symbols of non-allocable sections currently lead to
crashes: `whyLive` does not record the section, causing the second
iteration of the `while (true)` loop in printWhyLive to call
`std::get<Symbol *>(cur)` when `cur` is an `InputSectionBase *`.
In addition, handle GCC crtendS.o `__FRAME_END__`, which is defined
relative to a `.eh_frame` section created with
`__attribute__((used, section(".eh_frame")))`.
Fix#176890
This resolves the FIXME in IRSymtab and cleans up the semantics of the
IRSymtab. The list of preserved symbols really shouldn't be seen as a
property of the IR symbol table, since it's an LTO-specific concern, and
it's very tenuous to claim that this information is actually present in
the bitcode file to be exposed through its symbol table.
Instead, this PR moves this logic into LTO's view of the symbol, which
allows consumers to determine preserved-ness themselves. This was broken
out of #164916; this prevents that PR from introducing a circular
dependency, but it still seems like an independently good idea by virtue
of the above.
Add time-trace scopes to the DTLTO-specific input-handling code to
improve observability and debugging.
These scopes are tested via LLD, as the primary purpose of this code is
to support member files of non-thin archives as DTLTO inputs.
`llvm-lto2` does not currently support archives. Adding archive support
to `llvm-lto2` solely for testing these scopes does not appear to be
worthwhile.
As part of this change, the deletion of temporary DTLTO input files has
been moved. Cleanup now occurs after LTO has completed, rather than
during destruction of the LTO object. This is required since by the time
the LTO object is destroyed, time-traces have already been finalized, so
no additional trace data can be recorded.
Recording time-trace data for temporary file deletion is important, as
this has been a source of performance issues in the past and an area
where we expect to make further performance improvements if supported by
the data.
SIE internal tracker: TOOLCHAIN-21021
If the symbol is preemptible the addend should be 0, not our
definition's VA. Note that by using addAddendOnlyRelocIfNonPreemptible
the generic Elf_Rel code will ensure the VA is written out as the addend
if the symbol is non-preemptible, and so writeTo only needs to write out
the VA in the case that we don't call it (so long as we make sure to
call relocateAlloc to actually apply any such relocations).
Reviewers: MaskRay
Pull Request: https://github.com/llvm/llvm-project/pull/150729
Due to heavy use of using namespace llvm, Reloc is often ambiguous with
llvm::Reloc, the relocation model. Previously, this was sometimes
disambiguated with macho::Reloc. This ambiguity is even more problematic
when using pre-compiled headers, where it's no longer "obvious" whether
it should be Reloc or macho::Reloc.
Therefore, rename Reloc to Relocation. This is also consistent with
lld/ELF, where the type is also named Relocation.