-
Notifications
You must be signed in to change notification settings - Fork 15.3k
ELF: Introduce --randomize-section-padding option. #117653
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
Changes from 3 commits
75ad826
c420199
667e7ba
678959e
a02fa37
cd48297
bdbf795
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2753,6 +2753,21 @@ RelroPaddingSection::RelroPaddingSection(Ctx &ctx) | |
| : SyntheticSection(ctx, ".relro_padding", SHT_NOBITS, SHF_ALLOC | SHF_WRITE, | ||
| 1) {} | ||
|
|
||
| ShufflePaddingSection::ShufflePaddingSection(Ctx &ctx, uint64_t size, | ||
| OutputSection *parent) | ||
| : SyntheticSection(ctx, ".shuffle_padding", SHF_ALLOC, SHT_PROGBITS, 1), | ||
|
||
| size(size) { | ||
| this->parent = parent; | ||
| } | ||
|
|
||
| void ShufflePaddingSection::writeTo(uint8_t *buf) { | ||
| std::array<uint8_t, 4> filler = getParent()->getFiller(ctx); | ||
| uint8_t *end = buf + size; | ||
| for (; buf + 4 <= end; buf += 4) | ||
| memcpy(buf, &filler[0], 4); | ||
| memcpy(buf, &filler[0], end - buf); | ||
| } | ||
|
|
||
| // The string hash function for .gdb_index. | ||
| static uint32_t computeGdbHash(StringRef s) { | ||
| uint32_t h = 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -796,6 +796,15 @@ class RelroPaddingSection final : public SyntheticSection { | |
| void writeTo(uint8_t *buf) override {} | ||
| }; | ||
|
|
||
| class ShufflePaddingSection final : public SyntheticSection { | ||
|
||
| uint64_t size; | ||
|
|
||
| public: | ||
| ShufflePaddingSection(Ctx &ctx, uint64_t size, OutputSection *parent); | ||
| size_t getSize() const override { return size; } | ||
| void writeTo(uint8_t *buf) override; | ||
| }; | ||
|
|
||
| // Used by the merged DWARF32 .debug_names (a per-module index). If we | ||
| // move to DWARF64, most of this data will need to be re-sized. | ||
| class DebugNamesBaseSection : public SyntheticSection { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1444,6 +1444,38 @@ static void finalizeSynthetic(Ctx &ctx, SyntheticSection *sec) { | |
| } | ||
| } | ||
|
|
||
| static bool canInsertPadding(OutputSection *sec) { | ||
| StringRef s = sec->name; | ||
| return s == ".bss" || s == ".data" || s == ".data.rel.ro" || s == ".rodata" || | ||
smithp35 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| s.starts_with(".text"); | ||
| } | ||
|
|
||
| static void shufflePadding(Ctx &ctx) { | ||
| std::mt19937 g(*ctx.arg.shufflePadding); | ||
| PhdrEntry *curPtLoad = nullptr; | ||
| for (OutputSection *os : ctx.outputSections) { | ||
| if (!canInsertPadding(os)) | ||
| continue; | ||
| for (SectionCommand *bc : os->commands) { | ||
| if (auto *isd = dyn_cast<InputSectionDescription>(bc)) { | ||
| SmallVector<InputSection *, 0> tmp; | ||
| if (os->ptLoad != curPtLoad) { | ||
smithp35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| tmp.push_back( | ||
| make<ShufflePaddingSection>(ctx, g() % ctx.arg.maxPageSize, os)); | ||
| curPtLoad = os->ptLoad; | ||
| } | ||
| for (InputSection *isec : isd->sections) { | ||
| if (g() < (1 << 28)) | ||
|
||
| tmp.push_back( | ||
| make<ShufflePaddingSection>(ctx, isec->addralign, os)); | ||
| tmp.push_back(isec); | ||
| } | ||
| isd->sections = std::move(tmp); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // We need to generate and finalize the content that depends on the address of | ||
| // InputSections. As the generation of the content may also alter InputSection | ||
| // addresses we must converge to a fixed point. We do that here. See the comment | ||
|
|
@@ -1470,6 +1502,9 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { | |
| if (ctx.arg.emachine == EM_HEXAGON) | ||
| hexagonTLSSymbolUpdate(ctx); | ||
|
|
||
| if (ctx.arg.shufflePadding) | ||
| shufflePadding(ctx); | ||
|
|
||
| uint32_t pass = 0, assignPasses = 0; | ||
| for (;;) { | ||
| bool changed = ctx.target->needsThunks | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # REQUIRES: x86 | ||
| # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
|
|
||
| ## --shuffle-padding= inserts segment offset padding and pre-section padding, | ||
| ## and does not affect .bss flags. | ||
| # RUN: ld.lld --shuffle-padding=1 %t.o -o %t.out | ||
| # RUN: llvm-readelf -sS %t.out | FileCheck --check-prefix=HEADER %s | ||
| # HEADER: .bss NOBITS 0000000000202580 000580 000f90 00 WA 0 0 1 | ||
| # HEADER: 1: 000000000020350c 0 NOTYPE LOCAL DEFAULT 2 a | ||
| # HEADER: 2: 000000000020350e 0 NOTYPE LOCAL DEFAULT 2 b | ||
| # HEADER: 3: 000000000020350f 0 NOTYPE LOCAL DEFAULT 2 c | ||
|
|
||
| .section .bss.a,"a",@nobits | ||
| a: | ||
| .zero 1 | ||
|
|
||
| .section .bss.b,"a",@nobits | ||
| b: | ||
| .zero 1 | ||
|
|
||
| .section .bss.c,"a",@nobits | ||
| c: | ||
| .zero 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # REQUIRES: x86 | ||
| # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
|
|
||
| # RUN: ld.lld %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .data %t.out | FileCheck %s | ||
| # CHECK: Hex dump of section '.data': | ||
| # CHECK-NEXT: 0x00202158 010203 | ||
|
|
||
| ## --shuffle-padding= inserts segment offset padding and pre-section padding. | ||
| # RUN: ld.lld --shuffle-padding=1 %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .data %t.out | FileCheck --check-prefix=PAD1 %s | ||
| # PAD1: Hex dump of section '.data': | ||
| # PAD1: 0x00203500 00000000 00000000 00000000 01000203 | ||
|
|
||
| ## --shuffle-padding= does not affect .rodata flags. | ||
| # RUN: llvm-readelf -S %t.out | FileCheck --check-prefix=HEADER %s | ||
| # HEADER: .data PROGBITS 0000000000202580 000580 000f90 00 WA 0 0 1 | ||
|
|
||
| ## Size of segment offset padding and location of pre-section padding is | ||
| ## dependent on the seed. | ||
| # RUN: ld.lld --shuffle-padding=2 %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .data %t.out | FileCheck --check-prefix=PAD2 %s | ||
| # PAD2: Hex dump of section '.data': | ||
| # PAD2: 0x002037e0 00000000 00000000 00000000 00010203 | ||
|
|
||
| .section .data.a,"aw",@progbits | ||
| a: | ||
| .byte 1 | ||
|
|
||
| .section .data.b,"aw",@progbits | ||
| b: | ||
| .byte 2 | ||
|
|
||
| .section .data.c,"aw",@progbits | ||
| c: | ||
| .byte 3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # REQUIRES: x86 | ||
|
||
| # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
|
|
||
| # RUN: ld.lld %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .rodata %t.out | FileCheck %s | ||
| # CHECK: Hex dump of section '.rodata': | ||
| # CHECK-NEXT: 0x00200120 010203 | ||
|
|
||
| ## --shuffle-padding= inserts segment offset padding and pre-section padding. | ||
| # RUN: ld.lld --shuffle-padding=1 %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .rodata %t.out | FileCheck --check-prefix=PAD1 %s | ||
| # PAD1: Hex dump of section '.rodata': | ||
| # PAD1: 0x00200540 00000000 00010203 | ||
|
|
||
| ## --shuffle-padding= does not affect .rodata flags. | ||
| # RUN: llvm-readelf -S %t.out | FileCheck --check-prefix=HEADER %s | ||
| # HEADER: .rodata PROGBITS 0000000000200120 000120 000428 00 A 0 0 1 | ||
|
|
||
| ## Size of segment offset padding and location of pre-section padding is | ||
| ## dependent on the seed. | ||
| # RUN: ld.lld --shuffle-padding=2 %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .rodata %t.out | FileCheck --check-prefix=PAD2 %s | ||
| # PAD2: Hex dump of section '.rodata': | ||
| # PAD2: 0x00200dc0 00000000 00000000 01000203 | ||
|
|
||
| .section .rodata.a,"a",@progbits | ||
| a: | ||
| .byte 1 | ||
|
|
||
| .section .rodata.b,"a",@progbits | ||
| b: | ||
| .byte 2 | ||
|
|
||
| .section .rodata.c,"a",@progbits | ||
| c: | ||
| .byte 3 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # REQUIRES: x86 | ||
| # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
|
|
||
| # RUN: ld.lld %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .text %t.out | FileCheck %s | ||
| # CHECK: Hex dump of section '.text': | ||
| # CHECK-NEXT: 0x00201120 010203 | ||
|
|
||
| ## --shuffle-padding= inserts segment offset padding and pre-section padding. | ||
| # RUN: ld.lld --shuffle-padding=1 %t.o -o %t.out | ||
| # RUN: llvm-readelf -x .text %t.out | FileCheck --check-prefix=PAD1 %s | ||
| # PAD1: Hex dump of section '.text': | ||
| # PAD1: 0x00201540 cccccccc cccccccc 0102cc03 | ||
|
|
||
| ## --shuffle-padding= does not affect .text flags. | ||
| # RUN: llvm-readelf -S %t.out | FileCheck --check-prefix=HEADER %s | ||
| # HEADER: .text PROGBITS 0000000000201120 000120 00042c 00 AX 0 0 4 | ||
|
|
||
| .section .text.a,"ax" | ||
| .byte 1 | ||
|
|
||
| .section .text.b,"ax" | ||
| .byte 2 | ||
|
|
||
| .section .text.c,"ax" | ||
| .byte 3 |
Uh oh!
There was an error while loading. Please reload this page.