[ELF] Align the end of PT_GNU_RELRO associated PT_LOAD to a common-page-size boundary (#66042)

Close #57618: currently we align the end of PT_GNU_RELRO to a
common-page-size
boundary, but do not align the end of the associated PT_LOAD. This is
benign
when runtime_page_size >= common-page-size.

However, when runtime_page_size < common-page-size, it is possible that
`alignUp(end(PT_LOAD), page_size) < alignDown(end(PT_GNU_RELRO),
page_size)`.
In this case, rtld's mprotect call for PT_GNU_RELRO will apply to
unmapped
regions and lead to an error, e.g.

```
error while loading shared libraries: cannot apply additional memory protection after relocation: Cannot allocate memory
```

To fix the issue, add a padding section .relro_padding like mold, which
is contained in the PT_GNU_RELRO segment and the associated PT_LOAD
segment. The section also prevents strip from corrupting PT_LOAD program
headers.

.relro_padding has the largest `sortRank` among RELRO sections.
Therefore, it is naturally placed at the end of `PT_GNU_RELRO` segment
in the absence of `PHDRS`/`SECTIONS` commands.

In the presence of `SECTIONS` commands, we place .relro_padding
immediately before a symbol assignment using DATA_SEGMENT_RELRO_END (see
also https://reviews.llvm.org/D124656), if present.
DATA_SEGMENT_RELRO_END is changed to align to max-page-size instead of
common-page-size.

Some edge cases worth mentioning:

* ppc64-toc-addis-nop.s: when PHDRS is present, do not append
.relro_padding
* avoid-empty-program-headers.s: when the only RELRO section is .tbss,
it is not part of PT_LOAD segment, therefore we do not append
.relro_padding.

---

Close #65002: GNU ld from 2.39 onwards aligns the end of PT_GNU_RELRO to
a
max-page-size boundary (https://sourceware.org/PR28824) so that the last
page is
protected even if runtime_page_size > common-page-size.

In my opinion, losing protection for the last page when the runtime page
size is
larger than common-page-size is not really an issue. Double mapping a
page of up
to max-common-page for the protection could cause undesired VM waste.
Internally
we had users complaining about 2MiB max-page-size applying to shared
objects.

Therefore, the end of .relro_padding is padded to a common-page-size
boundary. Users who are really anxious can set common-page-size to match
their runtime page size.

---

17 tests need updating as there are lots of change detectors.
This commit is contained in:
Fangrui Song
2023-09-14 10:33:11 -07:00
committed by GitHub
parent 21ab252f97
commit 5a58e98c20
30 changed files with 241 additions and 60 deletions

View File

@@ -1586,8 +1586,8 @@ static void readConfigs(opt::InputArgList &args) {
// Page alignment can be disabled by the -n (--nmagic) and -N (--omagic).
// As PT_GNU_RELRO relies on Paging, do not create it when we have disabled
// it.
if (config->nmagic || config->omagic)
// it. Also disable RELRO for -r.
if (config->nmagic || config->omagic || config->relocatable)
config->zRelro = false;
std::tie(config->buildId, config->buildIdVector) = getBuildId(args);

View File

@@ -887,6 +887,10 @@ void LinkerScript::diagnoseOrphanHandling() const {
if (config->orphanHandling == OrphanHandlingPolicy::Place)
return;
for (const InputSectionBase *sec : orphanSections) {
// .relro_padding is inserted before DATA_SEGMENT_RELRO_END, if present,
// automatically. The section is not supposed to be specified by scripts.
if (sec == in.relroPadding.get())
continue;
// Input SHT_REL[A] retained by --emit-relocs are ignored by
// computeInputSections(). Don't warn/error.
if (isa<InputSection>(sec) &&
@@ -1079,6 +1083,11 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
}
}
// If .relro_padding is present, round up the end to a common-page-size
// boundary to protect the last page.
if (in.relroPadding && sec == in.relroPadding->getParent())
expandOutputSection(alignToPowerOf2(dot, config->commonPageSize) - dot);
// Non-SHF_ALLOC sections do not affect the addresses of other OutputSections
// as they are not part of the process image.
if (!(sec->flags & SHF_ALLOC)) {
@@ -1160,6 +1169,7 @@ void LinkerScript::adjustOutputSections() {
uint64_t flags = SHF_ALLOC;
SmallVector<StringRef, 0> defPhdrs;
bool seenRelro = false;
for (SectionCommand *&cmd : sectionCommands) {
if (!isa<OutputDesc>(cmd))
continue;
@@ -1196,9 +1206,17 @@ void LinkerScript::adjustOutputSections() {
if (sec->sectionIndex != UINT32_MAX)
maybePropagatePhdrs(*sec, defPhdrs);
// Discard .relro_padding if we have not seen one RELRO section. Note: when
// .tbss is the only RELRO section, there is no associated PT_LOAD segment
// (needsPtLoad), so we don't append .relro_padding in the case.
if (in.relroPadding && in.relroPadding->getParent() == sec && !seenRelro)
discardable = true;
if (discardable) {
sec->markDead();
cmd = nullptr;
} else {
seenRelro |=
sec->relro && !(sec->type == SHT_NOBITS && (sec->flags & SHF_TLS));
}
}

View File

@@ -105,6 +105,9 @@ struct SymbolAssignment : SectionCommand {
bool provide = false;
bool hidden = false;
// This assignment references DATA_SEGMENT_RELRO_END.
bool dataSegmentRelroEnd = false;
unsigned symOrder;
// Holds file name and line number for error reporting.
@@ -352,6 +355,8 @@ public:
SmallVector<PhdrsCommand, 0> phdrsCommands;
bool hasSectionsCommand = false;
bool seenDataAlign = false;
bool seenRelroEnd = false;
bool errorOnMissingSection = false;
// List of section patterns specified with KEEP commands. They will

View File

@@ -136,9 +136,6 @@ private:
// True if a script being read is in the --sysroot directory.
bool isUnderSysroot = false;
bool seenDataAlign = false;
bool seenRelroEnd = false;
// A set to detect an INCLUDE() cycle.
StringSet<> seen;
};
@@ -600,7 +597,7 @@ void ScriptParser::readSections() {
// If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
// the relro fields should be cleared.
if (!seenRelroEnd)
if (!script->seenRelroEnd)
for (SectionCommand *cmd : v)
if (auto *osd = dyn_cast<OutputDesc>(cmd))
osd->osec.relro = false;
@@ -916,7 +913,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
script->createOutputSection(unquote(outSec), getCurrentLocation());
OutputSection *osec = &cmd->osec;
// Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
osec->relro = seenDataAlign && !seenRelroEnd;
osec->relro = script->seenDataAlign && !script->seenRelroEnd;
size_t symbolsReferenced = script->referencedSymbols.size();
@@ -1051,6 +1048,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
size_t oldPos = pos;
SymbolAssignment *cmd = nullptr;
bool savedSeenRelroEnd = script->seenRelroEnd;
const StringRef op = peek();
if (op.starts_with("=")) {
// Support = followed by an expression without whitespace.
@@ -1071,6 +1069,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
}
if (cmd) {
cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd;
cmd->commandString =
tok.str() + " " +
llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
@@ -1439,7 +1438,7 @@ Expr ScriptParser::readPrimary() {
expect(",");
readExpr();
expect(")");
seenDataAlign = true;
script->seenDataAlign = true;
return [=] {
uint64_t align = std::max(uint64_t(1), e().getValue());
return (script->getDot() + align - 1) & -align;
@@ -1460,9 +1459,8 @@ Expr ScriptParser::readPrimary() {
expect(",");
readExpr();
expect(")");
seenRelroEnd = true;
Expr e = getPageSize();
return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
script->seenRelroEnd = true;
return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
}
if (tok == "DEFINED") {
StringRef name = unquote(readParenLiteral());

View File

@@ -2688,6 +2688,10 @@ size_t IBTPltSection::getSize() const {
bool IBTPltSection::isNeeded() const { return in.plt->getNumEntries() > 0; }
RelroPaddingSection::RelroPaddingSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 1, ".relro_padding") {
}
// The string hash function for .gdb_index.
static uint32_t computeGdbHash(StringRef s) {
uint32_t h = 0;
@@ -3839,6 +3843,7 @@ void InStruct::reset() {
got.reset();
gotPlt.reset();
igotPlt.reset();
relroPadding.reset();
armCmseSGSection.reset();
ppc64LongBranchTarget.reset();
mipsAbiFlags.reset();

View File

@@ -778,6 +778,16 @@ public:
size_t getSize() const override;
};
// Used to align the end of the PT_GNU_RELRO segment and the associated PT_LOAD
// segment to a common-page-size boundary. This padding section ensures that all
// pages in the PT_LOAD segment is covered by at least one section.
class RelroPaddingSection final : public SyntheticSection {
public:
RelroPaddingSection();
size_t getSize() const override { return 0; }
void writeTo(uint8_t *buf) override {}
};
class GdbIndexSection final : public SyntheticSection {
public:
struct AddressEntry {
@@ -1333,6 +1343,7 @@ struct InStruct {
std::unique_ptr<GotSection> got;
std::unique_ptr<GotPltSection> gotPlt;
std::unique_ptr<IgotPltSection> igotPlt;
std::unique_ptr<RelroPaddingSection> relroPadding;
std::unique_ptr<SyntheticSection> armCmseSGSection;
std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
std::unique_ptr<SyntheticSection> mipsAbiFlags;

View File

@@ -458,6 +458,13 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.gotPlt);
in.igotPlt = std::make_unique<IgotPltSection>();
add(*in.igotPlt);
// Add .relro_padding if DATA_SEGMENT_RELRO_END is used; otherwise, add the
// section in the absence of PHDRS/SECTIONS commands.
if (config->zRelro && ((script->phdrsCommands.empty() &&
!script->hasSectionsCommand) || script->seenRelroEnd)) {
in.relroPadding = std::make_unique<RelroPaddingSection>();
add(*in.relroPadding);
}
if (config->emachine == EM_ARM) {
in.armCmseSGSection = std::make_unique<ArmCmseSGSection>();
@@ -818,6 +825,9 @@ static bool isRelroSection(const OutputSection *sec) {
if (sec == in.gotPlt->getParent())
return config->zNow;
if (in.relroPadding && sec == in.relroPadding->getParent())
return true;
// .dynamic section contains data for the dynamic linker, and
// there's no need to write to it at runtime, so it's better to put
// it into RELRO.
@@ -857,7 +867,7 @@ enum RankFlags {
RF_BSS = 1 << 7,
};
static unsigned getSectionRank(const OutputSection &osec) {
static unsigned getSectionRank(OutputSection &osec) {
unsigned rank = osec.partition * RF_PARTITION;
// We want to put section specified by -T option first, so we
@@ -920,7 +930,9 @@ static unsigned getSectionRank(const OutputSection &osec) {
// TLS sections directly before the other RELRO sections.
if (!(osec.flags & SHF_TLS))
rank |= RF_NOT_TLS;
if (!isRelroSection(&osec))
if (isRelroSection(&osec))
osec.relro = true;
else
rank |= RF_NOT_RELRO;
// Place .ldata and .lbss after .bss. Making .bss closer to .text alleviates
// relocation overflow pressure.
@@ -1140,6 +1152,18 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
SmallVectorImpl<SectionCommand *>::iterator e) {
OutputSection *sec = &cast<OutputDesc>(*e)->osec;
// As a special case, place .relro_padding before the SymbolAssignment using
// DATA_SEGMENT_RELRO_END, if present.
if (in.relroPadding && sec == in.relroPadding->getParent()) {
auto i = std::find_if(b, e, [=](SectionCommand *a) {
if (auto *assign = dyn_cast<SymbolAssignment>(a))
return assign->dataSegmentRelroEnd;
return false;
});
if (i != e)
return i;
}
// Find the first element that has as close a rank as possible.
auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
return getRankProximity(sec, a) < getRankProximity(sec, b);
@@ -2334,6 +2358,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
relroEnd = sec;
}
}
relRo->p_align = 1;
for (OutputSection *sec : outputSections) {
if (!needsPtLoad(sec))
@@ -2677,16 +2702,6 @@ template <class ELFT> void Writer<ELFT>::setPhdrs(Partition &part) {
if (!p->hasLMA)
p->p_paddr = first->getLMA();
}
if (p->p_type == PT_GNU_RELRO) {
p->p_align = 1;
// musl/glibc ld.so rounds the size down, so we need to round up
// to protect the last page. This is a no-op on FreeBSD which always
// rounds up.
p->p_memsz =
alignToPowerOf2(p->p_offset + p->p_memsz, config->commonPageSize) -
p->p_offset;
}
}
}

View File

@@ -172,3 +172,18 @@ description in the ``OVERWRITE_SECTIONS`` command while the insert command
still applies (possibly after orphan section placement). It is recommended to
leave the brace empty (i.e. ``section : {}``) for the insert command, because
its description will be ignored anyway.
Built-in functions
~~~~~~~~~~~~~~~~~~
``DATA_SEGMENT_RELRO_END(offset, exp)`` defines the end of the ``PT_GNU_RELRO``
segment when ``-z relro`` (default) is in effect. Sections between
``DATA_SEGMENT_ALIGN`` and ``DATA_SEGMENT_RELRO_END`` are considered RELRO.
The typical use case is ``. = DATA_SEGMENT_RELRO_END(0, .);`` followed by
writable but non-RELRO sections. LLD ignores ``offset`` and ``exp`` and aligns
the current location to a max-page-size boundary, ensuring that the next
``PT_LOAD`` segment will not overlap with the ``PT_GNU_RELRO`` segment.
LLD will insert ``.relro_padding`` immediately before the symbol assignment
using ``DATA_SEGMENT_RELRO_END``.

View File

@@ -29,7 +29,8 @@ ELF Improvements
* ``--fat-lto-objects`` option is added to support LLVM FatLTO.
Without ``--fat-lto-objects``, LLD will link LLVM FatLTO objects using the
relocatable object file. (`D146778 <https://reviews.llvm.org/D146778>`_)
* common-page-size can now be larger than the system page-size.
(`#57618 <https://github.com/llvm/llvm-project/issues/57618>`_)
Breaking changes
----------------

View File

@@ -13,7 +13,7 @@
// CHECK: LOAD 0x000000 0x00000000 0x00000000 0x0016d 0x0016d R 0x10000
// CHECK: LOAD 0x000170 0x00010170 0x00010170 0x{{.*}} 0x{{.*}} R E 0x10000
// CHECK: LOAD 0x000174 0x00020174 0x00020174 0x{{.*}} 0x{{.*}} E 0x10000
// CHECK: LOAD 0x000178 0x00030178 0x00030178 0x00038 0x00038 RW 0x10000
// CHECK: LOAD 0x000178 0x00030178 0x00030178 0x00038 0x00e88 RW 0x10000
// CHECK: 01 .dynsym .gnu.hash .hash .dynstr
// CHECK: 02 .text
@@ -22,7 +22,7 @@
// DIFF: LOAD 0x000000 0x00000000 0x00000000 0x0014d 0x0014d R 0x10000
// DIFF: LOAD 0x000150 0x00010150 0x00010150 0x0000c 0x0000c R E 0x10000
// DIFF: LOAD 0x00015c 0x0002015c 0x0002015c 0x00038 0x00038 RW 0x10000
// DIFF: LOAD 0x00015c 0x0002015c 0x0002015c 0x00038 0x00ea4 RW 0x10000
// DIFF: 01 .dynsym .gnu.hash .hash .dynstr
// DIFF: 02 .text .foo

View File

@@ -21,16 +21,16 @@
# CHECK-NEXT: AddressAlignment:
# CHECK-NEXT: EntrySize:
# CHECK-NEXT: SectionData (
# CHECK-NEXT: 0000: 08232000 00000000 08232000 00000000
# CHECK-NEXT: 0000: 00302000 00000000 00302000 00000000
# CHECK-NEXT: )
# CHECK: Symbol {
# CHECK: Name: _end
# CHECK-NEXT: Value: 0x202308
# CHECK-NEXT: Value: 0x203000
# CHECK: Symbol {
# CHECK: Name: end
# CHECK-NEXT: Value: 0x202308
# CHECK-NEXT: Value: 0x203000
.global _start
_start:

View File

@@ -0,0 +1,79 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/a.s -o %t/a.o
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %p/Inputs/shared.s -o %t/b.o
# RUN: ld.lld -shared -soname=b %t/b.o -o %t/b.so
# RUN: ld.lld -z max-page-size=65536 -z norelro %t/a.o %t/b.so -T %t/1.t -o %t/a1
# RN: llvm-readelf -S -l %t/a1 | FileCheck %s --check-prefixes=CHECK1
# RUN: ld.lld -z max-page-size=65536 -z relro %t/a.o %t/b.so -T %t/1.t -o %t/a2
# RUN: llvm-readelf -S -l %t/a2 | FileCheck %s --check-prefixes=CHECK2
## -z norelro suppresses the .relro_padding section.
# CHECK1: Name Type Address Off Size ES Flg
# CHECK1: .foo PROGBITS
# CHECK1-NEXT: .orphan.rw PROGBITS
# CHECK1-NEXT: .branch_lt PROGBITS
# CHECK1-NEXT: .got PROGBITS
# CHECK1-NEXT: .data PROGBITS
# CHECK1-NEXT: .bss NOBITS
# CHECK2: Name Type Address Off Size ES Flg
# CHECK2-NEXT: NULL {{.*}}
# CHECK2: .orphan.ro PROGBITS {{.*}} A
# CHECK2: .dynamic DYNAMIC {{.*}} WA
# CHECK2-NEXT: .branch_lt PROGBITS {{.*}} WA
# CHECK2-NEXT: .got PROGBITS {{.*}} WA
# CHECK2-NEXT: .relro_padding NOBITS 00000000000100f0 0100f0 000f10 00 WA
# CHECK2-NEXT: .data PROGBITS {{.*}} WA
# CHECK2-NEXT: .foo PROGBITS {{.*}} WA
# CHECK2-NEXT: .orphan.rw PROGBITS {{.*}} WA
# CHECK2-NEXT: .bss NOBITS {{.*}} WA
#--- a.s
.global _start
_start:
addis 3, 2, bar2@toc@ha
ld 12, bar2@toc@l(3)
mtctr 12
bctrl
b bar
nop
.section .data,"aw"
.quad 0
.zero 4
.section .foo,"aw"
.section .bss,"",@nobits
.section .orphan.ro,"a",@progbits
.dc.a 0
.section .orphan.rw,"aw",@progbits
.dc.a .orphan.rw
#--- 1.t
SECTIONS {
. = SIZEOF_HEADERS;
.plt : { *(.plt) }
.text : { *(.text) }
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
.dynamic : { *(.dynamic) }
.branch_lt : { *(.branch_lt) }
.got : { *(.got) }
. = DATA_SEGMENT_RELRO_END (0, .);
.plt : { *(.plt) }
.data : { *(.data) }
.bss : { *(.bss) }
. = DATA_SEGMENT_END (.);
.comment 0 : { *(.comment) }
}

View File

@@ -7,18 +7,23 @@
## With relro or without DATA_SEGMENT_RELRO_END just aligns to
## page boundary.
# RUN: ld.lld --hash-style=sysv -z norelro %t/a.o %t/b.so -T %t/1.t -o %t/a1
# RUN: ld.lld --hash-style=sysv -z max-page-size=65536 -z norelro %t/a.o %t/b.so -T %t/1.t -o %t/a1
# RUN: llvm-readelf -S -l %t/a1 | FileCheck %s --check-prefixes=CHECK,CHECK1
# RUN: ld.lld --hash-style=sysv -z relro %t/a.o %t/b.so -T %t/1.t -o %t/a2
# RUN: ld.lld --hash-style=sysv -z max-page-size=65536 -z relro --orphan-handling=warn \
# RUN: %t/a.o %t/b.so -T %t/1.t -o %t/a2 2>&1 | FileCheck %s --check-prefix=WARN
# RUN: llvm-readelf -S -l %t/a2 | FileCheck %s --check-prefixes=CHECK,CHECK2
# WARN: warning: <internal>:(.dynsym) is being placed in '.dynsym'
# WARN-NOT: (.relro_padding)
# CHECK: Name Type Address Off Size ES Flg
# CHECK-NEXT: NULL {{.*}}
# CHECK: .orphan.ro PROGBITS {{.*}} A
# CHECK: .dynamic DYNAMIC {{.*}} WA
# CHECK-NEXT: __libc_atexit PROGBITS {{.*}} WA
# CHECK-NEXT: .got PROGBITS {{.*}} WA
# CHECK2-NEXT:.relro_padding NOBITS 0000000000010100 010100 000f00 00 WA
# CHECK-NEXT: .got.plt PROGBITS {{.*}} WA
# CHECK: .orphan.rw PROGBITS {{.*}} WA
@@ -26,18 +31,18 @@
# CHECK1-NOT: GNU_RELRO
# CHECK2: Program Headers:
# CHECK2-NEXT: Type
# CHECK2-NEXT: PHDR
# CHECK2-NEXT: LOAD
# CHECK2-NEXT: LOAD
# CHECK2-NEXT: LOAD
# CHECK2-NEXT: LOAD
# CHECK2-NEXT: DYNAMIC
# CHECK2-NEXT: GNU_RELRO
# CHECK2-NEXT: GNU_STACK
# CHECK2-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# CHECK2-NEXT: PHDR 0x000040
# CHECK2-NEXT: LOAD 0x000000
# CHECK2-NEXT: LOAD 0x0002b0
# CHECK2-NEXT: LOAD 0x010000 0x0000000000010000 0x0000000000010000 0x000100 0x001000 RW 0x10000
# CHECK2-NEXT: LOAD 0x020000 0x0000000000020000 0x0000000000020000 0x000034 0x000034 RW 0x10000
# CHECK2-NEXT: DYNAMIC 0x010000 0x0000000000010000 0x0000000000010000 0x0000f0 0x0000f0 RW 0x8
# CHECK2-NEXT: GNU_RELRO 0x010000 0x0000000000010000 0x0000000000010000 0x000100 0x001000 R 0x1
# CHECK2-NEXT: GNU_STACK 0x000000
# CHECK2: Section to Segment mapping:
# CHECK2: 06 .dynamic __libc_atexit .got {{$}}
# CHECK2: 06 .dynamic __libc_atexit .got .relro_padding {{$}}
# RUN: sed '/DATA_SEGMENT_RELRO_END/d' %t/1.t > %t/2.t
# RUN: not ld.lld %t/a.o %t/b.so -T %t/2.t -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR

View File

@@ -29,7 +29,7 @@
# CHECK2-NEXT: NULL
# CHECK2-NEXT: .foo.text PROGBITS 000000000020{{.*}} [[#%x,]] 000008 00 AX
# CHECK2-NEXT: .text PROGBITS [[#%x,]] [[#%x,]] 000008 00 AX
# CHECK2-NEXT: .byte PROGBITS [[#%x,]] [[#%x,]] 000001 00 AX
# CHECK2-NEXT: .byte PROGBITS [[#%x,]] [[#%x,]] 000001 00 WA
# CHECK2-NEXT: .foo.data PROGBITS [[#%x,]] [[#%x,]] 000008 00 WA
# CHECK2-NEXT: .data PROGBITS [[#%x,]] [[#%x,]] 000008 00 WA
# CHECK2: Type {{.*}} Flg Align

View File

@@ -19,7 +19,7 @@
# CHECK-NEXT: <internal>:(.bss.rel.ro)
## Ideally this is displayed as copy@v2.
# CHECK-NEXT: copy{{$}}
# CHECK-NEXT: .got.plt
# CHECK-NEXT: .relro_padding
#--- 1.s
.global _start

View File

@@ -87,6 +87,8 @@ labs = 0x1AB5
# CHECK-NEXT: 201420 201420 0 1 sharedFunc2
# CHECK-NEXT: 202430 202430 100 8 .dynamic
# CHECK-NEXT: 202430 202430 100 8 <internal>:(.dynamic)
# CHECK-NEXT: 202530 202530 ad0 1 .relro_padding
# CHECK-NEXT: 202530 202530 0 1 <internal>:(.relro_padding)
# CHECK-NEXT: 203530 203530 28 8 .got.plt
# CHECK-NEXT: 203530 203530 28 8 <internal>:(.got.plt)
# CHECK-NEXT: 203560 203560 10 16 .bss
@@ -100,8 +102,8 @@ labs = 0x1AB5
# CHECK-NEXT: 0 0 8 1 <internal>:(.comment)
# CHECK-NEXT: 0 0 1b0 8 .symtab
# CHECK-NEXT: 0 0 1b0 8 <internal>:(.symtab)
# CHECK-NEXT: 0 0 84 1 .shstrtab
# CHECK-NEXT: 0 0 84 1 <internal>:(.shstrtab)
# CHECK-NEXT: 0 0 93 1 .shstrtab
# CHECK-NEXT: 0 0 93 1 <internal>:(.shstrtab)
# CHECK-NEXT: 0 0 71 1 .strtab
# CHECK-NEXT: 0 0 71 1 <internal>:(.strtab)

View File

@@ -37,7 +37,7 @@
// CHECK-NEXT: Owner: GNU
// CHECK-NEXT: Data size:
// CHECK-NEXT: Type: NT_GNU_BUILD_ID (unique build ID bitstring)
// CHECK-NEXT: Build ID: ab81108a3d85b729980356331fddc2bfc4c10177{{$}}
// CHECK-NEXT: Build ID: d5101cb9d03b7e836ba9b64f5768a0b31980920f{{$}}
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]

View File

@@ -41,6 +41,7 @@
// PART0-NEXT: .plt PROGBITS
// PART0-NEXT: .init_array INIT_ARRAY {{0*}}[[INIT_ARRAY_ADDR:[^ ]*]]
// CHECK-NEXT: .dynamic DYNAMIC {{0*}}[[DYNAMIC_ADDR:[^ ]*]]
// PART0-NEXT: .relro_padding NOBITS
// PART0-NEXT: .data PROGBITS 000000000000[[DATA_SEGMENT:.]]178
// PART1-NEXT: .data PROGBITS 000000000000[[DATA_SEGMENT:.]]130
// PART0-NEXT: .got.plt PROGBITS {{0*}}[[GOT_PLT_ADDR:[^ ]*]]

View File

@@ -13,6 +13,8 @@
# CHECK-NEXT: .dynamic
# CHECK-NEXT: .got
# CHECK-NEXT: .toc
## The end of .relro_padding is aligned to a common-page-size boundary.
# CHECK-NEXT: .relro_padding NOBITS 0000000010020400 000400 000c00 00 WA 0 0 1
# CHECK-NEXT: .data
# CHECK-NEXT: .branch_lt

View File

@@ -8,6 +8,11 @@
// RUN: ld.lld %t.o %t.so -o %t3
// RUN: llvm-readobj -S -l -r %t3 | FileCheck %s
/// Due to -z rodynamic, The only RELRO section is .bss.rel.ro. Test that we
/// still append the .relro_padding section.
// RUN: ld.lld -z rodynamic %t.o %t.so -o %t4
// RUN: llvm-readelf -S -l %t4 | FileCheck %s --check-prefix=CHECK2
// CHECK: Name: .bss.rel.ro
// CHECK-NEXT: Type: SHT_NOBITS (0x8)
// CHECK-NEXT: Flags [ (0x3)
@@ -28,6 +33,20 @@
// CHECK: 0x202368 R_X86_64_COPY a 0x0
// CHECK: 0x20236C R_X86_64_COPY b 0x0
// CHECK2: LOAD 0x000356 0x0000000000202356 0x0000000000202356 0x000000 0x000caa RW 0x1000
// CHECK2: DYNAMIC 0x000258 0x0000000000200258 0x0000000000200258 0x0000b0 0x0000b0 R 0x8
// CHECK2: GNU_RELRO 0x000356 0x0000000000202356 0x0000000000202356 0x000000 0x000caa R 0x1
// CHECK2: Section to Segment mapping:
// CHECK2-NEXT: Segment Sections...
// CHECK2-NEXT: 00
// CHECK2-NEXT: 01 .dynsym .gnu.hash .hash .dynamic .dynstr .rela.dyn
// CHECK2-NEXT: 02 .text
// CHECK2-NEXT: 03 .bss.rel.ro .relro_padding
// CHECK2-NEXT: 04 .dynamic
// CHECK2-NEXT: 05 .bss.rel.ro .relro_padding
// CHECK2-NEXT: 06
.text
.global _start
_start:

View File

@@ -10,7 +10,7 @@
# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# SEG: LOAD 0x0001c8 0x00000000002011c8 0x00000000002011c8 0x000001 0x000001 R E 0x1000
# SEG-NEXT: LOAD 0x0001c9 0x00000000002021c9 0x00000000002021c9 0x000001 0x002001 RW 0x1000
# SEG-NEXT: LOAD 0x0001c9 0x00000000002021c9 0x00000000002021c9 0x000001 0x002e37 RW 0x1000
# SEG-NEXT: LOAD 0x0001ca 0x00000000002051ca 0x00000000002051ca 0x000001 0x000002 RW 0x1000
# SEG-NEXT: GNU_RELRO 0x0001c9 0x00000000002021c9 0x00000000002021c9 0x000001 0x002e37 R 0x1
# SEG-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
@@ -24,6 +24,7 @@
# [Nr] Name Type Address Off Size
# CHECK: .data.rel.ro PROGBITS 00000000002021c9 0001c9 000001
# CHECK-NEXT: .bss.rel.ro NOBITS 00000000002021ca 0001ca 002000
# CHECK-NEXT: .relro_padding NOBITS 00000000002041ca 0001ca 000e36
# CHECK-NEXT: .data PROGBITS 00000000002051ca 0001ca 000001
# CHECK-NEXT: .bss NOBITS 00000000002051cb 0001cb 000001

View File

@@ -28,4 +28,4 @@ _start:
.space 0x2000
// CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
// CHECK: GNU_RELRO 0x002150 0x0000000000000150 0x0000000000000150 0x000100 0x000eb0 R 0x1
// CHECK: GNU_RELRO 0x002150 0x0000000000000150 0x0000000000000150 0x000100 0x000100 R 0x1

View File

@@ -24,8 +24,8 @@
// CHECK-NEXT: GNU_RELRO
// CHECK: Section to Segment mapping:
// FULLRELRO: 03 .openbsd.randomdata .dynamic .got .got.plt {{$}}
// PARTRELRO: 03 .openbsd.randomdata .dynamic .got {{$}}
// FULLRELRO: 03 .openbsd.randomdata .dynamic .got .got.plt .relro_padding {{$}}
// PARTRELRO: 03 .openbsd.randomdata .dynamic .got .relro_padding {{$}}
// NORELRO-NOT: GNU_RELRO

View File

@@ -20,6 +20,7 @@
# NOSDATA-NEXT: .tbss
# NOSDATA-NEXT: .dynamic
# NOSDATA-NEXT: .got
# NOSDATA-NEXT: .relro_padding
# NOSDATA-NEXT: .data PROGBITS [[#%x,DATA:]]
# NOSDATA-NEXT: .bss NOBITS [[#%x,BSS:]]
@@ -36,6 +37,7 @@
# CHECK-NEXT: .tbss
# CHECK-NEXT: .dynamic
# CHECK-NEXT: .got
# CHECK-NEXT: .relro_padding
# CHECK-NEXT: .data
# CHECK-NEXT: .sdata PROGBITS [[#%x,SDATA:]]
# CHECK-NEXT: .sbss NOBITS [[#%x,SBSS:]]

View File

@@ -48,11 +48,12 @@ _start:
// CHECK-NEXT: .tdata 00000001
// CHECK-NEXT: .tbss 00000001
// CHECK-NEXT: .data.rel.ro 00000004
// CHECK-NEXT: .relro_padding 00000df5
// CHECK-NEXT: .data 00000002
// CHECK-NEXT: .foo.a 00000001
// CHECK-NEXT: .foo 00000001
// CHECK-NEXT: .bss 00000002
// CHECK-NEXT: .comment 00000008
// CHECK-NEXT: .symtab 00000030
// CHECK-NEXT: .shstrtab 00000075
// CHECK-NEXT: .shstrtab 00000084
// CHECK-NEXT: .strtab 00000008

View File

@@ -7,7 +7,7 @@
# RUN: llvm-readelf -l %t | FileCheck --check-prefix=NONE %s
# NONE: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000245 0x000245 R 0x1000
# NONE-NEXT: LOAD 0x000248 0x0000000000001248 0x0000000000001248 0x000001 0x000001 R E 0x1000
# NONE-NEXT: LOAD 0x000250 0x0000000000002250 0x0000000000002250 0x000090 0x000090 RW 0x1000
# NONE-NEXT: LOAD 0x000250 0x0000000000002250 0x0000000000002250 0x000090 0x000db0 RW 0x1000
# NONE-NEXT: LOAD 0x0002e0 0x00000000000032e0 0x00000000000032e0 0x000001 0x000001 RW 0x1000
## -z separate-code makes text segment (RX) separate.
@@ -16,7 +16,7 @@
# RUN: llvm-readelf -l %t | FileCheck --check-prefix=CODE %s
# CODE: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000245 0x000245 R 0x1000
# CODE-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000001 0x000001 R E 0x1000
# CODE-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000090 0x000090 RW 0x1000
# CODE-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000090 0x001000 RW 0x1000
# CODE-NEXT: LOAD 0x002090 0x0000000000003090 0x0000000000003090 0x000001 0x000001 RW 0x1000
## -z separate-loadable-segments makes all segments separate.
@@ -24,7 +24,7 @@
# RUN: llvm-readelf -l %t | FileCheck --check-prefix=ALL %s
# ALL: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000245 0x000245 R 0x1000
# ALL-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000001 0x000001 R E 0x1000
# ALL-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000090 0x000090 RW 0x1000
# ALL-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000090 0x001000 RW 0x1000
# ALL-NEXT: LOAD 0x003000 0x0000000000003000 0x0000000000003000 0x000001 0x000001 RW 0x1000
nop

View File

@@ -1,11 +1,11 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld %t.o -o %t
# RUN: ld.lld -z norelro %t.o -o %t
# RUN: llvm-readelf -x .init -x .fini -x .init_array -x .fini_array %t | \
# RUN: FileCheck --check-prefixes=CHECK,ORDERED %s
# RUN: ld.lld %t.o --shuffle-sections '*=1' -o %t1
# RUN: ld.lld -z norelro %t.o --shuffle-sections '*=1' -o %t1
# RUN: llvm-readelf -x .init -x .fini -x .init_array -x .fini_array %t1 | \
# RUN: FileCheck --check-prefixes=CHECK,SHUFFLED %s

View File

@@ -10,7 +10,7 @@
# RUN: ld.lld --shuffle-sections='*=1' %t.o -o %t1.out
# RUN: llvm-readelf -x .text %t1.out | FileCheck %s --check-prefix=SHUFFLE1
# SHUFFLE1: Hex dump of section '.text':
# SHUFFLE1-NEXT: 01020403
# SHUFFLE1-NEXT: 030402cc 01
## Test that --shuffle-sections= can be used with --symbol-ordering-file
# RUN: echo "foo" > %t_order.txt
@@ -21,7 +21,7 @@
# SHUFFLE2: Hex dump of section '.text':
# SHUFFLE2-NEXT: 02cccccc 010304
# RUN: ld.lld --symbol-ordering-file %t_order.txt --shuffle-sections='*=3' %t.o -o %t3.out
# RUN: ld.lld -z norelro --symbol-ordering-file %t_order.txt --shuffle-sections='*=3' %t.o -o %t3.out
# RUN: llvm-readelf -x .text %t3.out | FileCheck %s --check-prefix=SHUFFLE3
# SHUFFLE3: Hex dump of section '.text':
# SHUFFLE3-NEXT: 02cccccc 010403

View File

@@ -9,7 +9,7 @@
# CHECK-NEXT: .dynstr {{.*}} A
# CHECK-NEXT: .text {{.*}} AX
# CHECK-NEXT: .dynamic {{.*}} WA
# CHECK-NEXT: foo {{.*}} WA
# CHECK: foo {{.*}} WA
.section foo, "aw"
.byte 0

View File

@@ -23,6 +23,7 @@
# CHECK-NEXT: .text PROGBITS 0000000000201304 000304 000001 00 AX 0 0 4
# CHECK-NEXT: .tdata PROGBITS 0000000000202305 000305 000001 00 WAT 0 0 1
# CHECK-NEXT: .tbss NOBITS 0000000000202306 000306 000002 00 WAT 0 0 1
# CHECK-NEXT: .relro_padding NOBITS 0000000000202306 000306 000cfa 00 WA 0 0 1
# CHECK-NEXT: .data PROGBITS 0000000000203306 000306 000001 00 WA 0 0 1
# CHECK-NEXT: .bss NOBITS 0000000000203307 000307 001800 00 WA 0 0 1
## We spend size(.bss) % MAXPAGESIZE bytes for .bss.
@@ -36,7 +37,7 @@
# CHECK-NEXT: PHDR 0x000040 0x0000000000200040 0x0000000000200040 {{.*}} {{.*}} R 0x8
# CHECK-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000304 0x000304 R 0x1000
# CHECK-NEXT: LOAD 0x000304 0x0000000000201304 0x0000000000201304 0x000001 0x000001 R E 0x1000
# CHECK-NEXT: LOAD 0x000305 0x0000000000202305 0x0000000000202305 0x000001 0x000001 RW 0x1000
# CHECK-NEXT: LOAD 0x000305 0x0000000000202305 0x0000000000202305 0x000001 0x000cfb RW 0x1000
# CHECK-NEXT: LOAD 0x000306 0x0000000000203306 0x0000000000203306 0x000001 0x001801 RW 0x1000
# CHECK-NEXT: LOAD 0x000b07 0x0000000000205b07 0x0000000000205b07 0x000003 0x000005 RW 0x1000