LLVM: lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

24

25using namespace llvm;

26

27namespace {

29 bool recordScatteredRelocation(MachObjectWriter *Writer,

30 const MCAssembler &Asm,

31 const MCFragment *Fragment,

32 const MCFixup &Fixup,

33 MCValue Target,

34 unsigned Log2Size,

35 uint64_t &FixedValue);

36 void recordTLVPRelocation(MachObjectWriter *Writer,

37 const MCAssembler &Asm,

38 const MCFragment *Fragment,

39 const MCFixup &Fixup,

40 MCValue Target,

41 uint64_t &FixedValue);

42

43 void RecordX86Relocation(MachObjectWriter *Writer,

44 const MCAssembler &Asm,

45 const MCFragment *Fragment,

46 const MCFixup &Fixup,

47 MCValue Target,

48 uint64_t &FixedValue);

49 void RecordX86_64Relocation(MachObjectWriter *Writer, MCAssembler &Asm,

50 const MCFragment *Fragment, const MCFixup &Fixup,

51 MCValue Target, uint64_t &FixedValue);

52

53public:

54 X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)

55 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}

56

57 void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,

58 const MCFragment *Fragment, const MCFixup &Fixup,

59 MCValue Target, uint64_t &FixedValue) override {

61 RecordX86_64Relocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);

62 else

63 RecordX86Relocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);

64 }

65};

66}

67

77

79 switch (Kind) {

80 default:

84

97 }

98}

99

100void X86MachObjectWriter::RecordX86_64Relocation(

103 unsigned IsPCRel = Fixup.isPCRel();

106

107

108 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

109 uint32_t FixupAddress =

111 int64_t Value = 0;

112 unsigned Index = 0;

113 unsigned IsExtern = 0;

114 unsigned Type = 0;

115 const MCSymbol *RelSymbol = nullptr;

116

118

119 if (IsPCRel) {

120

121

122

123

124

125 Value += 1LL << Log2Size;

126 }

127

128 if (Target.isAbsolute()) {

129

131

132

133

134

135

136 if (IsPCRel) {

137 IsExtern = 1;

139 }

140 } else if (Target.getSubSym()) {

142 if (A->isTemporary())

145

147 if (B->isTemporary())

150

151

152 if (Target.getSpecifier()) {

153 reportError(Fixup.getLoc(), "unsupported relocation of modified symbol");

154 return;

155 }

156

157

158

159 if (IsPCRel) {

161 "unsupported pc-relative relocation of difference");

162 return;

163 }

164

165

166

167

168

169

170

171

172

173

174

175 if (A_Base == B_Base && A_Base) {

176 reportError(Fixup.getLoc(), "unsupported relocation with identical base");

177 return;

178 }

179

180

181

182 if (A->isUndefined() || B->isUndefined()) {

183 StringRef Name = A->isUndefined() ? A->getName() : B->getName();

186 "unsupported relocation with subtraction expression, symbol '" +

187 Name + "' can not be undefined in a subtraction expression");

188 return;

189 }

190

195

196 if (!A_Base)

197 Index = A->getFragment()->getParent()->getOrdinal() + 1;

199

200 MachO::any_relocation_info MRE;

201 MRE.r_word0 = FixupOffset;

203 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);

205

206 if (B_Base)

207 RelSymbol = B_Base;

208 else

209 Index = B->getFragment()->getParent()->getOrdinal() + 1;

211 } else {

214 const MCSection &Sec = Symbol->getSection();

216 Symbol->setUsedInReloc();

217 }

218 RelSymbol = Writer->getAtom(*Symbol);

219

220

221

222

223

224 if (Symbol->isInSection()) {

225 const MCSectionMachO &Section =

226 static_cast<const MCSectionMachO &>(*Fragment->getParent());

228 RelSymbol = nullptr;

229 }

230

231

232

233

