Skip to content

[lld/ELF] Add --override-section-flags flag #109454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ struct Config {
bool optEL = false;
bool optimizeBBJumps;
bool optRemarksWithHotness;
llvm::SmallVector<std::tuple<llvm::GlobPattern, uint32_t>, 0>
overrideSectionFlags;
bool picThunk;
bool pie;
bool printGcSections;
Expand Down
29 changes: 29 additions & 0 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,35 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
}
}

for (opt::Arg *arg : args.filtered(OPT_override_section_flags)) {
SmallVector<StringRef, 0> fields;
StringRef(arg->getValue()).split(fields, '=');
if (fields.size() != 2) {
error(arg->getSpelling() +
": parse error, no '=' found in --override-section-flags arg");
continue;
}

uint32_t flags = 0;
for (char c : fields[1]) {
if (c == 'a')
flags |= SHF_ALLOC;
else if (c == 'w')
flags |= SHF_WRITE;
else if (c == 'x')
flags |= SHF_EXECINSTR;
else
error(arg->getSpelling() + ": flags do not match [awx]+");
}

if (Expected<GlobPattern> pat = GlobPattern::create(fields[0])) {
config->overrideSectionFlags.emplace_back(std::move(*pat), flags);
} else {
error(arg->getSpelling() + ": " + toString(pat.takeError()));
continue;
}
}

for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
StringRef(arg->getValue()).split('=');
Expand Down
12 changes: 10 additions & 2 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,21 @@ static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &file,
return check(file.getObj().getSectionContents(hdr));
}

uint32_t effectiveSectionFlags(uint32_t flags, StringRef name) {
for (auto &[glob, overriddenFlags] : config->overrideSectionFlags) {
if (glob.match(name))
return overriddenFlags;
}
return flags;
}

InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
uint32_t type, uint64_t entsize,
uint32_t link, uint32_t info,
uint32_t addralign, ArrayRef<uint8_t> data,
StringRef name, Kind sectionKind)
: SectionBase(sectionKind, name, flags, entsize, addralign, type, info,
link),
: SectionBase(sectionKind, name, effectiveSectionFlags(flags, name),
entsize, addralign, type, info, link),
file(file), content_(data.data()), size(data.size()) {
// In order to reduce memory allocation, we assume that mergeable
// sections are smaller than 4 GiB, which is not an unreasonable
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ def omagic: FF<"omagic">, MetaVarName<"<magic>">,
defm orphan_handling:
Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;

defm override_section_flags:
EEq<"override-section-flags", "Override section flags">,
MetaVarName<"<section-glob>=[awx]+">;

defm pack_dyn_relocs:
EEq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
MetaVarName<"[none,android,relr,android+relr]">;
Expand Down
38 changes: 38 additions & 0 deletions lld/test/ELF/override-section-flags.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# REQUIRES: x86

# RUN: rm -rf %t && mkdir %t
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t/a.o

# RUN: ld.lld -pie %t/a.o -o %t/out \
# RUN: --override-section-flags 'foo0=' \
# RUN: --override-section-flags 'foo1=a' \
# RUN: --override-section-flags 'foo2=ax' \
# RUN: --override-section-flags 'foo3=aw' \
# RUN: --override-section-flags 'foo4=awx'

# RUN: llvm-readelf --sections --segments %t/out | FileCheck %s

# CHECK-DAG: foo0 PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}
# CHECK-DAG: foo1 PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} A {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}
# CHECK-DAG: foo2 PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} AX {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}
# CHECK-DAG: foo3 PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} WA {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}
# CHECK-DAG: foo4 PROGBITS {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} WAX {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}}


.globl _start
_start:

.section foo0,"aw"
.space 8

.section foo1,"aw"
.space 8

.section foo2,"aw"
.space 8

.section foo3,"ax"
.space 8

.section foo4,"a"
.space 8
Loading