Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lld/ELF/Arch/X86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
case R_X86_64_PC32:
case R_X86_64_PC64:
return R_PC;
case R_X86_64_PCNEXT32:
return RE_X86_64_PCNEXT32;
case R_X86_64_GOTOFF64:
return R_GOTPLTREL;
case R_X86_64_GOTPC32:
Expand Down Expand Up @@ -654,7 +656,7 @@ void X86_64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
uint64_t offset = rel.r_offset;
RelType type = rel.getType(false);
if (sym.isUndefined() && symIdx != 0 &&
if (sym.isUndefined() && symIdx != 0 && type != R_X86_64_PCNEXT32 &&
rs.maybeReportUndefined(cast<Undefined>(sym), offset))
continue;
int64_t addend = rs.getAddend<ELFT>(rel, type);
Expand Down Expand Up @@ -682,6 +684,9 @@ void X86_64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
case R_X86_64_PC64:
rs.processR_PC(type, offset, addend, sym);
continue;
case R_X86_64_PCNEXT32:
rs.process(RE_X86_64_PCNEXT32, type, offset, sym, addend);
continue;

// GOT-generating relocations:
case R_X86_64_GOTPC32:
Expand Down Expand Up @@ -1182,6 +1187,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_X86_64_GOTPC32:
case R_X86_64_GOTPCREL:
case R_X86_64_PC32:
case R_X86_64_PCNEXT32:
case R_X86_64_PLT32:
case R_X86_64_DTPOFF32:
case R_X86_64_SIZE32:
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,10 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
}
case RE_LOONGARCH_PAGE_PC:
return getLoongArchPageDelta(r.sym->getVA(ctx, a), p, r.type);
case RE_X86_64_PCNEXT32:
if (r.sym->isUndefined() || r.sym->isShared())
return 0;
return r.sym->getVA(ctx, a) - p;
case R_PC:
case RE_ARM_PCA: {
uint64_t dest;
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type,
R_GOTPLTONLY_PC, R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT,
R_GOTPLT_GOTREL, R_GOTPLT_PC, RE_PPC32_PLTREL, RE_PPC64_CALL_PLT,
RE_RISCV_ADD, RE_AARCH64_GOT_PAGE, RE_LOONGARCH_PLT_PAGE_PC,
RE_LOONGARCH_GOT, RE_LOONGARCH_GOT_PAGE_PC>(e))
RE_LOONGARCH_GOT, RE_LOONGARCH_GOT_PAGE_PC, RE_X86_64_PCNEXT32>(e))
return true;

// These never do, except if the entire file is position dependent or if
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/Relocations.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ enum RelExpr {
RE_LOONGARCH_PC_INDIRECT,
RE_LOONGARCH_TLSGD_PAGE_PC,
RE_LOONGARCH_TLSDESC_PAGE_PC,
RE_X86_64_PCNEXT32,
};

// Architecture-neutral representation of relocation.
Expand Down
37 changes: 37 additions & 0 deletions lld/test/ELF/x86-64-reloc-pcnext32.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t

# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/so.s -o %t/so.o
# RUN: ld.lld -shared %t/so.o -o %t/libso.so

# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/main.s -o %t/main.o
# RUN: ld.lld --image-base=0x1000 --section-start=.text=0x1000 %t/main.o %t/libso.so -o %t/out
# RUN: llvm-readelf -x .text %t/out | FileCheck %s

# CHECK: Hex dump of section '.text':
# CHECK-NEXT: 0x00001000 0c000000 00000000 00000000 c3

#--- so.s
.global shared_sym
shared_sym:
ret

#--- main.s
.globl _start
_start:
# R_X86_64_PCNEXT32 to defined local symbol at 0x100c (place is 0x1000, 0x100c - 0x1000 = 0x0c)
.reloc ., R_X86_64_PCNEXT32, local_sym
.byte 0x00, 0x00, 0x00, 0x00

# R_X86_64_PCNEXT32 to shared symbol (resolves to 0)
.reloc ., R_X86_64_PCNEXT32, shared_sym
.byte 0x00, 0x00, 0x00, 0x00

# R_X86_64_PCNEXT32 to undefined weak symbol (resolves to 0)
.reloc ., R_X86_64_PCNEXT32, undef_sym
.byte 0x00, 0x00, 0x00, 0x00

local_sym:
ret