234 if (RelSymbol) {

235

236 if (RelSymbol != Symbol)

237 Value += Asm.getSymbolOffset(*Symbol) - Asm.getSymbolOffset(*RelSymbol);

238 } else if (Symbol->isInSection() && Symbol->isVariable()) {

239

240 Index = Symbol->getFragment()->getParent()->getOrdinal() + 1;

242

243 if (IsPCRel)

244 Value -= FixupAddress + (1 << Log2Size);

245 } else if (Symbol->isVariable()) {

247 return;

248 } else {

250 "unsupported relocation of undefined symbol '" +

251 Symbol->getName() + "'");

252 return;

253 }

254

256 if (IsPCRel) {

257 if (IsRIPRel) {

259

260

261

264 else

268 } else if (Specifier) {

270 "unsupported symbol modifier in relocation");

271 return;

272 } else {

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289 switch (-(Target.getConstant() + (1LL << Log2Size))) {

293 }

294 }

295 } else {

296 if (Specifier) {

298 "unsupported symbol modifier in branch relocation");

299 return;

300 }

301

303 }

304 } else {

308

309

310

311

313 IsPCRel = 1;

316 "TLVP symbol modifier should have been rip-rel");

317 return;

318 } else if (Specifier) {

320 "unsupported symbol modifier in relocation");

321 return;

322 } else {

327 "32-bit absolute addressing is not supported in 64-bit mode");

328 return;

329 }

330 }

331 }

332 }

333

334

335 FixedValue = Value;

336

337

338 MachO::any_relocation_info MRE;

339 MRE.r_word0 = FixupOffset;

340 MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |

341 (IsExtern << 27) | (Type << 28);

343}

344

345bool X86MachObjectWriter::recordScatteredRelocation(MachObjectWriter *Writer,

346 const MCAssembler &Asm,

347 const MCFragment *Fragment,

348 const MCFixup &Fixup,

349 MCValue Target,

350 unsigned Log2Size,

351 uint64_t &FixedValue) {

352 uint64_t OriginalFixedValue = FixedValue;

353 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

354 unsigned IsPCRel = Fixup.isPCRel();

356

357

358 auto *A = static_cast<const MCSymbolMachO *>(Target.getAddSym());

359 if (A->getFragment()) {

361 "symbol '" + A->getName() +

362 "' can not be undefined in a subtraction expression");

363 return false;

364 }

365

367 uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());

368 FixedValue += SecAddr;

369 uint32_t Value2 = 0;

370

371 if (const MCSymbol *SB = Target.getSubSym()) {

372 if (!SB->getFragment()) {

374 "symbol '" + SB->getName() +

375 "' can not be undefined in a subtraction expression");

376 return false;

377 }

378

379

380

381

382

383

387 FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());

388 }

389

390

393

394

395 if (FixupOffset > 0xffffff) {

396 char Buffer[32];

397 format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));

398 reportError(Fixup.getLoc(), Twine("Section too large, can't encode "

399 "r_address (") +

400 Buffer +

401 ") into 24 bits of scattered "

402 "relocation entry.");

403 return false;

404 }

405

406 MachO::any_relocation_info MRE;

407 MRE.r_word0 = ((0 << 0) |

409 (Log2Size << 28) |

410 (IsPCRel << 30) |

414 } else {

415

416

417

418

419

420

421

422 if (FixupOffset > 0xffffff) {

423 FixedValue = OriginalFixedValue;

424 return false;

425 }

426 }

427

428 MachO::any_relocation_info MRE;

429 MRE.r_word0 = ((FixupOffset << 0) |

430 (Type << 24) |

431 (Log2Size << 28) |

432 (IsPCRel << 30) |

436 return true;

437}

438

439void X86MachObjectWriter::recordTLVPRelocation(MachObjectWriter *Writer,

440 const MCAssembler &Asm,

441 const MCFragment *Fragment,

442 const MCFixup &Fixup,

443 MCValue Target,

444 uint64_t &FixedValue) {

447 "Should only be called with a 32-bit TLVP relocation!");

448

450 uint32_t Value = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

451 unsigned IsPCRel = 0;

452

453

454

455

456

457 if (auto *SymB = Target.getSubSym()) {

458

459 uint32_t FixupAddress =

461 IsPCRel = 1;

462 FixedValue =

464 FixedValue += 1ULL << Log2Size;

465 } else {

466 FixedValue = 0;

467 }

