[ELF][PPC] Allow PT_LOAD to have overlapping p_offset ranges

This change affects the non-linker script case (precisely, when the
`SECTIONS` command is not used). It deletes 3 alignments at PT_LOAD
boundaries for the default case: the size of a powerpc64 binary can be
decreased by at most 192kb. The technique can be ported to other
targets.

Let me demonstrate the idea with a maxPageSize=65536 example:

When assigning the address to the first output section of a new PT_LOAD,
if the end p_vaddr of the previous PT_LOAD is 0x10020, we advance to
the next multiple of maxPageSize: 0x20000. The new PT_LOAD will thus
have p_vaddr=0x20000. Because p_offset and p_vaddr are congruent modulo
maxPageSize, p_offset will be 0x20000, leaving a p_offset gap [0x10020,
0x20000) in the output.

Alternatively, if we advance to 0x20020, the new PT_LOAD will have
p_vaddr=0x20020. We can pick either 0x10020 or 0x20020 for p_offset!
Obviously 0x10020 is the choice because it leaves no gap. At runtime,
p_vaddr will be rounded down by pagesize (65536 if
pagesize=maxPageSize). This PT_LOAD will load additional initial
contents from p_offset ranges [0x10000,0x10020), which will also be
loaded by the previous PT_LOAD. This is fine if -z noseparate-code is in
effect or if we are not transiting between executable and non-executable
segments.

ld.bfd -z noseparate-code leverages this technique to keep output small.
This patch implements the technique in lld, which is mostly effective on
targets with large defaultMaxPageSize (AArch64/MIPS/PPC: 65536). The 3
removed alignments can save almost 3*65536 bytes.

Two places that rely on p_vaddr%pagesize = 0 have to be updated.

1) We used to round p_memsz(PT_GNU_RELRO) up to commonPageSize (defaults
  to 4096 on all targets). Now p_vaddr%commonPageSize may be non-zero.
  The updated formula takes account of that factor.
2) Our TP offsets formulae are only correct if p_vaddr%p_align = 0.
  Fix them. See the updated comments in InputSection.cpp for details.

  On targets that we enable the technique (only PPC64 now),
  we can potentially make `p_vaddr(PT_TLS)%p_align(PT_TLS) != 0`
  if `sh_addralign(.tdata) < sh_addralign(.tbss)`

  This exposes many problems in ld.so implementations, especially the
  offsets of dynamic TLS blocks. Known issues:

  FreeBSD 13.0-CURRENT rtld-elf (i386/amd64/powerpc/arm64)
  glibc (HEAD) i386 and x86_64 https://sourceware.org/bugzilla/show_bug.cgi?id=24606
  musl<=1.1.22 on TLS Variant I architectures (aarch64/powerpc64/...)

  So, force p_vaddr%p_align = 0 by rounding dot up to p_align(PT_TLS).

The technique will be enabled (with updated tests) for other targets in
subsequent patches.

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D64906

llvm-svn: 369343
This commit is contained in:
Fangrui Song 2019-08-20 08:34:25 +00:00
parent ebc8fd3c0c
commit 01c7f4b606
35 changed files with 377 additions and 290 deletions

View File

@ -608,27 +608,39 @@ static int64_t getTlsTpOffset(const Symbol &s) {
if (&s == ElfSym::tlsModuleBase)
return 0;
// There are 2 TLS layouts. Among targets we support, x86 uses TLS Variant 2
// while most others use Variant 1. At run time TP will be aligned to p_align.
// Variant 1. TP will be followed by an optional gap (which is the size of 2
// pointers on ARM/AArch64, 0 on other targets), followed by alignment
// padding, then the static TLS blocks. The alignment padding is added so that
// (TP + gap + padding) is congruent to p_vaddr modulo p_align.
//
// Variant 2. Static TLS blocks, followed by alignment padding are placed
// before TP. The alignment padding is added so that (TP - padding -
// p_memsz) is congruent to p_vaddr modulo p_align.
elf::PhdrEntry *tls = Out::tlsPhdr;
switch (config->emachine) {
// Variant 1.
case EM_ARM:
case EM_AARCH64:
// Variant 1. The thread pointer points to a TCB with a fixed 2-word size,
// followed by a variable amount of alignment padding, followed by the TLS
// segment.
return s.getVA(0) + alignTo(config->wordsize * 2, Out::tlsPhdr->p_align);
case EM_386:
case EM_X86_64:
// Variant 2. The TLS segment is located just before the thread pointer.
return s.getVA(0) - alignTo(Out::tlsPhdr->p_memsz, Out::tlsPhdr->p_align);
return s.getVA(0) + config->wordsize * 2 +
((tls->p_vaddr - config->wordsize * 2) & (tls->p_align - 1));
case EM_MIPS:
case EM_PPC:
case EM_PPC64:
// The thread pointer points to a fixed offset from the start of the
// executable's TLS segment. An offset of 0x7000 allows a signed 16-bit
// offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the
// program's TLS segment.
return s.getVA(0) - 0x7000;
// Adjusted Variant 1. TP is placed with a displacement of 0x7000, which is
// to allow a signed 16-bit offset to reach 0x1000 of TCB/thread-library
// data and 0xf000 of the program's TLS segment.
return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)) - 0x7000;
case EM_RISCV:
return s.getVA(0);
return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1));
// Variant 2.
case EM_386:
case EM_X86_64:
return s.getVA(0) - tls->p_memsz -
((-tls->p_vaddr - tls->p_memsz) & (tls->p_align - 1));
default:
llvm_unreachable("unhandled Config->EMachine");
}

View File

@ -2202,21 +2202,64 @@ void Writer<ELFT>::addPhdrForSection(Partition &part, unsigned shType,
part.phdrs.push_back(entry);
}
// The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the
// first section after PT_GNU_RELRO have to be page aligned so that the dynamic
// linker can set the permissions.
// Place the first section of each PT_LOAD to a different page (of maxPageSize).
// This is achieved by assigning an alignment expression to addrExpr of each
// such section.
template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
auto pageAlign = [](OutputSection *cmd) {
if (cmd && !cmd->addrExpr)
cmd->addrExpr = [=] {
return alignTo(script->getDot(), config->maxPageSize);
};
const PhdrEntry *prev;
auto pageAlign = [&](const PhdrEntry *p) {
OutputSection *cmd = p->firstSec;
if (cmd && !cmd->addrExpr) {
// Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid
// padding in the file contents.
//
// When -z separate-code is used we must not have any overlap in pages
// between an executable segment and a non-executable segment. We align to
// the next maximum page size boundary on transitions between executable
// and non-executable segments.
//
// TODO Enable this technique on all targets.
bool enable = config->emachine == EM_PPC64;
if (!enable || (config->zSeparateCode && prev &&
(prev->p_flags & PF_X) != (p->p_flags & PF_X)))
cmd->addrExpr = [] {
return alignTo(script->getDot(), config->maxPageSize);
};
// PT_TLS is at the start of the first RW PT_LOAD. If `p` includes PT_TLS,
// it must be the RW. Align to p_align(PT_TLS) to make sure
// p_vaddr(PT_LOAD)%p_align(PT_LOAD) = 0. Otherwise, if
// sh_addralign(.tdata) < sh_addralign(.tbss), we will set p_align(PT_TLS)
// to sh_addralign(.tbss), while p_vaddr(PT_TLS)=p_vaddr(PT_LOAD) may not
// be congruent to 0 modulo p_align(PT_TLS).
//
// Technically this is not required, but as of 2019, some dynamic loaders
// don't handle p_vaddr%p_align != 0 correctly, e.g. glibc (i386 and
// x86-64) doesn't make runtime address congruent to p_vaddr modulo
// p_align for dynamic TLS blocks (PR/24606), FreeBSD rtld has the same
// bug, musl (TLS Variant 1 architectures) before 1.1.23 handled TLS
// blocks correctly. We need to keep the workaround for a while.
else if (Out::tlsPhdr && Out::tlsPhdr->firstSec == p->firstSec)
cmd->addrExpr = [] {
return alignTo(script->getDot(), config->maxPageSize) +
alignTo(script->getDot() % config->maxPageSize,
Out::tlsPhdr->p_align);
};
else
cmd->addrExpr = [] {
return alignTo(script->getDot(), config->maxPageSize) +
script->getDot() % config->maxPageSize;
};
}
};
for (Partition &part : partitions) {
prev = nullptr;
for (const PhdrEntry *p : part.phdrs)
if (p->p_type == PT_LOAD && p->firstSec)
pageAlign(p->firstSec);
if (p->p_type == PT_LOAD && p->firstSec) {
pageAlign(p);
prev = p;
}
}
}
@ -2342,10 +2385,11 @@ template <class ELFT> void Writer<ELFT>::setPhdrs(Partition &part) {
p->p_align = std::max<uint64_t>(p->p_align, config->maxPageSize);
} else if (p->p_type == PT_GNU_RELRO) {
p->p_align = 1;
// The glibc dynamic loader rounds the size down, so we need to round up
// 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 = alignTo(p->p_memsz, config->commonPageSize);
p->p_memsz = alignTo(p->p_offset + p->p_memsz, config->commonPageSize) -
p->p_offset;
}
}
}

