LLVM: lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

24#include

25

26using namespace llvm;

27

28#define DEBUG_TYPE "jitlink"

29

30namespace llvm {

32

35 std::shared_ptrorc::SymbolStringPool SSP, Triple TT,

38 : Obj(Obj),

42

43#ifndef NDEBUG

45 switch (SC) {

47 return "C_FILE (File name)";

49 return "C_BINCL (Beginning of include file)";

51 return "C_EINCL (Ending of include file)";

53 return "C_GSYM (Global variable)";

55 return "C_STSYM (Statically allocated symbol)";

57 return "C_BCOMM (Beginning of common block)";

59 return "C_ECOMM (End of common block)";

61 return "C_ENTRY (Alternate entry)";

63 return "C_BSTAT (Beginning of static block)";

65 return "C_ESTAT (End of static block)";

67 return "C_GTLS (Global thread-local variable)";

69 return "C_STTLS (Static thread-local variable)";

71 return "C_DWARF (DWARF section symbol)";

73 return "C_LSYM (Automatic variable allocated on stack)";

75 return "C_PSYM (Argument to subroutine allocated on stack)";

77 return "C_RSYM (Register variable)";

79 return "C_RPSYM (Argument to function stored in register)";

81 return "C_ECOML (Local member of common block)";

83 return "C_FUN (Function or procedure)";

85 return "C_EXT (External symbol)";

87 return "C_WEAKEXT (Weak external symbol)";

89 return "C_NULL";

91 return "C_STAT (Static)";

93 return "C_BLOCK (\".bb\" or \".eb\")";

95 return "C_FCN (\".bf\" or \".ef\")";

97 return "C_HIDEXT (Un-named external symbol)";

99 return "C_INFO (Comment string in .info section)";

101 return "C_DECL (Declaration of object)";

103 return "C_AUTO (Automatic variable)";

105 return "C_REG (Register variable)";

107 return "C_EXTDEF (External definition)";

109 return "C_LABEL (Label)";

111 return "C_ULABEL (Undefined label)";

113 return "C_MOS (Member of structure)";

115 return "C_ARG (Function argument)";

117 return "C_STRTAG (Structure tag)";

119 return "C_MOU (Member of union)";

121 return "C_UNTAG (Union tag)";

123 return "C_TPDEF (Type definition)";

125 return "C_USTATIC (Undefined static)";

127 return "C_ENTAG (Enumeration tag)";

129 return "C_MOE (Member of enumeration)";

131 return "C_REGPARM (Register parameter)";

133 return "C_FIELD (Bit field)";

135 return "C_EOS (End of structure)";

137 return "C_LINE";

139 return "C_ALIAS (Duplicate tag)";

141 return "C_HIDDEN (Special storage class for external)";

143 return "C_EFCN (Physical end of function)";

145 return "C_TCSYM (Reserved)";

146 }

148}

149#endif

150

151Error XCOFFLinkGraphBuilder::processSections() {

152 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");

153

155

160

163 << ", idx = " << Section.getIndex()

165 << ", vma = " << format_hex(Section.getAddress(), 16) << "\n";

166 });

167

168

169 if (Section.isDebugSection() || *SectionName == "pad")

170 continue;

172

174 if (Section.isText())

176 if (Section.isData() || Section.isBSS())

178

180

181

183 "Section with same index already exists");

184 SectionTable[Section.getIndex()] = {GraphSec, Section};

185 }

186

188}

189

190static std::optionalobject::XCOFFSymbolRef

196 return std::nullopt;

197

200 if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())

201 return std::nullopt;

203 static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());

205 DRI.p = Obj.getSymbolByIndex(Idx);

207}

208

209#ifndef NDEBUG

217 if (!CsectAuxEntry.isLabel()) {

218 std::string MCStr =

219 "[" +

222 "]";

224 }

225 }

229 OS << " (idx: " << Obj.getSymbolIndex(Sym.getRawDataRefImpl().p) << ")";

232 OS << " (csect idx: "

233 << Obj.getSymbolIndex(ParentSym->getRawDataRefImpl().p) << ")";

234 }

235 }

236 OS << "\n";

237}