468

469

470 MachO::any_relocation_info MRE;

475}

476

477void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,

478 const MCAssembler &Asm,

479 const MCFragment *Fragment,

480 const MCFixup &Fixup,

481 MCValue Target,

482 uint64_t &FixedValue) {

483 unsigned IsPCRel = Fixup.isPCRel();

486

487

489 recordTLVPRelocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);

490 return;

491 }

492

493

494

495

496 if (Target.getSubSym()) {

497 recordScatteredRelocation(Writer, Asm, Fragment, Fixup, Target, Log2Size,

498 FixedValue);

499 return;

500 }

501

502

503

505 if (IsPCRel)

506 Offset += 1 << Log2Size;

507

508

509

510

512 recordScatteredRelocation(Writer, Asm, Fragment, Fixup, Target, Log2Size,

513 FixedValue))

514 return;

515

516

517 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

518 unsigned Index = 0;

519 unsigned Type = 0;

520 const MCSymbol *RelSymbol = nullptr;

521

522 if (Target.isAbsolute()) {

523

524

525

526

528 } else {

529 assert(A && "Unknown symbol data");

530

531

532 if (A->isVariable()) {

533 MCValue Val;

534 bool Relocatable =

535 A->getVariableValue()->evaluateAsRelocatable(Val, &Asm);

541 isAbs = true;

542 }

543 if (isAbs) {

544 FixedValue = Res;

545 return;

546 }

547 }

548

549

551 RelSymbol = A;

552

553

554

555 if (A->isUndefined())

556 FixedValue -= Asm.getSymbolOffset(*A);

557 } else {

558

559 const MCSection &Sec = A->getSection();

562 }

563 if (IsPCRel)

565

567 }

568

569

570 MachO::any_relocation_info MRE;

571 MRE.r_word0 = FixupOffset;

573 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);

575}

576

577std::unique_ptr

580 return std::make_unique(Is64Bit, CPUType, CPUSubtype);

581}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static Error reportError(StringRef Message)

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

PowerPC TLS Dynamic Call Fixup

static bool is64Bit(const char *name)

static bool isFixupKindRIPRel(unsigned Kind)

Definition X86MachObjectWriter.cpp:68

static bool isSectionAtomizableBySymbols(const MCSection &Section)

True if the section is atomized using the symbols in it.

Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...

MCSection * getParent() const

unsigned getOrdinal() const

const MCSymbol * getAddSym() const

int64_t getConstant() const

const MCSymbol * getSubSym() const

bool isAbsolute() const

Is this an absolute (as opposed to relocatable) value.

bool doesSymbolRequireExternRelocation(const MCSymbol &S)

uint64_t getFragmentAddress(const MCAssembler &Asm, const MCFragment *Fragment) const

uint64_t getSectionAddress(const MCSection *Sec) const

void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE)

const MCSymbol & findAliasedSymbol(const MCSymbol &Sym) const

const MCSymbol * getAtom(const MCSymbol &S) const

uint64_t getSymbolAddress(const MCSymbol &S) const

Target - Wrapper for Target specific information.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ GENERIC_RELOC_LOCAL_SECTDIFF

@ X86_64_RELOC_SUBTRACTOR

@ S_ATTR_DEBUG

S_ATTR_DEBUG - A debug section.

@ reloc_riprel_4byte_movq_load_rex2

@ reloc_signed_4byte_relax

@ reloc_branch_4byte_pcrel

@ reloc_riprel_4byte_relax

@ reloc_riprel_4byte_relax_evex

@ reloc_riprel_4byte_relax_rex

@ reloc_riprel_4byte_movq_load

@ reloc_riprel_4byte_relax_rex2

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

static unsigned getFixupKindLog2Size(unsigned Kind)

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

@ FK_Data_8

A eight-byte fixup.

@ FK_Data_1

A one-byte fixup.

@ FK_Data_4

A four-byte fixup.

@ FK_Data_2

A two-byte fixup.

std::unique_ptr< MCObjectTargetWriter > createX86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)

Construct an X86 Mach-O object writer.

Definition X86MachObjectWriter.cpp:578