View File

@ -33,9 +33,9 @@
// CHECK-NEXT: Type: SharedObject (0x3)
// CHECK-NEXT: Machine: EM_PPC64 (0x15)
// CHECK-NEXT: Version: 1
// CHECK-NEXT: Entry: 0x10000
// CHECK-NEXT: Entry: 0x1022C
// CHECK-NEXT: ProgramHeaderOffset: 0x40
// CHECK-NEXT: SectionHeaderOffset: 0x200F8
// CHECK-NEXT: SectionHeaderOffset: 0x330
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: 0x2
// CHECK-NEXT: ]
@ -127,8 +127,8 @@
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: SHF_EXECINSTR (0x4)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x10000
// CHECK-NEXT: Offset: 0x10000
// CHECK-NEXT: Address: 0x1022C
// CHECK-NEXT: Offset: 0x22C
// CHECK-NEXT: Size: 12
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@ -147,8 +147,8 @@
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: SHF_WRITE (0x1)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x20000
// CHECK-NEXT: Offset: 0x20000
// CHECK-NEXT: Address: 0x20238
// CHECK-NEXT: Offset: 0x238
// CHECK-NEXT: Size: 96
// CHECK-NEXT: Link: 3
// CHECK-NEXT: Info: 0
@ -177,8 +177,8 @@
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: SHF_WRITE (0x1)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x30000
// CHECK-NEXT: Offset: 0x20060
// CHECK-NEXT: Address: 0x30298
// CHECK-NEXT: Offset: 0x298
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@ -194,7 +194,7 @@
// CHECK-NEXT: SHF_STRINGS (0x20)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
// CHECK-NEXT: Offset: 0x20060
// CHECK-NEXT: Offset: 0x298
// CHECK-NEXT: Size: 8
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@ -211,19 +211,19 @@
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
// CHECK-NEXT: Offset: 0x20068
// CHECK-NEXT: Offset: 0x2A0
// CHECK-NEXT: Size: 48
// CHECK-NEXT: Link: 10
// CHECK-NEXT: Info: 2
// CHECK-NEXT: AddressAlignment: 8
// CHECK-NEXT: EntrySize: 24
// CHECK-NEXT: SectionData (
// LE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
// LE-NEXT: 0010: 00000000 00000000 01000000 00020500 |................|
// LE-NEXT: 0020: 00000200 00000000 00000000 00000000 |................|
// BE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
// BE-NEXT: 0010: 00000000 00000000 00000001 00020005 |................|
// BE-NEXT: 0020: 00000000 00020000 00000000 00000000 |................|
// LE-NEXT: 0000: 00000000 00000000 00000000 00000000
// LE-NEXT: 0010: 00000000 00000000 01000000 00020500
// LE-NEXT: 0020: 38020200 00000000 00000000 00000000
// BE-NEXT: 0000: 00000000 00000000 00000000 00000000
// BE-NEXT: 0010: 00000000 00000000 00000001 00020005
// BE-NEXT: 0020: 00000000 00020238 00000000 00000000
// CHECK-NEXT: )
// CHECK-NEXT: }
// CHECK-NEXT: Section {
@ -233,7 +233,7 @@
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
// CHECK-NEXT: Offset: 0x20098
// CHECK-NEXT: Offset: 0x2D0
// CHECK-NEXT: Size: 84
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@ -255,7 +255,7 @@
// CHECK-NEXT: Flags [ (0x0)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x0
// CHECK-NEXT: Offset: 0x200EC
// CHECK-NEXT: Offset: 0x324
// CHECK-NEXT: Size: 10
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@ -293,9 +293,9 @@
// CHECK-NEXT: }
// CHECK-NEXT: ProgramHeader {
// CHECK-NEXT: Type: PT_LOAD (0x1)
// CHECK-NEXT: Offset: 0x10000
// CHECK-NEXT: VirtualAddress: 0x10000
// CHECK-NEXT: PhysicalAddress: 0x10000
// CHECK-NEXT: Offset: 0x22C
// CHECK-NEXT: VirtualAddress: 0x1022C
// CHECK-NEXT: PhysicalAddress: 0x1022C
// CHECK-NEXT: FileSize: 12
// CHECK-NEXT: MemSize: 12
// CHECK-NEXT: Flags [ (0x5)
@ -306,9 +306,9 @@
// CHECK-NEXT: }
// CHECK-NEXT: ProgramHeader {
// CHECK-NEXT: Type: PT_LOAD (0x1)
// CHECK-NEXT: Offset: 0x20000
// CHECK-NEXT: VirtualAddress: 0x20000
// CHECK-NEXT: PhysicalAddress: 0x20000
// CHECK-NEXT: Offset: 0x238
// CHECK-NEXT: VirtualAddress: 0x20238
// CHECK-NEXT: PhysicalAddress: 0x20238
// CHECK-NEXT: FileSize: 96
// CHECK-NEXT: MemSize: 96
// CHECK-NEXT: Flags [ (0x6)
@ -319,9 +319,9 @@
// CHECK-NEXT: }
// CHECK-NEXT: ProgramHeader {
// CHECK-NEXT: Type: PT_DYNAMIC (0x2)
// CHECK-NEXT: Offset: 0x20000
// CHECK-NEXT: VirtualAddress: 0x20000
// CHECK-NEXT: PhysicalAddress: 0x20000
// CHECK-NEXT: Offset: 0x238
// CHECK-NEXT: VirtualAddress: 0x20238
// CHECK-NEXT: PhysicalAddress: 0x20238
// CHECK-NEXT: FileSize: 96
// CHECK-NEXT: MemSize: 96
// CHECK-NEXT: Flags [ (0x6)
@ -332,11 +332,11 @@
// CHECK-NEXT: }
// CHECK-NEXT: ProgramHeader {
// CHECK-NEXT: Type: PT_GNU_RELRO (0x6474E552)
// CHECK-NEXT: Offset: 0x20000
// CHECK-NEXT: VirtualAddress: 0x20000
// CHECK-NEXT: PhysicalAddress: 0x20000
// CHECK-NEXT: Offset: 0x238
// CHECK-NEXT: VirtualAddress: 0x20238
// CHECK-NEXT: PhysicalAddress: 0x20238
// CHECK-NEXT: FileSize: 96
// CHECK-NEXT: MemSize: 4096
// CHECK-NEXT: MemSize: 3528
// CHECK-NEXT: Flags [ (0x4)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: ]

