Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion lld/ELF/Arch/X86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,26 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {

static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val);

static void warnIfRelocToLargeSection(uint8_t *loc, const Relocation &rel) {
if (!rel.sym || !rel.sym->getOutputSection())
return;
Symbol &sym = *rel.sym;
if (sym.getOutputSection()->flags & SHF_X86_64_LARGE) {
ErrorPlace errPlace = getErrorPlace(loc);
std::string hint;
if (!sym.isSection())
hint = "; references '" + lld::toString(sym) + '\'';
else if (auto *d = dyn_cast<Defined>(&sym))
hint = ("; references section '" + d->section->name + "'").str();
if (!errPlace.srcLoc.empty())
hint += "\n>>> referenced by " + errPlace.srcLoc;
if (!sym.isSection())
hint += getDefinedLocation(sym);
warn(errPlace.loc +
"Large section should not be addressed with PC32 relocation" + hint);
}
}

void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_X86_64_8:
Expand All @@ -779,11 +799,14 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
checkUInt(loc, val, 32, rel);
write32le(loc, val);
break;
case R_X86_64_PC32:
if (config->warnLarge && ctx.hasLargeSection)
warnIfRelocToLargeSection(loc, rel);
[[fallthrough]];
case R_X86_64_32S:
case R_X86_64_GOT32:
case R_X86_64_GOTPC32:
case R_X86_64_GOTPCREL:
case R_X86_64_PC32:
case R_X86_64_PLT32:
case R_X86_64_DTPOFF32:
case R_X86_64_SIZE32:
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ struct Config {
bool warnCommon;
bool warnMissingEntry;
bool warnSymbolOrdering;
bool warnLarge;
bool writeAddends;
bool zCombreloc;
bool zCopyreloc;
Expand Down Expand Up @@ -482,6 +483,8 @@ struct Ctx {
// True if all native vtable symbols have corresponding type info symbols
// during LTO.
bool ltoAllVtablesHaveTypeInfos;
// True if any output section has the SHF_X86_64_LARGE flag set.
bool hasLargeSection;

// Each symbol assignment and DEFINED(sym) reference is assigned an increasing
// order. Each DEFINED(sym) evaluation checks whether the reference happens
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ void Ctx::reset() {
scriptSymOrderCounter = 1;
scriptSymOrder.clear();
ltoAllVtablesHaveTypeInfos = false;
hasLargeSection = false;
}

llvm::raw_fd_ostream Ctx::openAuxiliaryFile(llvm::StringRef filename,
Expand Down Expand Up @@ -1440,6 +1441,7 @@ static void readConfigs(opt::InputArgList &args) {
config->warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
config->warnSymbolOrdering =
args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
config->warnLarge = args.hasFlag(OPT_warn_large, OPT_no_warn_large, false);
config->whyExtract = args.getLastArgValue(OPT_why_extract);
config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,10 @@ defm warn_symbol_ordering: BB<"warn-symbol-ordering",
"Warn about problems with the symbol ordering file (default)",
"Do not warn about problems with the symbol ordering file">;

defm warn_large: BB<"warn-32-bit-reloc-to-large-section",
"Warn about PC32 relocations to a large section",
"Do not warn about PC32 relocations to a large section">;

def warn_unresolved_symbols: F<"warn-unresolved-symbols">,
HelpText<"Report unresolved symbols as warnings">;

Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static std::optional<std::string> getLinkerScriptLocation(const Symbol &sym) {
return std::nullopt;
}

static std::string getDefinedLocation(const Symbol &sym) {
std::string elf::getDefinedLocation(const Symbol &sym) {
const char msg[] = "\n>>> defined in ";
if (sym.file)
return msg + toString(sym.file);
Expand Down
2 changes: 2 additions & 0 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ TargetInfo *getTarget();

template <class ELFT> bool isMipsPIC(const Defined *sym);

std::string getDefinedLocation(const Symbol &sym);

void reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v,
int64_t min, uint64_t max);
void reportRangeError(uint8_t *loc, int64_t v, int n, const Symbol &sym,
Expand Down
6 changes: 5 additions & 1 deletion lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "lld/Common/Filesystem.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/BLAKE3.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/RandomNumberGenerator.h"
Expand Down Expand Up @@ -2233,8 +2234,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
for (OutputSection *sec : outputSections)
for (OutputSection *sec : outputSections) {
sec->finalize();
if (sec->flags & SHF_X86_64_LARGE)
ctx.hasLargeSection = true;
}

script->checkFinalScriptConditions();

Expand Down
32 changes: 32 additions & 0 deletions lld/test/ELF/warn-large.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld %t.o -o /dev/null 2>&1 --warn-32-bit-reloc-to-large-section | FileCheck %s
# RUN: ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO --allow-empty

# CHECK: warning: {{.*}}warn-large.s{{.*}}:(.text+{{.*}}): Large section should not be addressed with PC32 relocation; references 'hello'
# CHECK-NEXT: >>> referenced by foo.c
# CHECK-NEXT: >>> defined in {{.*}}warn-large.s{{.*}}

# CHECK: warning: {{.*}}warn-large.s{{.*}}:(.text+{{.*}}): Large section should not be addressed with PC32 relocation; references section 'ldata'
# CHECK-NEXT: >>> referenced by foo.c

# NO-NOT: warning

.text
.file "foo.c"
.globl _start
.type _start, @function
_start:
movq hello(%rip), %rax
movq ok(%rip), %rax

.section ldata,"awl",@progbits

.type hello, @object
.globl hello
.p2align 2, 0x0
hello:
.long 1

ok:
.long 1