.weak undef_sym
11 changes: 11 additions & 0 deletions llvm/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,17 @@ is also not the same as `cmpb $foo, %dil`, which is an 8-bit comparison.
the assembler emits an `R_X86_64_GOTPCREL` relocation instead of a relaxable
`R_X86_64[_REX]_GOTPCRELX` relocation.


**@PCNEXT32** can be used on symbol references to indicate that the immediate
operand is an offset to the target symbol from the next code location, causing
the assembler to emit an `R_X86_64_PCNEXT32` relocation. If the target symbol
is defined, the relocation resolves identically to `R_X86_64_PC32` (`S + A - P`).
If the target symbol is undefined or in a shared library, it resolves to zero
displacement (`0`) without generating a linker diagnostic. This allows
undefined code prefetch targets (e.g. `prefetchit1 target@PCNEXT32(%rip)`) to
gracefully degrade to a harmless prefetch of the immediately following
instruction.

### Windows on ARM

#### Stack Probe Emission
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/ELFRelocs/x86_64.def
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
ELF_RELOC(R_X86_64_CODE_4_GOTPCRELX, 43)
ELF_RELOC(R_X86_64_CODE_4_GOTTPOFF, 44)
ELF_RELOC(R_X86_64_CODE_4_GOTPC32_TLSDESC, 45)
ELF_RELOC(R_X86_64_PCNEXT32, 46)
ELF_RELOC(R_X86_64_CODE_6_GOTTPOFF, 50)
5 changes: 5 additions & 0 deletions llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,11 @@ enum TOF {
/// See the X86-64 ELF ABI supplement for more details.
/// SYMBOL_LABEL @PLT
MO_PLT,
/// MO_PCNEXT32 - On a symbol operand this indicates that the immediate is
/// offset to the prefetch target symbol name from the next code location.
/// If the target symbol is undefined, it will resolve to zero displacement.
/// SYMBOL_LABEL @PCNEXT32
MO_PCNEXT32,
/// MO_TLSGD - On a symbol operand this indicates that the immediate is
/// the offset of the GOT entry with the TLS index structure that contains
/// the module number and variable offset for the symbol. Used in the
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ unsigned X86ELFObjectWriter::getRelocType64(SMLoc Loc, X86::Specifier Specifier,
case X86::S_PLT:
checkIs32(Loc, Type);
return ELF::R_X86_64_PLT32;
case X86::S_PCNEXT32:
checkIs32(Loc, Type);
return ELF::R_X86_64_PCNEXT32;
case X86::S_GOTPCREL:
checkIs32(Loc, Type);
// Older versions of ld.bfd/ld.gold/lld
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const MCAsmInfo::AtSpecifier atSpecifiers[] = {
{X86::S_INDNTPOFF, "INDNTPOFF"},
{MCSymbolRefExpr::VK_COFF_IMGREL32, "IMGREL"},
{X86::S_NTPOFF, "NTPOFF"},
{X86::S_PCNEXT32, "PCNEXT32"},
{X86::S_PCREL, "PCREL"},
{X86::S_PLT, "PLT"},
{X86::S_PLTOFF, "PLTOFF"},
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum {
S_GOTTPOFF,
S_INDNTPOFF,
S_NTPOFF,
S_PCNEXT32,
S_PCREL,
S_PLT,
S_PLTOFF,
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ void X86AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
case X86II::MO_GOT: O << "@GOT"; break;
case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
case X86II::MO_PLT: O << "@PLT"; break;
case X86II::MO_PCNEXT32:
O << "@PCNEXT32";
break;
case X86II::MO_TLVP: O << "@TLVP"; break;
case X86II::MO_TLVP_PIC_BASE:
O << "@TLVP" << '-';
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86MCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case X86II::MO_PLT:
Specifier = X86::S_PLT;
break;
case X86II::MO_PCNEXT32:
Specifier = X86::S_PCNEXT32;
break;
case X86II::MO_ABS8:
Specifier = X86::S_ABS8;
break;
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/MC/X86/elf-reloc-pcnext32.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s | llvm-readobj -r - | FileCheck %s

# CHECK: Section ({{.*}}) .rela.text {
# CHECK-NEXT: 0x3 R_X86_64_PCNEXT32 target 0xFFFFFFFFFFFFFFFC
# CHECK-NEXT: 0x7 R_X86_64_PCNEXT32 target 0x0
# CHECK-NEXT: }

prefetchit1 target@PCNEXT32(%rip)

.reloc ., R_X86_64_PCNEXT32, target
.long 0
Loading