1234285Sdim//===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===// 2234285Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6234285Sdim// 7234285Sdim//===----------------------------------------------------------------------===// 8234285Sdim 9234285Sdim#include "MCTargetDesc/X86FixupKinds.h" 10234285Sdim#include "MCTargetDesc/X86MCTargetDesc.h" 11321369Sdim#include "llvm/BinaryFormat/ELF.h" 12309124Sdim#include "llvm/MC/MCAsmInfo.h" 13309124Sdim#include "llvm/MC/MCContext.h" 14234285Sdim#include "llvm/MC/MCELFObjectWriter.h" 15234285Sdim#include "llvm/MC/MCExpr.h" 16321369Sdim#include "llvm/MC/MCFixup.h" 17327952Sdim#include "llvm/MC/MCObjectWriter.h" 18234285Sdim#include "llvm/MC/MCValue.h" 19234285Sdim#include "llvm/Support/ErrorHandling.h" 20321369Sdim#include <cassert> 21321369Sdim#include <cstdint> 22234285Sdim 23234285Sdimusing namespace llvm; 24234285Sdim 25234285Sdimnamespace { 26234285Sdim 27321369Sdimclass X86ELFObjectWriter : public MCELFObjectTargetWriter { 28321369Sdimpublic: 29321369Sdim X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine); 30321369Sdim ~X86ELFObjectWriter() override = default; 31288943Sdim 32321369Sdimprotected: 33321369Sdim unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 34321369Sdim const MCFixup &Fixup, bool IsPCRel) const override; 35321369Sdim}; 36234285Sdim 37321369Sdim} // end anonymous namespace 38321369Sdim 39243830SdimX86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, 40243830Sdim uint16_t EMachine) 41296417Sdim : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine, 42296417Sdim // Only i386 and IAMCU use Rel instead of RelA. 43296417Sdim /*HasRelocationAddend*/ 44296417Sdim (EMachine != ELF::EM_386) && 45296417Sdim (EMachine != ELF::EM_IAMCU)) {} 46234285Sdim 47353358Sdimenum X86_64RelType { RT64_NONE, RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 }; 48234285Sdim 49360784Sdimstatic X86_64RelType getType64(MCFixupKind Kind, 50288943Sdim MCSymbolRefExpr::VariantKind &Modifier, 51288943Sdim bool &IsPCRel) { 52360784Sdim switch (unsigned(Kind)) { 53288943Sdim default: 54288943Sdim llvm_unreachable("Unimplemented"); 55353358Sdim case FK_NONE: 56353358Sdim return RT64_NONE; 57288943Sdim case X86::reloc_global_offset_table8: 58288943Sdim Modifier = MCSymbolRefExpr::VK_GOT; 59288943Sdim IsPCRel = true; 60288943Sdim return RT64_64; 61288943Sdim case FK_Data_8: 62288943Sdim return RT64_64; 63288943Sdim case X86::reloc_signed_4byte: 64309124Sdim case X86::reloc_signed_4byte_relax: 65288943Sdim if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel) 66288943Sdim return RT64_32S; 67288943Sdim return RT64_32; 68288943Sdim case X86::reloc_global_offset_table: 69288943Sdim Modifier = MCSymbolRefExpr::VK_GOT; 70288943Sdim IsPCRel = true; 71288943Sdim return RT64_32; 72288943Sdim case FK_Data_4: 73288943Sdim case FK_PCRel_4: 74288943Sdim case X86::reloc_riprel_4byte: 75309124Sdim case X86::reloc_riprel_4byte_relax: 76309124Sdim case X86::reloc_riprel_4byte_relax_rex: 77288943Sdim case X86::reloc_riprel_4byte_movq_load: 78288943Sdim return RT64_32; 79341825Sdim case X86::reloc_branch_4byte_pcrel: 80341825Sdim Modifier = MCSymbolRefExpr::VK_PLT; 81341825Sdim return RT64_32; 82288943Sdim case FK_PCRel_2: 83288943Sdim case FK_Data_2: 84288943Sdim return RT64_16; 85288943Sdim case FK_PCRel_1: 86288943Sdim case FK_Data_1: 87288943Sdim return RT64_8; 88288943Sdim } 89288943Sdim} 90234285Sdim 91309124Sdimstatic void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) { 92309124Sdim if (Type != RT64_32) 93309124Sdim Ctx.reportError(Loc, 94309124Sdim "32 bit reloc applied to a field with a different size"); 95309124Sdim} 96309124Sdim 97309124Sdimstatic unsigned getRelocType64(MCContext &Ctx, SMLoc Loc, 98309124Sdim MCSymbolRefExpr::VariantKind Modifier, 99309124Sdim X86_64RelType Type, bool IsPCRel, 100360784Sdim MCFixupKind Kind) { 101288943Sdim switch (Modifier) { 102288943Sdim default: 103288943Sdim llvm_unreachable("Unimplemented"); 104288943Sdim case MCSymbolRefExpr::VK_None: 105321369Sdim case MCSymbolRefExpr::VK_X86_ABS8: 106288943Sdim switch (Type) { 107353358Sdim case RT64_NONE: 108353358Sdim if (Modifier == MCSymbolRefExpr::VK_None) 109353358Sdim return ELF::R_X86_64_NONE; 110353358Sdim llvm_unreachable("Unimplemented"); 111288943Sdim case RT64_64: 112288943Sdim return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64; 113288943Sdim case RT64_32: 114288943Sdim return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32; 115288943Sdim case RT64_32S: 116288943Sdim return ELF::R_X86_64_32S; 117288943Sdim case RT64_16: 118288943Sdim return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16; 119288943Sdim case RT64_8: 120288943Sdim return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8; 121234285Sdim } 122353358Sdim llvm_unreachable("unexpected relocation type!"); 123288943Sdim case MCSymbolRefExpr::VK_GOT: 124288943Sdim switch (Type) { 125288943Sdim case RT64_64: 126288943Sdim return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64; 127288943Sdim case RT64_32: 128288943Sdim return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32; 129288943Sdim case RT64_32S: 130288943Sdim case RT64_16: 131288943Sdim case RT64_8: 132353358Sdim case RT64_NONE: 133288943Sdim llvm_unreachable("Unimplemented"); 134288943Sdim } 135353358Sdim llvm_unreachable("unexpected relocation type!"); 136288943Sdim case MCSymbolRefExpr::VK_GOTOFF: 137288943Sdim assert(Type == RT64_64); 138288943Sdim assert(!IsPCRel); 139288943Sdim return ELF::R_X86_64_GOTOFF64; 140288943Sdim case MCSymbolRefExpr::VK_TPOFF: 141288943Sdim assert(!IsPCRel); 142288943Sdim switch (Type) { 143288943Sdim case RT64_64: 144288943Sdim return ELF::R_X86_64_TPOFF64; 145288943Sdim case RT64_32: 146288943Sdim return ELF::R_X86_64_TPOFF32; 147288943Sdim case RT64_32S: 148288943Sdim case RT64_16: 149288943Sdim case RT64_8: 150353358Sdim case RT64_NONE: 151288943Sdim llvm_unreachable("Unimplemented"); 152288943Sdim } 153353358Sdim llvm_unreachable("unexpected relocation type!"); 154288943Sdim case MCSymbolRefExpr::VK_DTPOFF: 155288943Sdim assert(!IsPCRel); 156288943Sdim switch (Type) { 157288943Sdim case RT64_64: 158288943Sdim return ELF::R_X86_64_DTPOFF64; 159288943Sdim case RT64_32: 160288943Sdim return ELF::R_X86_64_DTPOFF32; 161288943Sdim case RT64_32S: 162288943Sdim case RT64_16: 163288943Sdim case RT64_8: 164353358Sdim case RT64_NONE: 165288943Sdim llvm_unreachable("Unimplemented"); 166288943Sdim } 167353358Sdim llvm_unreachable("unexpected relocation type!"); 168288943Sdim case MCSymbolRefExpr::VK_SIZE: 169288943Sdim assert(!IsPCRel); 170288943Sdim switch (Type) { 171288943Sdim case RT64_64: 172288943Sdim return ELF::R_X86_64_SIZE64; 173288943Sdim case RT64_32: 174288943Sdim return ELF::R_X86_64_SIZE32; 175288943Sdim case RT64_32S: 176288943Sdim case RT64_16: 177288943Sdim case RT64_8: 178353358Sdim case RT64_NONE: 179288943Sdim llvm_unreachable("Unimplemented"); 180288943Sdim } 181353358Sdim llvm_unreachable("unexpected relocation type!"); 182309124Sdim case MCSymbolRefExpr::VK_TLSCALL: 183309124Sdim return ELF::R_X86_64_TLSDESC_CALL; 184309124Sdim case MCSymbolRefExpr::VK_TLSDESC: 185309124Sdim return ELF::R_X86_64_GOTPC32_TLSDESC; 186288943Sdim case MCSymbolRefExpr::VK_TLSGD: 187309124Sdim checkIs32(Ctx, Loc, Type); 188288943Sdim return ELF::R_X86_64_TLSGD; 189288943Sdim case MCSymbolRefExpr::VK_GOTTPOFF: 190309124Sdim checkIs32(Ctx, Loc, Type); 191288943Sdim return ELF::R_X86_64_GOTTPOFF; 192288943Sdim case MCSymbolRefExpr::VK_TLSLD: 193309124Sdim checkIs32(Ctx, Loc, Type); 194288943Sdim return ELF::R_X86_64_TLSLD; 195288943Sdim case MCSymbolRefExpr::VK_PLT: 196309124Sdim checkIs32(Ctx, Loc, Type); 197288943Sdim return ELF::R_X86_64_PLT32; 198288943Sdim case MCSymbolRefExpr::VK_GOTPCREL: 199309124Sdim checkIs32(Ctx, Loc, Type); 200309124Sdim // Older versions of ld.bfd/ld.gold/lld 201309124Sdim // do not support GOTPCRELX/REX_GOTPCRELX, 202309124Sdim // and we want to keep back-compatibility. 203309124Sdim if (!Ctx.getAsmInfo()->canRelaxRelocations()) 204309124Sdim return ELF::R_X86_64_GOTPCREL; 205360784Sdim switch (unsigned(Kind)) { 206309124Sdim default: 207309124Sdim return ELF::R_X86_64_GOTPCREL; 208309124Sdim case X86::reloc_riprel_4byte_relax: 209309124Sdim return ELF::R_X86_64_GOTPCRELX; 210309124Sdim case X86::reloc_riprel_4byte_relax_rex: 211309124Sdim case X86::reloc_riprel_4byte_movq_load: 212309124Sdim return ELF::R_X86_64_REX_GOTPCRELX; 213309124Sdim } 214353358Sdim llvm_unreachable("unexpected relocation type!"); 215288943Sdim } 216288943Sdim} 217234285Sdim 218353358Sdimenum X86_32RelType { RT32_NONE, RT32_32, RT32_16, RT32_8 }; 219234285Sdim 220288943Sdimstatic X86_32RelType getType32(X86_64RelType T) { 221288943Sdim switch (T) { 222353358Sdim case RT64_NONE: 223353358Sdim return RT32_NONE; 224288943Sdim case RT64_64: 225288943Sdim llvm_unreachable("Unimplemented"); 226288943Sdim case RT64_32: 227288943Sdim case RT64_32S: 228288943Sdim return RT32_32; 229288943Sdim case RT64_16: 230288943Sdim return RT32_16; 231288943Sdim case RT64_8: 232288943Sdim return RT32_8; 233288943Sdim } 234288943Sdim llvm_unreachable("unexpected relocation type!"); 235288943Sdim} 236276479Sdim 237309124Sdimstatic unsigned getRelocType32(MCContext &Ctx, 238309124Sdim MCSymbolRefExpr::VariantKind Modifier, 239309124Sdim X86_32RelType Type, bool IsPCRel, 240360784Sdim MCFixupKind Kind) { 241288943Sdim switch (Modifier) { 242288943Sdim default: 243288943Sdim llvm_unreachable("Unimplemented"); 244288943Sdim case MCSymbolRefExpr::VK_None: 245321369Sdim case MCSymbolRefExpr::VK_X86_ABS8: 246288943Sdim switch (Type) { 247353358Sdim case RT32_NONE: 248353358Sdim if (Modifier == MCSymbolRefExpr::VK_None) 249353358Sdim return ELF::R_386_NONE; 250353358Sdim llvm_unreachable("Unimplemented"); 251288943Sdim case RT32_32: 252288943Sdim return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32; 253288943Sdim case RT32_16: 254288943Sdim return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16; 255288943Sdim case RT32_8: 256288943Sdim return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8; 257288943Sdim } 258353358Sdim llvm_unreachable("unexpected relocation type!"); 259288943Sdim case MCSymbolRefExpr::VK_GOT: 260288943Sdim assert(Type == RT32_32); 261309124Sdim if (IsPCRel) 262309124Sdim return ELF::R_386_GOTPC; 263309124Sdim // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we 264309124Sdim // want to maintain compatibility. 265309124Sdim if (!Ctx.getAsmInfo()->canRelaxRelocations()) 266309124Sdim return ELF::R_386_GOT32; 267309124Sdim 268360784Sdim return Kind == MCFixupKind(X86::reloc_signed_4byte_relax) 269360784Sdim ? ELF::R_386_GOT32X 270360784Sdim : ELF::R_386_GOT32; 271288943Sdim case MCSymbolRefExpr::VK_GOTOFF: 272288943Sdim assert(Type == RT32_32); 273288943Sdim assert(!IsPCRel); 274288943Sdim return ELF::R_386_GOTOFF; 275353358Sdim case MCSymbolRefExpr::VK_TLSCALL: 276353358Sdim return ELF::R_386_TLS_DESC_CALL; 277353358Sdim case MCSymbolRefExpr::VK_TLSDESC: 278353358Sdim return ELF::R_386_TLS_GOTDESC; 279288943Sdim case MCSymbolRefExpr::VK_TPOFF: 280288943Sdim assert(Type == RT32_32); 281288943Sdim assert(!IsPCRel); 282288943Sdim return ELF::R_386_TLS_LE_32; 283288943Sdim case MCSymbolRefExpr::VK_DTPOFF: 284288943Sdim assert(Type == RT32_32); 285288943Sdim assert(!IsPCRel); 286288943Sdim return ELF::R_386_TLS_LDO_32; 287288943Sdim case MCSymbolRefExpr::VK_TLSGD: 288288943Sdim assert(Type == RT32_32); 289288943Sdim assert(!IsPCRel); 290288943Sdim return ELF::R_386_TLS_GD; 291288943Sdim case MCSymbolRefExpr::VK_GOTTPOFF: 292288943Sdim assert(Type == RT32_32); 293288943Sdim assert(!IsPCRel); 294288943Sdim return ELF::R_386_TLS_IE_32; 295288943Sdim case MCSymbolRefExpr::VK_PLT: 296288943Sdim assert(Type == RT32_32); 297288943Sdim return ELF::R_386_PLT32; 298288943Sdim case MCSymbolRefExpr::VK_INDNTPOFF: 299288943Sdim assert(Type == RT32_32); 300288943Sdim assert(!IsPCRel); 301288943Sdim return ELF::R_386_TLS_IE; 302288943Sdim case MCSymbolRefExpr::VK_NTPOFF: 303288943Sdim assert(Type == RT32_32); 304288943Sdim assert(!IsPCRel); 305288943Sdim return ELF::R_386_TLS_LE; 306288943Sdim case MCSymbolRefExpr::VK_GOTNTPOFF: 307288943Sdim assert(Type == RT32_32); 308288943Sdim assert(!IsPCRel); 309288943Sdim return ELF::R_386_TLS_GOTIE; 310288943Sdim case MCSymbolRefExpr::VK_TLSLDM: 311288943Sdim assert(Type == RT32_32); 312288943Sdim assert(!IsPCRel); 313288943Sdim return ELF::R_386_TLS_LDM; 314288943Sdim } 315288943Sdim} 316276479Sdim 317309124Sdimunsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, 318288943Sdim const MCFixup &Fixup, 319288943Sdim bool IsPCRel) const { 320288943Sdim MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 321360784Sdim MCFixupKind Kind = Fixup.getKind(); 322309124Sdim X86_64RelType Type = getType64(Kind, Modifier, IsPCRel); 323288943Sdim if (getEMachine() == ELF::EM_X86_64) 324309124Sdim return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind); 325234285Sdim 326296417Sdim assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) && 327296417Sdim "Unsupported ELF machine type."); 328309124Sdim return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind); 329234285Sdim} 330234285Sdim 331341825Sdimstd::unique_ptr<MCObjectTargetWriter> 332341825Sdimllvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) { 333360784Sdim return std::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine); 334234285Sdim} 335