[llvm] [JITLink][XCOFF] Setup initial build support for XCOFF (PR #127266)

Mikael Holmén via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 4 02:28:48 PDT 2025


================
@@ -0,0 +1,415 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic XCOFF LinkGraph building code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "XCOFFLinkGraphBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/ppc64.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+XCOFFLinkGraphBuilder::XCOFFLinkGraphBuilder(
+    const object::XCOFFObjectFile &Obj,
+    std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
+    SubtargetFeatures Features,
+    LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
+    : Obj(Obj),
+      G(std::make_unique<LinkGraph>(
+          std::string(Obj.getFileName()), std::move(SSP), std::move(TT),
+          std::move(Features), std::move(GetEdgeKindName))) {}
+
+static llvm::StringRef getStorageClassString(XCOFF::StorageClass SC) {
+  switch (SC) {
+  case XCOFF::StorageClass::C_FILE:
+    return "C_FILE (File name)";
+  case XCOFF::StorageClass::C_BINCL:
+    return "C_BINCL (Beginning of include file)";
+  case XCOFF::StorageClass::C_EINCL:
+    return "C_EINCL (Ending of include file)";
+  case XCOFF::StorageClass::C_GSYM:
+    return "C_GSYM (Global variable)";
+  case XCOFF::StorageClass::C_STSYM:
+    return "C_STSYM (Statically allocated symbol)";
+  case XCOFF::StorageClass::C_BCOMM:
+    return "C_BCOMM (Beginning of common block)";
+  case XCOFF::StorageClass::C_ECOMM:
+    return "C_ECOMM (End of common block)";
+  case XCOFF::StorageClass::C_ENTRY:
+    return "C_ENTRY (Alternate entry)";
+  case XCOFF::StorageClass::C_BSTAT:
+    return "C_BSTAT (Beginning of static block)";
+  case XCOFF::StorageClass::C_ESTAT:
+    return "C_ESTAT (End of static block)";
+  case XCOFF::StorageClass::C_GTLS:
+    return "C_GTLS (Global thread-local variable)";
+  case XCOFF::StorageClass::C_STTLS:
+    return "C_STTLS (Static thread-local variable)";
+  case XCOFF::StorageClass::C_DWARF:
+    return "C_DWARF (DWARF section symbol)";
+  case XCOFF::StorageClass::C_LSYM:
+    return "C_LSYM (Automatic variable allocated on stack)";
+  case XCOFF::StorageClass::C_PSYM:
+    return "C_PSYM (Argument to subroutine allocated on stack)";
+  case XCOFF::StorageClass::C_RSYM:
+    return "C_RSYM (Register variable)";
+  case XCOFF::StorageClass::C_RPSYM:
+    return "C_RPSYM (Argument to function stored in register)";
+  case XCOFF::StorageClass::C_ECOML:
+    return "C_ECOML (Local member of common block)";
+  case XCOFF::StorageClass::C_FUN:
+    return "C_FUN (Function or procedure)";
+  case XCOFF::StorageClass::C_EXT:
+    return "C_EXT (External symbol)";
+  case XCOFF::StorageClass::C_WEAKEXT:
+    return "C_WEAKEXT (Weak external symbol)";
+  case XCOFF::StorageClass::C_NULL:
+    return "C_NULL";
+  case XCOFF::StorageClass::C_STAT:
+    return "C_STAT (Static)";
+  case XCOFF::StorageClass::C_BLOCK:
+    return "C_BLOCK (\".bb\" or \".eb\")";
+  case XCOFF::StorageClass::C_FCN:
+    return "C_FCN (\".bf\" or \".ef\")";
+  case XCOFF::StorageClass::C_HIDEXT:
+    return "C_HIDEXT (Un-named external symbol)";
+  case XCOFF::StorageClass::C_INFO:
+    return "C_INFO (Comment string in .info section)";
+  case XCOFF::StorageClass::C_DECL:
+    return "C_DECL (Declaration of object)";
+  case XCOFF::StorageClass::C_AUTO:
+    return "C_AUTO (Automatic variable)";
+  case XCOFF::StorageClass::C_REG:
+    return "C_REG (Register variable)";
+  case XCOFF::StorageClass::C_EXTDEF:
+    return "C_EXTDEF (External definition)";
+  case XCOFF::StorageClass::C_LABEL:
+    return "C_LABEL (Label)";
+  case XCOFF::StorageClass::C_ULABEL:
+    return "C_ULABEL (Undefined label)";
+  case XCOFF::StorageClass::C_MOS:
+    return "C_MOS (Member of structure)";
+  case XCOFF::StorageClass::C_ARG:
+    return "C_ARG (Function argument)";
+  case XCOFF::StorageClass::C_STRTAG:
+    return "C_STRTAG (Structure tag)";
+  case XCOFF::StorageClass::C_MOU:
+    return "C_MOU (Member of union)";
+  case XCOFF::StorageClass::C_UNTAG:
+    return "C_UNTAG (Union tag)";
+  case XCOFF::StorageClass::C_TPDEF:
+    return "C_TPDEF (Type definition)";
+  case XCOFF::StorageClass::C_USTATIC:
+    return "C_USTATIC (Undefined static)";
+  case XCOFF::StorageClass::C_ENTAG:
+    return "C_ENTAG (Enumeration tag)";
+  case XCOFF::StorageClass::C_MOE:
+    return "C_MOE (Member of enumeration)";
+  case XCOFF::StorageClass::C_REGPARM:
+    return "C_REGPARM (Register parameter)";
+  case XCOFF::StorageClass::C_FIELD:
+    return "C_FIELD (Bit field)";
+  case XCOFF::StorageClass::C_EOS:
+    return "C_EOS (End of structure)";
+  case XCOFF::StorageClass::C_LINE:
+    return "C_LINE";
+  case XCOFF::StorageClass::C_ALIAS:
+    return "C_ALIAS (Duplicate tag)";
+  case XCOFF::StorageClass::C_HIDDEN:
+    return "C_HIDDEN (Special storage class for external)";
+  case XCOFF::StorageClass::C_EFCN:
+    return "C_EFCN (Physical end of function)";
+  case XCOFF::StorageClass::C_TCSYM:
+    return "C_TCSYM (Reserved)";
+  }
+}
+
+Error XCOFFLinkGraphBuilder::processSections() {
+  LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
+
+  UndefSection = &G->createSection("*UND*", orc::MemProt::None);
+
+  for (object::SectionRef Section : Obj.sections()) {
+    auto SectionName = Section.getName();
+    if (!SectionName)
+      return SectionName.takeError();
+
+    LLVM_DEBUG({
+      dbgs() << "    section = " << *SectionName
+             << ", idx = " << Section.getIndex()
+             << ", size = " << format_hex_no_prefix(Section.getSize(), 8)
+             << ", vma = " << format_hex(Section.getAddress(), 16) << "\n";
+    });
+
+    // We can skip debug (including dawrf) and pad sections
+    if (Section.isDebugSection() || *SectionName == "pad")
+      continue;
+    LLVM_DEBUG(dbgs() << "        creating graph section\n");
+
+    orc::MemProt Prot = orc::MemProt::Read;
+    if (Section.isText())
+      Prot |= orc::MemProt::Exec;
+    if (Section.isData() || Section.isBSS())
+      Prot |= orc::MemProt::Write;
+
+    jitlink::Section *GraphSec = &G->createSection(*SectionName, Prot);
+    // TODO: Check for no_alloc for certain sections
+
+    assert(!SectionTable.contains(Section.getIndex()) &&
+           "Section with same index already exists");
+    SectionTable[Section.getIndex()] = {GraphSec, Section};
+  }
+
+  return Error::success();
+}
+
+static std::optional<object::XCOFFSymbolRef>
+getXCOFFSymbolContainingSymbolRef(const object::XCOFFObjectFile &Obj,
+                                  const object::SymbolRef &Sym) {
+  const object::XCOFFSymbolRef SymRef =
+      Obj.toSymbolRef(Sym.getRawDataRefImpl());
+  if (!SymRef.isCsectSymbol())
+    return std::nullopt;
+
+  Expected<object::XCOFFCsectAuxRef> CsectAuxEntOrErr =
+      SymRef.getXCOFFCsectAuxRef();
+  if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
+    return std::nullopt;
+  uint32_t Idx =
+      static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
+  object::DataRefImpl DRI;
+  DRI.p = Obj.getSymbolByIndex(Idx);
+  return object::XCOFFSymbolRef(DRI, &Obj);
+}
+
+static void printSymbolEntry(raw_ostream &OS,
----------------
mikaelholmen wrote:

If compiling with
-DLLVM_ENABLE_ASSERTIONS=OFF
we get
```
../lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp:206:13: error: unused function 'printSymbolEntry' [-Werror,-Wunused-function]
  206 | static void printSymbolEntry(raw_ostream &OS,
      |             ^~~~~~~~~~~~~~~~
1 error generated.
```

https://github.com/llvm/llvm-project/pull/127266


More information about the llvm-commits mailing list