diff options
Diffstat (limited to 'lld/ELF/Writer.cpp')
| -rw-r--r-- | lld/ELF/Writer.cpp | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 49616fa03e63..3e92b7653e31 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -297,8 +297,9 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) { } } + sym->isExported = sym->includeInDynsym(ctx); if (ctx.arg.hasDynSymTab) - sym->isPreemptible = computeIsPreemptible(ctx, *sym); + sym->isPreemptible = sym->isExported && computeIsPreemptible(ctx, *sym); } } @@ -1448,6 +1449,40 @@ 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 == ".lbss" || + s == ".ldata" || s == ".lrodata" || s == ".ltext" || s == ".rodata" || + s.starts_with(".text"); +} + +static void randomizeSectionPadding(Ctx &ctx) { + std::mt19937 g(*ctx.arg.randomizeSectionPadding); + 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) { + tmp.push_back(make<RandomizePaddingSection>( + ctx, g() % ctx.arg.maxPageSize, os)); + curPtLoad = os->ptLoad; + } + for (InputSection *isec : isd->sections) { + // Probability of inserting padding is 1 in 16. + if (g() % 16 == 0) + tmp.push_back( + make<RandomizePaddingSection>(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 @@ -1474,6 +1509,9 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { if (ctx.arg.emachine == EM_HEXAGON) hexagonTLSSymbolUpdate(ctx); + if (ctx.arg.randomizeSectionPadding) + randomizeSectionPadding(ctx); + uint32_t pass = 0, assignPasses = 0; for (;;) { bool changed = ctx.target->needsThunks @@ -1888,9 +1926,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (ctx.in.symTab) ctx.in.symTab->addSymbol(sym); - if (sym->includeInDynsym(ctx)) { + // computeBinding might localize a linker-synthesized hidden symbol + // (e.g. __global_pointer$) that was considered exported. + if (sym->isExported && !sym->isLocal()) { ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym); - if (auto *file = dyn_cast_or_null<SharedFile>(sym->file)) + if (auto *file = dyn_cast<SharedFile>(sym->file)) if (file->isNeeded && !sym->isUndefined()) addVerneed(ctx, *sym); } @@ -2365,6 +2405,11 @@ Writer<ELFT>::createPhdrs(Partition &part) { addHdr(PT_GNU_STACK, perm)->p_memsz = ctx.arg.zStackSize; } + // PT_OPENBSD_NOBTCFI is an OpenBSD-specific header to mark that the + // executable is expected to violate branch-target CFI checks. + if (ctx.arg.zNoBtCfi) + addHdr(PT_OPENBSD_NOBTCFI, PF_X); + // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable // is expected to perform W^X violations, such as calling mprotect(2) or // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on |