238#endif

239

240Error XCOFFLinkGraphBuilder::processCsectsAndSymbols() {

241 LLVM_DEBUG(dbgs() << " Creating graph blocks and symbols...\n");

242

243 for ([[maybe_unused]] auto [K, V] : SectionTable) {

245 << " section: " << V.Section->getName() << ")\n");

246 }

247

250

252 if (!Flags)

253 return Flags.takeError();

254

258

259 auto SymbolIndex = Obj.getSymbolIndex(Symbol.getEntryAddress());

261 if (!SymbolName)

263

264 if (External) {

266 SymbolIndexTable[SymbolIndex] =

267 &G->addExternalSymbol(*SymbolName, Symbol.getSize(), Weak);

268 continue;

269 }

270

271 if (Symbol.isCsectSymbol()) {

272 LLVM_DEBUG(dbgs() << " skipped: not a csect symbol\n");

273 continue;

274 }

275

277 object::XCOFFSymbolRef CsectSymbol = ParentSym ? *ParentSym : Symbol;

278

279 auto CsectSymbolIndex = Obj.getSymbolIndex(CsectSymbol.getEntryAddress());

281

282 bool IsUndefinedSection = !SectionTable.contains(ParentSectionNumber);

283 Section *ParentSection = !IsUndefinedSection

284 ? SectionTable[ParentSectionNumber].Section

285 : UndefSection;

287

288

289 if (!CsectTable.contains(CsectSymbolIndex) && !IsUndefinedSection) {

290 object::SectionRef &SectionRef =

291 SectionTable[ParentSectionNumber].SectionData;

294 return Data.takeError();

295 auto CsectSymbolAddr = CsectSymbol.getAddress();

296 if (!CsectSymbolAddr)

297 return CsectSymbolAddr.takeError();

298

299 ArrayRef SectionBuffer{*Data};

301

303 << ", size = " << CsectSymbol.getSize()

304 << ", storage class = "

306 << "\n");

307

308 B = &G->createContentBlock(

310 orc::ExecutorAddr(*CsectSymbolAddr), CsectSymbol.getAlignment(), 0);

311

312 CsectTable[CsectSymbolIndex] = B;

313 } else {

314 B = CsectTable[CsectSymbolIndex];

315 }

316

323

324

326 auto SymbolAddr = Symbol.getAddress();

327 if (!SymbolAddr)

328 return SymbolAddr.takeError();

329 auto IsCallableOrErr = Symbol.isFunction();

330 if (!IsCallableOrErr)

331 return IsCallableOrErr.takeError();

332

333 auto BlockOffset = *SymbolAddr - B->getAddress().getValue();

334

336 << ", scope = " << getScopeName(S) << ", B = "

337 << format_hex(B->getAddress().getValue(), 16) << "\n");

338

339 SymbolIndexTable[SymbolIndex] =

340 &G->addDefinedSymbol(*B, BlockOffset, *SymbolName, Symbol.getSize(), L,

341 S, *IsCallableOrErr, true);

342 }

343

345}

346

347Error XCOFFLinkGraphBuilder::processRelocations() {

349

350 for (object::SectionRef Section : Obj.sections()) {

352 if (!SectionName)

354

355 LLVM_DEBUG(dbgs() << " Relocations for section " << *SectionName

356 << ":\n");

357

358 for (object::RelocationRef Relocation : Section.relocations()) {

359 SmallString<16> RelocName;

360 Relocation.getTypeName(RelocName);

361 object::SymbolRef Symbol = *Relocation.getSymbol();

362

363 auto TargetSymbol = Symbol.getName();

364 if (!TargetSymbol)

365 return TargetSymbol.takeError();

366

367 auto SymbolIndex = Obj.getSymbolIndex(Symbol.getRawDataRefImpl().p);

368

370 << " (idx: " << SymbolIndex << ")"

371 << " " << RelocName << " " << *TargetSymbol << "\n";);

372

373 assert(SymbolIndexTable.contains(SymbolIndex) &&

374 "Relocation needs a record in the symbol table");

375 auto *S = SymbolIndexTable[SymbolIndex];

376 auto It = find_if(G->blocks(),

377 [Target = orc::ExecutorAddr(Section.getAddress() +

378 Relocation.getOffset())](

379 const Block *B) -> bool {

380 return B->getRange().contains(Target);

381 });

382 assert(It != G->blocks().end() &&

383 "Cannot find the target relocation block");

385

386 auto TargetBlockOffset = Section.getAddress() + Relocation.getOffset() -

387 B->getAddress().getValue();

388 switch (Relocation.getType()) {

391 break;

392 default:

393 SmallString<16> RelocType;

394 Relocation.getTypeName(RelocType);

396 "Unsupported Relocation Type: " + RelocType, std::error_code());

397 }

398 }