View File

@ -12,10 +12,10 @@
## FIXME the addend for offset 0x20000 should be TOC base+0x8000+1, not 0x80001.
# CHECK: .rela.dyn {
# CHECK-NEXT: 0x20000 R_PPC64_RELATIVE - 0x8001
# CHECK-NEXT: 0x20008 R_PPC64_RELATIVE - 0x20001
# CHECK-NEXT: 0x20010 R_PPC64_ADDR64 external 0x1
# CHECK-NEXT: 0x20018 R_PPC64_ADDR64 global 0x1
# CHECK-NEXT: 0x303B0 R_PPC64_RELATIVE - 0x8001
# CHECK-NEXT: 0x303B8 R_PPC64_RELATIVE - 0x303B1
# CHECK-NEXT: 0x303C0 R_PPC64_ADDR64 external 0x1
# CHECK-NEXT: 0x303C8 R_PPC64_ADDR64 global 0x1
# CHECK-NEXT: }
.data

View File

@ -63,6 +63,6 @@ caller:
# CHECK-EMPTY:
# CHECK-NEXT: def:
# CHECK-NEXT: addis 2, 12, 2
# CHECK-NEXT: addi 2, 2, -32616
# CHECK-NEXT: addi 2, 2, -32456
# CHECK-NEXT: li 3, 55
# CHECK-NEXT: blr

View File

@ -2,37 +2,37 @@
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s
# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s
# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s
# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \
# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
# RUN: -z separate-code %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s
# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \
# RUN: %t.o -o %t
# RUN: -z separate-code %t.o -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s
# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s
# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \
# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
# RUN: -z separate-code %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
# MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x14): improper alignment for relocation R_PPC64_REL24: 0x19 is not aligned to 4 bytes
# MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x24): improper alignment for relocation R_PPC64_REL24: 0xB is not aligned to 4 bytes
@ -72,19 +72,19 @@ test:
# .branch_lt[0]
# THUNK-LABEL: __long_branch_callee:
# THUNK-NEXT: 10010028: addis 12, 2, 1
# THUNK-NEXT: ld 12, -32768(12)
# THUNK-NEXT: ld 12, -32760(12)
# THUNK-NEXT: mtctr 12
# THUNK-NEXT: bctr
# .branch_lt[1]
# THUNK-LABEL: __long_branch_tail_callee:
# THUNK-NEXT: 10010038: addis 12, 2, 1
# THUNK-NEXT: ld 12, -32760(12)
# THUNK-NEXT: ld 12, -32752(12)
# THUNK-NEXT: mtctr 12
# THUNK-NEXT: bctr
# The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768.
# Name Type Address Off Size
# BRANCHLT: .got PROGBITS 0000000010020000 020000 000008
# BRANCHLT: .branch_lt PROGBITS 0000000010030000 030000 000010
# BRANCHLT: .branch_lt PROGBITS 0000000010030008 020008 000010
# BRANCHLT-NOT: .plt

View File

@ -28,5 +28,7 @@ test:
# Verify that we don't overwrite any of the extended opcode bits on a DQ form
# instruction.
# CHECK-LABEL: test
# CHECK: lxv 3, -32768(3)
# CHECK: stxv 3, -32768(3)
# CHECK: addis 3, 2, 1
# CHECK-NEXT: lxv 3, -32752(3)
# CHECK-NEXT: addis 3, 2, 1
# CHECK-NEXT: stxv 3, -32752(3)

View File

@ -137,15 +137,15 @@ k:
// OutputRelocs-NEXT: R_PPC64_DTPMOD64
// The got entry for i is at .got+8*3 = 0x420510
// The got entry for i is at .got+8*1 = 0x4209e0
// i@dtprel = 1024 - 0x8000 = -31744 = 0xffffffffffff8400
// HEX-LE: section '.got':
// HEX-LE-NEXT: 4204f8 f8844200 00000000 00000000 00000000
// HEX-LE-NEXT: 420508 00000000 00000000
// HEX-LE-NEXT: 4209d8 d8894200 00000000 00000000 00000000
// HEX-LE-NEXT: 4209e8 00000000 00000000
// HEX-BE: section '.got':
// HEX-BE-NEXT: 4204f8 00000000 004284f8 00000000 00000000
// HEX-BE-NEXT: 420508 00000000 00000000
// HEX-BE-NEXT: 4209d8 00000000 004289d8 00000000 00000000
// HEX-BE-NEXT: 4209e8 00000000 00000000
// Dis: test:
// Dis: addi 4, 3, -31744

View File

@ -34,12 +34,12 @@ _start:
.Lfunc_end0:
.size _start, .Lfunc_end0-.Lfunc_begin0
# NM-DAG: 0000000010028000 d .TOC.
# NM-DAG: 0000000010010000 T _start
# NM-DAG: 00000000100281f0 d .TOC.
# NM-DAG: 00000000100101d0 T _start
# 0x10010000 = (4097<<16) + 0
# CHECK: 10010000: lis 4, 4097
# CHECK-NEXT: 10010004: addi 4, 4, 0
# .TOC. - _start = (2<<16) - 32768
# CHECK-NEXT: 10010008: lis 5, 2
# CHECK-NEXT: 1001000c: addi 5, 5, -32768
# 0x100101d0 = (4097<<16) + 464
# CHECK: 100101d0: lis 4, 4097
# CHECK-NEXT: 100101d4: addi 4, 4, 464
# .TOC. - _start = (2<<16) - 32736
# CHECK-NEXT: 100101d8: lis 5, 2
# CHECK-NEXT: 100101dc: addi 5, 5, -32736

View File

@ -6,7 +6,7 @@
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 16 bytes
# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8009 is not aligned to 16 bytes
.global test
.p2align 4
@ -21,6 +21,6 @@ test:
lxv 3, qword@toc@l(3)
blr
.p2align 4
.comm pad, 1, 1
.comm qword, 16, 1

View File

@ -6,7 +6,7 @@
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 4 bytes
# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8009 is not aligned to 4 bytes
.global test
.p2align 4
@ -21,6 +21,6 @@ test:
lwa 3, word@toc@l(3)
blr
.p2align 4
.comm pad, 1, 1
.comm word, 4, 1

View File

