Skip to content

Commit 75ad826

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.6-beta.1
1 parent 30af6fb commit 75ad826

File tree

9 files changed

+104
-2
lines changed

9 files changed

+104
-2
lines changed

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct Config {
329329
bool relrPackDynRelocs = false;
330330
llvm::DenseSet<llvm::StringRef> saveTempsArgs;
331331
llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
332+
std::optional<uint64_t> shufflePadding;
332333
bool singleRoRx;
333334
bool shared;
334335
bool symbolic;

lld/ELF/Driver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
14101410
ctx.arg.searchPaths = args::getStrings(args, OPT_library_path);
14111411
ctx.arg.sectionStartMap = getSectionStartMap(ctx, args);
14121412
ctx.arg.shared = args.hasArg(OPT_shared);
1413+
if (args.hasArg(OPT_shuffle_padding))
1414+
ctx.arg.shufflePadding = args::getInteger(args, OPT_shuffle_padding, 0);
14131415
ctx.arg.singleRoRx = !args.hasFlag(OPT_rosegment, OPT_no_rosegment, true);
14141416
ctx.arg.soName = args.getLastArgValue(OPT_soname);
14151417
ctx.arg.sortSection = getSortSection(ctx, args);

lld/ELF/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ defm section_start: Eq<"section-start", "Set address of section">,
434434

435435
def shared: F<"shared">, HelpText<"Build a shared object">;
436436

437+
def shuffle_padding: JJ<"shuffle-padding=">,
438+
HelpText<"Randomly insert padding between input sections using given seed">;
439+
437440
defm soname: Eq<"soname", "Set DT_SONAME">;
438441

439442
defm sort_section:

lld/ELF/OutputSections.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@ class OutputSection final : public SectionBase {
124124
void sortInitFini();
125125
void sortCtorsDtors();
126126

127+
std::array<uint8_t, 4> getFiller(Ctx &);
128+
127129
// Used for implementation of --compress-debug-sections and
128130
// --compress-sections.
129131
CompressedData compressed;
130132

131133
private:
132134
SmallVector<InputSection *, 0> storage;
133-
134-
std::array<uint8_t, 4> getFiller(Ctx &);
135135
};
136136

137137
struct OutputDesc final : SectionCommand {

lld/ELF/SyntheticSections.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,21 @@ RelroPaddingSection::RelroPaddingSection(Ctx &ctx)
27532753
: SyntheticSection(ctx, ".relro_padding", SHT_NOBITS, SHF_ALLOC | SHF_WRITE,
27542754
1) {}
27552755

2756+
ShufflePaddingSection::ShufflePaddingSection(Ctx &ctx, uint64_t size,
2757+
OutputSection *parent)
2758+
: SyntheticSection(ctx, ".shuffle_padding", SHF_ALLOC, SHT_PROGBITS, 1),
2759+
size(size) {
2760+
this->parent = parent;
2761+
}
2762+
2763+
void ShufflePaddingSection::writeTo(uint8_t *buf) {
2764+
std::array<uint8_t, 4> filler = getParent()->getFiller(ctx);
2765+
uint8_t *end = buf + size;
2766+
for (; buf + 4 <= end; buf += 4)
2767+
memcpy(buf, &filler[0], 4);
2768+
memcpy(buf, &filler[0], end - buf);
2769+
}
2770+
27562771
// The string hash function for .gdb_index.
27572772
static uint32_t computeGdbHash(StringRef s) {
27582773
uint32_t h = 0;

lld/ELF/SyntheticSections.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,15 @@ class RelroPaddingSection final : public SyntheticSection {
796796
void writeTo(uint8_t *buf) override {}
797797
};
798798

799+
class ShufflePaddingSection final : public SyntheticSection {
800+
uint64_t size;
801+
802+
public:
803+
ShufflePaddingSection(Ctx &ctx, uint64_t size, OutputSection *parent);
804+
size_t getSize() const override { return size; }
805+
void writeTo(uint8_t *buf) override;
806+
};
807+
799808
// Used by the merged DWARF32 .debug_names (a per-module index). If we
800809
// move to DWARF64, most of this data will need to be re-sized.
801810
class DebugNamesBaseSection : public SyntheticSection {

lld/ELF/Writer.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,37 @@ static void finalizeSynthetic(Ctx &ctx, SyntheticSection *sec) {
14441444
}
14451445
}
14461446

1447+
static bool canInsertPadding(OutputSection *sec) {
1448+
StringRef s = sec->name;
1449+
return s == ".bss" || s == ".data" || s == ".data.rel.ro" ||
1450+
s == ".rodata" || s.starts_with(".text");
1451+
}
1452+
1453+
static void shufflePadding(Ctx &ctx) {
1454+
std::mt19937 g(*ctx.arg.shufflePadding);
1455+
PhdrEntry *curPtLoad = nullptr;
1456+
for (OutputSection *os : ctx.outputSections) {
1457+
if (!canInsertPadding(os))
1458+
continue;
1459+
for (SectionCommand *bc : os->commands) {
1460+
if (auto *isd = dyn_cast<InputSectionDescription>(bc)) {
1461+
SmallVector<InputSection *, 0> tmp;
1462+
if (os->ptLoad != curPtLoad) {
1463+
tmp.push_back(
1464+
make<ShufflePaddingSection>(ctx, g() % ctx.arg.maxPageSize, os));
1465+
curPtLoad = os->ptLoad;
1466+
}
1467+
for (InputSection *isec : isd->sections) {
1468+
if (g() < (1<<28))
1469+
tmp.push_back(make<ShufflePaddingSection>(ctx, isec->addralign, os));
1470+
tmp.push_back(isec);
1471+
}
1472+
isd->sections = std::move(tmp);
1473+
}
1474+
}
1475+
}
1476+
}
1477+
14471478
// We need to generate and finalize the content that depends on the address of
14481479
// InputSections. As the generation of the content may also alter InputSection
14491480
// addresses we must converge to a fixed point. We do that here. See the comment
@@ -1470,6 +1501,9 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
14701501
if (ctx.arg.emachine == EM_HEXAGON)
14711502
hexagonTLSSymbolUpdate(ctx);
14721503

1504+
if (ctx.arg.shufflePadding)
1505+
shufflePadding(ctx);
1506+
14731507
uint32_t pass = 0, assignPasses = 0;
14741508
for (;;) {
14751509
bool changed = ctx.target->needsThunks

lld/docs/ld.lld.1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,15 @@ were concatenated in the order they appeared on the command line.
577577
Set address of section.
578578
.It Fl -shared , Fl -Bsharable
579579
Build a shared object.
580+
.It Fl -shuffle-padding Ns = Ns Ar seed
581+
Randomly insert padding between input sections using the given seed.
582+
Padding is inserted into output sections with names matching the following patterns:
583+
.Cm .bss ,
584+
.Cm .data ,
585+
.Cm .data.rel.ro ,
586+
.Cm .rodata
587+
and
588+
.Cm .text* .
580589
.It Fl -shuffle-sections Ns = Ns Ar seed
581590
Shuffle matched sections using the given seed before mapping them to the output sections.
582591
If -1, reverse the section order. If 0, use a random seed.

lld/test/ELF/shuffle-padding.s

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3+
4+
# RUN: ld.lld %t.o -o %t.out
5+
# RUN: llvm-readelf -x .rodata %t.out | FileCheck %s
6+
# CHECK: Hex dump of section '.rodata':
7+
# CHECK-NEXT: 0x00201120 010203
8+
9+
## --shuffle-padding= inserts segment offset padding and pre-section padding.
10+
# RUN: ld.lld --shuffle-padding=1 %t.o -o %t.out
11+
# RUN: llvm-readelf -x .rodata %t.out | FileCheck --check-prefix=PAD1 %s
12+
# PAD1: Hex dump of section '.rodata':
13+
# PAD1-NEXT: 0x00201548 0102cc03
14+
15+
## Size of segment offset padding and location of pre-section padding is
16+
## dependent on the seed.
17+
# RUN: ld.lld --shuffle-padding=2 %t.o -o %t.out
18+
# RUN: llvm-readelf -x .rodata %t.out | FileCheck --check-prefix=PAD2 %s
19+
# PAD2: Hex dump of section '.rodata':
20+
# PAD2-NEXT: 0x00201dc8 cc010203
21+
22+
.section .rodata.a,"ax"
23+
.byte 1
24+
25+
.section .rodata.b,"ax"
26+
.byte 2
27+
28+
.section .rodata.c,"ax"
29+
.byte 3

0 commit comments

Comments
 (0)