399 }

400

402}

403

405 LLVM_DEBUG(dbgs() << "Building XCOFFLinkGraph...\n");

406

407

408

409 if (auto Err = processSections())

410 return Err;

411 if (auto Err = processCsectsAndSymbols())

412 return Err;

413 if (auto Err = processRelocations())

414 return Err;

415

416 return std::move(G);

417}

418

419}

420}

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

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

static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)

ArrayRef< T > slice(size_t N, size_t M) const

slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.

bool contains(const_arg_type_t< KeyT > Val) const

Return true if the specified key is in the map, false otherwise.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

reference get()

Returns a reference to the stored T value.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

Manages the enabling and disabling of subtarget specific features.

Triple - Helper class for working with autoconf configuration names.

const char *(*)(Edge::Kind) GetEdgeKindNameFunction

Represents an object file section.

Expected< std::unique_ptr< LinkGraph > > buildGraph()

Definition XCOFFLinkGraphBuilder.cpp:404

XCOFFLinkGraphBuilder(const object::XCOFFObjectFile &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)

Definition XCOFFLinkGraphBuilder.cpp:33

DataRefImpl getRawDataRefImpl() const

section_iterator_range sections() const

This is a value type class that represents a single section in the list of sections in the object fil...

Expected< StringRef > getContents() const

uint64_t getAddress() const

This is a value type class that represents a single symbol in the list of symbols in the object file.

uint32_t getAlignment() const

Get the alignment of this symbol as the actual value (not log 2).

Expected< uint64_t > getAddress() const

Returns the symbol virtual address (i.e.

xcoff_symbol_iterator_range symbols() const

LLVM_ABI Expected< XCOFFCsectAuxRef > getXCOFFCsectAuxRef() const

int16_t getSectionNumber() const

LLVM_ABI bool isCsectSymbol() const

LLVM_ABI Expected< StringRef > getName() const

uintptr_t getEntryAddress() const

XCOFF::StorageClass getStorageClass() const

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

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

constexpr char SymbolName[]

Key for Kernel::Metadata::mSymbolName.

LLVM_ABI StringRef getMappingClassString(XCOFF::StorageMappingClass SMC)

@ R_POS

Positive relocation.

LLVM_ABI const char * getLinkageName(Linkage L)

For errors and debugging output.

static llvm::StringRef getStorageClassString(XCOFF::StorageClass SC)

Definition XCOFFLinkGraphBuilder.cpp:44

static void printSymbolEntry(raw_ostream &OS, const object::XCOFFObjectFile &Obj, const object::XCOFFSymbolRef &Sym)

Definition XCOFFLinkGraphBuilder.cpp:210

LLVM_ABI const char * getScopeName(Scope S)

For debugging output.

Linkage

Describes symbol linkage. This can be used to resolve definition clashes.

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

static std::optional< object::XCOFFSymbolRef > getXCOFFSymbolContainingSymbolRef(const object::XCOFFObjectFile &Obj, const object::SymbolRef &Sym)

Definition XCOFFLinkGraphBuilder.cpp:191

MemProt

Describes Read/Write/Exec permissions for memory.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)

format_hex - Output N as a fixed width hexadecimal.

FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)

format_hex_no_prefix - Output N as a fixed width hexadecimal.

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

@ Global

Append to llvm.global_dtors.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

FormattedString left_justify(StringRef Str, unsigned Width)

left_justify - append spaces after string so total output is Width characters.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

Implement std::hash so that hash_code can be used in STL containers.