@ -4,13 +4,13 @@
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func-global-entry.s -o %t2.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func-local-entry.s -o %t3.o
// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o %t3.o -o %t
// RUN: llvm-objdump -d %t | FileCheck %s
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func-global-entry.s -o %t2.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func-local-entry.s -o %t3.o
// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o %t3.o -o %t
// RUN: llvm-objdump -d %t | FileCheck %s
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
.text
.abiversion 2
@ -69,12 +69,12 @@ glob:
# foo_external_diff+8. Also check that foo_external_same has no global entry
# point and we branch to start of foo_external_same.
// CHECK: _start:
// CHECK: 10010020: {{.*}} bl .+144
// CHECK: 10010034: {{.*}} bl .+84
// CHECK: foo_external_diff:
// CHECK-NEXT: 10010080: {{.*}} addis 2, 12, 1
// CHECK-NEXT: 10010084: {{.*}} addi 2, 2, 32640
// CHECK-NEXT: 10010088: {{.*}} addis 5, 2, 1
// CHECK: foo_external_same:
// CHECK-NEXT: 100100b0: {{.*}} add 3, 4, 3
// CHECK-LABEL: _start:
// CHECK: 100101f0: bl .+144
// CHECK: 10010204: bl .+84
// CHECK-LABEL: foo_external_diff:
// CHECK-NEXT: 10010250: addis 2, 12, 2
// CHECK-NEXT: 10010254: addi 2, 2, -32696
// CHECK-NEXT: 10010258: addis 5, 2, 1
// CHECK-LABEL: foo_external_same:
// CHECK-NEXT: 10010280: add 3, 4, 3

View File

@ -14,43 +14,43 @@
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s
# NM-DAG: 0000000010028000 d .TOC.
# NM-DAG: 0000000010010000 T ifunc
# NM-DAG: 0000000010010004 T ifunc2
# NM-DAG: 0000000010028248 d .TOC.
# NM-DAG: 00000000100101f8 T ifunc
# NM-DAG: 00000000100101fc T ifunc2
# SECTIONS: .plt NOBITS 0000000010030000
# SECTIONS: .plt NOBITS 0000000010030250 000250 000010 00 WA 0 0 8
# __plt_ifunc - . = 0x10010020 - 0x10010010 = 16
# __plt_ifunc2 - . = 0x10010044 - 0x10010018 = 28
# __plt_ifunc - . = 0x10010218 - 0x10010208 = 16
# __plt_ifunc2 - . = 0x1001022c - 0x10010210 = 28
# CHECK: _start:
# CHECK-NEXT: addis 2, 12, 1
# CHECK-NEXT: addi 2, 2, 32760
# CHECK-NEXT: 10010010: bl .+16
# CHECK-NEXT: addis 2, 12, 2
# CHECK-NEXT: addi 2, 2, -32696
# CHECK-NEXT: 10010208: bl .+16
# CHECK-NEXT: ld 2, 24(1)
# CHECK-NEXT: 10010018: bl .+28
# CHECK-NEXT: 10010210: bl .+28
# CHECK-NEXT: ld 2, 24(1)
# .plt[0] - .TOC. = 0x10030000 - 0x10028000 = (1<<16) - 32768
# .plt[0] - .TOC. = 0x10030250 - 0x10028248 = (1<<16) - 32760
# CHECK: __plt_ifunc:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32768(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
# .plt[1] - .TOC. = 0x10030000+8 - 0x10028000 = (1<<16) - 32760
# CHECK: __plt_ifunc2:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32760(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
# .plt[1] - .TOC. = 0x10030250+8 - 0x10028248 = (1<<16) - 32752
# CHECK: __plt_ifunc2:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32752(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
## Check that we emit 2 R_PPC64_IRELATIVE in .rela.dyn.
## glibc powerpc64 does not eagerly resolve R_PPC64_IRELATIVE if they are in .rela.plt.
# REL: .rela.dyn {
# REL-NEXT: 0x10030000 R_PPC64_IRELATIVE - 0x10010000
# REL-NEXT: 0x10030008 R_PPC64_IRELATIVE - 0x10010004
# REL-NEXT: 0x10030250 R_PPC64_IRELATIVE - 0x100101F8
# REL-NEXT: 0x10030258 R_PPC64_IRELATIVE - 0x100101FC
# REL-NEXT: }
.type ifunc STT_GNU_IFUNC

View File

@ -1,14 +1,14 @@
// REQUIRES: ppc
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
// RUN: ld.lld -shared %t.o -o %t.so
// RUN: ld.lld -shared %t.o -z separate-code -o %t.so
// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s
// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s
// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: ld.lld -shared %t.o -o %t.so
// RUN: ld.lld -shared %t.o -z separate-code -o %t.so
// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s
// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s

View File

@ -1,7 +1,7 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=ppc64le %s -o %t.o
# RUN: ld.lld %t.o -o %t
# RUN: ld.lld %t.o -z separate-code -o %t
# RUN: llvm-nm %t | FileCheck %s
# CHECK-DAG: 0000000010010000 t __long_branch_callee

View File

@ -1,13 +1,13 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
# RUN: ld.lld --no-toc-optimize %t.o -o %t
# RUN: ld.lld --no-toc-optimize -z separate-code %t.o -o %t
# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
# RUN: llvm-readelf -x .branch_lt %t | FileCheck %s -check-prefix=BRANCH-LE
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
# RUN: ld.lld --no-toc-optimize %t.o -o %t
# RUN: ld.lld --no-toc-optimize -z separate-code %t.o -o %t
# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
# RUN: llvm-readelf -x .branch_lt %t | FileCheck %s -check-prefix=BRANCH-BE
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
@ -82,13 +82,13 @@ a:
# CHECK: 12010038: bl .+16
# BRANCH-LE: section '.branch_lt':
# BRANCH-LE-NEXT: 0x12030008 08000110 00000000
# BRANCH-LE-NEXT: 0x12030018 08000110 00000000
# BRANCH-BE: section '.branch_lt':
# BRANCH-BE-NEXT: 0x12030008 00000000 10010008
# BRANCH-BE-NEXT: 0x12030018 00000000 10010008
# .branch_lt - .TOC. = 0x12030008 - 0x12028000 = (1<<16) - 32760
# .branch_lt - .TOC. = 0x12030018 - 0x12028000 = (1<<16) - 32744
# CHECK: __long_branch_callee:
# CHECK-NEXT: 12010048: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32760(12)
# CHECK-NEXT: ld 12, -32744(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr

View File

