aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/COFF/Chunks.cpp2
-rw-r--r--lld/COFF/DriverUtils.cpp3
-rw-r--r--lld/COFF/Options.td1
-rw-r--r--lld/ELF/Arch/AArch64.cpp7
-rw-r--r--lld/ELF/Arch/RISCV.cpp49
-rw-r--r--lld/ELF/Arch/RISCVInternalRelocations.h113
-rw-r--r--lld/ELF/Driver.cpp18
-rw-r--r--lld/ELF/InputFiles.cpp5
-rw-r--r--lld/ELF/Options.td2
-rw-r--r--lld/ELF/Relocations.cpp30
-rw-r--r--lld/ELF/ScriptParser.cpp7
-rw-r--r--lld/ELF/Symbols.h6
-rw-r--r--lld/ELF/SyntheticSections.cpp170
-rw-r--r--lld/ELF/SyntheticSections.h43
-rw-r--r--lld/ELF/Target.cpp9
-rw-r--r--lld/ELF/Target.h1
-rw-r--r--lld/MachO/Arch/X86_64.cpp5
-rw-r--r--lld/MachO/ConcatOutputSection.cpp6
-rw-r--r--lld/MachO/Config.h1
-rw-r--r--lld/MachO/Driver.cpp82
-rw-r--r--lld/MachO/ICF.cpp63
-rw-r--r--lld/MachO/InputFiles.cpp18
-rw-r--r--lld/MachO/InputSection.cpp3
-rw-r--r--lld/MachO/Options.td8
-rw-r--r--lld/MachO/SectionPriorities.cpp130
-rw-r--r--lld/MachO/SectionPriorities.h28
-rw-r--r--lld/MachO/Sections.cpp2
-rw-r--r--lld/MachO/SymbolTable.cpp35
-rw-r--r--lld/MachO/SyntheticSections.cpp62
-rw-r--r--lld/MachO/UnwindInfoSection.cpp75
-rw-r--r--lld/MinGW/Driver.cpp2
-rw-r--r--lld/docs/ELF/linker_script.rst19
-rw-r--r--lld/docs/ReleaseNotes.rst3
-rw-r--r--lld/docs/ld.lld.113
-rw-r--r--lld/test/COFF/arm64ec-codemap.test36
-rw-r--r--lld/test/COFF/driver.test3
-rw-r--r--lld/test/ELF/aarch64-funcinit64-invalid.s18
-rw-r--r--lld/test/ELF/aarch64-funcinit64.s19
-rw-r--r--lld/test/ELF/dso-undef-extract-lazy.s41
-rw-r--r--lld/test/ELF/linkerscript/version-script.s2
-rw-r--r--lld/test/ELF/riscv-vendor-relocations.s15
-rw-r--r--lld/test/ELF/version-script-extern-undefined.s2
-rw-r--r--lld/test/MachO/handle-invalid-section-reference-too-big.test128
-rw-r--r--lld/test/MachO/handle-invalid-section-reference-zero.test128
-rw-r--r--lld/test/MachO/invalid/bad-offsets.s45
-rw-r--r--lld/test/MachO/order-file-cstring.s22
-rw-r--r--lld/test/MachO/read-workers.s3
-rw-r--r--lld/test/MachO/set-slop-scale.s11
-rw-r--r--lld/test/MachO/weak-alias-override.s97
-rw-r--r--lld/test/MachO/x86-64-relocs.s18
-rw-r--r--lld/test/MinGW/driver.test6
-rw-r--r--lld/test/wasm/alias.s4
-rw-r--r--lld/test/wasm/bss-only.s4
-rw-r--r--lld/test/wasm/build-id.test8
-rw-r--r--lld/test/wasm/call-indirect.s12
-rw-r--r--lld/test/wasm/comdats.ll10
-rw-r--r--lld/test/wasm/compress-relocs.s12
-rw-r--r--lld/test/wasm/compress-relocs64.s12
-rw-r--r--lld/test/wasm/custom-section-name.ll16
-rw-r--r--lld/test/wasm/data-layout.s14
-rw-r--r--lld/test/wasm/data-segment-merging.ll16
-rw-r--r--lld/test/wasm/data-segments.ll28
-rw-r--r--lld/test/wasm/debuginfo.test2
-rwxr-xr-xlld/test/wasm/dylink-non-pie.s2
-rw-r--r--lld/test/wasm/emit-relocs.s6
-rw-r--r--lld/test/wasm/externref.s2
-rw-r--r--lld/test/wasm/gc-sections.ll12
-rw-r--r--lld/test/wasm/global-base.test8
-rw-r--r--lld/test/wasm/globals.s2
-rw-r--r--lld/test/wasm/import-memory.test2
-rw-r--r--lld/test/wasm/init-fini.ll2
-rw-r--r--lld/test/wasm/large-memory.test2
-rw-r--r--lld/test/wasm/local-symbols.ll10
-rw-r--r--lld/test/wasm/locals-duplicate.test24
-rw-r--r--lld/test/wasm/lto/tls.ll4
-rw-r--r--lld/test/wasm/lto/used.ll4
-rw-r--r--lld/test/wasm/map-file.s18
-rw-r--r--lld/test/wasm/memory-naming.test6
-rw-r--r--lld/test/wasm/merge-string.s14
-rw-r--r--lld/test/wasm/multi-table.s8
-rw-r--r--lld/test/wasm/no-strip-segment.s8
-rw-r--r--lld/test/wasm/no-tls.s2
-rw-r--r--lld/test/wasm/page-size.s4
-rw-r--r--lld/test/wasm/pic-static.ll8
-rw-r--r--lld/test/wasm/reloc-relative.s24
-rw-r--r--lld/test/wasm/runtime-relocations-himem.s60
-rw-r--r--lld/test/wasm/shared-memory-no-atomics.yaml2
-rw-r--r--lld/test/wasm/shared-memory.yaml12
-rw-r--r--lld/test/wasm/stack-first.test29
-rw-r--r--lld/test/wasm/startstop.ll16
-rw-r--r--lld/test/wasm/table-base.s4
-rw-r--r--lld/test/wasm/tls-align.s2
-rw-r--r--lld/test/wasm/tls-non-shared-memory-basic.s4
-rw-r--r--lld/test/wasm/tls-non-shared-memory.s14
-rw-r--r--lld/test/wasm/tls.s2
-rw-r--r--lld/test/wasm/undefined-weak-call.s4
-rw-r--r--lld/test/wasm/weak-alias-overide.ll4
-rw-r--r--lld/test/wasm/weak-alias.ll4
-rw-r--r--lld/test/wasm/weak-symbols.s8
-rw-r--r--lld/test/wasm/weak-undefined-pic.s2
-rw-r--r--lld/test/wasm/weak-undefined.s4
-rw-r--r--lld/test/wasm/wrap_import.s32
-rw-r--r--lld/wasm/Driver.cpp10
-rw-r--r--lld/wasm/InputChunks.cpp14
-rw-r--r--lld/wasm/Options.td5
-rw-r--r--lld/wasm/SyntheticSections.cpp12
106 files changed, 1540 insertions, 629 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 548d87b..409491d 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -946,7 +946,7 @@ void ECCodeMapChunk::writeTo(uint8_t *buf) const {
auto table = reinterpret_cast<chpe_range_entry *>(buf);
for (uint32_t i = 0; i < map.size(); i++) {
const ECCodeMapEntry &entry = map[i];
- uint32_t start = entry.first->getRVA();
+ uint32_t start = entry.first->getRVA() & ~0xfff;
table[i].StartOffset = start | entry.type;
table[i].Length = entry.last->getRVA() + entry.last->getSize() - start;
}
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 10a3934..42c7f93 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -862,6 +862,9 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> argv) {
<< "', did you mean '" << nearest << "'";
}
+ if (args.hasArg(OPT_link))
+ Warn(ctx) << "ignoring /link, did you pass it multiple times?";
+
if (args.hasArg(OPT_lib))
Warn(ctx) << "ignoring /lib since it's not the first argument";
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index d77478f..6c4c7f8 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -71,6 +71,7 @@ def noimplib : F<"noimplib">,
def lib : F<"lib">,
HelpText<"Act like lib.exe; must be first argument if present">;
def libpath : P<"libpath", "Additional library search path">;
+def link : F<"link">, HelpText<"Ignored for compatibility">;
def linkrepro : Joined<["/", "-", "/?", "-?"], "linkrepro:">,
MetaVarName<"directory">,
HelpText<"Write repro.tar containing inputs and command to reproduce link">;
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 2a97df4..4613539 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -114,6 +114,7 @@ AArch64::AArch64(Ctx &ctx) : TargetInfo(ctx) {
copyRel = R_AARCH64_COPY;
relativeRel = R_AARCH64_RELATIVE;
iRelativeRel = R_AARCH64_IRELATIVE;
+ iRelSymbolicRel = R_AARCH64_FUNCINIT64;
gotRel = R_AARCH64_GLOB_DAT;
pltRel = R_AARCH64_JUMP_SLOT;
symbolicRel = R_AARCH64_ABS64;
@@ -137,6 +138,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
case R_AARCH64_ABS16:
case R_AARCH64_ABS32:
case R_AARCH64_ABS64:
+ case R_AARCH64_FUNCINIT64:
case R_AARCH64_ADD_ABS_LO12_NC:
case R_AARCH64_LDST128_ABS_LO12_NC:
case R_AARCH64_LDST16_ABS_LO12_NC:
@@ -267,7 +269,8 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const {
}
RelType AArch64::getDynRel(RelType type) const {
- if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64)
+ if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64 ||
+ type == R_AARCH64_FUNCINIT64)
return type;
return R_AARCH64_NONE;
}
@@ -762,7 +765,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
relocateNoSym(loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, val);
break;
default:
- llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
+ llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
}
}
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 5ed89e4..7ec75b0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -8,6 +8,7 @@
#include "InputFiles.h"
#include "OutputSections.h"
+#include "RISCVInternalRelocations.h"
#include "RelocScan.h"
#include "Symbols.h"
#include "SyntheticSections.h"
@@ -345,8 +346,15 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
case R_RISCV_SUB_ULEB128:
return RE_RISCV_LEB128;
default:
- Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
- << ") against symbol " << &s;
+ if (type.v & INTERNAL_RISCV_VENDOR_MASK) {
+ Err(ctx) << getErrorLoc(ctx, loc)
+ << "unsupported vendor-specific relocation " << type
+ << " against symbol " << &s;
+ return R_NONE;
+ }
+ Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation ("
+ << (type.v & ~INTERNAL_RISCV_VENDOR_MASK) << ") against symbol "
+ << &s;
return R_NONE;
}
}
@@ -859,7 +867,7 @@ static bool relax(Ctx &ctx, int pass, InputSection &sec) {
std::fill_n(aux.relocTypes.get(), relocs.size(), R_RISCV_NONE);
aux.writes.clear();
- for (auto [i, r] : llvm::enumerate(relocs)) {
+ for (auto [i, r] : llvm::enumerate(riscv_vendor_relocs(relocs))) {
const uint64_t loc = secAddr + r.offset - delta;
uint32_t &cur = aux.relocDeltas[i], remove = 0;
switch (r.type) {
@@ -1503,12 +1511,19 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
rvVendor = sym.getName();
continue;
} else if (!rvVendor.empty()) {
- Err(ctx) << getErrorLoc(ctx, loc)
- << "unknown vendor-specific relocation (" << type.v
- << ") in namespace '" << rvVendor << "' against symbol '" << &sym
- << "'";
+ uint32_t VendorFlag = getRISCVVendorRelMarker(rvVendor);
+ if (!VendorFlag) {
+ Err(ctx) << getErrorLoc(ctx, loc)
+ << "unknown vendor-specific relocation (" << type.v
+ << ") in namespace '" << rvVendor << "' against symbol '"
+ << &sym << "'";
+ rvVendor = "";
+ continue;
+ }
+
rvVendor = "";
- continue;
+ assert((type.v < 256) && "Out of range relocation detected!");
+ type.v |= VendorFlag;
}
rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
@@ -1533,3 +1548,21 @@ template <class ELFT> void RISCV::scanSection1(InputSectionBase &sec) {
void RISCV::scanSection(InputSectionBase &sec) {
invokeELFT(scanSection1, sec);
}
+
+namespace lld::elf {
+uint32_t getRISCVVendorRelMarker(StringRef rvVendor) {
+ return StringSwitch<uint32_t>(rvVendor)
+ .Case("QUALCOMM", INTERNAL_RISCV_VENDOR_QUALCOMM)
+ .Case("ANDES", INTERNAL_RISCV_VENDOR_ANDES)
+ .Default(0);
+}
+
+std::optional<StringRef> getRISCVVendorString(RelType ty) {
+ if ((ty.v & INTERNAL_RISCV_VENDOR_MASK) == INTERNAL_RISCV_VENDOR_QUALCOMM)
+ return "QUALCOMM";
+ if ((ty.v & INTERNAL_RISCV_VENDOR_MASK) == INTERNAL_RISCV_VENDOR_ANDES)
+ return "ANDES";
+ return std::nullopt;
+}
+
+} // namespace lld::elf
diff --git a/lld/ELF/Arch/RISCVInternalRelocations.h b/lld/ELF/Arch/RISCVInternalRelocations.h
new file mode 100644
index 0000000..35e2f53
--- /dev/null
+++ b/lld/ELF/Arch/RISCVInternalRelocations.h
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_ARCH_RISCVINTERNALRELOCATIONS_H
+#define LLD_ELF_ARCH_RISCVINTERNALRELOCATIONS_H
+
+#include "Relocations.h"
+#include "Symbols.h"
+
+namespace lld::elf {
+
+// Bit 8 of RelType is used to indicate linker-internal relocations that are
+// not vendor-specific.
+// These are internal relocation numbers for GP/X0 relaxation. They aren't part
+// of the psABI spec.
+constexpr uint32_t INTERNAL_R_RISCV_GPREL_I = 256;
+constexpr uint32_t INTERNAL_R_RISCV_GPREL_S = 257;
+constexpr uint32_t INTERNAL_R_RISCV_X0REL_I = 258;
+constexpr uint32_t INTERNAL_R_RISCV_X0REL_S = 259;
+
+// Bits 9 -> 31 of RelType are used to indicate vendor-specific relocations.
+constexpr uint32_t INTERNAL_RISCV_VENDOR_MASK = 0xFFFFFFFF << 9;
+constexpr uint32_t INTERNAL_RISCV_VENDOR_QUALCOMM = 1 << 9;
+constexpr uint32_t INTERNAL_RISCV_VENDOR_ANDES = 2 << 9;
+
+constexpr uint32_t INTERNAL_RISCV_QC_ABS20_U =
+ INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_ABS20_U;
+constexpr uint32_t INTERNAL_RISCV_QC_E_BRANCH =
+ INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_BRANCH;
+constexpr uint32_t INTERNAL_RISCV_QC_E_32 =
+ INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_32;
+constexpr uint32_t INTERNAL_RISCV_QC_E_CALL_PLT =
+ INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_CALL_PLT;
+
+constexpr uint32_t INTERNAL_RISCV_NDS_BRANCH_10 =
+ INTERNAL_RISCV_VENDOR_ANDES | llvm::ELF::R_RISCV_NDS_BRANCH_10;
+
+uint32_t getRISCVVendorRelMarker(llvm::StringRef rvVendor);
+std::optional<llvm::StringRef> getRISCVVendorString(RelType ty);
+
+class vendor_reloc_iterator {
+public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = Relocation;
+ using difference_type = std::ptrdiff_t;
+ using pointer = Relocation *;
+ using reference = Relocation; // returned by value
+
+ vendor_reloc_iterator(MutableArrayRef<Relocation>::iterator i,
+ MutableArrayRef<Relocation>::iterator e)
+ : it(i), end(e) {}
+
+ // Dereference
+ Relocation operator*() const {
+ Relocation r = *it;
+ r.type.v |= rvVendorFlag;
+ return r;
+ }
+
+ struct vendor_reloc_proxy {
+ Relocation r;
+ const Relocation *operator->() const { return &r; }
+ };
+
+ vendor_reloc_proxy operator->() const {
+ return vendor_reloc_proxy{this->operator*()};
+ }
+
+ vendor_reloc_iterator &operator++() {
+ ++it;
+ if (it != end && it->type == llvm::ELF::R_RISCV_VENDOR) {
+ rvVendorFlag = getRISCVVendorRelMarker(it->sym->getName());
+ ++it;
+ } else {
+ rvVendorFlag = 0;
+ }
+ return *this;
+ }
+
+ vendor_reloc_iterator operator++(int) {
+ vendor_reloc_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ bool operator==(const vendor_reloc_iterator &other) const {
+ return it == other.it;
+ }
+ bool operator!=(const vendor_reloc_iterator &other) const {
+ return it != other.it;
+ }
+
+ Relocation *getUnderlyingRelocation() const { return &*it; }
+
+private:
+ MutableArrayRef<Relocation>::iterator it;
+ MutableArrayRef<Relocation>::iterator end;
+ uint32_t rvVendorFlag = 0;
+};
+
+inline auto riscv_vendor_relocs(MutableArrayRef<Relocation> arr) {
+ return llvm::make_range(vendor_reloc_iterator(arr.begin(), arr.end()),
+ vendor_reloc_iterator(arr.end(), arr.end()));
+}
+
+} // namespace lld::elf
+
+#endif
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index e52d3a0..8647752 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -156,23 +156,23 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(Ctx &ctx,
std::pair<ELFKind, uint16_t> ret =
StringSwitch<std::pair<ELFKind, uint16_t>>(s)
- .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64})
- .Cases("aarch64elfb", "aarch64linuxb", {ELF64BEKind, EM_AARCH64})
- .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM})
- .Cases("armelfb", "armelfb_linux_eabi", {ELF32BEKind, EM_ARM})
+ .Cases({"aarch64elf", "aarch64linux"}, {ELF64LEKind, EM_AARCH64})
+ .Cases({"aarch64elfb", "aarch64linuxb"}, {ELF64BEKind, EM_AARCH64})
+ .Cases({"armelf", "armelf_linux_eabi"}, {ELF32LEKind, EM_ARM})
+ .Cases({"armelfb", "armelfb_linux_eabi"}, {ELF32BEKind, EM_ARM})
.Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
- .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS})
- .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS})
+ .Cases({"elf32btsmip", "elf32btsmipn32"}, {ELF32BEKind, EM_MIPS})
+ .Cases({"elf32ltsmip", "elf32ltsmipn32"}, {ELF32LEKind, EM_MIPS})
.Case("elf32lriscv", {ELF32LEKind, EM_RISCV})
- .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC})
- .Cases("elf32lppc", "elf32lppclinux", {ELF32LEKind, EM_PPC})
+ .Cases({"elf32ppc", "elf32ppclinux"}, {ELF32BEKind, EM_PPC})
+ .Cases({"elf32lppc", "elf32lppclinux"}, {ELF32LEKind, EM_PPC})
.Case("elf32loongarch", {ELF32LEKind, EM_LOONGARCH})
.Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
.Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
.Case("elf64lriscv", {ELF64LEKind, EM_RISCV})
.Case("elf64ppc", {ELF64BEKind, EM_PPC64})
.Case("elf64lppc", {ELF64LEKind, EM_PPC64})
- .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64})
+ .Cases({"elf_amd64", "elf_x86_64"}, {ELF64LEKind, EM_X86_64})
.Case("elf_i386", {ELF32LEKind, EM_386})
.Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
.Case("elf64_sparc", {ELF64BEKind, EM_SPARCV9})
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index a5921fe..240a6d0 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1676,8 +1676,9 @@ template <class ELFT> void SharedFile::parse() {
const uint16_t ver = versyms[i], idx = ver & ~VERSYM_HIDDEN;
if (sym.isUndefined()) {
- // For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but
- // as of binutils 2.34, GNU ld produces VER_NDX_LOCAL.
+ // Index 0 (VER_NDX_LOCAL) is used for unversioned undefined symbols.
+ // GNU ld versions between 2.35 and 2.45 also generate VER_NDX_GLOBAL
+ // for this case (https://sourceware.org/PR33577).
if (ver != VER_NDX_LOCAL && ver != VER_NDX_GLOBAL) {
if (idx >= verneeds.size()) {
ErrAlways(ctx) << "corrupt input file: version need index " << idx
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 75184de..c2111e5 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -154,7 +154,7 @@ def bp_startup_sort: JJ<"bp-startup-sort=">, MetaVarName<"[none,function]">,
// Auxiliary options related to balanced partition
defm bp_compression_sort_startup_functions: BB<"bp-compression-sort-startup-functions",
- "When --irpgo-profile is pecified, prioritize function similarity for compression in addition to startup time", "">;
+ "When --irpgo-profile is specified, prioritize function similarity for compression in addition to startup time", "">;
def verbose_bp_section_orderer: FF<"verbose-bp-section-orderer">,
HelpText<"Print information on balanced partitioning">;
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index d21376f..59aa430 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -849,8 +849,8 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type,
// only the low bits are used.
if (e == R_GOT || e == R_PLT)
return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.isPic;
- // R_AARCH64_AUTH_ABS64 requires a dynamic relocation.
- if (e == RE_AARCH64_AUTH)
+ // R_AARCH64_AUTH_ABS64 and iRelSymbolicRel require a dynamic relocation.
+ if (e == RE_AARCH64_AUTH || type == ctx.target->iRelSymbolicRel)
return false;
// The behavior of an undefined weak reference is implementation defined.
@@ -1023,6 +1023,23 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
}
return;
}
+ if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
+ if (sym.isPreemptible) {
+ auto diag = Err(ctx);
+ diag << "relocation " << type
+ << " cannot be used against preemptible symbol '" << &sym << "'";
+ printLocation(diag, *sec, sym, offset);
+ } else if (isIfunc) {
+ auto diag = Err(ctx);
+ diag << "relocation " << type
+ << " cannot be used against ifunc symbol '" << &sym << "'";
+ printLocation(diag, *sec, sym, offset);
+ } else {
+ part.relaDyn->addReloc({ctx.target->iRelativeRel, sec, offset, false,
+ sym, addend, R_ABS});
+ return;
+ }
+ }
part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
// MIPS ABI turns using of GOT and dynamic relocations inside out.
@@ -1278,7 +1295,7 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type,
// label, so TLSDESC=>IE will be categorized as R_RELAX_TLS_GD_TO_LE. We fix
// the categorization in RISCV::relocateAllosec->
if (sym.isPreemptible) {
- sym.setFlags(NEEDS_TLSGD_TO_IE);
+ sym.setFlags(NEEDS_TLSIE);
sec->addReloc({ctx.target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_IE),
type, offset, addend, &sym});
} else {
@@ -1618,18 +1635,13 @@ void elf::postScanRelocations(Ctx &ctx) {
else
got->addConstant({R_ABS, ctx.target->tlsOffsetRel, offsetOff, 0, &sym});
}
- if (flags & NEEDS_TLSGD_TO_IE) {
- got->addEntry(sym);
- ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsGotRel, *got,
- sym.getGotOffset(ctx), sym);
- }
if (flags & NEEDS_GOT_DTPREL) {
got->addEntry(sym);
got->addConstant(
{R_ABS, ctx.target->tlsOffsetRel, sym.getGotOffset(ctx), 0, &sym});
}
- if ((flags & NEEDS_TLSIE) && !(flags & NEEDS_TLSGD_TO_IE))
+ if (flags & NEEDS_TLSIE)
addTpOffsetGotEntry(ctx, sym);
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 4b9c941..b61dc647 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -450,7 +450,7 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
.Case("elf64-powerpc", {ELF64BEKind, EM_PPC64})
.Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64})
.Case("elf64-x86-64", {ELF64LEKind, EM_X86_64})
- .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS})
+ .Cases({"elf32-tradbigmips", "elf32-bigmips"}, {ELF32BEKind, EM_MIPS})
.Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS})
.Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS})
.Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
@@ -463,7 +463,8 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
.Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH})
.Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH})
.Case("elf64-s390", {ELF64BEKind, EM_S390})
- .Cases("elf32-hexagon", "elf32-littlehexagon", {ELF32LEKind, EM_HEXAGON})
+ .Cases({"elf32-hexagon", "elf32-littlehexagon"},
+ {ELF32LEKind, EM_HEXAGON})
.Default({ELFNoneKind, EM_NONE});
}
@@ -745,7 +746,7 @@ StringMatcher ScriptParser::readFilePatterns() {
SortSectionPolicy ScriptParser::peekSortKind() {
return StringSwitch<SortSectionPolicy>(peek())
.Case("REVERSE", SortSectionPolicy::Reverse)
- .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name)
+ .Cases({"SORT", "SORT_BY_NAME"}, SortSectionPolicy::Name)
.Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment)
.Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority)
.Case("SORT_NONE", SortSectionPolicy::None)
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index c117e3b..034c873 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -48,7 +48,7 @@ enum {
NEEDS_COPY = 1 << 3,
NEEDS_TLSDESC = 1 << 4,
NEEDS_TLSGD = 1 << 5,
- NEEDS_TLSGD_TO_IE = 1 << 6,
+ // 1 << 6 unused
NEEDS_GOT_DTPREL = 1 << 7,
NEEDS_TLSIE = 1 << 8,
NEEDS_GOT_AUTH = 1 << 9,
@@ -313,6 +313,8 @@ public:
// represents the Verdef index within the input DSO, which will be converted
// to a Verneed index in the output. Otherwise, this represents the Verdef
// index (VER_NDX_LOCAL, VER_NDX_GLOBAL, or a named version).
+ // VER_NDX_LOCAL indicates a defined symbol that has been localized by a
+ // version script's local: directive or --exclude-libs.
uint16_t versionId;
LLVM_PREFERRED_TYPE(bool)
uint8_t versionScriptAssigned : 1;
@@ -350,7 +352,7 @@ public:
bool needsDynReloc() const {
return flags.load(std::memory_order_relaxed) &
(NEEDS_COPY | NEEDS_GOT | NEEDS_PLT | NEEDS_TLSDESC | NEEDS_TLSGD |
- NEEDS_TLSGD_TO_IE | NEEDS_GOT_DTPREL | NEEDS_TLSIE);
+ NEEDS_GOT_DTPREL | NEEDS_TLSIE);
}
void allocateAux(Ctx &ctx) {
assert(auxIdx == 0);
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index a4150eb..1e9d44f 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -54,8 +54,6 @@ using llvm::support::endian::read32le;
using llvm::support::endian::write32le;
using llvm::support::endian::write64le;
-constexpr size_t MergeNoTailSection::numShards;
-
static uint64_t readUint(Ctx &ctx, uint8_t *buf) {
return ctx.arg.is64 ? read64(ctx, buf) : read32(ctx, buf);
}
@@ -542,43 +540,6 @@ void EhFrameSection::finalizeContents() {
this->size = off;
}
-// Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table
-// to get an FDE from an address to which FDE is applied. This function
-// returns a list of such pairs.
-SmallVector<EhFrameSection::FdeData, 0> EhFrameSection::getFdeData() const {
- uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff;
- SmallVector<FdeData, 0> ret;
-
- uint64_t va = getPartition(ctx).ehFrameHdr->getVA();
- for (CieRecord *rec : cieRecords) {
- uint8_t enc = getFdeEncoding(rec->cie);
- for (EhSectionPiece *fde : rec->fdes) {
- uint64_t pc = getFdePc(buf, fde->outputOff, enc);
- uint64_t fdeVA = getParent()->addr + fde->outputOff;
- if (!isInt<32>(pc - va)) {
- Err(ctx) << fde->sec << ": PC offset is too large: 0x"
- << Twine::utohexstr(pc - va);
- continue;
- }
- ret.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)});
- }
- }
-
- // Sort the FDE list by their PC and uniqueify. Usually there is only
- // one FDE for a PC (i.e. function), but if ICF merges two functions
- // into one, there can be more than one FDEs pointing to the address.
- auto less = [](const FdeData &a, const FdeData &b) {
- return a.pcRel < b.pcRel;
- };
- llvm::stable_sort(ret, less);
- auto eq = [](const FdeData &a, const FdeData &b) {
- return a.pcRel == b.pcRel;
- };
- ret.erase(llvm::unique(ret, eq), ret.end());
-
- return ret;
-}
-
static uint64_t readFdeAddr(Ctx &ctx, uint8_t *buf, int size) {
switch (size) {
case DW_EH_PE_udata2:
@@ -632,14 +593,79 @@ void EhFrameSection::writeTo(uint8_t *buf) {
}
}
- // Apply relocations. .eh_frame section contents are not contiguous
- // in the output buffer, but relocateAlloc() still works because
- // getOffset() takes care of discontiguous section pieces.
+ // Apply relocations to .eh_frame entries. This includes CIE personality
+ // pointers, FDE initial_location fields, and LSDA pointers.
for (EhInputSection *s : sections)
ctx.target->relocateEh(*s, buf);
- if (getPartition(ctx).ehFrameHdr && getPartition(ctx).ehFrameHdr->getParent())
- getPartition(ctx).ehFrameHdr->write();
+ EhFrameHeader *hdr = getPartition(ctx).ehFrameHdr.get();
+ if (!hdr || !hdr->getParent())
+ return;
+
+ // Write the .eh_frame_hdr section, which contains a binary search table of
+ // pointers to FDEs. This must be written after .eh_frame relocation since
+ // the content depends on relocated initial_location fields in FDEs.
+ using FdeData = EhFrameSection::FdeData;
+ SmallVector<FdeData, 0> fdes;
+ uint64_t va = hdr->getVA();
+ for (CieRecord *rec : cieRecords) {
+ uint8_t enc = getFdeEncoding(rec->cie);
+ for (EhSectionPiece *fde : rec->fdes) {
+ uint64_t pc = getFdePc(buf, fde->outputOff, enc);
+ uint64_t fdeVA = getParent()->addr + fde->outputOff;
+ if (!isInt<32>(pc - va)) {
+ Err(ctx) << fde->sec << ": PC offset is too large: 0x"
+ << Twine::utohexstr(pc - va);
+ continue;
+ }
+ fdes.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)});
+ }
+ }
+
+ // Sort the FDE list by their PC and uniqueify. Usually there is only
+ // one FDE for a PC (i.e. function), but if ICF merges two functions
+ // into one, there can be more than one FDEs pointing to the address.
+ llvm::stable_sort(fdes, [](const FdeData &a, const FdeData &b) {
+ return a.pcRel < b.pcRel;
+ });
+ fdes.erase(
+ llvm::unique(fdes, [](auto &a, auto &b) { return a.pcRel == b.pcRel; }),
+ fdes.end());
+
+ // Write header.
+ uint8_t *hdrBuf = ctx.bufferStart + hdr->getParent()->offset + hdr->outSecOff;
+ hdrBuf[0] = 1; // version
+ hdrBuf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; // eh_frame_ptr_enc
+ hdrBuf[2] = DW_EH_PE_udata4; // fde_count_enc
+ hdrBuf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; // table_enc
+ write32(ctx, hdrBuf + 4,
+ getParent()->addr - hdr->getVA() - 4); // eh_frame_ptr
+ write32(ctx, hdrBuf + 8, fdes.size()); // fde_count
+ hdrBuf += 12;
+
+ // Write binary search table. Each entry describes the starting PC and the FDE
+ // address.
+ for (FdeData &fde : fdes) {
+ write32(ctx, hdrBuf, fde.pcRel);
+ write32(ctx, hdrBuf + 4, fde.fdeVARel);
+ hdrBuf += 8;
+ }
+}
+
+EhFrameHeader::EhFrameHeader(Ctx &ctx)
+ : SyntheticSection(ctx, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 4) {}
+
+void EhFrameHeader::writeTo(uint8_t *buf) {
+ // The section content is written during EhFrameSection::writeTo.
+}
+
+size_t EhFrameHeader::getSize() const {
+ // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
+ return 12 + getPartition(ctx).ehFrame->numFdes * 8;
+}
+
+bool EhFrameHeader::isNeeded() const {
+ return isLive() && getPartition(ctx).ehFrame->isNeeded();
}
GotSection::GotSection(Ctx &ctx)
@@ -2749,9 +2775,9 @@ RelroPaddingSection::RelroPaddingSection(Ctx &ctx)
: SyntheticSection(ctx, ".relro_padding", SHT_NOBITS, SHF_ALLOC | SHF_WRITE,
1) {}
-PaddingSection::PaddingSection(Ctx &ctx, uint64_t size, OutputSection *parent)
- : SyntheticSection(ctx, ".padding", SHT_PROGBITS, SHF_ALLOC, 1),
- size(size) {
+PaddingSection::PaddingSection(Ctx &ctx, uint64_t amount, OutputSection *parent)
+ : SyntheticSection(ctx, ".padding", SHT_PROGBITS, SHF_ALLOC, 1) {
+ size = amount;
this->parent = parent;
}
@@ -3660,51 +3686,6 @@ void GdbIndexSection::writeTo(uint8_t *buf) {
bool GdbIndexSection::isNeeded() const { return !chunks.empty(); }
-EhFrameHeader::EhFrameHeader(Ctx &ctx)
- : SyntheticSection(ctx, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 4) {}
-
-void EhFrameHeader::writeTo(uint8_t *buf) {
- // Unlike most sections, the EhFrameHeader section is written while writing
- // another section, namely EhFrameSection, which calls the write() function
- // below from its writeTo() function. This is necessary because the contents
- // of EhFrameHeader depend on the relocated contents of EhFrameSection and we
- // don't know which order the sections will be written in.
-}
-
-// .eh_frame_hdr contains a binary search table of pointers to FDEs.
-// Each entry of the search table consists of two values,
-// the starting PC from where FDEs covers, and the FDE's address.
-// It is sorted by PC.
-void EhFrameHeader::write() {
- uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff;
- using FdeData = EhFrameSection::FdeData;
- SmallVector<FdeData, 0> fdes = getPartition(ctx).ehFrame->getFdeData();
-
- buf[0] = 1;
- buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
- buf[2] = DW_EH_PE_udata4;
- buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
- write32(ctx, buf + 4,
- getPartition(ctx).ehFrame->getParent()->addr - this->getVA() - 4);
- write32(ctx, buf + 8, fdes.size());
- buf += 12;
-
- for (FdeData &fde : fdes) {
- write32(ctx, buf, fde.pcRel);
- write32(ctx, buf + 4, fde.fdeVARel);
- buf += 8;
- }
-}
-
-size_t EhFrameHeader::getSize() const {
- // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
- return 12 + getPartition(ctx).ehFrame->numFdes * 8;
-}
-
-bool EhFrameHeader::isNeeded() const {
- return isLive() && getPartition(ctx).ehFrame->isNeeded();
-}
-
VersionDefinitionSection::VersionDefinitionSection(Ctx &ctx)
: SyntheticSection(ctx, ".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC,
sizeof(uint32_t)) {}
@@ -3786,9 +3767,10 @@ void VersionTableSection::writeTo(uint8_t *buf) {
buf += 2;
for (const SymbolTableEntry &s : getPartition(ctx).dynSymTab->getSymbols()) {
// For an unextracted lazy symbol (undefined weak), it must have been
- // converted to Undefined and have VER_NDX_GLOBAL version here.
+ // converted to Undefined.
assert(!s.sym->isLazy());
- write16(ctx, buf, s.sym->versionId);
+ // Undefined symbols should use index 0 when unversioned.
+ write16(ctx, buf, s.sym->isUndefined() ? 0 : s.sym->versionId);
buf += 2;
}
}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 38e6811..e01a5ad 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -68,7 +68,6 @@ public:
uint32_t fdeVARel;
};
- SmallVector<FdeData, 0> getFdeData() const;
ArrayRef<CieRecord *> getCieRecords() const { return cieRecords; }
template <class ELFT>
void iterateFDEWithLSDA(llvm::function_ref<void(InputSection &)> fn);
@@ -78,8 +77,6 @@ private:
// allocating one for each EhInputSection.
llvm::DenseMap<size_t, CieRecord *> offsetToCie;
- uint64_t size = 0;
-
template <llvm::endianness E> void addRecords(EhInputSection *s);
template <class ELFT>
void iterateFDEWithLSDAAux(EhInputSection &sec,
@@ -97,6 +94,17 @@ private:
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> cieMap;
};
+// .eh_frame_hdr contains a binary search table for .eh_frame FDEs. The section
+// is covered by a PT_GNU_EH_FRAME segment, which allows the runtime unwinder to
+// locate it via functions like `dl_iterate_phdr`.
+class EhFrameHeader final : public SyntheticSection {
+public:
+ EhFrameHeader(Ctx &);
+ void writeTo(uint8_t *buf) override;
+ size_t getSize() const override;
+ bool isNeeded() const override;
+};
+
class GotSection final : public SyntheticSection {
public:
GotSection(Ctx &);
@@ -127,7 +135,6 @@ public:
protected:
size_t numEntries = 0;
uint32_t tlsIndexOff = -1;
- uint64_t size = 0;
struct AuthEntryInfo {
size_t offset;
bool isSymbolFunc;
@@ -182,7 +189,6 @@ public:
static bool classof(const SectionBase *s) {
return isa<SyntheticSection>(s) && cast<SyntheticSection>(s)->bss;
}
- uint64_t size;
};
class MipsGotSection final : public SyntheticSection {
@@ -312,8 +318,6 @@ private:
// Number of "Header" entries.
static const unsigned headerEntriesNum = 2;
- uint64_t size = 0;
-
// Symbol and addend.
using GotEntry = std::pair<Symbol *, int64_t>;
@@ -407,8 +411,6 @@ public:
private:
const bool dynamic;
- uint64_t size = 0;
-
llvm::DenseMap<llvm::CachedHashStringRef, unsigned> stringMap;
SmallVector<StringRef, 0> strings;
};
@@ -475,7 +477,6 @@ public:
private:
std::vector<std::pair<int32_t, uint64_t>> computeContents();
- uint64_t size = 0;
};
class RelocationBaseSection : public SyntheticSection {
@@ -780,10 +781,8 @@ public:
};
class PaddingSection final : public SyntheticSection {
- uint64_t size;
-
public:
- PaddingSection(Ctx &ctx, uint64_t size, OutputSection *parent);
+ PaddingSection(Ctx &ctx, uint64_t amount, OutputSection *parent);
size_t getSize() const override { return size; }
void writeTo(uint8_t *buf) override;
};
@@ -978,24 +977,6 @@ private:
size_t size;
};
-// --eh-frame-hdr option tells linker to construct a header for all the
-// .eh_frame sections. This header is placed to a section named .eh_frame_hdr
-// and also to a PT_GNU_EH_FRAME segment.
-// At runtime the unwinder then can find all the PT_GNU_EH_FRAME segments by
-// calling dl_iterate_phdr.
-// This section contains a lookup table for quick binary search of FDEs.
-// Detailed info about internals can be found in Ian Lance Taylor's blog:
-// http://www.airs.com/blog/archives/460 (".eh_frame")
-// http://www.airs.com/blog/archives/462 (".eh_frame_hdr")
-class EhFrameHeader final : public SyntheticSection {
-public:
- EhFrameHeader(Ctx &);
- void write();
- void writeTo(uint8_t *buf) override;
- size_t getSize() const override;
- bool isNeeded() const override;
-};
-
// For more information about .gnu.version and .gnu.version_r see:
// https://www.akkadia.org/drepper/symbol-versioning
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 89e4dbe..3fc3e3f 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -24,6 +24,7 @@
//===----------------------------------------------------------------------===//
#include "Target.h"
+#include "Arch/RISCVInternalRelocations.h"
#include "InputFiles.h"
#include "OutputSections.h"
#include "RelocScan.h"
@@ -40,6 +41,14 @@ using namespace lld::elf;
std::string elf::toStr(Ctx &ctx, RelType type) {
StringRef s = getELFRelocationTypeName(ctx.arg.emachine, type);
+ if (ctx.arg.emachine == EM_RISCV && s == "Unknown") {
+ auto VendorString = getRISCVVendorString(type);
+ if (VendorString)
+ s = getRISCVVendorRelocationTypeName(type & ~INTERNAL_RISCV_VENDOR_MASK,
+ *VendorString);
+ if (s == "Unknown")
+ return ("Unknown vendor-specific (" + Twine(type) + ")").str();
+ }
if (s == "Unknown")
return ("Unknown (" + Twine(type) + ")").str();
return std::string(s);
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 90d8ddf..8da0b5c 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -145,6 +145,7 @@ public:
RelType relativeRel = 0;
RelType iRelativeRel = 0;
RelType symbolicRel = 0;
+ RelType iRelSymbolicRel = 0;
RelType tlsDescRel = 0;
RelType tlsGotRel = 0;
RelType tlsModuleIndexRel = 0;
diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index a7c4b45..f351399 100644
--- a/lld/MachO/Arch/X86_64.cpp
+++ b/lld/MachO/Arch/X86_64.cpp
@@ -54,7 +54,8 @@ static constexpr std::array<RelocAttrs, 10> relocAttrsArray{{
{"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE1) |
B(BYTE4) | B(BYTE8)},
{"SIGNED", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
- {"BRANCH", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE1) | B(BYTE4)},
+ {"BRANCH",
+ B(PCREL) | B(EXTERN) | B(LOCAL) | B(BRANCH) | B(BYTE1) | B(BYTE4)},
{"GOT_LOAD", B(PCREL) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)},
{"GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)},
{"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)},
@@ -104,7 +105,7 @@ int64_t X86_64::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset,
void X86_64::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value,
uint64_t relocVA) const {
if (r.pcrel) {
- uint64_t pc = relocVA + (1 << r.length) + pcrelOffset(r.type);
+ uint64_t pc = relocVA + (1ull << r.length) + pcrelOffset(r.type);
value -= pc;
}
diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp
index 8067d23..e559676 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -306,7 +306,7 @@ void TextOutputSection::finalize() {
// contains several branch instructions in succession, then the distance
// from the current position to the position where the thunks are inserted
// grows. So leave room for a bunch of thunks.
- unsigned slop = 256 * thunkSize;
+ unsigned slop = config->slopScale * thunkSize;
while (finalIdx < endIdx) {
uint64_t expectedNewSize =
alignToPowerOf2(addr + size, inputs[finalIdx]->align) +
@@ -384,7 +384,9 @@ void TextOutputSection::finalize() {
// above. If you hit this: For the current algorithm, just bumping up
// slop above and trying again is probably simplest. (See also PR51578
// comment 5).
- fatal(Twine(__FUNCTION__) + ": FIXME: thunk range overrun");
+ fatal(Twine(__FUNCTION__) +
+ ": FIXME: thunk range overrun. Consider increasing the "
+ "slop-scale with `--slop-scale=<unsigned_int>`.");
}
thunkInfo.isec =
makeSyntheticInputSection(isec->getSegName(), isec->getName());
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index a2ca577..759a8cb 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -224,6 +224,7 @@ struct Configuration {
bool disableVerify;
bool separateCstringLiteralSections;
bool tailMergeStrings;
+ unsigned slopScale = 256;
bool callGraphProfileSort = false;
llvm::StringRef printSymbolOrder;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 9b67db9..f4f3aba 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -41,6 +41,7 @@
#include "llvm/Object/Archive.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
@@ -53,6 +54,10 @@
#include "llvm/TextAPI/Architecture.h"
#include "llvm/TextAPI/PackedVersion.h"
+#if !_WIN32
+#include <sys/mman.h>
+#endif
+
using namespace llvm;
using namespace llvm::MachO;
using namespace llvm::object;
@@ -292,12 +297,13 @@ struct DeferredFile {
using DeferredFiles = std::vector<DeferredFile>;
#if LLVM_ENABLE_THREADS
-class SerialBackgroundQueue {
+class SerialBackgroundWorkQueue {
std::deque<std::function<void()>> queue;
std::thread *running;
std::mutex mutex;
public:
+ std::atomic_bool stopAllWork = false;
void queueWork(std::function<void()> work) {
mutex.lock();
if (running && queue.empty()) {
@@ -312,7 +318,7 @@ public:
queue.emplace_back(std::move(work));
if (!running)
running = new std::thread([&]() {
- while (true) {
+ while (!stopAllWork) {
mutex.lock();
if (queue.empty()) {
mutex.unlock();
@@ -331,6 +337,8 @@ public:
}
};
+static SerialBackgroundWorkQueue pageInQueue;
+
// Most input files have been mapped but not yet paged in.
// This code forces the page-ins on multiple threads so
// the process is not stalled waiting on disk buffer i/o.
@@ -339,8 +347,8 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
static const size_t largeArchive = 10 * 1024 * 1024;
#ifndef NDEBUG
using namespace std::chrono;
- std::atomic_int numDeferedFilesTouched = 0;
static std::atomic_uint64_t totalBytes = 0;
+ std::atomic_int numDeferedFilesAdvised = 0;
auto t0 = high_resolution_clock::now();
#endif
@@ -348,24 +356,34 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
const StringRef &buff = deferredFile.buffer.getBuffer();
if (buff.size() > largeArchive)
return;
+
#ifndef NDEBUG
totalBytes += buff.size();
- numDeferedFilesTouched += 1;
+ numDeferedFilesAdvised += 1;
#endif
-
+#if _WIN32
// Reference all file's mmap'd pages to load them into memory.
- for (const char *page = buff.data(), *end = page + buff.size(); page < end;
- page += pageSize) {
+ for (const char *page = buff.data(), *end = page + buff.size();
+ page < end && !pageInQueue.stopAllWork; page += pageSize) {
[[maybe_unused]] volatile char t = *page;
(void)t;
}
+#else
+#define DEBUG_TYPE "lld-madvise"
+ auto aligned =
+ llvm::alignDown(reinterpret_cast<uintptr_t>(buff.data()), pageSize);
+ if (madvise((void *)aligned, buff.size(), MADV_WILLNEED) < 0)
+ LLVM_DEBUG(llvm::dbgs() << "madvise error: " << strerror(errno) << "\n");
+#undef DEBUG_TYPE
+#endif
};
+
{ // Create scope for waiting for the taskGroup
std::atomic_size_t index = 0;
llvm::parallel::TaskGroup taskGroup;
for (int w = 0; w < config->readWorkers; w++)
taskGroup.spawn([&index, &preloadDeferredFile, &deferred]() {
- while (true) {
+ while (!pageInQueue.stopAllWork) {
size_t localIndex = index.fetch_add(1);
if (localIndex >= deferred.size())
break;
@@ -373,17 +391,17 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
}
});
}
+
#ifndef NDEBUG
auto dt = high_resolution_clock::now() - t0;
if (Process::GetEnv("LLD_MULTI_THREAD_PAGE"))
llvm::dbgs() << "multiThreadedPageIn " << totalBytes << "/"
- << numDeferedFilesTouched << "/" << deferred.size() << "/"
+ << numDeferedFilesAdvised << "/" << deferred.size() << "/"
<< duration_cast<milliseconds>(dt).count() / 1000. << "\n";
#endif
}
static void multiThreadedPageIn(const DeferredFiles &deferred) {
- static SerialBackgroundQueue pageInQueue;
pageInQueue.queueWork([=]() {
DeferredFiles files = deferred;
multiThreadedPageInBackground(files);
@@ -489,7 +507,7 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
continue;
}
- if (archiveContents)
+ if (config->readWorkers && archiveContents)
archiveContents->push_back({path, isLazy, *mb});
if (!hasObjCSection(*mb))
continue;
@@ -841,18 +859,18 @@ static PlatformVersion parsePlatformVersion(const Arg *arg) {
// TODO(compnerd) see if we can generate this case list via XMACROS
platformVersion.platform =
StringSwitch<PlatformType>(lowerDash(platformStr))
- .Cases("macos", "1", PLATFORM_MACOS)
- .Cases("ios", "2", PLATFORM_IOS)
- .Cases("tvos", "3", PLATFORM_TVOS)
- .Cases("watchos", "4", PLATFORM_WATCHOS)
- .Cases("bridgeos", "5", PLATFORM_BRIDGEOS)
- .Cases("mac-catalyst", "6", PLATFORM_MACCATALYST)
- .Cases("ios-simulator", "7", PLATFORM_IOSSIMULATOR)
- .Cases("tvos-simulator", "8", PLATFORM_TVOSSIMULATOR)
- .Cases("watchos-simulator", "9", PLATFORM_WATCHOSSIMULATOR)
- .Cases("driverkit", "10", PLATFORM_DRIVERKIT)
- .Cases("xros", "11", PLATFORM_XROS)
- .Cases("xros-simulator", "12", PLATFORM_XROS_SIMULATOR)
+ .Cases({"macos", "1"}, PLATFORM_MACOS)
+ .Cases({"ios", "2"}, PLATFORM_IOS)
+ .Cases({"tvos", "3"}, PLATFORM_TVOS)
+ .Cases({"watchos", "4"}, PLATFORM_WATCHOS)
+ .Cases({"bridgeos", "5"}, PLATFORM_BRIDGEOS)
+ .Cases({"mac-catalyst", "6"}, PLATFORM_MACCATALYST)
+ .Cases({"ios-simulator", "7"}, PLATFORM_IOSSIMULATOR)
+ .Cases({"tvos-simulator", "8"}, PLATFORM_TVOSSIMULATOR)
+ .Cases({"watchos-simulator", "9"}, PLATFORM_WATCHOSSIMULATOR)
+ .Cases({"driverkit", "10"}, PLATFORM_DRIVERKIT)
+ .Cases({"xros", "11"}, PLATFORM_XROS)
+ .Cases({"xros-simulator", "12"}, PLATFORM_XROS_SIMULATOR)
.Default(PLATFORM_UNKNOWN);
if (platformVersion.platform == PLATFORM_UNKNOWN)
error(Twine("malformed platform: ") + platformStr);
@@ -948,7 +966,7 @@ getUndefinedSymbolTreatment(const ArgList &args) {
StringRef treatmentStr = args.getLastArgValue(OPT_undefined);
auto treatment =
StringSwitch<UndefinedSymbolTreatment>(treatmentStr)
- .Cases("error", "", UndefinedSymbolTreatment::error)
+ .Cases({"error", ""}, UndefinedSymbolTreatment::error)
.Case("warning", UndefinedSymbolTreatment::warning)
.Case("suppress", UndefinedSymbolTreatment::suppress)
.Case("dynamic_lookup", UndefinedSymbolTreatment::dynamic_lookup)
@@ -972,7 +990,7 @@ getUndefinedSymbolTreatment(const ArgList &args) {
static ICFLevel getICFLevel(const ArgList &args) {
StringRef icfLevelStr = args.getLastArgValue(OPT_icf_eq);
auto icfLevel = StringSwitch<ICFLevel>(icfLevelStr)
- .Cases("none", "", ICFLevel::none)
+ .Cases({"none", ""}, ICFLevel::none)
.Case("safe", ICFLevel::safe)
.Case("safe_thunks", ICFLevel::safe_thunks)
.Case("all", ICFLevel::all)
@@ -1447,6 +1465,8 @@ static void createFiles(const InputArgList &args) {
multiThreadedPageIn(archiveContents);
for (auto *archive : archives)
archive->addLazySymbols();
+
+ pageInQueue.stopAllWork = true;
}
#endif
}
@@ -1845,8 +1865,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
"'");
config->readWorkers = workers;
#else
- error(arg->getSpelling() +
- ": option unavailable because lld was not built with thread support");
+ warn(arg->getSpelling() +
+ ": option unavailable because lld was not built with thread support");
#endif
}
if (auto *arg = args.getLastArg(OPT_threads_eq)) {
@@ -1995,6 +2015,14 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
OPT_no_separate_cstring_literal_sections, false);
config->tailMergeStrings =
args.hasFlag(OPT_tail_merge_strings, OPT_no_tail_merge_strings, false);
+ if (auto *arg = args.getLastArg(OPT_slop_scale_eq)) {
+ StringRef v(arg->getValue());
+ unsigned slop = 0;
+ if (!llvm::to_integer(v, slop))
+ error(arg->getSpelling() +
+ ": expected a non-negative integer, but got '" + v + "'");
+ config->slopScale = slop;
+ }
auto IncompatWithCGSort = [&](StringRef firstArgStr) {
// Throw an error only if --call-graph-profile-sort is explicitly specified
diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index 7b31378c3..e0fc897 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -173,14 +173,37 @@ bool ICF::equalsConstant(const ConcatInputSection *ia,
// a valid offset in the literal section.
return isecA->getOffset(valueA) == isecB->getOffset(valueB) &&
ra.addend == rb.addend;
- else {
- assert(valueA == 0 && valueB == 0);
- // For section relocs, we compare the content at the section offset.
- return isecA->getOffset(ra.addend) == isecB->getOffset(rb.addend);
- }
+ assert(valueA == 0 && valueB == 0);
+ // For section relocs, we compare the content at the section offset.
+ return isecA->getOffset(ra.addend) == isecB->getOffset(rb.addend);
};
- return std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(),
- f);
+ if (!llvm::equal(ia->relocs, ib->relocs, f))
+ return false;
+
+ // Check unwind info structural compatibility: if there are symbols with
+ // associated unwind info, check that both sections have compatible symbol
+ // layouts. For simplicity, we only attempt folding when all symbols are at
+ // offset zero within the section (which is typically the case with
+ // .subsections_via_symbols.)
+ auto hasUnwind = [](Defined *d) { return d->unwindEntry() != nullptr; };
+ const auto *itA = llvm::find_if(ia->symbols, hasUnwind);
+ const auto *itB = llvm::find_if(ib->symbols, hasUnwind);
+ if (itA == ia->symbols.end())
+ return itB == ib->symbols.end();
+ if (itB == ib->symbols.end())
+ return false;
+ const Defined *da = *itA;
+ const Defined *db = *itB;
+ if (da->value != 0 || db->value != 0)
+ return false;
+ auto isZero = [](Defined *d) { return d->value == 0; };
+ // Since symbols are stored in order of value, and since we have already
+ // checked that da/db have value zero, we just need to do the isZero check on
+ // the subsequent symbols.
+ return std::find_if_not(std::next(itA), ia->symbols.end(), isZero) ==
+ ia->symbols.end() &&
+ std::find_if_not(std::next(itB), ib->symbols.end(), isZero) ==
+ ib->symbols.end();
}
// Compare the "moving" parts of two ConcatInputSections -- i.e. everything not
@@ -217,31 +240,19 @@ bool ICF::equalsVariable(const ConcatInputSection *ia,
}
return isecA->icfEqClass[icfPass % 2] == isecB->icfEqClass[icfPass % 2];
};
- if (!std::equal(ia->relocs.begin(), ia->relocs.end(), ib->relocs.begin(), f))
+ if (!llvm::equal(ia->relocs, ib->relocs, f))
return false;
- // If there are symbols with associated unwind info, check that the unwind
- // info matches. For simplicity, we only handle the case where there are only
- // symbols at offset zero within the section (which is typically the case with
- // .subsections_via_symbols.)
+ // Compare unwind info equivalence classes.
auto hasUnwind = [](Defined *d) { return d->unwindEntry() != nullptr; };
const auto *itA = llvm::find_if(ia->symbols, hasUnwind);
- const auto *itB = llvm::find_if(ib->symbols, hasUnwind);
if (itA == ia->symbols.end())
- return itB == ib->symbols.end();
- if (itB == ib->symbols.end())
- return false;
+ return true;
const Defined *da = *itA;
- const Defined *db = *itB;
- if (da->unwindEntry()->icfEqClass[icfPass % 2] !=
- db->unwindEntry()->icfEqClass[icfPass % 2] ||
- da->value != 0 || db->value != 0)
- return false;
- auto isZero = [](Defined *d) { return d->value == 0; };
- return std::find_if_not(std::next(itA), ia->symbols.end(), isZero) ==
- ia->symbols.end() &&
- std::find_if_not(std::next(itB), ib->symbols.end(), isZero) ==
- ib->symbols.end();
+ // equalsConstant() guarantees that both sections have unwind info.
+ const Defined *db = *llvm::find_if(ib->symbols, hasUnwind);
+ return da->unwindEntry()->icfEqClass[icfPass % 2] ==
+ db->unwindEntry()->icfEqClass[icfPass % 2];
}
// Find the first InputSection after BEGIN whose equivalence class differs
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 20e4a1d..81caef5 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -217,7 +217,8 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
if (entry != cachedReads.end())
return entry->second;
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = MemoryBuffer::getFile(path);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
+ MemoryBuffer::getFile(path, false, /*RequiresNullTerminator=*/false);
if (std::error_code ec = mbOrErr.getError()) {
error("cannot open " + path + ": " + ec.message());
return std::nullopt;
@@ -594,8 +595,8 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
// FIXME This logic was written around x86_64 behavior -- ARM64 doesn't
// have pcrel section relocations. We may want to factor this out into
// the arch-specific .cpp file.
- assert(target->hasAttr(r.type, RelocAttrBits::BYTE4));
- referentOffset = sec.addr + relInfo.r_address + 4 + totalAddend -
+ referentOffset = sec.addr + relInfo.r_address +
+ (1ull << relInfo.r_length) + totalAddend -
referentSecHead.addr;
} else {
// The addend for a non-pcrel relocation is its absolute address.
@@ -808,6 +809,17 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
continue;
if ((sym.n_type & N_TYPE) == N_SECT) {
+ if (sym.n_sect == 0) {
+ fatal("section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+ toString(this) + " has an invalid section index [0]");
+ }
+ if (sym.n_sect > sections.size()) {
+ fatal("section symbol " + StringRef(strtab + sym.n_strx) + " in " +
+ toString(this) + " has an invalid section index [" +
+ Twine(static_cast<unsigned>(sym.n_sect)) +
+ "] greater than the total number of sections [" +
+ Twine(sections.size()) + "]");
+ }
Subsections &subsections = sections[sym.n_sect - 1]->subsections;
// parseSections() may have chosen not to parse this section.
if (subsections.empty())
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index b173e14..2b2d28e 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -348,6 +348,9 @@ WordLiteralInputSection::WordLiteralInputSection(const Section &section,
}
uint64_t WordLiteralInputSection::getOffset(uint64_t off) const {
+ if (off >= data.size())
+ fatal(toString(this) + ": offset is outside the section");
+
auto *osec = cast<WordLiteralSection>(parent);
const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data());
switch (sectionType(getFlags())) {
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index be1a1cc..f5f7549 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -1095,6 +1095,14 @@ defm tail_merge_strings
: BB<"tail-merge-strings", "Enable string tail merging",
"Disable string tail merging to improve link-time performance">,
Group<grp_rare>;
+def slop_scale_eq
+ : Joined<["--"], "slop_scale=">,
+ MetaVarName<"<unsigned_int>">,
+ HelpText<"Specify the slop scale. Default value is 256. If your binary "
+ "has too many consecutive branch instructions resulting in "
+ "thunk-range overrun, then you need to increase this value to a "
+ "higher value, such as 512 or 1024, etc">,
+ Group<grp_rare>;
def grp_deprecated : OptionGroup<"deprecated">, HelpText<"DEPRECATED">;
diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp
index cf657aa..b652d1e 100644
--- a/lld/MachO/SectionPriorities.cpp
+++ b/lld/MachO/SectionPriorities.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/xxhash.h"
#include <numeric>
@@ -246,33 +247,45 @@ DenseMap<const InputSection *, int> CallGraphSort::run() {
return orderMap;
}
-std::optional<int>
-macho::PriorityBuilder::getSymbolOrCStringPriority(const StringRef key,
- InputFile *f) {
+void macho::PriorityBuilder::SymbolPriorityEntry::setPriority(
+ int priority, StringRef objectFile) {
+ if (!objectFile.empty())
+ objectFiles.try_emplace(objectFile, priority);
+ else
+ anyObjectFile = std::min(anyObjectFile, priority);
+}
- auto it = priorities.find(key);
- if (it == priorities.end())
- return std::nullopt;
- const SymbolPriorityEntry &entry = it->second;
+int macho::PriorityBuilder::SymbolPriorityEntry::getPriority(
+ const InputFile *f) const {
if (!f)
- return entry.anyObjectFile;
+ return anyObjectFile;
// We don't use toString(InputFile *) here because it returns the full path
// for object files, and we only want the basename.
- StringRef filename;
- if (f->archiveName.empty())
- filename = path::filename(f->getName());
- else
- filename = saver().save(path::filename(f->archiveName) + "(" +
- path::filename(f->getName()) + ")");
- return std::min(entry.objectFiles.lookup(filename), entry.anyObjectFile);
+ StringRef basename = path::filename(f->getName());
+ StringRef filename =
+ f->archiveName.empty()
+ ? basename
+ : saver().save(path::filename(f->archiveName) + "(" + basename + ")");
+ return std::min(objectFiles.lookup(filename), anyObjectFile);
}
std::optional<int>
-macho::PriorityBuilder::getSymbolPriority(const Defined *sym) {
+macho::PriorityBuilder::getCStringPriority(uint32_t hash,
+ const InputFile *f) const {
+ auto it = cStringPriorities.find(hash);
+ if (it == cStringPriorities.end())
+ return std::nullopt;
+ return it->second.getPriority(f);
+}
+
+std::optional<int>
+macho::PriorityBuilder::getSymbolPriority(const Defined *sym) const {
if (sym->isAbsolute())
return std::nullopt;
- return getSymbolOrCStringPriority(utils::getRootSymbol(sym->getName()),
- sym->isec()->getFile());
+ auto it = priorities.find(utils::getRootSymbol(sym->getName()));
+ if (it == priorities.end())
+ return std::nullopt;
+ return it->second.getPriority(sym->isec()->getFile());
}
void macho::PriorityBuilder::extractCallGraphProfile() {
@@ -307,7 +320,7 @@ void macho::PriorityBuilder::parseOrderFile(StringRef path) {
int prio = std::numeric_limits<int>::min();
MemoryBufferRef mbref = *buffer;
for (StringRef line : args::getLines(mbref)) {
- StringRef objectFile, symbolOrCStrHash;
+ StringRef objectFile;
line = line.take_until([](char c) { return c == '#'; }); // ignore comments
line = line.ltrim();
@@ -338,22 +351,16 @@ void macho::PriorityBuilder::parseOrderFile(StringRef path) {
}
// The rest of the line is either <symbol name> or
- // CStringEntryPrefix<cstring hash>
+ // cStringEntryPrefix<cstring hash>
line = line.trim();
- if (line.starts_with(CStringEntryPrefix)) {
- StringRef possibleHash = line.drop_front(CStringEntryPrefix.size());
+ if (line.consume_front(cStringEntryPrefix)) {
uint32_t hash = 0;
- if (to_integer(possibleHash, hash))
- symbolOrCStrHash = possibleHash;
- } else
- symbolOrCStrHash = utils::getRootSymbol(line);
-
- if (!symbolOrCStrHash.empty()) {
- SymbolPriorityEntry &entry = priorities[symbolOrCStrHash];
- if (!objectFile.empty())
- entry.objectFiles.insert(std::make_pair(objectFile, prio));
- else
- entry.anyObjectFile = std::min(entry.anyObjectFile, prio);
+ if (to_integer(line, hash))
+ cStringPriorities[hash].setPriority(prio, objectFile);
+ } else {
+ StringRef symbol = utils::getRootSymbol(line);
+ if (!symbol.empty())
+ priorities[symbol].setPriority(prio, objectFile);
}
++prio;
@@ -405,40 +412,39 @@ macho::PriorityBuilder::buildInputSectionPriorities() {
return sectionPriorities;
}
-std::vector<StringPiecePair> macho::PriorityBuilder::buildCStringPriorities(
- ArrayRef<CStringInputSection *> inputs) {
- // Split the input strings into hold and cold sets.
- // Order hot set based on -order_file_cstring for performance improvement;
- // TODO: Order cold set of cstrings for compression via BP.
- std::vector<std::pair<int, StringPiecePair>>
- hotStringPrioritiesAndStringPieces;
- std::vector<StringPiecePair> coldStringPieces;
- std::vector<StringPiecePair> orderedStringPieces;
-
+void macho::PriorityBuilder::forEachStringPiece(
+ ArrayRef<CStringInputSection *> inputs,
+ std::function<void(CStringInputSection &, StringPiece &, size_t)> f,
+ bool forceInputOrder, bool computeHash) const {
+ std::vector<std::tuple<int, CStringInputSection *, size_t>> orderedPieces;
+ std::vector<std::pair<CStringInputSection *, size_t>> unorderedPieces;
for (CStringInputSection *isec : inputs) {
for (const auto &[stringPieceIdx, piece] : llvm::enumerate(isec->pieces)) {
if (!piece.live)
continue;
-
- std::optional<int> priority = getSymbolOrCStringPriority(
- std::to_string(piece.hash), isec->getFile());
- if (!priority)
- coldStringPieces.emplace_back(isec, stringPieceIdx);
+ // Process pieces in input order if we have no cstrings in our orderfile
+ if (forceInputOrder || cStringPriorities.empty()) {
+ f(*isec, piece, stringPieceIdx);
+ continue;
+ }
+ uint32_t hash =
+ computeHash
+ ? (xxh3_64bits(isec->getStringRef(stringPieceIdx)) & 0x7fffffff)
+ : piece.hash;
+ if (auto priority = getCStringPriority(hash, isec->getFile()))
+ orderedPieces.emplace_back(*priority, isec, stringPieceIdx);
else
- hotStringPrioritiesAndStringPieces.emplace_back(
- *priority, std::make_pair(isec, stringPieceIdx));
+ unorderedPieces.emplace_back(isec, stringPieceIdx);
}
}
-
- // Order hot set for perf
- llvm::stable_sort(hotStringPrioritiesAndStringPieces);
- for (auto &[priority, stringPiecePair] : hotStringPrioritiesAndStringPieces)
- orderedStringPieces.push_back(stringPiecePair);
-
- // TODO: Order cold set for compression
-
- orderedStringPieces.insert(orderedStringPieces.end(),
- coldStringPieces.begin(), coldStringPieces.end());
-
- return orderedStringPieces;
+ if (orderedPieces.empty() && unorderedPieces.empty())
+ return;
+ llvm::stable_sort(orderedPieces, [](const auto &left, const auto &right) {
+ return std::get<0>(left) < std::get<0>(right);
+ });
+ for (auto &[priority, isec, pieceIdx] : orderedPieces)
+ f(*isec, isec->pieces[pieceIdx], pieceIdx);
+ // TODO: Add option to order the remaining cstrings for compression
+ for (auto &[isec, pieceIdx] : unorderedPieces)
+ f(*isec, isec->pieces[pieceIdx], pieceIdx);
}
diff --git a/lld/MachO/SectionPriorities.h b/lld/MachO/SectionPriorities.h
index cc4e30f..24d2dbc 100644
--- a/lld/MachO/SectionPriorities.h
+++ b/lld/MachO/SectionPriorities.h
@@ -16,7 +16,6 @@
namespace lld::macho {
using SectionPair = std::pair<const InputSection *, const InputSection *>;
-using StringPiecePair = std::pair<CStringInputSection *, size_t>;
class PriorityBuilder {
public:
@@ -29,7 +28,7 @@ public:
//
// An order file has one entry per line, in the following format:
//
- // <cpu>:<object file>:[<symbol name> | CStringEntryPrefix <cstring hash>]
+ // <cpu>:<object file>:[<symbol name> | cStringEntryPrefix <cstring hash>]
//
// <cpu> and <object file> are optional.
// If not specified, then that entry tries to match either,
@@ -42,7 +41,7 @@ public:
// lowest-ordered entry (the one nearest to the front of the list.)
//
// or 2) any cstring literal with the given hash, if the entry has the
- // CStringEntryPrefix prefix defined below in the file. <cstring hash> is the
+ // cStringEntryPrefix prefix defined below in the file. <cstring hash> is the
// hash of cstring literal content.
//
// Cstring literals are not symbolized, we can't identify them by name
@@ -54,6 +53,16 @@ public:
// The file can also have line comments that start with '#'.
void parseOrderFile(StringRef path);
+ /// Call \p f for each string piece in \p inputs. If there are any cstring
+ /// literals in the orderfile (and \p forceInputOrder is false) then string
+ /// pieces are ordered by the orderfile. \p computeHash must be set when
+ /// \p deduplicateLiterals is false because then the string piece hash is not
+ /// set.
+ void forEachStringPiece(
+ ArrayRef<CStringInputSection *> inputs,
+ std::function<void(CStringInputSection &, StringPiece &, size_t)> f,
+ bool forceInputOrder = false, bool computeHash = false) const;
+
// Returns layout priorities for some or all input sections. Sections are laid
// out in decreasing order; that is, a higher priority section will be closer
// to the beginning of its output section.
@@ -66,8 +75,6 @@ public:
// Each section gets assigned the priority of the highest-priority symbol it
// contains.
llvm::DenseMap<const InputSection *, int> buildInputSectionPriorities();
- std::vector<StringPiecePair>
- buildCStringPriorities(ArrayRef<CStringInputSection *>);
private:
// The symbol with the smallest priority should be ordered first in the output
@@ -78,13 +85,16 @@ private:
int anyObjectFile = 0;
// The priority given to a matching symbol from a particular object file.
llvm::DenseMap<llvm::StringRef, int> objectFiles;
+ void setPriority(int priority, StringRef objectFile);
+ int getPriority(const InputFile *f) const;
};
- const llvm::StringRef CStringEntryPrefix = "CSTR;";
+ const llvm::StringRef cStringEntryPrefix = "CSTR;";
- std::optional<int> getSymbolPriority(const Defined *sym);
- std::optional<int> getSymbolOrCStringPriority(const StringRef key,
- InputFile *f);
+ std::optional<int> getSymbolPriority(const Defined *sym) const;
+ std::optional<int> getCStringPriority(uint32_t hash,
+ const InputFile *f) const;
llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities;
+ llvm::DenseMap<uint32_t, SymbolPriorityEntry> cStringPriorities;
llvm::MapVector<SectionPair, uint64_t> callGraphProfile;
};
diff --git a/lld/MachO/Sections.cpp b/lld/MachO/Sections.cpp
index a27d902..47169c7 100644
--- a/lld/MachO/Sections.cpp
+++ b/lld/MachO/Sections.cpp
@@ -27,7 +27,7 @@ bool isCodeSection(StringRef name, StringRef segName, uint32_t flags) {
if (segName == segment_names::text)
return StringSwitch<bool>(name)
- .Cases(section_names::textCoalNt, section_names::staticInit, true)
+ .Cases({section_names::textCoalNt, section_names::staticInit}, true)
.Default(false);
return false;
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index baddddc..a7db5a3a 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -61,8 +61,8 @@ struct DuplicateSymbolDiag {
SmallVector<DuplicateSymbolDiag> dupSymDiags;
} // namespace
-// Move symbols at \p fromOff in \p fromIsec into \p toIsec, unless that symbol
-// is \p skip.
+// Move local symbols at \p fromOff in \p fromIsec into \p toIsec, unless that
+// symbol is \p skip, in which case we just remove it.
static void transplantSymbolsAtOffset(InputSection *fromIsec,
InputSection *toIsec, Defined *skip,
uint64_t fromOff, uint64_t toOff) {
@@ -78,22 +78,23 @@ static void transplantSymbolsAtOffset(InputSection *fromIsec,
auto insertIt = llvm::upper_bound(toIsec->symbols, toOff, symSucceedsOff);
llvm::erase_if(fromIsec->symbols, [&](Symbol *s) {
auto *d = cast<Defined>(s);
- if (d->value != fromOff)
+ if (d == skip)
+ return true;
+ if (d->value != fromOff || d->isExternal())
return false;
- if (d != skip) {
- // This repeated insertion will be quadratic unless insertIt is the end
- // iterator. However, that is typically the case for files that have
- // .subsections_via_symbols set.
- insertIt = toIsec->symbols.insert(insertIt, d);
- d->originalIsec = toIsec;
- d->value = toOff;
- // We don't want to have more than one unwindEntry at a given address, so
- // drop the redundant ones. We We can safely drop the unwindEntries of
- // the symbols in fromIsec since we will be adding another unwindEntry as
- // we finish parsing toIsec's file. (We can assume that toIsec has its
- // own unwindEntry because of the ODR.)
- d->originalUnwindEntry = nullptr;
- }
+
+ // This repeated insertion will be quadratic unless insertIt is the end
+ // iterator. However, that is typically the case for files that have
+ // .subsections_via_symbols set.
+ insertIt = toIsec->symbols.insert(insertIt, d);
+ d->originalIsec = toIsec;
+ d->value = toOff;
+ // We don't want to have more than one unwindEntry at a given address, so
+ // drop the redundant ones. We can safely drop the unwindEntries of the
+ // symbols in fromIsec since we will be adding another unwindEntry as we
+ // finish parsing toIsec's file. (We can assume that toIsec has its own
+ // unwindEntry because of the ODR.)
+ d->originalUnwindEntry = nullptr;
return true;
});
}
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 187cccb..fecc51f 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -1721,26 +1721,24 @@ void CStringSection::writeTo(uint8_t *buf) const {
// and don't need this alignment. They will be emitted at some arbitrary address
// `A`, but ld64 will treat them as being 16-byte aligned with an offset of
// `16 % A`.
-static Align getStringPieceAlignment(const CStringInputSection *isec,
+static Align getStringPieceAlignment(const CStringInputSection &isec,
const StringPiece &piece) {
- return llvm::Align(1ULL << llvm::countr_zero(isec->align | piece.inSecOff));
+ return llvm::Align(1ULL << llvm::countr_zero(isec.align | piece.inSecOff));
}
void CStringSection::finalizeContents() {
size = 0;
- // TODO: Call buildCStringPriorities() to support cstring ordering when
- // deduplication is off, although this may negatively impact build
- // performance.
- for (CStringInputSection *isec : inputs) {
- for (const auto &[i, piece] : llvm::enumerate(isec->pieces)) {
- if (!piece.live)
- continue;
- piece.outSecOff = alignTo(size, getStringPieceAlignment(isec, piece));
- StringRef string = isec->getStringRef(i);
- size = piece.outSecOff + string.size() + 1; // account for null terminator
- }
+ priorityBuilder.forEachStringPiece(
+ inputs,
+ [&](CStringInputSection &isec, StringPiece &piece, size_t pieceIdx) {
+ piece.outSecOff = alignTo(size, getStringPieceAlignment(isec, piece));
+ StringRef string = isec.getStringRef(pieceIdx);
+ size =
+ piece.outSecOff + string.size() + 1; // account for null terminator
+ },
+ /*forceInputOrder=*/false, /*computeHash=*/true);
+ for (CStringInputSection *isec : inputs)
isec->isFinal = true;
- }
}
void DeduplicatedCStringSection::finalizeContents() {
@@ -1748,20 +1746,19 @@ void DeduplicatedCStringSection::finalizeContents() {
DenseMap<CachedHashStringRef, Align> strToAlignment;
// Used for tail merging only
std::vector<CachedHashStringRef> deduplicatedStrs;
- for (const CStringInputSection *isec : inputs) {
- for (const auto &[i, piece] : llvm::enumerate(isec->pieces)) {
- if (!piece.live)
- continue;
- auto s = isec->getCachedHashStringRef(i);
- assert(isec->align != 0);
- auto align = getStringPieceAlignment(isec, piece);
- auto [it, wasInserted] = strToAlignment.try_emplace(s, align);
- if (config->tailMergeStrings && wasInserted)
- deduplicatedStrs.push_back(s);
- if (!wasInserted && it->second < align)
- it->second = align;
- }
- }
+ priorityBuilder.forEachStringPiece(
+ inputs,
+ [&](CStringInputSection &isec, StringPiece &piece, size_t pieceIdx) {
+ auto s = isec.getCachedHashStringRef(pieceIdx);
+ assert(isec.align != 0);
+ auto align = getStringPieceAlignment(isec, piece);
+ auto [it, wasInserted] = strToAlignment.try_emplace(s, align);
+ if (config->tailMergeStrings && wasInserted)
+ deduplicatedStrs.push_back(s);
+ if (!wasInserted && it->second < align)
+ it->second = align;
+ },
+ /*forceInputOrder=*/true);
// Like lexigraphical sort, except we read strings in reverse and take the
// longest string first
@@ -1801,9 +1798,10 @@ void DeduplicatedCStringSection::finalizeContents() {
// Sort the strings for performance and compression size win, and then
// assign an offset for each string and save it to the corresponding
// StringPieces for easy access.
- for (auto &[isec, i] : priorityBuilder.buildCStringPriorities(inputs)) {
- auto &piece = isec->pieces[i];
- auto s = isec->getCachedHashStringRef(i);
+ priorityBuilder.forEachStringPiece(inputs, [&](CStringInputSection &isec,
+ StringPiece &piece,
+ size_t pieceIdx) {
+ auto s = isec.getCachedHashStringRef(pieceIdx);
// Any string can be tail merged with itself with an offset of zero
uint64_t tailMergeOffset = 0;
auto mergeIt =
@@ -1829,7 +1827,7 @@ void DeduplicatedCStringSection::finalizeContents() {
stringOffsetMap[tailMergedString] = piece.outSecOff;
assert(isAligned(strToAlignment.at(tailMergedString), piece.outSecOff));
}
- }
+ });
for (CStringInputSection *isec : inputs)
isec->isFinal = true;
}
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 6e9f6c2..bf01b12 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -153,8 +153,6 @@ private:
// The entries here will be in the same order as their originating symbols
// in symbolsVec.
std::vector<CompactUnwindEntry> cuEntries;
- // Indices into the cuEntries vector.
- std::vector<size_t> cuIndices;
std::vector<Symbol *> personalities;
SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *>
personalityTable;
@@ -400,8 +398,7 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
// There should only be a handful of unique personality pointers, so we can
// encode them as 2-bit indices into a small array.
void UnwindInfoSectionImpl::encodePersonalities() {
- for (size_t idx : cuIndices) {
- CompactUnwindEntry &cu = cuEntries[idx];
+ for (CompactUnwindEntry &cu : cuEntries) {
if (cu.personality == nullptr)
continue;
// Linear search is fast enough for a small array.
@@ -467,27 +464,24 @@ void UnwindInfoSectionImpl::finalize() {
symbolsVec = symbols.takeVector();
relocateCompactUnwind(cuEntries);
- // Rather than sort & fold the 32-byte entries directly, we create a
- // vector of indices to entries and sort & fold that instead.
- cuIndices.resize(cuEntries.size());
- std::iota(cuIndices.begin(), cuIndices.end(), 0);
- llvm::sort(cuIndices, [&](size_t a, size_t b) {
- return cuEntries[a].functionAddress < cuEntries[b].functionAddress;
+ // Sort the entries by address.
+ llvm::sort(cuEntries, [&](auto &a, auto &b) {
+ return a.functionAddress < b.functionAddress;
});
// Record the ending boundary before we fold the entries.
- cueEndBoundary = cuEntries[cuIndices.back()].functionAddress +
- cuEntries[cuIndices.back()].functionLength;
+ cueEndBoundary =
+ cuEntries.back().functionAddress + cuEntries.back().functionLength;
// Fold adjacent entries with matching encoding+personality and without LSDA
- // We use three iterators on the same cuIndices to fold in-situ:
+ // We use three iterators to fold in-situ:
// (1) `foldBegin` is the first of a potential sequence of matching entries
// (2) `foldEnd` is the first non-matching entry after `foldBegin`.
// The semi-open interval [ foldBegin .. foldEnd ) contains a range
// entries that can be folded into a single entry and written to ...
// (3) `foldWrite`
- auto foldWrite = cuIndices.begin();
- for (auto foldBegin = cuIndices.begin(); foldBegin < cuIndices.end();) {
+ auto foldWrite = cuEntries.begin();
+ for (auto foldBegin = cuEntries.begin(); foldBegin != cuEntries.end();) {
auto foldEnd = foldBegin;
// Common LSDA encodings (e.g. for C++ and Objective-C) contain offsets from
// a base address. The base address is normally not contained directly in
@@ -503,9 +497,9 @@ void UnwindInfoSectionImpl::finalize() {
// directly in the LSDA, two functions at different addresses would
// necessarily have different LSDAs, so their CU entries would not have been
// folded anyway.
- while (++foldEnd < cuIndices.end() &&
- cuEntries[*foldBegin].encoding == cuEntries[*foldEnd].encoding &&
- !cuEntries[*foldBegin].lsda && !cuEntries[*foldEnd].lsda &&
+ while (++foldEnd != cuEntries.end() &&
+ foldBegin->encoding == foldEnd->encoding && !foldBegin->lsda &&
+ !foldEnd->lsda &&
// If we've gotten to this point, we don't have an LSDA, which should
// also imply that we don't have a personality function, since in all
// likelihood a personality function needs the LSDA to do anything
@@ -513,21 +507,20 @@ void UnwindInfoSectionImpl::finalize() {
// and no LSDA though (e.g. the C++ personality __gxx_personality_v0
// is just a no-op without LSDA), so we still check for personality
// function equivalence to handle that case.
- cuEntries[*foldBegin].personality ==
- cuEntries[*foldEnd].personality &&
- canFoldEncoding(cuEntries[*foldEnd].encoding))
+ foldBegin->personality == foldEnd->personality &&
+ canFoldEncoding(foldEnd->encoding))
;
*foldWrite++ = *foldBegin;
foldBegin = foldEnd;
}
- cuIndices.erase(foldWrite, cuIndices.end());
+ cuEntries.erase(foldWrite, cuEntries.end());
encodePersonalities();
// Count frequencies of the folded encodings
EncodingMap encodingFrequencies;
- for (size_t idx : cuIndices)
- encodingFrequencies[cuEntries[idx].encoding]++;
+ for (const CompactUnwindEntry &cu : cuEntries)
+ encodingFrequencies[cu.encoding]++;
// Make a vector of encodings, sorted by descending frequency
for (const auto &frequency : encodingFrequencies)
@@ -558,21 +551,19 @@ void UnwindInfoSectionImpl::finalize() {
// and 127..255 references a local per-second-level-page table.
// First we try the compact format and determine how many entries fit.
// If more entries fit in the regular format, we use that.
- for (size_t i = 0; i < cuIndices.size();) {
- size_t idx = cuIndices[i];
+ for (size_t i = 0; i < cuEntries.size();) {
secondLevelPages.emplace_back();
SecondLevelPage &page = secondLevelPages.back();
page.entryIndex = i;
uint64_t functionAddressMax =
- cuEntries[idx].functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK;
+ cuEntries[i].functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK;
size_t n = commonEncodings.size();
size_t wordsRemaining =
SECOND_LEVEL_PAGE_WORDS -
sizeof(unwind_info_compressed_second_level_page_header) /
sizeof(uint32_t);
- while (wordsRemaining >= 1 && i < cuIndices.size()) {
- idx = cuIndices[i];
- const CompactUnwindEntry *cuPtr = &cuEntries[idx];
+ while (wordsRemaining >= 1 && i < cuEntries.size()) {
+ const CompactUnwindEntry *cuPtr = &cuEntries[i];
if (cuPtr->functionAddress >= functionAddressMax)
break;
if (commonEncodingIndexes.count(cuPtr->encoding) ||
@@ -593,21 +584,21 @@ void UnwindInfoSectionImpl::finalize() {
// If this is not the final page, see if it's possible to fit more entries
// by using the regular format. This can happen when there are many unique
// encodings, and we saturated the local encoding table early.
- if (i < cuIndices.size() &&
+ if (i < cuEntries.size() &&
page.entryCount < REGULAR_SECOND_LEVEL_ENTRIES_MAX) {
page.kind = UNWIND_SECOND_LEVEL_REGULAR;
page.entryCount = std::min(REGULAR_SECOND_LEVEL_ENTRIES_MAX,
- cuIndices.size() - page.entryIndex);
+ cuEntries.size() - page.entryIndex);
i = page.entryIndex + page.entryCount;
} else {
page.kind = UNWIND_SECOND_LEVEL_COMPRESSED;
}
}
- for (size_t idx : cuIndices) {
- lsdaIndex[idx] = entriesWithLsda.size();
- if (cuEntries[idx].lsda)
- entriesWithLsda.push_back(idx);
+ for (size_t i = 0; i < cuEntries.size(); ++i) {
+ lsdaIndex[i] = entriesWithLsda.size();
+ if (cuEntries[i].lsda)
+ entriesWithLsda.push_back(i);
}
// compute size of __TEXT,__unwind_info section
@@ -626,7 +617,7 @@ void UnwindInfoSectionImpl::finalize() {
// All inputs are relocated and output addresses are known, so write!
void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
- assert(!cuIndices.empty() && "call only if there is unwind info");
+ assert(!cuEntries.empty() && "call only if there is unwind info");
// section header
auto *uip = reinterpret_cast<unwind_info_section_header *>(buf);
@@ -660,7 +651,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
uint64_t l2PagesOffset = level2PagesOffset;
auto *iep = reinterpret_cast<unwind_info_section_header_index_entry *>(i32p);
for (const SecondLevelPage &page : secondLevelPages) {
- size_t idx = cuIndices[page.entryIndex];
+ size_t idx = page.entryIndex;
iep->functionOffset = cuEntries[idx].functionAddress - in.header->addr;
iep->secondLevelPagesSectionOffset = l2PagesOffset;
iep->lsdaIndexArraySectionOffset =
@@ -695,7 +686,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
for (const SecondLevelPage &page : secondLevelPages) {
if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
uintptr_t functionAddressBase =
- cuEntries[cuIndices[page.entryIndex]].functionAddress;
+ cuEntries[page.entryIndex].functionAddress;
auto *p2p =
reinterpret_cast<unwind_info_compressed_second_level_page_header *>(
pp);
@@ -708,8 +699,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
p2p->encodingsCount = page.localEncodings.size();
auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);
for (size_t i = 0; i < page.entryCount; i++) {
- const CompactUnwindEntry &cue =
- cuEntries[cuIndices[page.entryIndex + i]];
+ const CompactUnwindEntry &cue = cuEntries[page.entryIndex + i];
auto it = commonEncodingIndexes.find(cue.encoding);
if (it == commonEncodingIndexes.end())
it = page.localEncodingIndexes.find(cue.encoding);
@@ -728,8 +718,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
p2p->entryCount = page.entryCount;
auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);
for (size_t i = 0; i < page.entryCount; i++) {
- const CompactUnwindEntry &cue =
- cuEntries[cuIndices[page.entryIndex + i]];
+ const CompactUnwindEntry &cue = cuEntries[page.entryIndex + i];
*ep++ = cue.functionAddress;
*ep++ = cue.encoding;
}
diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index 1180097..1569026 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -451,6 +451,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
add("-machine:arm64ec");
else if (s == "arm64xpe")
add("-machine:arm64x");
+ else if (s == "mipspe")
+ add("-machine:mips");
else
error("unknown parameter: -m" + s);
}
diff --git a/lld/docs/ELF/linker_script.rst b/lld/docs/ELF/linker_script.rst
index c9cb47f..edbb78ef 100644
--- a/lld/docs/ELF/linker_script.rst
+++ b/lld/docs/ELF/linker_script.rst
@@ -17,6 +17,25 @@ possible. We reserve the right to make different implementation choices where
it is appropriate for LLD. Intentional deviations will be documented in this
file.
+Linker Script Specification
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are two lld options related to setting the linker script,
+`--script=<file>` and `--default-script=<file>`. The usage are illustrated below.
+
+::
+
+ # `-T` is the alias for `--script` option.
+ lld -T linker_script.lds
+
+ # `-dT` is the alias for `--default-script` option.
+ lld -dT linker_script.lds
+
+When both options are given, `--script=<file>` takes precedence.
+The intended use case of `--default-script` is to be used by toolchain
+configurations, and users can override the script by specifying `--script` if
+needed.
+
Symbol assignment
~~~~~~~~~~~~~~~~~
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 29db1cd..60db612 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -52,5 +52,8 @@ MachO Improvements
WebAssembly Improvements
------------------------
+* The ``--stack-first`` flag is now enabled by default. The old
+ behavior can be enabled using ``--no-stack-first``.
+
Fixes
#####
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index bb1a53a..cfdde0a 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -719,6 +719,19 @@ a given pattern are handled as if they were given as arguments of
Creates a separate output section for every orphan input section.
.It Fl -unresolved-symbols Ns = Ns Ar value
Determine how to handle unresolved symbols.
+.Ar value
+may be:
+.Pp
+.Bl -tag -width 2n -compact
+.It Cm report-all
+Report unresolved symbols (default).
+.It Cm ignore-in-object-files
+Only report unresolved symbols contained in shared libraries.
+.It Cm ignore-in-shared-libs
+Only report unresolved symbols contained in object files.
+.It Cm ignore-all
+Do not report unresolved symbols.
+.El
.It Fl -use-android-relr-tags
Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*.
.It Fl v , Fl V
diff --git a/lld/test/COFF/arm64ec-codemap.test b/lld/test/COFF/arm64ec-codemap.test
index 0502611..bbc682d 100644
--- a/lld/test/COFF/arm64ec-codemap.test
+++ b/lld/test/COFF/arm64ec-codemap.test
@@ -7,6 +7,7 @@ RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym2.s -o arm64e
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec.s -o data-sec.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec2.s -o data-sec2.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows empty-sec.s -o arm64ec-empty-sec.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows entry-thunk.s -o entry-thunk.obj
RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-func-sym.s -o x86_64-func-sym.obj
RUN: llvm-mc -filetype=obj -triple=x86_64-windows empty-sec.s -o x86_64-empty-sec.obj
RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
@@ -162,15 +163,17 @@ RUN: loadconfig-arm64ec.obj -dll -noentry -merge:test=.testdata -merge:
RUN: llvm-readobj --coff-load-config testcm.dll | FileCheck -check-prefix=CODEMAPCM %s
CODEMAPCM: CodeMap [
-CODEMAPCM-NEXT: 0x4008 - 0x4016 X64
+CODEMAPCM-NEXT: 0x4000 - 0x4016 X64
CODEMAPCM-NEXT: ]
RUN: llvm-objdump -d testcm.dll | FileCheck -check-prefix=DISASMCM %s
DISASMCM: Disassembly of section .testdat:
DISASMCM-EMPTY:
DISASMCM-NEXT: 0000000180004000 <.testdat>:
-DISASMCM-NEXT: 180004000: 00000001 udf #0x1
-DISASMCM-NEXT: 180004004: 00000000 udf #0x0
+DISASMCM-NEXT: 180004000: 01 00 addl %eax, (%rax)
+DISASMCM-NEXT: 180004002: 00 00 addb %al, (%rax)
+DISASMCM-NEXT: 180004004: 00 00 addb %al, (%rax)
+DISASMCM-NEXT: 180004006: 00 00 addb %al, (%rax)
DISASMCM-NEXT: 180004008: b8 03 00 00 00 movl $0x3, %eax
DISASMCM-NEXT: 18000400d: c3 retq
DISASMCM-NEXT: 18000400e: 00 00 addb %al, (%rax)
@@ -207,6 +210,14 @@ DISASMMS-NEXT: 0000000180006000 <test2>:
DISASMMS-NEXT: 180006000: 528000a0 mov w0, #0x5 // =5
DISASMMS-NEXT: 180006004: d65f03c0 ret
+Test the code map that includes an ARM64EC function padded by its entry-thunk offset.
+
+RUN: lld-link -out:testpad.dll -machine:arm64ec entry-thunk.obj loadconfig-arm64ec.obj -dll -noentry -include:func
+RUN: llvm-readobj --coff-load-config testpad.dll | FileCheck -check-prefix=CODEMAPPAD %s
+CODEMAPPAD: CodeMap [
+CODEMAPPAD: 0x1000 - 0x1010 ARM64EC
+CODEMAPPAD-NEXT: ]
+
#--- arm64-func-sym.s
.text
@@ -266,3 +277,22 @@ x86_64_func_sym2:
.section .empty1, "xr"
.section .empty2, "xr"
.section .empty3, "xr"
+
+#--- entry-thunk.s
+ .section .text,"xr",discard,func
+ .globl func
+ .p2align 2, 0x0
+func:
+ mov w0, #1
+ ret
+
+ .section .wowthk$aa,"xr",discard,thunk
+ .globl thunk
+ .p2align 2
+thunk:
+ ret
+
+ .section .hybmp$x,"yi"
+ .symidx func
+ .symidx thunk
+ .word 1 // entry thunk
diff --git a/lld/test/COFF/driver.test b/lld/test/COFF/driver.test
index 8f58ff4..1c265bf 100644
--- a/lld/test/COFF/driver.test
+++ b/lld/test/COFF/driver.test
@@ -17,6 +17,9 @@ LIBHELP: OVERVIEW: LLVM Lib
# RUN: env LLD_IN_TEST=1 not lld-link /WX /lib 2>&1 | FileCheck -check-prefix=LIBBAD %s
LIBBAD: ignoring /lib since it's not the first argument
+# RUN: env LLD_IN_TEST=1 not lld-link /link 2>&1 | FileCheck -check-prefix=LINKBAD %s
+LINKBAD: ignoring /link, did you pass it multiple times?
+
# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
# RUN: not lld-link /out:/ %t.obj 2>&1 | FileCheck -check-prefix=DIR %s
DIR: cannot open output file
diff --git a/lld/test/ELF/aarch64-funcinit64-invalid.s b/lld/test/ELF/aarch64-funcinit64-invalid.s
new file mode 100644
index 0000000..4577db7
--- /dev/null
+++ b/lld/test/ELF/aarch64-funcinit64-invalid.s
@@ -0,0 +1,18 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck --check-prefix=ERR %s
+
+.rodata
+# ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against local symbol
+.8byte func@FUNCINIT
+
+.data
+# ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against ifunc symbol 'ifunc'
+.8byte ifunc@FUNCINIT
+
+.text
+func:
+.type ifunc, @gnu_indirect_function
+ifunc:
+ret
diff --git a/lld/test/ELF/aarch64-funcinit64.s b/lld/test/ELF/aarch64-funcinit64.s
new file mode 100644
index 0000000..5f2b863
--- /dev/null
+++ b/lld/test/ELF/aarch64-funcinit64.s
@@ -0,0 +1,19 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readelf -s -r %t | FileCheck %s
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readelf -s -r %t | FileCheck %s
+# RUN: not ld.lld %t.o -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s
+
+.data
+# CHECK: R_AARCH64_IRELATIVE [[FOO:[0-9a-f]*]]
+# ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against preemptible symbol 'foo'
+.8byte foo@FUNCINIT
+
+.text
+# CHECK: {{0*}}[[FOO]] {{.*}} foo
+.globl foo
+foo:
+ret
diff --git a/lld/test/ELF/dso-undef-extract-lazy.s b/lld/test/ELF/dso-undef-extract-lazy.s
index 40b0758..5d92545 100644
--- a/lld/test/ELF/dso-undef-extract-lazy.s
+++ b/lld/test/ELF/dso-undef-extract-lazy.s
@@ -25,6 +25,11 @@
# CHECK-FETCH: GLOBAL DEFAULT {{[0-9]+}} foo
+## Unversioned undefined symbols also extract the archive definitions.
+# RUN: yaml2obj %t/ver.yaml -o %t4.so
+# RUN: ld.lld %t1.o %t4.so %t2.a -o %t.exe
+# RUN: llvm-readelf --dyn-symbols %t.exe | FileCheck %s --check-prefix=CHECK-FETCH
+
#--- main.s
.text
.globl _start
@@ -38,3 +43,39 @@ foo:
#--- shlib.s
.global foo
+
+#--- ver.yaml
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .gnu.version
+ Type: SHT_GNU_versym
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000200210
+ AddressAlign: 0x0000000000000002
+ EntSize: 0x0000000000000002
+## Test both index 0 and 1 for unversioned undefined symbols.
+## https://sourceware.org/PR33577
+ Entries: [ 0, 0, 1 ]
+ - Name: .gnu.version_r
+ Type: SHT_GNU_verneed
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000200250
+ AddressAlign: 0x0000000000000004
+ Dependencies:
+ - Version: 1
+ File: dso.so.0
+ Entries:
+ - Name: v1
+ Hash: 1937
+ Flags: 0
+ Other: 3
+DynamicSymbols:
+ - Name: _start
+ Binding: STB_GLOBAL
+ - Name: foo
+ Binding: STB_GLOBAL
diff --git a/lld/test/ELF/linkerscript/version-script.s b/lld/test/ELF/linkerscript/version-script.s
index 52382ee..6b97fed 100644
--- a/lld/test/ELF/linkerscript/version-script.s
+++ b/lld/test/ELF/linkerscript/version-script.s
@@ -17,7 +17,7 @@
# CHECK-NEXT: Name:
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Version: 0
# CHECK-NEXT: Name: und
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
diff --git a/lld/test/ELF/riscv-vendor-relocations.s b/lld/test/ELF/riscv-vendor-relocations.s
index b0f3c4a..f121ade 100644
--- a/lld/test/ELF/riscv-vendor-relocations.s
+++ b/lld/test/ELF/riscv-vendor-relocations.s
@@ -8,12 +8,19 @@
TARGET:
nop
-.global INVALID_VENDOR
+.local INVALID_VENDOR
+.local QUALCOMM
+.local ANDES
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
.reloc 1f, R_RISCV_CUSTOM255, TARGET
-1:
- nop
-
# CHECK: error: {{.*}}:(.text+0x4): malformed consecutive R_RISCV_VENDOR relocations
# CHECK: error: {{.*}}:(.text+0x4): unknown vendor-specific relocation (255) in namespace 'INVALID_VENDOR' against symbol 'TARGET'
+.reloc 1f, R_RISCV_VENDOR, QUALCOMM+0
+.reloc 1f, R_RISCV_CUSTOM192, TARGET
+# CHECK: error: {{.*}}:(.text+0x4): unsupported vendor-specific relocation R_RISCV_QC_ABS20_U against symbol TARGET
+.reloc 1f, R_RISCV_VENDOR, ANDES+0
+.reloc 1f, R_RISCV_CUSTOM241, TARGET
+# CHECK: error: {{.*}}:(.text+0x4): unsupported vendor-specific relocation R_RISCV_NDS_BRANCH_10 against symbol TARGET
+1:
+ nop
diff --git a/lld/test/ELF/version-script-extern-undefined.s b/lld/test/ELF/version-script-extern-undefined.s
index 3811422..010b4d5 100644
--- a/lld/test/ELF/version-script-extern-undefined.s
+++ b/lld/test/ELF/version-script-extern-undefined.s
@@ -11,7 +11,7 @@
# CHECK-NEXT: Name:
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Version: 0
# CHECK-NEXT: Name: _Z3abbi
# CHECK-NEXT: }
# CHECK-NEXT: ]
diff --git a/lld/test/MachO/handle-invalid-section-reference-too-big.test b/lld/test/MachO/handle-invalid-section-reference-too-big.test
new file mode 100644
index 0000000..1642d63
--- /dev/null
+++ b/lld/test/MachO/handle-invalid-section-reference-too-big.test
@@ -0,0 +1,128 @@
+# REQUIRES: aarch64
+
+## This is a regression test which makes sure that when there is an invalid section index
+## associated with a section symbol, the linker does not segfault.
+
+## Test YAML content was created using the following steps
+## 1. Create an object file from the following assembly
+## `llvm-mc -filetype=obj -triple=arm64-apple-darwin symbol.s -o symbol.o`
+##
+## .text
+## .section __TEST,__mystuff
+## .globl _mysec
+## _mysec:
+## .byte 0xC3
+##
+## 2. Use obj2yaml to convert object file to yaml
+## `obj2yaml symbol.o -o symbol.yaml`
+##
+## 3. Manually set n_sect value of ltmp1 symbol to 10 which is greater than the number of sections 2.
+##
+
+# RUN: yaml2obj %s -o %t
+# RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
+
+# FATAL: error: section symbol ltmp0 in {{.*}} has an invalid section index [10] greater than the total number of sections [2]
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x100000C
+ cpusubtype: 0x0
+ filetype: 0x1
+ ncmds: 3
+ sizeofcmds: 336
+ flags: 0x0
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: ''
+ vmaddr: 0
+ vmsize: 1
+ fileoff: 368
+ filesize: 1
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0
+ size: 0
+ offset: 0x170
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000000
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: ''
+ - sectname: __mystuff
+ segname: __TEST
+ addr: 0x0
+ size: 1
+ offset: 0x170
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x0
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: C3
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 376
+ nsyms: 3
+ stroff: 424
+ strsize: 24
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 2
+ iextdefsym: 2
+ nextdefsym: 1
+ iundefsym: 3
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 14
+ n_type: 0xE
+ n_sect: 10
+ n_desc: 0
+ n_value: 0
+ - n_strx: 8
+ n_type: 0xE
+ n_sect: 2
+ n_desc: 0
+ n_value: 0
+ - n_strx: 1
+ n_type: 0xF
+ n_sect: 2
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - _mysec
+ - ltmp1
+ - ltmp0
+ - ''
+ - ''
+ - ''
+ - ''
+...
diff --git a/lld/test/MachO/handle-invalid-section-reference-zero.test b/lld/test/MachO/handle-invalid-section-reference-zero.test
new file mode 100644
index 0000000..ab63670
--- /dev/null
+++ b/lld/test/MachO/handle-invalid-section-reference-zero.test
@@ -0,0 +1,128 @@
+# REQUIRES: aarch64
+
+## This is a regression test which makes sure that when there is an invalid section index
+## associated with a section symbol, the linker does not segfault.
+
+## Test YAML content was created using the following steps
+## 1. Create an object file from the following assembly
+## `llvm-mc -filetype=obj -triple=arm64-apple-darwin symbol.s -o symbol.o`
+##
+## .text
+## .section __TEST,__mystuff
+## .globl _mysec
+## _mysec:
+## .byte 0xC3
+##
+## 2. Use obj2yaml to convert object file to yaml
+## `obj2yaml symbol.o -o symbol.yaml`
+##
+## 3. Manually set n_sect value of ltmp1 symbol to 0 instead of 1.
+##
+
+# RUN: yaml2obj %s -o %t
+# RUN: not %lld -platform_version macos 10.14 11.0 -arch arm64 %t 2>&1 | FileCheck %s --check-prefix=FATAL
+
+# FATAL: error: section symbol ltmp0 in {{.*}} has an invalid section index [0]
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x100000C
+ cpusubtype: 0x0
+ filetype: 0x1
+ ncmds: 3
+ sizeofcmds: 336
+ flags: 0x0
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: ''
+ vmaddr: 0
+ vmsize: 1
+ fileoff: 368
+ filesize: 1
+ maxprot: 7
+ initprot: 7
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0
+ size: 0
+ offset: 0x170
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000000
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: ''
+ - sectname: __mystuff
+ segname: __TEST
+ addr: 0x0
+ size: 1
+ offset: 0x170
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x0
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: C3
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 376
+ nsyms: 3
+ stroff: 424
+ strsize: 24
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 2
+ iextdefsym: 2
+ nextdefsym: 1
+ iundefsym: 3
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 14
+ n_type: 0xE
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 8
+ n_type: 0xE
+ n_sect: 2
+ n_desc: 0
+ n_value: 0
+ - n_strx: 1
+ n_type: 0xF
+ n_sect: 2
+ n_desc: 0
+ n_value: 0
+ StringTable:
+ - ''
+ - _mysec
+ - ltmp1
+ - ltmp0
+ - ''
+ - ''
+ - ''
+ - ''
+...
diff --git a/lld/test/MachO/invalid/bad-offsets.s b/lld/test/MachO/invalid/bad-offsets.s
new file mode 100644
index 0000000..e1244ee
--- /dev/null
+++ b/lld/test/MachO/invalid/bad-offsets.s
@@ -0,0 +1,45 @@
+## Test that we properly detect and report out-of-bounds offsets in literal sections.
+## We're intentionally testing fatal errors (for malformed input files), and
+## fatal errors aren't supported for testing when main is run twice.
+# XFAIL: main-run-twice
+
+# REQUIRES: x86
+# RUN: rm -rf %t; split-file %s %t
+
+## Test WordLiteralInputSection bounds checking
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/word-literal.s -o %t/word-literal.o
+# RUN: not %lld -dylib %t/word-literal.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=WORD
+
+## Test CStringInputSection bounds checking
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/cstring.s -o %t/cstring.o
+# RUN: not %lld -dylib %t/cstring.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CSTRING
+
+# WORD: error: {{.*}}word-literal.o:(__literal4): offset is outside the section
+# CSTRING: error: {{.*}}cstring.o:(__cstring): offset is outside the section
+
+#--- word-literal.s
+.section __TEXT,__literal4,4byte_literals
+L_literal:
+ .long 0x01020304
+
+.text
+.globl _main
+_main:
+ # We use a subtractor expression to force a section relocation. Symbol relocations
+ # don't trigger the error.
+ .long L_literal - _main + 4
+
+.subsections_via_symbols
+
+#--- cstring.s
+## Create a cstring section with a reference that points past the end
+.cstring
+L_str:
+ .asciz "foo"
+
+.text
+.globl _main
+_main:
+ .long L_str - _main + 4
+
+.subsections_via_symbols \ No newline at end of file
diff --git a/lld/test/MachO/order-file-cstring.s b/lld/test/MachO/order-file-cstring.s
index 3c6d2a3..d673430 100644
--- a/lld/test/MachO/order-file-cstring.s
+++ b/lld/test/MachO/order-file-cstring.s
@@ -4,32 +4,34 @@
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/test.s -o %t/test.o
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/more-cstrings.s -o %t/more-cstrings.o
-# RUN: %lld --deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-0 %t/test.o %t/more-cstrings.o
+# RUN: %lld -arch arm64 -lSystem -e _main -o %t/test-0 %t/test.o %t/more-cstrings.o
# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-0 | FileCheck %s --check-prefix=ORIGIN_SYM
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-0 | FileCheck %s --check-prefix=ORIGIN_SEC
-# RUN: %lld --deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-1 %t/test.o %t/more-cstrings.o -order_file %t/ord-1
+# RUN: %lld -arch arm64 -lSystem -e _main -o %t/test-1 %t/test.o %t/more-cstrings.o -order_file %t/ord-1
# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-1 | FileCheck %s --check-prefix=ONE_SYM
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-1 | FileCheck %s --check-prefix=ONE_SEC
+# RUN: %lld --no-deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-1-dup %t/test.o %t/more-cstrings.o -order_file %t/ord-1
+# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-1-dup | FileCheck %s --check-prefix=ONE_SYM
+# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-1-dup | FileCheck %s --check-prefix=ONE_SEC
-# RUN: %lld --deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-2 %t/test.o %t/more-cstrings.o -order_file %t/ord-2
+# RUN: %lld -arch arm64 -lSystem -e _main -o %t/test-2 %t/test.o %t/more-cstrings.o -order_file %t/ord-2
# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-2 | FileCheck %s --check-prefix=TWO_SYM
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-2 | FileCheck %s --check-prefix=TWO_SEC
-# RUN: %lld --deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-3 %t/test.o %t/more-cstrings.o -order_file %t/ord-3
+# RUN: %lld -arch arm64 -lSystem -e _main -o %t/test-3 %t/test.o %t/more-cstrings.o -order_file %t/ord-3
# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-3 | FileCheck %s --check-prefix=THREE_SYM
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-3 | FileCheck %s --check-prefix=THREE_SEC
-# RUN: %lld --deduplicate-strings -arch arm64 -lSystem -e _main -o %t/test-4 %t/test.o %t/more-cstrings.o -order_file %t/ord-4
+# RUN: %lld -arch arm64 -lSystem -e _main -o %t/test-4 %t/test.o %t/more-cstrings.o -order_file %t/ord-4
# RUN: llvm-nm --numeric-sort --format=just-symbols %t/test-4 | FileCheck %s --check-prefix=FOUR_SYM
# RUN: llvm-objdump --macho --section="__TEXT,__cstring" %t/test-4 | FileCheck %s --check-prefix=FOUR_SEC
# RUN: llvm-readobj --string-dump=__cstring %t/test-4 | FileCheck %s --check-prefix=FOUR_SEC_ESCAPE
-
# We expect:
-# 1) Covered cstring symbols are reordered
-# 2) the rest of the cstring symbols remain original relative order within the cstring section
+# 1) Covered cstring symbols to be reordered
+# 2) the rest of the cstring symbols remain in the original relative order within the cstring section
# ORIGIN_SYM: _local_foo1
# ORIGIN_SYM: _globl_foo2
@@ -58,8 +60,8 @@ CSTR;1496286555
#foo3
CSTR;1343999025
-# ONE_SYM: _globl_foo2
-# ONE_SYM: _local_foo2
+# ONE_SYM-DAG: _globl_foo2
+# ONE_SYM-DAG: _local_foo2
# ONE_SYM: _bar
# ONE_SYM: _bar2
# ONE_SYM: _globl_foo3
diff --git a/lld/test/MachO/read-workers.s b/lld/test/MachO/read-workers.s
index 294106b..4d2f88c 100644
--- a/lld/test/MachO/read-workers.s
+++ b/lld/test/MachO/read-workers.s
@@ -1,7 +1,4 @@
# REQUIRES: x86 && thread_support
-## Sometimes fails, particularly in an ASAN build, do not run until
-## https://github.com/llvm/llvm-project/pull/157917 addresses the cause.
-# UNSUPPORTED: target={{.*}}
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
## A non-negative integer is allowed.
diff --git a/lld/test/MachO/set-slop-scale.s b/lld/test/MachO/set-slop-scale.s
new file mode 100644
index 0000000..a18acce
--- /dev/null
+++ b/lld/test/MachO/set-slop-scale.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-darwin %s -o %t.o
+# RUN: %lld -o /dev/null %t.o --slop_scale=1
+# RUN: not %lld -o /dev/null %t.o --slop_scale=-1 2>&1 | FileCheck %s
+# CHECK: error: --slop_scale=: expected a non-negative integer, but got '-1'
+
+.text
+.global _main
+_main:
+ mov $0, %rax
+ ret
diff --git a/lld/test/MachO/weak-alias-override.s b/lld/test/MachO/weak-alias-override.s
new file mode 100644
index 0000000..224ddc4
--- /dev/null
+++ b/lld/test/MachO/weak-alias-override.s
@@ -0,0 +1,97 @@
+# REQUIRES: x86
+# RUN: rm -rf %t; split-file %s %t
+# RUN: mkdir -p %t/bin
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/weak.o %t/weak.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/strong_a.o %t/strong_a.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/strong_b.o %t/strong_b.s
+
+# --- Test Case 1: No overrides
+# RUN: %lld %t/weak.o -o %t/bin/alone -e _s
+# RUN: llvm-nm -am %t/bin/alone | FileCheck --check-prefix=NM_ALONE %s
+
+# NM_ALONE: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_ALONE: [[#P_ADDR]] (__TEXT,__const) weak external _weak_a
+# NM_ALONE: [[#P_ADDR]] (__TEXT,__const) weak external _weak_b
+
+# --- Test Case 2: Override weak_a
+# RUN: %lld %t/weak.o %t/strong_a.o -o %t/bin/with_a -e _s
+# RUN: llvm-nm -am %t/bin/with_a | FileCheck --check-prefix=NM_WITH_A %s
+# RUN: llvm-nm -am %t/bin/with_a | FileCheck --check-prefix=NM_WITH_A_BAD %s
+
+# NM_WITH_A: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_A: [[#%x, A_ADDR:]] (__TEXT,__const) external _strong_a
+# NM_WITH_A: [[#A_ADDR]] (__TEXT,__const) external _weak_a
+# NM_WITH_A: [[#P_ADDR]] (__TEXT,__const) weak external _weak_b
+
+# --- Addresses of _placeholder_int and _strong_a must not match.
+# NM_WITH_A_BAD: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_A_BAD-NOT: [[#P_ADDR]] (__TEXT,__const) external _strong_a
+
+# --- Test Case 3: Override weak_b
+# RUN: %lld %t/weak.o %t/strong_b.o -o %t/bin/with_b -e _s
+# RUN: llvm-nm -am %t/bin/with_b | FileCheck --check-prefix=NM_WITH_B %s
+# RUN: llvm-nm -am %t/bin/with_b | FileCheck --check-prefix=NM_WITH_B_BAD %s
+
+# NM_WITH_B: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_B: [[#%x, B_ADDR:]] (__TEXT,__const) external _strong_b
+# NM_WITH_B: [[#P_ADDR]] (__TEXT,__const) weak external _weak_a
+# NM_WITH_B: [[#B_ADDR]] (__TEXT,__const) external _weak_b
+
+# --- Addresses of _placeholder_int and _strong_a must not match.
+# NM_WITH_B_BAD: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_B_BAD-NOT: [[#P_ADDR]] (__TEXT,__const) external _strong_b
+
+# --- Test Case 4: Override weak_a and weak_b
+# RUN: %lld %t/weak.o %t/strong_a.o %t/strong_b.o -o %t/bin/with_ab -e _s
+# RUN: llvm-nm -am %t/bin/with_ab | FileCheck --check-prefix=NM_WITH_AB %s
+# RUN: llvm-nm -am %t/bin/with_ab | FileCheck --check-prefix=NM_WITH_AB_BAD %s
+
+# NM_WITH_AB: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_AB: [[#%x, A_ADDR:]] (__TEXT,__const) external _strong_a
+# NM_WITH_AB: [[#%x, B_ADDR:]] (__TEXT,__const) external _strong_b
+# NM_WITH_AB: [[#A_ADDR]] (__TEXT,__const) external _weak_a
+# NM_WITH_AB: [[#B_ADDR]] (__TEXT,__const) external _weak_b
+
+# --- Addresses of _placeholder_int, _strong_a, and _strong_b must all be distinct
+# NM_WITH_AB_BAD: [[#%x, P_ADDR:]] (__TEXT,__const) weak external _placeholder_int
+# NM_WITH_AB_BAD-NOT: [[#P_ADDR]] (__TEXT,__const) external _strong_a
+# NM_WITH_AB_BAD-NOT: [[#P_ADDR]] (__TEXT,__const) external _strong_b
+
+#--- weak.s
+.section __TEXT,__const
+.globl _placeholder_int
+.weak_definition _placeholder_int
+_placeholder_int:
+ .long 0
+
+.globl _weak_a
+.set _weak_a, _placeholder_int
+.weak_definition _weak_a
+
+.globl _weak_b
+.set _weak_b, _placeholder_int
+.weak_definition _weak_b
+
+.globl _s
+_s:
+ .quad _weak_a
+ .quad _weak_b
+
+#--- strong_a.s
+.section __TEXT,__const
+.globl _strong_a
+_strong_a:
+ .long 1
+
+.globl _weak_a
+_weak_a = _strong_a
+
+#--- strong_b.s
+.section __TEXT,__const
+.globl _strong_b
+_strong_b:
+ .long 2
+
+.globl _weak_b
+_weak_b = _strong_b
diff --git a/lld/test/MachO/x86-64-relocs.s b/lld/test/MachO/x86-64-relocs.s
index 5303948..d29f689 100644
--- a/lld/test/MachO/x86-64-relocs.s
+++ b/lld/test/MachO/x86-64-relocs.s
@@ -4,6 +4,7 @@
# RUN: llvm-objdump --no-print-imm-hex --section-headers --syms -d %t | FileCheck %s
# CHECK-LABEL: Sections:
+# CHECK: __branch_target {{[0-9a-z]+}} [[#%x, BRANCH_SECT:]]
# CHECK: __data {{[0-9a-z]+}} [[#%x, DATA_ADDR:]]
# CHECK-LABEL: SYMBOL TABLE:
@@ -12,10 +13,18 @@
# CHECK-LABEL: <_main>:
## Test X86_64_RELOC_BRANCH
+## Test symbol (extern) relocations first (most common case)
# CHECK: callq 0x[[#%x, F_ADDR]] <_f>
# CHECK: jrcxz 0x[[#%x, F_ADDR]] <_f>
# CHECK: callq 0x[[#%x, G_ADDR]] <_g>
# CHECK: jrcxz 0x[[#%x, G_ADDR]] <_g>
+## Test section (local) BRANCH relocations
+# CHECK: callq 0x[[#%x, BRANCH_SECT]]
+## NOTE: ld64 rejects 1-byte local branch relocations as unsupported, but it
+## doesn't take any extra code for us to support it
+# CHECK: jrcxz 0x[[#%x, BRANCH_SECT]]
+
+# CHECK-LABEL: <_f>:
## Test extern (symbol) X86_64_RELOC_SIGNED
# CHECK: leaq [[#%u, LOCAL_OFF:]](%rip), %rsi
# CHECK-NEXT: [[#%x, DATA_ADDR - LOCAL_OFF]]
@@ -33,9 +42,12 @@
_main:
callq _f # X86_64_RELOC_BRANCH with r_length=2
jrcxz _f # X86_64_RELOC_BRANCH with r_length=0
- # test negative addends
+ # Test negative addends
callq _f - 1
jrcxz _f - 1
+ # Test section relocations
+ callq L_.branch_target
+ jrcxz L_.branch_target
mov $0, %rax
ret
@@ -48,6 +60,10 @@ _f:
movq L_.ptr_1(%rip), %rsi
ret
+.section __TEXT,__branch_target
+L_.branch_target:
+ ret
+
.data
## References to this generate a symbol relocation
_local:
diff --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test
index 47809d8..ef03c01 100644
--- a/lld/test/MinGW/driver.test
+++ b/lld/test/MinGW/driver.test
@@ -37,6 +37,12 @@ ARM64X-SAME: -machine:arm64x
ARM64X-SAME: -alternatename:__image_base__=__ImageBase
ARM64X-SAME: foo.o
+RUN: ld.lld -### foo.o -m mipspe 2>&1 | FileCheck -check-prefix=MIPS %s
+MIPS: -out:a.exe
+MIPS-SAME: -machine:mips
+MIPS-SAME: -alternatename:__image_base__=__ImageBase
+MIPS-SAME: foo.o
+
RUN: ld.lld -### foo.o -m i386pep -shared 2>&1 | FileCheck -check-prefix=SHARED %s
RUN: ld.lld -### foo.o -m i386pep --shared 2>&1 | FileCheck -check-prefix=SHARED %s
RUN: ld.lld -### foo.o -m i386pep --dll 2>&1 | FileCheck -check-prefix=SHARED %s
diff --git a/lld/test/wasm/alias.s b/lld/test/wasm/alias.s
index 0bb035b..83f40a8 100644
--- a/lld/test/wasm/alias.s
+++ b/lld/test/wasm/alias.s
@@ -24,7 +24,7 @@ _start:
# CHECK-NEXT: FunctionTypes: [ 0 ]
# CHECK-NEXT: - Type: MEMORY
# CHECK-NEXT: Memories:
-# CHECK-NEXT: - Minimum: 0x2
+# CHECK-NEXT: - Minimum: 0x1
# CHECK-NEXT: - Type: GLOBAL
# CHECK-NEXT: Globals:
# CHECK-NEXT: - Index: 0
@@ -32,7 +32,7 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/bss-only.s b/lld/test/wasm/bss-only.s
index 1c0500f..bec7592 100644
--- a/lld/test/wasm/bss-only.s
+++ b/lld/test/wasm/bss-only.s
@@ -26,13 +26,13 @@ b:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 67568
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 2028
+# CHECK-NEXT: Value: 66540
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/build-id.test b/lld/test/wasm/build-id.test
index dd6e223710..5fafd21 100644
--- a/lld/test/wasm/build-id.test
+++ b/lld/test/wasm/build-id.test
@@ -43,12 +43,12 @@ foo:
# DEFAULT: Contents of section build_id:
-# DEFAULT-NEXT: 0079 10299168 1e3c845a 3c8f80ae 2f16cc22 .).h.<.Z<.../.."
-# DEFAULT-NEXT: 0089 2d
+# DEFAULT-NEXT: 0079 103f86e6 3bb81959 2e99ffa9 acfed331 .?..;..Y.......1
+# DEFAULT-NEXT: 0089 3a
# SHA1: Contents of section build_id:
-# SHA1-NEXT: 0079 145abdda 387a9bc4 e3aed3c3 3319cd37 .Z..8z......3..7
-# SHA1-NEXT: 0089 0212237c e4 ..#|.
+# SHA1-NEXT: 0079 1410ade4 e75d1c9d 71023465 03b7572f .....]..q.4e..W/
+# SHA1-NEXT: 0089 c06c5ae0 74 .lZ.t
# UUID: Contents of section build_id:
# UUID-NEXT: 0079 10
diff --git a/lld/test/wasm/call-indirect.s b/lld/test/wasm/call-indirect.s
index 7bf39a9..64eaa59 100644
--- a/lld/test/wasm/call-indirect.s
+++ b/lld/test/wasm/call-indirect.s
@@ -82,13 +82,13 @@ indirect_func:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66576
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1032
+# CHECK-NEXT: Value: 65544
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
@@ -125,23 +125,23 @@ indirect_func:
# CHECK-NEXT: Body: 42010B
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Locals:
-# CHECK-NEXT: Body: 410028028088808000118080808000001A410028028488808000118180808000001A0B
+# CHECK-NEXT: Body: 410028028080848000118080808000001A410028028480848000118180808000001A0B
# CHECK-NEXT: - Index: 2
# CHECK-NEXT: Locals:
# CHECK-NEXT: Body: 41020B
# CHECK-NEXT: - Index: 3
# CHECK-NEXT: Locals:
-# CHECK-NEXT: Body: 410028028888808000118180808000001A0B
+# CHECK-NEXT: Body: 410028028880848000118180808000001A0B
# CHECK-NEXT: - Index: 4
# CHECK-NEXT: Locals:
# CHECK-NEXT: Body: 42012000118280808000001A0B
# CHECK-NEXT: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: '010000000200000002000000'
# CHECK-NEXT: - Type: CUSTOM
# CHECK-NEXT: Name: name
diff --git a/lld/test/wasm/comdats.ll b/lld/test/wasm/comdats.ll
index 2dd687f..1662a98 100644
--- a/lld/test/wasm/comdats.ll
+++ b/lld/test/wasm/comdats.ll
@@ -23,13 +23,13 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: memory
@@ -69,7 +69,7 @@ entry:
; CHECK-NEXT: Body: 1080808080001082808080001A0B
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4180888080000B
+; CHECK-NEXT: Body: 4180808480000B
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 0B
@@ -81,9 +81,9 @@ entry:
; CHECK-NEXT: Body: 4181808080000B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '616263'
diff --git a/lld/test/wasm/compress-relocs.s b/lld/test/wasm/compress-relocs.s
index 41d4ff5..37f1b3b 100644
--- a/lld/test/wasm/compress-relocs.s
+++ b/lld/test/wasm/compress-relocs.s
@@ -47,16 +47,16 @@ test_memory_and_indirect_call_relocs:
end_function
# CHECK: test_memory_and_indirect_call_relocs
-# CHECK: 41 90 88 80 80 00 i32.const 1040
+# CHECK: 41 90 80 84 80 00 i32.const 65552
# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0
-# CHECK: 28 02 94 88 80 80 00 i32.load 1044
+# CHECK: 28 02 94 80 84 80 00 i32.load 65556
# CHECK: 11 81 80 80 80 00 80 80 80 80 00 call_indirect 1
# CHECK: 41 81 80 80 80 00 i32.const 1
# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0
# COMPRESS: test_memory_and_indirect_call_relocs
-# COMPRESS: 41 90 08 i32.const 1040
+# COMPRESS: 41 90 80 04 i32.const 65552
# COMPRESS: 11 00 00 call_indirect 0
-# COMPRESS: 28 02 94 08 i32.load 1044
+# COMPRESS: 28 02 94 80 04 i32.load 65556
# COMPRESS: 11 01 00 call_indirect 1
# COMPRESS: 41 01 i32.const 1
# COMPRESS: 11 00 00 call_indirect 0
@@ -91,11 +91,11 @@ test_relative_relocs:
end_function
# CHECK: test_relative_relocs
-# CHECK: 41 90 88 80 80 00 i32.const 1040
+# CHECK: 41 90 80 84 80 00 i32.const 65552
# CHECK: 41 81 80 80 80 00 i32.const 1
# CHECK: 41 83 80 80 80 00 i32.const 3
# COMPRESS: test_relative_relocs
-# COMPRESS: 41 90 08 i32.const 1040
+# COMPRESS: 41 90 80 04 i32.const 65552
# COMPRESS: 41 01 i32.const 1
# COMPRESS: 41 03 i32.const 3
diff --git a/lld/test/wasm/compress-relocs64.s b/lld/test/wasm/compress-relocs64.s
index 44e7a08..f3ff646 100644
--- a/lld/test/wasm/compress-relocs64.s
+++ b/lld/test/wasm/compress-relocs64.s
@@ -36,12 +36,12 @@ test_memory_and_indirect_call_relocs:
end_function
# CHECK: test_memory_and_indirect_call_relocs
-# CHECK: 42 90 88 80 80 80 80 80 80 80 00 i64.const 1040
-# CHECK: 29 03 98 88 80 80 80 80 80 80 80 00 i64.load 1048
+# CHECK: 42 90 80 84 80 80 80 80 80 80 00 i64.const 65552
+# CHECK: 29 03 98 80 84 80 80 80 80 80 80 00 i64.load 65560
# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1
# COMPRESS: test_memory_and_indirect_call_relocs
-# COMPRESS: 42 90 08 i64.const 1040
-# COMPRESS: 29 03 98 08 i64.load 1048
+# COMPRESS: 42 90 80 04 i64.const 65552
+# COMPRESS: 29 03 98 80 04 i64.load 65560
# COMPRESS: 42 01 i64.const 1
.globl test_relative_relocs
@@ -56,11 +56,11 @@ test_relative_relocs:
end_function
# CHECK: test_relative_relocs
-# CHECK: 42 90 88 80 80 80 80 80 80 80 00 i64.const 1040
+# CHECK: 42 90 80 84 80 80 80 80 80 80 00 i64.const 65552
# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1
# CHECK: 42 83 80 80 80 80 80 80 80 80 00 i64.const 3
# COMPRESS: test_relative_relocs
-# COMPRESS: 42 90 08 i64.const 1040
+# COMPRESS: 42 90 80 04 i64.const 65552
# COMPRESS: 42 01 i64.const 1
# COMPRESS: 42 03 i64.const 3
diff --git a/lld/test/wasm/custom-section-name.ll b/lld/test/wasm/custom-section-name.ll
index 8799fbf..89cb72f 100644
--- a/lld/test/wasm/custom-section-name.ll
+++ b/lld/test/wasm/custom-section-name.ll
@@ -16,29 +16,29 @@ target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '00000000'
-; CHECK-NEXT: - SectionOffset: 17
+; CHECK-NEXT: - SectionOffset: 19
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1028
+; CHECK-NEXT: Value: 65540
; CHECK-NEXT: Content: 2A000000
-; CHECK-NEXT: - SectionOffset: 27
+; CHECK-NEXT: - SectionOffset: 30
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1032
+; CHECK-NEXT: Value: 65544
; CHECK-NEXT: Content: '07000000'
-; BSS-NEXT: - SectionOffset: 37
+; BSS-NEXT: - SectionOffset: 41
; BSS-NEXT: InitFlags: 0
; BSS-NEXT: Offset:
; BSS-NEXT: Opcode: I32_CONST
-; BSS-NEXT: Value: 1036
+; BSS-NEXT: Value: 65548
; BSS-NEXT: Content: '00000000'
; NO-BSS-NOT: - SectionOffset:
diff --git a/lld/test/wasm/data-layout.s b/lld/test/wasm/data-layout.s
index a68bc03..8df834d 100644
--- a/lld/test/wasm/data-layout.s
+++ b/lld/test/wasm/data-layout.s
@@ -63,33 +63,33 @@ local_struct_internal_ptr:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: [[PTR]]_CONST
-# CHECK-NEXT: Value: 66624
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: [[PTR]]
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: [[PTR]]_CONST
-# CHECK-NEXT: Value: 1080
+# CHECK-NEXT: Value: 65592
# CHECK-NEXT: - Index: 2
# CHECK-NEXT: Type: [[PTR]]
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: [[PTR]]_CONST
-# CHECK-NEXT: Value: 66624
+# CHECK-NEXT: Value: 65600
# CHECK: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: [[PTR]]_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: 68656C6C6F0A00
-# CHECK-NEXT: - SectionOffset: 20
+# CHECK-NEXT: - SectionOffset: 22
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: [[PTR]]_CONST
-# CHECK-NEXT: Value: 1040
+# CHECK-NEXT: Value: 65552
# RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry \
diff --git a/lld/test/wasm/data-segment-merging.ll b/lld/test/wasm/data-segment-merging.ll
index e6f3c5e..34c49e8 100644
--- a/lld/test/wasm/data-segment-merging.ll
+++ b/lld/test/wasm/data-segment-merging.ll
@@ -15,11 +15,11 @@
; MERGE-LABEL: - Type: DATA
; MERGE-NEXT: Segments:
-; MERGE-NEXT: - SectionOffset: 7
+; MERGE-NEXT: - SectionOffset: 8
; MERGE-NEXT: InitFlags: 0
; MERGE-NEXT: Offset:
; MERGE: Content: 636F6E7374616E74000000002B
-; MERGE-NEXT: - SectionOffset: 26
+; MERGE-NEXT: - SectionOffset: 28
; MERGE-NEXT: InitFlags: 0
; MERGE-NEXT: Offset:
; MERGE: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000
@@ -41,27 +41,27 @@
; SEPARATE-NOT: DATACOUNT
; SEPARATE-LABEL: - Type: DATA
; SEPARATE-NEXT: Segments:
-; SEPARATE-NEXT: - SectionOffset: 7
+; SEPARATE-NEXT: - SectionOffset: 8
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: 636F6E7374616E7400
-; SEPARATE-NEXT: - SectionOffset: 22
+; SEPARATE-NEXT: - SectionOffset: 24
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: 2B
-; SEPARATE-NEXT: - SectionOffset: 29
+; SEPARATE-NEXT: - SectionOffset: 32
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: 68656C6C6F00
-; SEPARATE-NEXT: - SectionOffset: 41
+; SEPARATE-NEXT: - SectionOffset: 45
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: 676F6F6462796500
-; SEPARATE-NEXT: - SectionOffset: 55
+; SEPARATE-NEXT: - SectionOffset: 60
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: '776861746576657200'
-; SEPARATE-NEXT: - SectionOffset: 70
+; SEPARATE-NEXT: - SectionOffset: 76
; SEPARATE-NEXT: InitFlags: 0
; SEPARATE-NEXT: Offset:
; SEPARATE: Content: 2A000000
diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll
index 6c401c4..237f428 100644
--- a/lld/test/wasm/data-segments.ll
+++ b/lld/test/wasm/data-segments.ll
@@ -61,20 +61,20 @@
; ACTIVE-NEXT: Body: 0B
; ACTIVE-NEXT: - Type: DATA
; ACTIVE-NEXT: Segments:
-; ACTIVE-NEXT: - SectionOffset: 7
+; ACTIVE-NEXT: - SectionOffset: 8
; ACTIVE-NEXT: InitFlags: 0
; ACTIVE-NEXT: Offset:
; ACTIVE32-NEXT: Opcode: I32_CONST
; ACTIVE64-NEXT: Opcode: I64_CONST
-; ACTIVE-NEXT: Value: 1024
+; ACTIVE-NEXT: Value: 65536
; ACTIVE-NEXT: Content: 636F6E7374616E74000000002B
-; ACTIVE-NEXT: - SectionOffset: 26
+; ACTIVE-NEXT: - SectionOffset: 28
; ACTIVE-NEXT: InitFlags: 0
; ACTIVE-NEXT: Offset:
; ACTIVE32-NEXT: Opcode: I32_CONST
; ACTIVE64-NEXT: Opcode: I64_CONST
-; ACTIVE-NEXT: Value: 1040
-; ACTIVE-NEXT: Content: 68656C6C6F00676F6F646279650000002A000000
+; ACTIVE-NEXT: Value: 65552
+; ACTIVE-NEXT: Content: 68656C6C6F00676F6F646279650000002A00000063000000
; ACTIVE-NEXT: - Type: CUSTOM
; ACTIVE-NEXT: Name: name
; ACTIVE-NEXT: FunctionNames:
@@ -201,7 +201,7 @@
; DIS-NEXT: block
; DIS-NEXT: block
-; NOPIC-DIS-NEXT: [[PTR]].const 11064
+; NOPIC-DIS-NEXT: [[PTR]].const 75576
; PIC-DIS-NEXT: local.get 0
; DIS-NEXT: i32.const 0
@@ -211,8 +211,8 @@
; DIS-NEXT: # 2: down to label0
; DIS-NEXT: end
-; NOPIC-DIS-NEXT: [[PTR]].const 1024
-; NOPIC-DIS-NEXT: [[PTR]].const 1024
+; NOPIC-DIS-NEXT: [[PTR]].const 65536
+; NOPIC-DIS-NEXT: [[PTR]].const 65536
; NOPIC-DIS-NEXT: global.set 1
; PIC-DIS-NEXT: [[PTR]].const 0
; PIC-DIS-NEXT: global.get 1
@@ -224,7 +224,7 @@
; DIS-NEXT: i32.const 4
; DIS-NEXT: memory.init 0, 0
-; NOPIC-DIS-NEXT: [[PTR]].const 1028
+; NOPIC-DIS-NEXT: [[PTR]].const 65540
; PIC-DIS-NEXT: [[PTR]].const 4
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
@@ -233,7 +233,7 @@
; DIS-NEXT: i32.const 13
; DIS-NEXT: memory.init 1, 0
-; NOPIC-DIS-NEXT: [[PTR]].const 1044
+; NOPIC-DIS-NEXT: [[PTR]].const 65556
; PIC-DIS-NEXT: [[PTR]].const 20
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
@@ -241,7 +241,7 @@
; DIS-NEXT: i32.const 0
; DIS-NEXT: i32.const 20
; DIS-NEXT: memory.init 2, 0
-; NOPIC-DIS-NEXT: [[PTR]].const 1064
+; NOPIC-DIS-NEXT: [[PTR]].const 65576
; PIC-DIS-NEXT: [[PTR]].const 40
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
@@ -249,13 +249,13 @@
; DIS-NEXT: [[PTR]].const 10000
; DIS-NEXT: memory.fill 0
-; NOPIC-DIS-NEXT: [[PTR]].const 11064
+; NOPIC-DIS-NEXT: [[PTR]].const 75576
; PIC-DIS-NEXT: local.get 0
; DIS-NEXT: i32.const 2
; DIS-NEXT: i32.atomic.store 0
-; NOPIC-DIS-NEXT: [[PTR]].const 11064
+; NOPIC-DIS-NEXT: [[PTR]].const 75576
; PIC-DIS-NEXT: local.get 0
; DIS-NEXT: i32.const -1
@@ -264,7 +264,7 @@
; DIS-NEXT: br 1 # 1: down to label1
; DIS-NEXT: end
-; NOPIC-DIS-NEXT: [[PTR]].const 11064
+; NOPIC-DIS-NEXT: [[PTR]].const 75576
; PIC-DIS-NEXT: local.get 0
; DIS-NEXT: i32.const 1
diff --git a/lld/test/wasm/debuginfo.test b/lld/test/wasm/debuginfo.test
index 9cb1cc3..7e6bd51 100644
--- a/lld/test/wasm/debuginfo.test
+++ b/lld/test/wasm/debuginfo.test
@@ -50,7 +50,7 @@ CHECK-NEXT: DW_AT_type (0x000000ac "int[2]")
CHECK-NEXT: DW_AT_external (true)
CHECK-NEXT: DW_AT_decl_file ("{{.*}}hi_foo.c")
CHECK-NEXT: DW_AT_decl_line (1)
-CHECK: DW_AT_location (DW_OP_addr 0x400)
+CHECK: DW_AT_location (DW_OP_addr 0x10000)
CHECK: DW_TAG_array_type
diff --git a/lld/test/wasm/dylink-non-pie.s b/lld/test/wasm/dylink-non-pie.s
index 3157b8c..fddfddb 100755
--- a/lld/test/wasm/dylink-non-pie.s
+++ b/lld/test/wasm/dylink-non-pie.s
@@ -32,7 +32,7 @@ f_p:
# DIS: <__wasm_apply_data_relocs>:
# DIS-EMPTY:
-# DIS-NEXT: i32.const 1024
+# DIS-NEXT: i32.const 65536
# DIS-NEXT: global.get 0
# DIS-NEXT: i32.store 0
# DIS-NEXT: end
diff --git a/lld/test/wasm/emit-relocs.s b/lld/test/wasm/emit-relocs.s
index 385344c..3df345c 100644
--- a/lld/test/wasm/emit-relocs.s
+++ b/lld/test/wasm/emit-relocs.s
@@ -41,11 +41,11 @@ foo:
# CHECK: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: '00000000'
# There should be a single relocation in this section (just the live symbol)
@@ -75,5 +75,5 @@ foo:
# CHECK-NEXT: Kind: DATA
# CHECK-NEXT: Name: __stack_low
# CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN, ABSOLUTE ]
-# CHECK-NEXT: Offset: 1040
# CHECK-NEXT: Size: 0
+# CHECK-NEXT: - Index: 3
diff --git a/lld/test/wasm/externref.s b/lld/test/wasm/externref.s
index ffc63a6..1443e5f 100644
--- a/lld/test/wasm/externref.s
+++ b/lld/test/wasm/externref.s
@@ -35,7 +35,7 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: EXTERNREF
# CHECK-NEXT: Mutable: true
diff --git a/lld/test/wasm/gc-sections.ll b/lld/test/wasm/gc-sections.ll
index e709ab7..69d7ed2 100644
--- a/lld/test/wasm/gc-sections.ll
+++ b/lld/test/wasm/gc-sections.ll
@@ -57,7 +57,7 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I64
; CHECK-NEXT: Mutable: true
@@ -67,11 +67,11 @@ entry:
; CHECK: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '02000000'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
@@ -123,7 +123,7 @@ entry:
; NO-GC-NEXT: Mutable: true
; NO-GC-NEXT: InitExpr:
; NO-GC-NEXT: Opcode: I32_CONST
-; NO-GC-NEXT: Value: 66576
+; NO-GC-NEXT: Value: 65536
; NO-GC-NEXT: - Index: 1
; NO-GC-NEXT: Type: I64
; NO-GC-NEXT: Mutable: true
@@ -139,11 +139,11 @@ entry:
; NO-GC: - Type: DATA
; NO-GC-NEXT: Segments:
-; NO-GC-NEXT: - SectionOffset: 7
+; NO-GC-NEXT: - SectionOffset: 8
; NO-GC-NEXT: InitFlags: 0
; NO-GC-NEXT: Offset:
; NO-GC-NEXT: Opcode: I32_CONST
-; NO-GC-NEXT: Value: 1024
+; NO-GC-NEXT: Value: 65536
; NO-GC-NEXT: Content: '010000000000000002000000'
; NO-GC-NEXT: - Type: CUSTOM
; NO-GC-NEXT: Name: name
diff --git a/lld/test/wasm/global-base.test b/lld/test/wasm/global-base.test
index 0e65f0c..e84b8ec 100644
--- a/lld/test/wasm/global-base.test
+++ b/lld/test/wasm/global-base.test
@@ -19,19 +19,19 @@ CHECK-1024-NEXT: Type: I32
CHECK-1024-NEXT: Mutable: true
CHECK-1024-NEXT: InitExpr:
CHECK-1024-NEXT: Opcode: I32_CONST
-CHECK-1024-NEXT: Value: 66560
+CHECK-1024-NEXT: Value: 65536
CHECK-1024-NEXT: - Index: 1
CHECK-1024-NEXT: Type: I32
CHECK-1024-NEXT: Mutable: false
CHECK-1024-NEXT: InitExpr:
CHECK-1024-NEXT: Opcode: I32_CONST
-CHECK-1024-NEXT: Value: 1024
+CHECK-1024-NEXT: Value: 65536
CHECK-1024-NEXT: - Index: 2
CHECK-1024-NEXT: Type: I32
CHECK-1024-NEXT: Mutable: false
CHECK-1024-NEXT: InitExpr:
CHECK-1024-NEXT: Opcode: I32_CONST
-CHECK-1024-NEXT: Value: 1024
+CHECK-1024-NEXT: Value: 65536
CHECK-1024: - Type: EXPORT
CHECK-1024: - Name: __data_end
@@ -50,7 +50,7 @@ CHECK-16777216-NEXT: Type: I32
CHECK-16777216-NEXT: Mutable: true
CHECK-16777216-NEXT: InitExpr:
CHECK-16777216-NEXT: Opcode: I32_CONST
-CHECK-16777216-NEXT: Value: 16842752
+CHECK-16777216-NEXT: Value: 65536
CHECK-16777216-NEXT: - Index: 1
CHECK-16777216-NEXT: Type: I32
CHECK-16777216-NEXT: Mutable: false
diff --git a/lld/test/wasm/globals.s b/lld/test/wasm/globals.s
index 6e049e1..47d9ba8 100644
--- a/lld/test/wasm/globals.s
+++ b/lld/test/wasm/globals.s
@@ -42,7 +42,7 @@ immutable_global:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
diff --git a/lld/test/wasm/import-memory.test b/lld/test/wasm/import-memory.test
index dd7066d..9b8148e 100644
--- a/lld/test/wasm/import-memory.test
+++ b/lld/test/wasm/import-memory.test
@@ -10,7 +10,7 @@
# CHECK-NEXT: Field: memory
# CHECK-NEXT: Kind: MEMORY
# CHECK-NEXT: Memory:
-# CHECK-NEXT: Minimum: 0x2
+# CHECK-NEXT: Minimum: 0x1
# CHECK-NEXT: - Type:
diff --git a/lld/test/wasm/init-fini.ll b/lld/test/wasm/init-fini.ll
index ef2f41f..7471ebb 100644
--- a/lld/test/wasm/init-fini.ll
+++ b/lld/test/wasm/init-fini.ll
@@ -78,7 +78,7 @@ entry:
; CHECK-NEXT: Body: 10041005100A100F1012100F10141004100C100F10161002100E0B
; CHECK: - Index: 22
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 02404186808080004100418088808000108080808000450D00000B0B
+; CHECK-NEXT: Body: 02404186808080004100418080848000108080808000450D00000B0B
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
; CHECK-NEXT: FunctionNames:
diff --git a/lld/test/wasm/large-memory.test b/lld/test/wasm/large-memory.test
index 5b737e4..a2888c6 100644
--- a/lld/test/wasm/large-memory.test
+++ b/lld/test/wasm/large-memory.test
@@ -12,7 +12,7 @@ RUN: obj2yaml %t2.wasm | FileCheck %s --check-prefixes=CHECK,CHECK-4G
CHECK: - Type: MEMORY
CHECK-NEXT: Memories:
CHECK-NEXT: - Flags: [ HAS_MAX ]
-CHECK-NEXT: Minimum: 0x2
+CHECK-NEXT: Minimum: 0x1
CHECK-2G-NEXT: Maximum: 0x8000
CHECK-4G-NEXT: Maximum: 0x10000
diff --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll
index 8faee64..6c639a8 100644
--- a/lld/test/wasm/local-symbols.ll
+++ b/lld/test/wasm/local-symbols.ll
@@ -45,13 +45,13 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: memory
@@ -67,17 +67,17 @@ entry:
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4100280284888080000B
+; CHECK-NEXT: Body: 4100280284808480000B
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1080808080001A0B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '0100000003000000'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test
index 5c3135a..88819b2 100644
--- a/lld/test/wasm/locals-duplicate.test
+++ b/lld/test/wasm/locals-duplicate.test
@@ -26,7 +26,7 @@
; CHECK-NEXT: Maximum: 0x7
; CHECK-NEXT: - Type: MEMORY
; CHECK-NEXT: Memories:
-; CHECK-NEXT: - Minimum: 0x2
+; CHECK-NEXT: - Minimum: 0x2
; CHECK-NEXT: - Type: GLOBAL
; CHECK-NEXT: Globals:
; CHECK-NEXT: - Index: 0
@@ -34,19 +34,19 @@
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66592
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1028
+; CHECK-NEXT: Value: 65540
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1036
+; CHECK-NEXT: Value: 65548
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: memory
@@ -119,13 +119,13 @@
; CHECK-NEXT: Body: 41020B
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4180888080000B
+; CHECK-NEXT: Body: 4180808480000B
; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4184888080000B
+; CHECK-NEXT: Body: 4184808480000B
; CHECK-NEXT: - Index: 5
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4188888080000B
+; CHECK-NEXT: Body: 4188808480000B
; CHECK-NEXT: - Index: 6
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4181808080000B
@@ -146,13 +146,13 @@
; CHECK-NEXT: Body: 41020B
; CHECK-NEXT: - Index: 12
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 418C888080000B
+; CHECK-NEXT: Body: 418C808480000B
; CHECK-NEXT: - Index: 13
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4190888080000B
+; CHECK-NEXT: Body: 4190808480000B
; CHECK-NEXT: - Index: 14
; CHECK-NEXT: Locals:
-; CHECK-NEXT: Body: 4194888080000B
+; CHECK-NEXT: Body: 4194808480000B
; CHECK-NEXT: - Index: 15
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 4184808080000B
@@ -164,11 +164,11 @@
; CHECK-NEXT: Body: 4186808080000B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '010000000100000001000000010000000100000001000000'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
diff --git a/lld/test/wasm/lto/tls.ll b/lld/test/wasm/lto/tls.ll
index b61edfb..9c1642e 100644
--- a/lld/test/wasm/lto/tls.ll
+++ b/lld/test/wasm/lto/tls.ll
@@ -30,13 +30,13 @@ attributes #0 = { noinline nounwind optnone "target-features"="+atomics,+bulk-me
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Type: I32
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK: GlobalNames:
; CHECK-NEXT: - Index: 0
diff --git a/lld/test/wasm/lto/used.ll b/lld/test/wasm/lto/used.ll
index a185103..dd36259 100644
--- a/lld/test/wasm/lto/used.ll
+++ b/lld/test/wasm/lto/used.ll
@@ -26,11 +26,11 @@ return:
; CHECK: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: '01000000'
; CHECK: - Type: CUSTOM
diff --git a/lld/test/wasm/map-file.s b/lld/test/wasm/map-file.s
index 2757f50..380ab57 100644
--- a/lld/test/wasm/map-file.s
+++ b/lld/test/wasm/map-file.s
@@ -59,15 +59,15 @@ somezeroes:
# CHECK-NEXT: - 66 b write_global
# CHECK-NEXT: - 71 f {{.*}}{{/|\\}}map-file.s.tmp1.o:(_start)
# CHECK-NEXT: - 71 f _start
-# CHECK-NEXT: - 82 11 DATA
-# CHECK-NEXT: 400 83 8 .data
-# CHECK-NEXT: 400 89 8 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
-# CHECK-NEXT: 400 89 8 somedata
-# CHECK-NEXT: 408 82 4 .bss
-# CHECK-NEXT: 408 0 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.bss.somezeroes)
-# CHECK-NEXT: 408 0 4 somezeroes
-# CHECK-NEXT: - 93 12 CUSTOM(.debug_info)
-# CHECK-NEXT: - a5 61 CUSTOM(name)
+# CHECK-NEXT: - 82 12 DATA
+# CHECK-NEXT: 10000 83 8 .data
+# CHECK-NEXT: 10000 8a 8 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
+# CHECK-NEXT: 10000 8a 8 somedata
+# CHECK-NEXT: 10008 82 4 .bss
+# CHECK-NEXT: 10008 0 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.bss.somezeroes)
+# CHECK-NEXT: 10008 0 4 somezeroes
+# CHECK-NEXT: - 94 12 CUSTOM(.debug_info)
+# CHECK-NEXT: - a6 61 CUSTOM(name)
# RUN: not wasm-ld %t1.o -o /dev/null -Map=/ 2>&1 \
# RUN: | FileCheck -check-prefix=FAIL %s
diff --git a/lld/test/wasm/memory-naming.test b/lld/test/wasm/memory-naming.test
index 766d9cd5..66143c3 100644
--- a/lld/test/wasm/memory-naming.test
+++ b/lld/test/wasm/memory-naming.test
@@ -57,7 +57,7 @@
# CHECK-IMPORT-NEXT: Field: bar
# CHECK-IMPORT-NEXT: Kind: MEMORY
# CHECK-IMPORT-NEXT: Memory:
-# CHECK-IMPORT-NEXT: Minimum: 0x2
+# CHECK-IMPORT-NEXT: Minimum: 0x1
# CHECK-IMPORT: - Type: EXPORT
# CHECK-IMPORT-NEXT: Exports:
# CHECK-IMPORT-NEXT: - Name: _start
@@ -77,7 +77,7 @@
# CHECK-IMPORT-DEFAULT-NEXT: Field: foo
# CHECK-IMPORT-DEFAULT-NEXT: Kind: MEMORY
# CHECK-IMPORT-DEFAULT-NEXT: Memory:
-# CHECK-IMPORT-DEFAULT-NEXT: Minimum: 0x2
+# CHECK-IMPORT-DEFAULT-NEXT: Minimum: 0x1
# CHECK-IMPORT-DEFAULT-NEXT: - Type:
# RUN:wasm-ld --import-memory=foo,bar --export-memory=qux -o %t.both.wasm %t.start.o
@@ -91,7 +91,7 @@
# CHECK-BOTH-NEXT: Field: bar
# CHECK-BOTH-NEXT: Kind: MEMORY
# CHECK-BOTH-NEXT: Memory:
-# CHECK-BOTH-NEXT: Minimum: 0x2
+# CHECK-BOTH-NEXT: Minimum: 0x1
# CHECK-BOTH: - Type: EXPORT
# CHECK-BOTH-NEXT: Exports:
# CHECK-BOTH-NEXT: - Name: qux
diff --git a/lld/test/wasm/merge-string.s b/lld/test/wasm/merge-string.s
index a4b89abf..229f393 100644
--- a/lld/test/wasm/merge-string.s
+++ b/lld/test/wasm/merge-string.s
@@ -41,21 +41,21 @@ negative_addend:
// COMMON-NEXT: Mutable: true
// COMMON-NEXT: InitExpr:
// COMMON-NEXT: Opcode: I32_CONST
-// COMMON-NEXT: Value: 66576
+// COMMON-NEXT: Value: 65536
// COMMON-NEXT: - Index: 1
// COMMON-NEXT: Type: I32
// COMMON-NEXT: Mutable: false
// COMMON-NEXT: InitExpr:
// COMMON-NEXT: Opcode: I32_CONST
-// MERGE-NEXT: Value: 1024
-// NOMERGE-NEXT: Value: 1028
+// MERGE-NEXT: Value: 65536
+// NOMERGE-NEXT: Value: 65540
// COMMON-NEXT: - Index: 2
// COMMON-NEXT: Type: I32
// COMMON-NEXT: Mutable: false
// COMMON-NEXT: InitExpr:
// COMMON-NEXT: Opcode: I32_CONST
-// MERGE-NEXT: Value: 1025
-// NOMERGE-NEXT: Value: 1029
+// MERGE-NEXT: Value: 65537
+// NOMERGE-NEXT: Value: 65541
// COMMON-NEXT: - Type: EXPORT
// COMMON-NEXT: Exports:
// COMMON-NEXT: - Name: memory
@@ -71,11 +71,11 @@ negative_addend:
//
// COMMON: - Type: DATA
// COMMON-NEXT: Segments:
-// COMMON-NEXT: - SectionOffset: 7
+// COMMON-NEXT: - SectionOffset: 8
// COMMON-NEXT: InitFlags: 0
// COMMON-NEXT: Offset:
// COMMON-NEXT: Opcode: I32_CONST
-// COMMON-NEXT: Value: 1024
+// COMMON-NEXT: Value: 65536
// MERGE-NEXT: Content: '61626300'
// NOMERGE-NEXT: Content: '6162630061626300626300'
diff --git a/lld/test/wasm/multi-table.s b/lld/test/wasm/multi-table.s
index afe8dda..31cba9f 100644
--- a/lld/test/wasm/multi-table.s
+++ b/lld/test/wasm/multi-table.s
@@ -87,7 +87,7 @@ call_indirect_explicit_tables:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66576
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
@@ -127,14 +127,14 @@ call_indirect_explicit_tables:
# CHECK-NEXT: Body: 42010B
# CHECK-NEXT: - Index: 3
# CHECK-NEXT: Locals: []
-# CHECK-NEXT: Body: 41002802808880800011818080800083808080001A41002802848880800011828080800083808080001A0B
+# CHECK-NEXT: Body: 41002802808084800011818080800083808080001A41002802848084800011828080800083808080001A0B
# CHECK-NEXT: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: '0100000002000000'
# CHECK-NEXT: - Type: CUSTOM
# CHECK-NEXT: Name: name
diff --git a/lld/test/wasm/no-strip-segment.s b/lld/test/wasm/no-strip-segment.s
index e70acae..2b79ed6 100644
--- a/lld/test/wasm/no-strip-segment.s
+++ b/lld/test/wasm/no-strip-segment.s
@@ -47,16 +47,16 @@ grab_liba:
# "greetings" section
# CHECK: - Type: DATA
# CHECK: Segments:
-# CHECK: - SectionOffset: 7
+# CHECK: - SectionOffset: 8
# CHECK: InitFlags: 0
# CHECK: Offset:
# CHECK: Opcode: I32_CONST
-# CHECK: Value: 1024
+# CHECK: Value: 65536
# CHECK: Content: 68656C6C6F00776F726C6400
# "weahters" section.
-# CHECK: - SectionOffset: 25
+# CHECK: - SectionOffset: 27
# CHECK: InitFlags: 0
# CHECK: Offset:
# CHECK: Opcode: I32_CONST
-# CHECK: Value: 1036
+# CHECK: Value: 65548
# CHECK: Content: 636C6F75647900
diff --git a/lld/test/wasm/no-tls.s b/lld/test/wasm/no-tls.s
index c0786c8..c082c1e 100644
--- a/lld/test/wasm/no-tls.s
+++ b/lld/test/wasm/no-tls.s
@@ -28,7 +28,7 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# __tls_base
# CHECK-NEXT: - Index: 1
diff --git a/lld/test/wasm/page-size.s b/lld/test/wasm/page-size.s
index a2bf694..17850b5 100644
--- a/lld/test/wasm/page-size.s
+++ b/lld/test/wasm/page-size.s
@@ -19,7 +19,7 @@ foo:
# CHECK-CUSTOM: - Type: MEMORY
# CHECK-CUSTOM-NEXT: Memories:
# CHECK-CUSTOM-NEXT: - Flags: [ HAS_PAGE_SIZE ]
-# CHECK-CUSTOM-NEXT: Minimum: 0x10410
+# CHECK-CUSTOM-NEXT: Minimum: 0x10004
# CHECK-CUSTOM-NEXT: PageSize: 0x1
# RUN: llvm-objdump --disassemble-symbols=_start %t.custom.wasm | FileCheck %s --check-prefix=CHECK-CUSTOM-DIS
@@ -51,7 +51,7 @@ foo:
# CHECK-CUSTOM-IMPORT-NEXT: Kind: MEMORY
# CHECK-CUSTOM-IMPORT-NEXT: Memory:
# CHECK-CUSTOM-IMPORT-NEXT: Flags: [ HAS_PAGE_SIZE ]
-# CHECK-CUSTOM-IMPORT-NEXT: Minimum: 0x10410
+# CHECK-CUSTOM-IMPORT-NEXT: Minimum: 0x10004
# CHECK-CUSTOM-IMPORT-NEXT: PageSize: 0x1
# RUN: llvm-objdump --disassemble-symbols=_start %t.custom-import.wasm | FileCheck %s --check-prefix=CHECK-CUSTOM-IMPORT-DIS
diff --git a/lld/test/wasm/pic-static.ll b/lld/test/wasm/pic-static.ll
index 794b721..12ac4c3 100644
--- a/lld/test/wasm/pic-static.ll
+++ b/lld/test/wasm/pic-static.ll
@@ -62,7 +62,7 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: Value: 65536
; GOT.func.ret32
; CHECK-NEXT: - Index: 1
@@ -70,7 +70,7 @@ entry:
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1
+; CHECK-NEXT: Value: 1
; GOT.func.missing_function
; CHECK-NEXT: - Index: 2
@@ -102,7 +102,7 @@ entry:
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; GOT.mem.ret32_ptr
; CHECK-NEXT: - Index: 6
@@ -110,7 +110,7 @@ entry:
; CHECK-NEXT: Mutable: false
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1032
+; CHECK-NEXT: Value: 65544
; __memory_base
; CHECK-NEXT: - Index: 7
diff --git a/lld/test/wasm/reloc-relative.s b/lld/test/wasm/reloc-relative.s
index fde1d1d..5aab061 100644
--- a/lld/test/wasm/reloc-relative.s
+++ b/lld/test/wasm/reloc-relative.s
@@ -50,40 +50,40 @@ far:
# CHECK: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: 68656C6C6F0A00
-# CHECK-NEXT: - SectionOffset: 20
+# CHECK-NEXT: - SectionOffset: 22
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1031
+# CHECK-NEXT: Value: 65543
# CHECK-NEXT: Content: 000000002A000000
-# CHECK-NEXT: - SectionOffset: 34
+# CHECK-NEXT: - SectionOffset: 37
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1039
+# CHECK-NEXT: Value: 65551
# CHECK-NEXT: Content: FCFFFFFFFCFFFFFF
-# CHECK-NEXT: - SectionOffset: 48
+# CHECK-NEXT: - SectionOffset: 52
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1047
+# CHECK-NEXT: Value: 65559
# CHECK-NEXT: Content: E9FFFFFFE9FFFFFF
-# CHECK-NEXT: - SectionOffset: 62
+# CHECK-NEXT: - SectionOffset: 67
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1055
+# CHECK-NEXT: Value: 65567
# CHECK-NEXT: Content: '0800000008000000'
-# CHECK-NEXT: - SectionOffset: 76
+# CHECK-NEXT: - SectionOffset: 82
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1063
+# CHECK-NEXT: Value: 65575
# CHECK-NEXT: Content: '15000000'
diff --git a/lld/test/wasm/runtime-relocations-himem.s b/lld/test/wasm/runtime-relocations-himem.s
new file mode 100644
index 0000000..a12a93a
--- /dev/null
+++ b/lld/test/wasm/runtime-relocations-himem.s
@@ -0,0 +1,60 @@
+## Verifies runtime relocation code for addresses over 2gb works correctly.
+## We have had issues with LEB encoding of address over 2gb in i32.const
+## instruction leading to invalid binaries.
+
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld --global-base=2147483648 --experimental-pic --unresolved-symbols=import-dynamic -no-gc-sections --shared-memory --no-entry -o %t.wasm %t.o
+# XUN: obj2yaml %t.wasm | FileCheck %s
+# RUN: llvm-objdump -d --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --
+
+.globl tls_sym
+.globl data_sym
+.globl _start
+.globaltype __tls_base, i32
+
+_start:
+ .functype _start () -> ()
+ global.get __tls_base
+ i32.const tls_sym@TLSREL
+ i32.add
+ drop
+ i32.const data_sym
+ drop
+ end_function
+
+.section tls_sec,"T",@
+.p2align 2
+tls_sym:
+ .int32 0
+ .int32 extern_sym
+ .size tls_sym, 8
+
+.section data_sec,"",@
+.p2align 2
+data_sym:
+ .int32 0
+ .int32 extern_sym
+ .size data_sym, 8
+
+.section .custom_section.target_features,"",@
+ .int8 2
+ .int8 43
+ .int8 7
+ .ascii "atomics"
+ .int8 43
+ .int8 11
+ .ascii "bulk-memory"
+
+# CHECK: <__wasm_apply_data_relocs>:
+# CHECK-EMPTY:
+# CHECK-NEXT: i32.const -2147483636
+# CHECK-NEXT: global.get 0
+# CHECK-NEXT: i32.store 0
+# CHECK-NEXT: end
+
+# CHECK: <__wasm_apply_tls_relocs>:
+# CHECK-EMPTY:
+# CHECK-NEXT: i32.const -2147483644
+# CHECK-NEXT: global.get 0
+# CHECK-NEXT: i32.store 0
+# CHECK-NEXT: end
diff --git a/lld/test/wasm/shared-memory-no-atomics.yaml b/lld/test/wasm/shared-memory-no-atomics.yaml
index 942c690..62f4ac9 100644
--- a/lld/test/wasm/shared-memory-no-atomics.yaml
+++ b/lld/test/wasm/shared-memory-no-atomics.yaml
@@ -55,7 +55,7 @@ Sections:
# NO-SHARED: - Type: MEMORY
# NO-SHARED-NEXT: Memories:
-# NO-SHARED-NEXT: - Minimum: 0x2
+# NO-SHARED-NEXT: - Minimum: 0x1
# NO-SHARED-NOT: Maximum:
# SHARED: --shared-memory is disallowed by {{.*}}shared-memory-no-atomics.yaml.tmp1.o because it was not compiled with 'atomics' or 'bulk-memory' features.
diff --git a/lld/test/wasm/shared-memory.yaml b/lld/test/wasm/shared-memory.yaml
index 4cdbb95..b3490c8 100644
--- a/lld/test/wasm/shared-memory.yaml
+++ b/lld/test/wasm/shared-memory.yaml
@@ -1,16 +1,16 @@
# RUN: yaml2obj %s -o %t1.o
-# RUN: wasm-ld --no-entry --shared-memory --features=atomics,bulk-memory %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
+# RUN: wasm-ld --no-entry --no-gc-sections --shared-memory --features=atomics,bulk-memory %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
-# RUN: not wasm-ld --no-entry --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
+# RUN: not wasm-ld --no-entry --no-gc-sections --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
-# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 --features=bulk-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-ATOMICS
+# RUN: not wasm-ld --no-entry --no-gc-sections --shared-memory --max-memory=131072 --features=bulk-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-ATOMICS
-# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-BULK-MEM
+# RUN: not wasm-ld --no-entry --no-gc-sections --shared-memory --max-memory=131072 --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-BULK-MEM
# RUN: wasm-ld --relocatable --features=atomics %t1.o -o - | obj2yaml | FileCheck %s --check-prefix ATOMICS-RELOCATABLE
-# RUN: wasm-ld --no-entry --shared-memory --max-memory=131072 --features=atomics,bulk-memory %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
+# XUN: wasm-ld --no-entry --no-gc-sections --shared-memory --max-memory=131072 --features=atomics,bulk-memory %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
--- !WASM
FileHeader:
@@ -22,7 +22,7 @@ Sections:
Field: __linear_memory
Kind: MEMORY
Memory:
- Minimum: 0x00000001
+ Minimum: 0x00000009
- Module: env
Field: __indirect_function_table
Kind: TABLE
diff --git a/lld/test/wasm/stack-first.test b/lld/test/wasm/stack-first.test
index 72e1a00..91f06a4 100644
--- a/lld/test/wasm/stack-first.test
+++ b/lld/test/wasm/stack-first.test
@@ -5,9 +5,20 @@
; Also test that __heap_base is still aligned with the --stack-first option.
RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/stack-first.s -o %t.o
-RUN: wasm-ld -z stack-size=512 --stack-first --export=__data_end --export=__heap_base --export=someByte -o %t.wasm %t.o
+
+; Check that the default is `--stack-first`
+RUN: wasm-ld -z stack-size=512 --export=__data_end --export=__heap_base --export=someByte -o %t.wasm %t.o
+RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Check `--no-stack-first`
+RUN: wasm-ld -z stack-size=512 --no-stack-first --export=__data_end --export=__heap_base --export=someByte -o %t.wasm %t.o
+RUN: obj2yaml %t.wasm | FileCheck %s --check-prefix=NOT-FIRST
+
+; Check `--stack-first`
+RUN: wasm-ld -z stack-size=512 --no-stack-first --stack-first --export=__data_end --export=__heap_base --export=someByte -o %t.wasm %t.o
RUN: obj2yaml %t.wasm | FileCheck %s
+
CHECK: - Type: GLOBAL
CHECK-NEXT: Globals:
CHECK-NEXT: - Index: 0
@@ -51,3 +62,19 @@ CHECK-NEXT: Index: 2
CHECK-NEXT: - Name: __heap_base
CHECK-NEXT: Kind: GLOBAL
CHECK-NEXT: Index: 3
+
+NOT-FIRST: - Type: GLOBAL
+NOT-FIRST-NEXT: Globals:
+NOT-FIRST-NEXT: - Index: 0
+NOT-FIRST-NEXT: Type: I32
+NOT-FIRST-NEXT: Mutable: true
+NOT-FIRST-NEXT: InitExpr:
+NOT-FIRST-NEXT: Opcode: I32_CONST
+NOT-FIRST-NEXT: Value: 1552
+NOT-FIRST-NEXT: - Index: 1
+NOT-FIRST-NEXT: Type: I32
+NOT-FIRST-NEXT: Mutable: false
+NOT-FIRST-NEXT: InitExpr:
+NOT-FIRST-NEXT: Opcode: I32_CONST
+NOT-FIRST-NEXT: Value: 1024
+
diff --git a/lld/test/wasm/startstop.ll b/lld/test/wasm/startstop.ll
index e7a5c80..c22956f 100644
--- a/lld/test/wasm/startstop.ll
+++ b/lld/test/wasm/startstop.ll
@@ -27,19 +27,19 @@ entry:
; CHECK: - Type: DATA
; CHECK-NEXT: Segments:
-; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: - SectionOffset: 8
; CHECK-NEXT: InitFlags: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: Content: 03000000040000002A0000002B000000
-; ASM: 0000006e <get_start>:
+; ASM: 00000070 <get_start>:
; ASM-EMPTY:
-; ASM-NEXT: 70: i32.const 1024
-; ASM-NEXT: 76: end
+; ASM-NEXT: 72: i32.const 65536
+; ASM-NEXT: 78: end
-; ASM: 00000077 <get_end>:
+; ASM: 00000079 <get_end>:
; ASM-EMPTY:
-; ASM-NEXT: 79: i32.const 1040
-; ASM-NEXT: 7f: end
+; ASM-NEXT: 7b: i32.const 65552
+; ASM-NEXT: 81: end
diff --git a/lld/test/wasm/table-base.s b/lld/test/wasm/table-base.s
index 56fff41..92156c4 100644
--- a/lld/test/wasm/table-base.s
+++ b/lld/test/wasm/table-base.s
@@ -29,7 +29,7 @@ _start:
# CHECK-DEFAULT-NEXT: Mutable: true
# CHECK-DEFAULT-NEXT: InitExpr:
# CHECK-DEFAULT-NEXT: Opcode: I32_CONST
-# CHECK-DEFAULT-NEXT: Value: 66560
+# CHECK-DEFAULT-NEXT: Value: 65536
# CHECK-DEFAULT-NEXT: - Index: 1
# CHECK-DEFAULT-NEXT: Type: I32
# CHECK-DEFAULT-NEXT: Mutable: false
@@ -58,7 +58,7 @@ _start:
# CHECK-100-NEXT: Mutable: true
# CHECK-100-NEXT: InitExpr:
# CHECK-100-NEXT: Opcode: I32_CONST
-# CHECK-100-NEXT: Value: 66560
+# CHECK-100-NEXT: Value: 65536
# CHECK-100-NEXT: - Index: 1
# CHECK-100-NEXT: Type: I32
# CHECK-100-NEXT: Mutable: false
diff --git a/lld/test/wasm/tls-align.s b/lld/test/wasm/tls-align.s
index 4fd296e..3b51165 100644
--- a/lld/test/wasm/tls-align.s
+++ b/lld/test/wasm/tls-align.s
@@ -65,7 +65,7 @@ tls2:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66592
+# CHECK-NEXT: Value: 65536
# __tls_base
# CHECK-NEXT: - Index: 1
diff --git a/lld/test/wasm/tls-non-shared-memory-basic.s b/lld/test/wasm/tls-non-shared-memory-basic.s
index 8ef0173..66ccf8f 100644
--- a/lld/test/wasm/tls-non-shared-memory-basic.s
+++ b/lld/test/wasm/tls-non-shared-memory-basic.s
@@ -27,11 +27,11 @@ tls1:
# CHECK: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: 2B000000
# CHECK-NEXT: - Type: CUSTOM
# CHECK-NOT: - Type: IMPORT
diff --git a/lld/test/wasm/tls-non-shared-memory.s b/lld/test/wasm/tls-non-shared-memory.s
index 04fbb62..0d73acb 100644
--- a/lld/test/wasm/tls-non-shared-memory.s
+++ b/lld/test/wasm/tls-non-shared-memory.s
@@ -63,38 +63,38 @@ tls1:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66576
+# CHECK-NEXT: Value: 65536
# __tls_base
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# GOT.data.internal.tls1
# CHECK-NEXT: - Index: 2
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK: - Type: DATA
# .data
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: 2B000000
# .tdata
-# CHECK-NEXT: - SectionOffset: 17
+# CHECK-NEXT: - SectionOffset: 19
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1028
+# CHECK-NEXT: Value: 65540
# CHECK-NEXT: Content: 2A000000
# CHECK-NEXT: - Type: CUSTOM
diff --git a/lld/test/wasm/tls.s b/lld/test/wasm/tls.s
index b1f47f6..21f25f5 100644
--- a/lld/test/wasm/tls.s
+++ b/lld/test/wasm/tls.s
@@ -98,7 +98,7 @@ tls3:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66592
+# CHECK-NEXT: Value: 65536
# __tls_base
# CHECK-NEXT: - Index: 1
diff --git a/lld/test/wasm/undefined-weak-call.s b/lld/test/wasm/undefined-weak-call.s
index 7490104..47775c8 100644
--- a/lld/test/wasm/undefined-weak-call.s
+++ b/lld/test/wasm/undefined-weak-call.s
@@ -61,7 +61,7 @@ callWeakFuncs:
# CHECK-NEXT: Maximum: 0x1
# CHECK-NEXT: - Type: MEMORY
# CHECK-NEXT: Memories:
-# CHECK-NEXT: - Minimum: 0x2
+# CHECK-NEXT: - Minimum: 0x1
# CHECK-NEXT: - Type: GLOBAL
# CHECK-NEXT: Globals:
# CHECK-NEXT: - Index: 0
@@ -69,7 +69,7 @@ callWeakFuncs:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/weak-alias-overide.ll b/lld/test/wasm/weak-alias-overide.ll
index ca6f4bf..30bf7cf 100644
--- a/lld/test/wasm/weak-alias-overide.ll
+++ b/lld/test/wasm/weak-alias-overide.ll
@@ -44,7 +44,7 @@ entry:
; CHECK-NEXT: Maximum: 0x3
; CHECK-NEXT: - Type: MEMORY
; CHECK-NEXT: Memories:
-; CHECK-NEXT: - Minimum: 0x2
+; CHECK-NEXT: - Minimum: 0x1
; CHECK-NEXT: - Type: GLOBAL
; CHECK-NEXT: Globals:
; CHECK-NEXT: - Index: 0
@@ -52,7 +52,7 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66560
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll
index 1768b8f..86e42a7 100644
--- a/lld/test/wasm/weak-alias.ll
+++ b/lld/test/wasm/weak-alias.ll
@@ -41,7 +41,7 @@ entry:
; CHECK-NEXT: Maximum: 0x2
; CHECK-NEXT: - Type: MEMORY
; CHECK-NEXT: Memories:
-; CHECK-NEXT: - Minimum: 0x2
+; CHECK-NEXT: - Minimum: 0x1
; CHECK-NEXT: - Type: GLOBAL
; CHECK-NEXT: Globals:
; CHECK-NEXT: - Index: 0
@@ -49,7 +49,7 @@ entry:
; CHECK-NEXT: Mutable: true
; CHECK-NEXT: InitExpr:
; CHECK-NEXT: Opcode: I32_CONST
-; CHECK-NEXT: Value: 66560
+; CHECK-NEXT: Value: 65536
; CHECK-NEXT: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/weak-symbols.s b/lld/test/wasm/weak-symbols.s
index 165ec17..ed85851 100644
--- a/lld/test/wasm/weak-symbols.s
+++ b/lld/test/wasm/weak-symbols.s
@@ -48,13 +48,13 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66576
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Index: 1
# CHECK-NEXT: Type: I32
# CHECK-NEXT: Mutable: false
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
@@ -97,11 +97,11 @@ _start:
# CHECK-NEXT: Body: 4181808080000B
# CHECK-NEXT: - Type: DATA
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 7
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 1024
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: Content: '01000000'
# CHECK-NEXT: - Type: CUSTOM
# CHECK-NEXT: Name: name
diff --git a/lld/test/wasm/weak-undefined-pic.s b/lld/test/wasm/weak-undefined-pic.s
index 5937380..1a3a171 100644
--- a/lld/test/wasm/weak-undefined-pic.s
+++ b/lld/test/wasm/weak-undefined-pic.s
@@ -45,7 +45,7 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# Global 'undefined_weak:foo' representing the GOT entry for foo
# Unlike other internal GOT entries that need to be mutable this one
# is immutable and not updated by `__wasm_apply_global_relocs`
diff --git a/lld/test/wasm/weak-undefined.s b/lld/test/wasm/weak-undefined.s
index e1f551d..558cac5 100644
--- a/lld/test/wasm/weak-undefined.s
+++ b/lld/test/wasm/weak-undefined.s
@@ -67,7 +67,7 @@ _start:
# CHECK-NEXT: Maximum: 0x1
# CHECK-NEXT: - Type: MEMORY
# CHECK-NEXT: Memories:
-# CHECK-NEXT: - Minimum: 0x2
+# CHECK-NEXT: - Minimum: 0x1
# CHECK-NEXT: - Type: GLOBAL
# CHECK-NEXT: Globals:
# CHECK-NEXT: - Index: 0
@@ -75,7 +75,7 @@ _start:
# CHECK-NEXT: Mutable: true
# CHECK-NEXT: InitExpr:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: 66560
+# CHECK-NEXT: Value: 65536
# CHECK-NEXT: - Type: EXPORT
# CHECK-NEXT: Exports:
# CHECK-NEXT: - Name: memory
diff --git a/lld/test/wasm/wrap_import.s b/lld/test/wasm/wrap_import.s
new file mode 100644
index 0000000..ce3b6f5
--- /dev/null
+++ b/lld/test/wasm/wrap_import.s
@@ -0,0 +1,32 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
+# RUN: wasm-ld -wrap nosuchsym -wrap foo -allow-undefined -o %t.wasm %t.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+.globl foo
+.globl _start
+
+foo:
+ .functype foo () -> ()
+ end_function
+
+_start:
+ .functype _start () -> ()
+ call foo
+ end_function
+
+# CHECK: - Type: IMPORT
+# CHECK-NEXT: Imports:
+# CHECK-NEXT: - Module: env
+# CHECK-NEXT: Field: __wrap_foo
+# CHECK-NEXT: Kind: FUNCTION
+# CHECK-NEXT SigIndex: 0
+
+# CHECK: - Type: CODE
+# CHECK-NEXT: Functions:
+# CHECK-NEXT: Index: 1
+
+# CHECK: FunctionNames:
+# CHECK-NEXT: - Index: 0
+# CHECK-NEXT: Name: __wrap_foo
+# CHECK-NEXT: - Index: 1
+# CHECK-NEXT: Name: _start
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 9c0e1b5..97e5078 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -595,7 +595,7 @@ static void readConfigs(opt::InputArgList &args) {
ctx.arg.shlibSigCheck = !args.hasArg(OPT_no_shlib_sigcheck);
ctx.arg.stripAll = args.hasArg(OPT_strip_all);
ctx.arg.stripDebug = args.hasArg(OPT_strip_debug);
- ctx.arg.stackFirst = args.hasArg(OPT_stack_first);
+ ctx.arg.stackFirst = args.hasFlag(OPT_stack_first, OPT_no_stack_first, true);
ctx.arg.trace = args.hasArg(OPT_trace);
ctx.arg.thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
ctx.arg.thinLTOCachePolicy = CHECK(
@@ -1173,9 +1173,10 @@ struct WrappedSymbol {
Symbol *wrap;
};
-static Symbol *addUndefined(StringRef name) {
+static Symbol *addUndefined(StringRef name,
+ const WasmSignature *signature = nullptr) {
return symtab->addUndefinedFunction(name, std::nullopt, std::nullopt,
- WASM_SYMBOL_UNDEFINED, nullptr, nullptr,
+ WASM_SYMBOL_UNDEFINED, nullptr, signature,
false);
}
@@ -1198,7 +1199,8 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
continue;
Symbol *real = addUndefined(saver().save("__real_" + name));
- Symbol *wrap = addUndefined(saver().save("__wrap_" + name));
+ Symbol *wrap =
+ addUndefined(saver().save("__wrap_" + name), sym->getSignature());
v.push_back({sym, real, wrap});
// We want to tell LTO not to inline symbols to be overwritten
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 44927e7a..14e02e6 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -423,8 +423,6 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
bool is64 = ctx.arg.is64.value_or(false);
bool generated = false;
- unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
- : WASM_OPCODE_I32_CONST;
unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD;
@@ -451,8 +449,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
<< " output offset=" << offset << "\n");
// Calculate the address at which to apply the relocation
- writeU8(os, opcode_ptr_const, "CONST");
- writeSleb128(os, offset, "offset");
+ writePtrConst(os, offset, is64, "offset");
// In PIC mode we need to add the __memory_base
if (ctx.isPic) {
@@ -466,8 +463,6 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
// Now figure out what we want to store at this location
bool is64 = relocIs64(rel.Type);
- unsigned opcode_reloc_const =
- is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST;
unsigned opcode_reloc_add =
is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
unsigned opcode_reloc_store =
@@ -477,8 +472,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
writeUleb128(os, sym->getGOTIndex(), "global index");
if (rel.Addend) {
- writeU8(os, opcode_reloc_const, "CONST");
- writeSleb128(os, rel.Addend, "addend");
+ writePtrConst(os, rel.Addend, is64, "addend");
writeU8(os, opcode_reloc_add, "ADD");
}
} else {
@@ -491,8 +485,8 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
baseSymbol = ctx.sym.tlsBase;
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
- writeU8(os, opcode_reloc_const, "CONST");
- writeSleb128(os, file->calcNewValue(rel, tombstone, this), "offset");
+ writePtrConst(os, file->calcNewValue(rel, tombstone, this), is64,
+ "offset");
writeU8(os, opcode_reloc_add, "ADD");
}
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index 2f699e2..33ecf03 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -250,8 +250,9 @@ def no_entry: FF<"no-entry">,
def no_shlib_sigcheck: FF<"no-shlib-sigcheck">,
HelpText<"Do not check signatures of functions defined in shared libraries.">;
-def stack_first: FF<"stack-first">,
- HelpText<"Place stack at start of linear memory rather than after data">;
+defm stack_first: B<"stack-first",
+ "Place stack at start of linear memory (default)",
+ "Place the stack after static data region">;
def table_base: JJ<"table-base=">,
HelpText<"Table offset at which to place address taken functions (Defaults to 1)">;
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index e119270..5e7b9c2 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -196,7 +196,9 @@ void ImportSection::addImport(Symbol *sym) {
StringRef module = sym->importModule.value_or(defaultModule);
StringRef name = sym->importName.value_or(sym->getName());
if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
- ImportKey<WasmSignature> key(*(f->getSignature()), module, name);
+ const WasmSignature *sig = f->getSignature();
+ assert(sig && "imported functions must have a signature");
+ ImportKey<WasmSignature> key(*sig, module, name);
auto entry = importedFunctions.try_emplace(key, numImportedFunctions);
if (entry.second) {
importedSymbols.emplace_back(sym);
@@ -434,8 +436,6 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) {
void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
assert(!ctx.arg.extendedConst);
bool is64 = ctx.arg.is64.value_or(false);
- unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
- : WASM_OPCODE_I32_CONST;
unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD;
@@ -452,8 +452,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");
// Add the virtual address of the data symbol
- writeU8(os, opcode_ptr_const, "CONST");
- writeSleb128(os, d->getVA(), "offset");
+ writePtrConst(os, d->getVA(), is64, "offset");
} else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
if (f->isStub)
continue;
@@ -462,8 +461,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
writeUleb128(os, ctx.sym.tableBase->getGlobalIndex(), "__table_base");
// Add the table index to __table_base
- writeU8(os, opcode_ptr_const, "CONST");
- writeSleb128(os, f->getTableIndex(), "offset");
+ writePtrConst(os, f->getTableIndex(), is64, "offset");
} else {
assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));
continue;