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 (.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())](
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.