@ -15,8 +15,8 @@
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
## DT_PLTGOT points to .plt
# SEC: .plt NOBITS 0000000010030000 030000 000018
# SEC: 0x0000000000000003 (PLTGOT) 0x10030000
# SEC: .plt NOBITS 00000000100303e8 0003e8 000018
# SEC: 0x0000000000000003 (PLTGOT) 0x100303e8
## .plt[0] holds the address of _dl_runtime_resolve.
## .plt[1] holds the link map.
@ -24,12 +24,12 @@
# RELOC: 0x10030010 R_PPC64_JMP_SLOT foo 0x0
# CHECK: _start:
# CHECK: 10010008: bl .+16
# CHECK: 10010298: bl .+16
# CHECK-LABEL: 0000000010010018 __plt_foo:
# CHECK-LABEL: 00000000100102a8 __plt_foo:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 0
# CHECK-NEXT: ld 12, 32560(12)
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32744(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr

View File

@ -2,11 +2,11 @@
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t
# RUN: ld.lld %t -o %t2
# RUN: llvm-objdump -d %t2 | FileCheck %s
# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
# RUN: ld.lld %t -o %t2
# RUN: llvm-objdump -d %t2 | FileCheck %s
# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s
# CHECK: Disassembly of section .text:
# CHECK-EMPTY:
@ -19,9 +19,9 @@ _start:
li 3,42
sc
# CHECK: 10010000: {{.*}} li 0, 1
# CHECK: 10010004: {{.*}} li 3, 42
# CHECK: 10010008: {{.*}} sc
# CHECK: 10010158: li 0, 1
# CHECK: 1001015c: li 3, 42
# CHECK: 10010160: sc
.global bar
bar:
@ -31,8 +31,8 @@ bar:
nop
blr
# CHECK: 1001000c: {{.*}} bl .-12
# CHECK: 10010010: {{.*}} nop
# CHECK: 10010014: {{.*}} bl .-20
# CHECK: 10010018: {{.*}} nop
# CHECK: 1001001c: {{.*}} blr
# CHECK: 10010164: bl .-12
# CHECK-NEXT: nop
# CHECK-NEXT: 1001016c: bl .-20
# CHECK-NEXT: nop
# CHECK-NEXT: blr

View File

@ -48,11 +48,11 @@ rel64:
# REL-NEXT: 0x28 R_PPC64_REL32 .REL32_AND_REL64 0x0
# REL-NEXT: }
# SEC: .REL32_AND_REL64 PROGBITS 0000000010010020
# SEC: .REL32_AND_REL64 PROGBITS 00000000100101b4
## CIE Personality Address: 0x10010020-(0x10000168+2)+4 = 0xfeba
## FDE PC Begin: 0x10010020-(0x10000178+8) = 0xfea0
## CIE Personality Address: 0x100101b4-(0x10000168+2)+4 = 0x1004e
## FDE PC Begin: 0x100101b4-(0x10000178+8) = 0x10034
# HEX: section '.eh_frame':
# HEX-NEXT: 0x10000158
# HEX-NEXT: 0x10000168 {{....}}bafe 00000000
# HEX-NEXT: 0x10000178 {{[0-9a-f]+}} {{[0-9a-f]+}} a0fe0000
# HEX-NEXT: 0x10000168 {{....}}4e00 01000000 0000{{....}}
# HEX-NEXT: 0x10000178 {{[0-9a-f]+}} {{[0-9a-f]+}} 34000100

View File

@ -26,31 +26,31 @@ _start:
ld 1, .L1@toc@l(2)
# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_LO_DS:
# CHECK: 1001000c: ld 1, -32768(2)
# CHECK: ld 1, -32768(2)
.section .R_PPC64_TOC16_LO,"ax",@progbits
addi 1, 2, .L1@toc@l
# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_LO:
# CHECK: 10010010: addi 1, 2, -32768
# CHECK: addi 1, 2, -32768
.section .R_PPC64_TOC16_HI,"ax",@progbits
addis 1, 2, .L1@toc@h
# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_HI:
# CHECK: 10010014: addis 1, 2, -1
# CHECK: addis 1, 2, -1
.section .R_PPC64_TOC16_HA,"ax",@progbits
addis 1, 2, .L1@toc@ha
# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_HA:
# CHECK: 10010018: addis 1, 2, 0
# CHECK: addis 1, 2, 0
.section .R_PPC64_ADDR16_LO,"ax",@progbits
li 1, .Lfoo@l
# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_LO:
# CHECK: li 1, 0
# CHECK: li 1, 464
.section .R_PPC64_ADDR16_HI,"ax",@progbits
li 1, .Lfoo@h
@ -91,11 +91,11 @@ _start:
.section .R_PPC64_TOC,"a",@progbits
.quad .TOC.@tocbase
# SEC: .got PROGBITS 0000000010020000
# SEC: .got PROGBITS 0000000010020208
## tocbase = .got+0x8000 = 0x10028000
## tocbase = .got+0x8000 = 0x10028208
# DATALE-LABEL: section '.R_PPC64_TOC':
# DATALE: 00800210 00000000
# DATALE: 08820210 00000000
# DATABE-LABEL: section '.R_PPC64_TOC':
# DATABE: 00000000 10028000
# DATABE: 00000000 10028208

View File

@ -1,7 +1,7 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
# RUN: ld.lld --no-toc-optimize -shared %t.o -o %t
# RUN: ld.lld --no-toc-optimize -shared -z separate-code %t.o -o %t
# RUN: llvm-objdump -d -start-address=0x10000 -stop-address=0x10018 %t | FileCheck %s -check-prefix=CALLEE_DUMP
# RUN: llvm-objdump -d -start-address=0x2010020 -stop-address=0x2010070 %t | FileCheck %s -check-prefix=CALLER_DUMP
# RUN: llvm-readelf --sections %t | FileCheck %s -check-prefix=SECTIONS
@ -92,11 +92,10 @@ b:
# CALLER_DUMP: 2010020: {{.*}} addis 2, 12, 2
# CALLER_DUMP: 2010038: {{.*}} bl .+56
# Verify the thunks contents: TOC-pointer + offset = .branch_lt[0]
# 0x20280F0 + 32560 = 0x2030020
## .branch_lt[0] - .TOC. =
# CALLER_DUMP: __long_branch_callee:
# CALLER_DUMP: 2010060: {{.*}} addis 12, 2, 0
# CALLER_DUMP: 2010064: {{.*}} ld 12, 32560(12)
# CALLER_DUMP: 2010060: {{.*}} addis 12, 2, 1
# CALLER_DUMP: 2010064: {{.*}} ld 12, -32712(12)
# CALLER_DUMP: 2010068: {{.*}} mtctr 12
# CALLER_DUMP: 201006c: {{.*}} bctr
@ -104,11 +103,11 @@ b:
# .plt section has a 2 entry header and a single entry for the long branch.
# [Nr] Name Type Address Off Size
# SECTIONS: [10] .got PROGBITS 00000000020200f0 20200f0 000008
# SECTIONS: [13] .plt NOBITS 0000000002030008 2030008 000018
# SECTIONS: [14] .branch_lt NOBITS 0000000002030020 2030008 000008
# SECTIONS: [13] .plt NOBITS 0000000002030110 2020110 000018
# SECTIONS: [14] .branch_lt NOBITS 0000000002030128 2020110 000008
# There is a relative dynamic relocation for (.plt + 16 bytes), with a base
# address equal to callees local entry point (0x10000 + 8).
# DYNRELOC: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 3 entries:
# DYNRELOC: Offset Info Type Symbol's Value
# DYNRELOC: 0000000002030020 0000000000000016 R_PPC64_RELATIVE 10008
# DYNRELOC: 0000000002030128 0000000000000016 R_PPC64_RELATIVE 10008

View File

@ -16,12 +16,12 @@
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
# GD-REL: .rela.dyn {
# GD-REL-NEXT: 0x200F0 R_PPC64_DTPMOD64 a 0x0
# GD-REL-NEXT: 0x200F8 R_PPC64_DTPREL64 a 0x0
# GD-REL-NEXT: 0x20100 R_PPC64_DTPMOD64 b 0x0
# GD-REL-NEXT: 0x20108 R_PPC64_DTPREL64 b 0x0
# GD-REL-NEXT: 0x20110 R_PPC64_DTPMOD64 c 0x0
# GD-REL-NEXT: 0x20118 R_PPC64_DTPREL64 c 0x0
# GD-REL-NEXT: 0x20540 R_PPC64_DTPMOD64 a 0x0
# GD-REL-NEXT: 0x20548 R_PPC64_DTPREL64 a 0x0
# GD-REL-NEXT: 0x20550 R_PPC64_DTPMOD64 b 0x0
# GD-REL-NEXT: 0x20558 R_PPC64_DTPREL64 b 0x0
# GD-REL-NEXT: 0x20560 R_PPC64_DTPMOD64 c 0x0
# GD-REL-NEXT: 0x20568 R_PPC64_DTPREL64 c 0x0
# GD-REL-NEXT: }
## &DTPMOD(a) - .TOC. = &.got[0] - (.got+0x8000) = -32768
@ -59,8 +59,8 @@
# LE-NEXT: addi 3, 3, -28656
# IE-REL: .rela.dyn {
# IE-REL-NEXT: 0x100200C0 R_PPC64_TPREL64 b 0x0
# IE-REL-NEXT: 0x100200C8 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: 0x10020418 R_PPC64_TPREL64 b 0x0
# IE-REL-NEXT: 0x10020420 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: }
## a is relaxed to use LE.

View File

@ -23,10 +23,10 @@
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
# IE-REL: .rela.dyn {
# IE-REL-NEXT: 0x200B0 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: 0x200C0 R_PPC64_TPREL64 i 0x0
# IE-REL-NEXT: 0x200C8 R_PPC64_TPREL64 l 0x0
# IE-REL-NEXT: 0x200B8 R_PPC64_TPREL64 s 0x0
# IE-REL-NEXT: 0x204A0 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: 0x204B0 R_PPC64_TPREL64 i 0x0
# IE-REL-NEXT: 0x204B8 R_PPC64_TPREL64 l 0x0
# IE-REL-NEXT: 0x204A8 R_PPC64_TPREL64 s 0x0
# IE-REL-NEXT: }
# INPUT-REL: R_PPC64_GOT_TPREL16_HA c 0x0

View File

@ -0,0 +1,34 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
# RUN: ld.lld %t.o -o %t
# RUN: llvm-readelf -S -l %t | FileCheck --check-prefix=SEC %s
# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DIS %s
# SEC: Name Type Address Off Size ES Flg Lk Inf Al
# SEC: .tdata PROGBITS 0000000010020300 000300 000001 00 WAT 0 0 1
# SEC: .tbss NOBITS 0000000010020400 000301 000008 00 WAT 0 0 256
# SEC: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# SEC: TLS 0x000300 0x0000000010020300 0x0000000010020300 0x000001 0x000108 R 0x100
## We currently have a hack in Writer.cpp:fixSectionAlignments() to force
## p_vaddr(PT_TLS)%p_align(PT_TLS)=0, to work around bugs in some dynamic loaders.
## p_vaddr rounded down to p_align has TP offset -0x7000.
## The first address of PT_TLS (p_vaddr) has TP offset (p_vaddr%p_align - 0x7000).
## Once we delete the hack, it is likely p_vaddr%p_align != 0.
## a@tprel = st_value(a) + p_vaddr%p_align - 0x7000 = .tbss-.tdata + p_vaddr%p_align - 0x7000
## = 0x10020400-0x10020300 + 0 - 0x7000 = -28416
# DIS: ld 3, -28416(13)
ld 3, a@tprel(13)
.section .tdata,"awT"
.byte 0
.section .tbss,"awT"
.p2align 8
a:
.quad 0

View File

@ -1,4 +1,5 @@
# REQUIRES: ppc
# XFAIL: *
# RUN: llvm-readelf -relocations --wide %p/Inputs/ppc64le-quadword-ldst.o | FileCheck --check-prefix=QuadInputRelocs %s

View File

@ -4,12 +4,15 @@
# RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so
# RUN: ld.lld -shared -soname=t2.so %t2.o -o %t2.so
## Place all sections in the same segment so that .text and .TOC. are on the same page.
# RUN: echo 'PHDRS { all PT_LOAD; }' > %t.script
#
# RUN: ld.lld %t2.so %t.o -o %t
# RUN: ld.lld %t2.so %t.o -T %t.script -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=Dis %s
#
# RUN: ld.lld --no-toc-optimize %t2.so %t.o -o %t
# RUN: ld.lld %t2.so %t.o -T %t.script --no-toc-optimize -o %t
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NoOpt %s
# InputRelocs: Relocation section '.rela.text'
@ -39,18 +42,18 @@ bytes:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: lbz 3, 32624(2)
# Dis-NEXT: lbz 3, -32752(2)
# Dis-NEXT: nop
# Dis-NEXT: stb 3, 32625(2)
# Dis-NEXT: stb 3, -32751(2)
# Dis-NEXT: blr
# NoOpt-LABEL: bytes:
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lbz 3, 32624(3)
# NoOpt-NEXT: lbz 3, -32752(3)
# NoOpt-NEXT: addis 4, 2, 0
# NoOpt-NEXT: stb 3, 32625(4)
# NoOpt-NEXT: stb 3, -32751(4)
# NoOpt-NEXT: blr
.global halfs
@ -73,22 +76,22 @@ halfs:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: lhz 3, 32626(2)
# Dis-NEXT: lhz 3, -32750(2)
# Dis-NEXT: nop
# Dis-NEXT: lha 4, 32626(2)
# Dis-NEXT: lha 4, -32750(2)
# Dis-NEXT: nop
# Dis-NEXT: sth 4, 32628(2)
# Dis-NEXT: sth 4, -32748(2)
# Dis-NEXT: blr
# NoOpt-LABEL: halfs:
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lhz 3, 32626(3)
# NoOpt-NEXT: lhz 3, -32750(3)
# NoOpt-NEXT: addis 4, 2, 0
# NoOpt-NEXT: lha 4, 32626(4)
# NoOpt-NEXT: lha 4, -32750(4)
# NoOpt-NEXT: addis 5, 2, 0
# NoOpt-NEXT: sth 4, 32628(5)
# NoOpt-NEXT: sth 4, -32748(5)
# NoOpt-NEXT: blr
@ -112,22 +115,22 @@ words:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: lwz 3, 32632(2)
# Dis-NEXT: lwz 3, -32744(2)
# Dis-NEXT: nop
# Dis-NEXT: lwa 4, 32632(2)
# Dis-NEXT: lwa 4, -32744(2)
# Dis-NEXT: nop
# Dis-NEXT: stw 4, 32636(2)
# Dis-NEXT: stw 4, -32740(2)
# Dis-NEXT: blr
# NoOpt-LABEL: words
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lwz 3, 32632(3)
# NoOpt-NEXT: lwz 3, -32744(3)
# NoOpt-NEXT: addis 4, 2, 0
# NoOpt-NEXT: lwa 4, 32632(4)
# NoOpt-NEXT: lwa 4, -32744(4)
# NoOpt-NEXT: addis 5, 2, 0
# NoOpt-NEXT: stw 4, 32636(5)
# NoOpt-NEXT: stw 4, -32740(5)
# NoOpt-NEXT: blr
.global doublewords
@ -149,18 +152,18 @@ doublewords:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: ld 3, 32640(2)
# Dis-NEXT: ld 3, -32736(2)
# Dis-NEXT: nop
# Dis-NEXT: std 3, 32648(2)
# Dis-NEXT: std 3, -32728(2)
# Dis-NEXT: blr
# NoOpt-LABEL: doublewords
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: ld 3, 32640(3)
# NoOpt-NEXT: ld 3, -32736(3)
# NoOpt-NEXT: addis 4, 2, 0
# NoOpt-NEXT: std 3, 32648(4)
# NoOpt-NEXT: std 3, -32728(4)
# NoOpt-NEXT: blr
.global vec_dq
@ -182,18 +185,18 @@ vec_dq:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: lxv 3, 32656(2)
# Dis-NEXT: lxv 3, -32720(2)
# Dis-NEXT: nop
# Dis-NEXT: stxv 3, 32672(2)
# Dis-NEXT: stxv 3, -32704(2)
# Dis-NEXT: blr
# NoOpt-LABEL: vec_dq:
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lxv 3, 32656(3)
# NoOpt-NEXT: lxv 3, -32720(3)
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: stxv 3, 32672(3)
# NoOpt-NEXT: stxv 3, -32704(3)
# NoOpt-NEXT: blr
.global vec_ds
@ -218,26 +221,26 @@ vec_ds:
# Dis-NEXT: addis
# Dis-NEXT: addi
# Dis-NEXT: nop
# Dis-NEXT: lxsd 3, 32656(2)
# Dis-NEXT: lxsd 3, -32720(2)
# Dis-NEXT: nop
# Dis-NEXT: stxsd 3, 32672(2)
# Dis-NEXT: stxsd 3, -32704(2)
# Dis-NEXT: nop
# Dis-NEXT: lxssp 3, 32656(2)
# Dis-NEXT: lxssp 3, -32720(2)
# Dis-NEXT: nop
# Dis-NEXT: stxssp 3, 32672(2)
# Dis-NEXT: stxssp 3, -32704(2)
# Dis-NEXT: blr
# NoOpt-LABEL: vec_ds:
# NoOpt-NEXT: addis
# NoOpt-NEXT: addi
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lxsd 3, 32656(3)
# NoOpt-NEXT: lxsd 3, -32720(3)
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: stxsd 3, 32672(3)
# NoOpt-NEXT: stxsd 3, -32704(3)
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: lxssp 3, 32656(3)
# NoOpt-NEXT: lxssp 3, -32720(3)
# NoOpt-NEXT: addis 3, 2, 0
# NoOpt-NEXT: stxssp 3, 32672(3)
# NoOpt-NEXT: stxssp 3, -32704(3)
# NoOpt-NEXT: blr

View File

@ -61,17 +61,16 @@ _start:
# The .TOC. symbol represents the TOC base address: .got + 0x8000 = 0x10028000,
# which is stored in the first entry of .got
# NM: 0000000010028000 d .TOC.
# NM: 0000000010030000 D global_a
# NM: 00000000100281e8 d .TOC.
# NM: 00000000100301f0 D global_a
# HEX-LE: section '.got':
# HEX-LE-NEXT: 0x10020000 00800210 00000000
# HEX-LE-NEXT: 0x100201e8 e8810210 00000000
# HEX-BE: section '.got':
# HEX-BE-NEXT: 0x10020000 00000000 10028000
# HEX-BE-NEXT: 0x100201e8 00000000 100281e8
# r2 stores the TOC base address. To access global_a with r3, it
# computes the address with TOC plus an offset.
# The offset global_a - .TOC. = 0x10030000 - 0x10028000 = 0x8000
# gets materialized as (1 << 16) - 32768.
# global_a - .TOC. = 0x100301f0 - 0x100281e8 = (1 << 16) - 32760
# CHECK: _start:
# CHECK: 10010008: addis 3, 2, 1
# CHECK-NEXT: 1001000c: addi 3, 3, -32768
# CHECK: 100101d0: addis 3, 2, 1
# CHECK-NEXT: 100101d4: addi 3, 3, -32760

View File

@ -1,7 +1,7 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unkown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
# RUN: ld.lld -shared %t.o -o %t.so
# RUN: ld.lld -shared -soname=t.so %t.o -o %t.so
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax.s -o %t2.o
# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefix=RELOCS %s
@ -23,20 +23,20 @@
# RELOCS-NEXT: 0x14 R_PPC64_TOC16_LO_DS .toc 0x10
# RELOCS-NEXT: }
# SECTIONS: .got PROGBITS 0000000010020090
# SECTIONS: .toc PROGBITS 0000000010020090
# SECTIONS: .got PROGBITS 00000000100202f8
# SECTIONS: .toc PROGBITS 00000000100202f8
# NM: 0000000010030000 D default
# NM: 0000000010030310 D default
# .LCONST1 is .toc[0].
# .LCONST1 - (.got+0x8000) = 0x10020090 - (0x10020090+0x8000) = -32768
# .LCONST1 - (.got+0x8000) = 0x10020350 - (0x10020350+0x8000) = -32768
# CHECK: nop
# CHECK: lwa 3, -32768(2)
addis 3, 2, .LCONST1@toc@ha
lwa 3, .LCONST1@toc@l(3)
# .LCONST2 is .toc[1]
# .LCONST2 - (.got+0x8000) = 0x10020098 - (0x10020090+0x8000) = -32760
# .LCONST2 - (.got+0x8000) = 0x10020358 - (0x10020350+0x8000) = -32760
# CHECK: nop
# CHECK: ld 4, -32760(2)
addis 4, 2, .LCONST2@toc@ha
@ -45,8 +45,8 @@
# .Ldefault is .toc[2]. `default` is not preemptable when producing an executable.
# After toc-indirection to toc-relative relaxation, it is loaded using an
# offset relative to r2.
# CHECK: nop
# CHECK: addi 5, 2, 32624
# CHECK: addis 5, 2, 1
# CHECK: addi 5, 5, -32744
# CHECK: lwa 5, 0(5)
addis 5, 2, .Ldefault@toc@ha
ld 5, .Ldefault@toc@l(5)

View File

@ -13,16 +13,16 @@
## still perform toc-indirect to toc-relative relaxation because the distance
## to the address of the canonical PLT is fixed.
# SEC: .text PROGBITS 0000000010010000
# SEC: .plt NOBITS 0000000010030000
# SEC: 0000000010010010 0 FUNC GLOBAL DEFAULT 3 ifunc
# SEC: .text PROGBITS 00000000100101e0
# SEC: .plt NOBITS 0000000010030200
# SEC: 00000000100101f0 0 FUNC GLOBAL DEFAULT 3 ifunc
## .toc[0] stores the address of the canonical PLT.
# HEX: section '.toc':
# HEX-NEXT: 0x10020000 10000110 00000000
# HEX-NEXT: 0x100201f8 f0010110 00000000
# REL: .rela.dyn {
# REL-NEXT: 0x10030000 R_PPC64_IRELATIVE - 0x10010008
# REL-NEXT: 0x10030200 R_PPC64_IRELATIVE - 0x100101e8
# REL-NEXT: }
# DIS: addi 3, 3,

View File

@ -17,15 +17,15 @@
# SECTIONS: .rodata PROGBITS 00000000100001c8
# HEX-LE: section '.toc':
# HEX-LE-NEXT: 10020008 c8010010 00000000
# HEX-LE-NEXT: 10020228 c8010010 00000000
# HEX-BE: section '.toc':
# HEX-BE-NEXT: 10020008 00000000 100001c8
# HEX-BE-NEXT: 10020228 00000000 100001c8
# CHECK-LABEL: _start
# CHECK: clrldi 3, 3, 62
# CHECK-NEXT: addis 4, 2, -2
# CHECK-NEXT: addi 4, 4, -32312
# CHECK-NEXT: addis 4, 2, -3
# CHECK-NEXT: addi 4, 4, 32680
# CHECK-NEXT: sldi 3, 3, 2
.text

View File

@ -1,21 +1,23 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
# RUN: ld.lld -shared %t.o -o %t.so
# RUN: ld.lld -shared -soname=t.so %t.o -o %t.so
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax.s -o %t2.o
# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefixes=RELOCS-LE,RELOCS %s
# RUN: ld.lld %t1.o %t2.o %t.so -o %t
# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=COMMON,EXE %s
# RUN: ld.lld -shared %t1.o %t2.o %t.so -o %t2.so
# RUN: llvm-objdump -d --no-show-raw-insn %t2.so | FileCheck --check-prefixes=COMMON,SHARED %s
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
# RUN: ld.lld -shared %t.o -o %t.so
# RUN: ld.lld -shared -soname=t.so %t.o -o %t.so
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-toc-relax.s -o %t2.o
# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefixes=RELOCS-BE,RELOCS %s
# RUN: ld.lld %t1.o %t2.o %t.so -o %t
# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=COMMON,EXE %s
# RUN: ld.lld -shared %t1.o %t2.o %t.so -o %t2.so
@ -50,22 +52,22 @@
# RELOCS-NEXT: 0x18 R_PPC64_ADDR64 default 0x0
# RELOCS-NEXT: }
# NM-DAG: 0000000010030000 D default
# NM-DAG: 0000000010030000 d hidden
# NM-DAG: 0000000010040000 d hidden2
# NM-DAG: 00000000100303a0 D default
# NM-DAG: 00000000100303a0 d hidden
# NM-DAG: 00000000100403a0 d hidden2
# 'hidden' is non-preemptable. It is relaxed.
# address(hidden) - (.got+0x8000) = 0x10030000 - (0x100200c0+0x8000) = 32576
# COMMON: nop
# COMMON: addi 3, 2, 32576
# address(hidden) - (.got+0x8000) = 0x100303a0 - (0x10020380+0x8000) = (1<<16) - 32736
# COMMON: addis 3, 2, 1
# COMMON: addi 3, 3, -32736
# COMMON: lwa 3, 0(3)
addis 3, 2, .Lhidden@toc@ha
ld 3, .Lhidden@toc@l(3)
lwa 3, 0(3)
# address(hidden2) - (.got+0x8000) = 0x10040000 - (0x100200c0+0x8000) = (1<<16)+32576
# COMMON: addis 3, 2, 1
# COMMON: addi 3, 3, 32576
# address(hidden2) - (.got+0x8000) = 0x100403a0 - (0x10020380+0x8000) = (2<<16) - 32736
# COMMON: addis 3, 2, 2
# COMMON: addi 3, 3, -32736
# COMMON: lwa 3, 0(3)
addis 3, 2, .Lhidden2@toc@ha
ld 3, .Lhidden2@toc@l(3)
@ -82,9 +84,9 @@
lwa 4, 0(4)
# 'default' has default visibility. It is non-preemptable when producing an executable.
# address(default) - (.got+0x8000) = 0x10030000 - (0x100200c0+0x8000) = 32576
# EXE: nop
# EXE: addi 5, 2, 32576
# address(default) - (.got+0x8000) = 0x100303a0 - (0x10020380+0x8000) = (1<<16) - 32736
# EXE: addis 5, 2, 1
# EXE: addi 5, 5, -32736
# EXE: lwa 5, 0(5)
# SHARED: nop

View File

@ -14,11 +14,11 @@
# for recursive calls as well as keeps the logic for recursive calls consistent
# with non-recursive calls.
# CHECK-LABEL: 0000000000010000 recursive_func:
# CHECK: 10028: bl .+32
# CHECK-LABEL: 0000000000010290 recursive_func:
# CHECK: 102b8: bl .+32
# CHECK-NEXT: ld 2, 24(1)
# CHECK-LABEL: 0000000000010048 __plt_recursive_func:
# CHECK-LABEL: 00000000000102d8 __plt_recursive_func:
.abiversion 2
.section ".text"

View File

@ -3,14 +3,14 @@
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -shared -soname=t2.so %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so %t3.o -o %t
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -shared -soname=t2.so %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so %t3.o -o %t
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
@ -29,9 +29,9 @@ _start:
nop
bl bar_local
// CHECK-LABEL: _start:
// CHECK-NEXT: 10010008: bl .+64
// CHECK-NEXT: 1001000c: ld 2, 24(1)
// CHECK-NEXT: 10010010: bl .-16
// CHECK-NEXT: 100102c8: bl .+64
// CHECK-NEXT: 100102cc: ld 2, 24(1)
// CHECK-NEXT: 100102d0: bl .-16
// CHECK-EMPTY:
# Calling a function in another object file which will have same
@ -43,16 +43,16 @@ _diff_object:
bl foo_not_shared
nop
// CHECK-LABEL: _diff_object:
// CHECK-NEXT: 10010014: bl .+28
// CHECK-NEXT: 10010018: bl .+24
// CHECK-NEXT: 1001001c: nop
// CHECK-NEXT: 100102d4: bl .+28
// CHECK-NEXT: 100102d8: bl .+24
// CHECK-NEXT: 100102dc: nop
# Branching to a local function does not need a nop
.global noretbranch
noretbranch:
b bar_local
// CHECK-LABEL: noretbranch:
// CHECK: 10010020: b .+67108832
// CHECK: 100102e0: b .+67108832
// CHECK-EMPTY:
// This should come last to check the end-of-buffer condition.
@ -61,5 +61,5 @@ last:
bl foo
nop
// CHECK-LABEL: last:
// CHECK-NEXT: 10010024: bl .+36
// CHECK-NEXT: 10010028: ld 2, 24(1)
// CHECK-NEXT: 100102e4: bl .+36
// CHECK-NEXT: 100102e8: ld 2, 24(1)

View File

@ -24,6 +24,6 @@ _start:
# be unreachable. But, we should link successfully. We should not, however,
# generate a .plt entry (this would be wasted space). For now, we do nothing
# (leaving the zero relative offset present in the input).
# CHECK: 10010000: bl .+0
# CHECK: 10010004: nop
# CHECK: 10010008: blr
# CHECK: 10010158: bl .+0
# CHECK: 1001015c: nop
# CHECK: 10010160: blr

View File

@ -1,7 +1,7 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/copy-in-shared.s -o %t2.o
// RUN: ld.lld -shared %t.o %t2.o -o %t.so
// RUN: ld.lld -shared -soname=t.so %t.o %t2.o -z separate-code -o %t.so
// A linker script that will map .bss.rel.ro into .bss.
// RUN: echo "SECTIONS { \
@ -9,8 +9,8 @@
// RUN: } " > %t.script
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o
// RUN: ld.lld %t3.o %t.so -z relro -o %t --script=%t.script 2>&1
// RUN: llvm-readobj --program-headers %t | FileCheck %s
// RUN: ld.lld %t3.o %t.so -z relro -z separate-code -o %t --script=%t.script 2>&1
// RUN: llvm-readelf -l %t | FileCheck %s
.section .text, "ax", @progbits
.global bar
.global foo
@ -27,14 +27,5 @@ _start:
// as relro.
.space 0x2000
// CHECK: Type: PT_GNU_RELRO (0x6474E552)
// CHECK-NEXT: Offset:
// CHECK-NEXT: VirtualAddress:
// CHECK-NEXT: PhysicalAddress:
// CHECK-NEXT: FileSize:
// CHECK-NEXT: MemSize: 4096
// CHECK-NEXT: Flags [ (0x4)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: ]
// CHECK-NEXT: Alignment: 1
// CHECK-NEXT: }
// CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
// CHECK: GNU_RELRO 0x002150 0x0000000000000150 0x0000000000000150 0x000100 0x000eb0 R 0x1