[llvm] 50bb1b9 - [yaml2obj] Initial the support of yaml2obj for 32-bit XCOFF.
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 6 21:15:28 PDT 2021
Author: Esme-Yi
Date: 2021-06-07T04:14:44Z
New Revision: 50bb1b930dbce6ac2bd6af599f2e2a7d00f36ea5
URL: https://github.com/llvm/llvm-project/commit/50bb1b930dbce6ac2bd6af599f2e2a7d00f36ea5
DIFF: https://github.com/llvm/llvm-project/commit/50bb1b930dbce6ac2bd6af599f2e2a7d00f36ea5.diff
LOG: [yaml2obj] Initial the support of yaml2obj for 32-bit XCOFF.
Summary: The patch implements the mapping of the Yaml
information to XCOFF object file to enable the yaml2obj
tool for XCOFF. Currently only 32-bit is supported.
Reviewed By: jhenderson, shchenz
Differential Revision: https://reviews.llvm.org/D95505
Added:
llvm/lib/ObjectYAML/XCOFFEmitter.cpp
llvm/test/tools/yaml2obj/XCOFF/basic-doc.yaml
llvm/test/tools/yaml2obj/XCOFF/full-contents.yaml
Modified:
llvm/include/llvm/BinaryFormat/XCOFF.h
llvm/include/llvm/ObjectYAML/ObjectYAML.h
llvm/include/llvm/ObjectYAML/XCOFFYAML.h
llvm/include/llvm/ObjectYAML/yaml2obj.h
llvm/lib/ObjectYAML/CMakeLists.txt
llvm/lib/ObjectYAML/ObjectYAML.cpp
llvm/lib/ObjectYAML/XCOFFYAML.cpp
llvm/lib/ObjectYAML/yaml2obj.cpp
llvm/utils/gn/secondary/llvm/lib/ObjectYAML/BUILD.gn
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h
index 803a3ab04fc75..3fcf302366abb 100644
--- a/llvm/include/llvm/BinaryFormat/XCOFF.h
+++ b/llvm/include/llvm/BinaryFormat/XCOFF.h
@@ -33,6 +33,8 @@ constexpr uint8_t AllocRegNo = 31;
enum ReservedSectionNum : int16_t { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
+enum MagicNumber : uint16_t { XCOFF32 = 0x01DF, XCOFF64 = 0x01F7 };
+
// x_smclas field of x_csect from system header: /usr/include/syms.h
/// Storage Mapping Class definitions.
enum StorageMappingClass : uint8_t {
diff --git a/llvm/include/llvm/ObjectYAML/ObjectYAML.h b/llvm/include/llvm/ObjectYAML/ObjectYAML.h
index dd26ce3e9703b..312777aadd4c3 100644
--- a/llvm/include/llvm/ObjectYAML/ObjectYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ObjectYAML.h
@@ -15,6 +15,7 @@
#include "llvm/ObjectYAML/MachOYAML.h"
#include "llvm/ObjectYAML/MinidumpYAML.h"
#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/ObjectYAML/XCOFFYAML.h"
#include "llvm/Support/YAMLTraits.h"
#include <memory>
@@ -31,6 +32,7 @@ struct YamlObjectFile {
std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
std::unique_ptr<MinidumpYAML::Object> Minidump;
std::unique_ptr<WasmYAML::Object> Wasm;
+ std::unique_ptr<XCOFFYAML::Object> Xcoff;
};
template <> struct MappingTraits<YamlObjectFile> {
diff --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
index f99004e69762f..2630175642c40 100644
--- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h
@@ -23,32 +23,62 @@ struct FileHeader {
llvm::yaml::Hex16 Magic;
uint16_t NumberOfSections;
int32_t TimeStamp;
- llvm::yaml::Hex32 SymbolTableOffset; // File offset to symbol table.
- int32_t NumberOfSymTableEntries;
+ llvm::yaml::Hex64 SymbolTableOffset;
+ uint32_t NumberOfSymTableEntries;
uint16_t AuxHeaderSize;
llvm::yaml::Hex16 Flags;
};
+struct Relocation {
+ llvm::yaml::Hex64 VirtualAddress;
+ llvm::yaml::Hex64 SymbolIndex;
+ llvm::yaml::Hex8 Info;
+ llvm::yaml::Hex8 Type;
+};
+
+struct Section {
+ StringRef SectionName;
+ llvm::yaml::Hex64 Address;
+ llvm::yaml::Hex64 Size;
+ llvm::yaml::Hex64 FileOffsetToData;
+ llvm::yaml::Hex64 FileOffsetToRelocations;
+ llvm::yaml::Hex64 FileOffsetToLineNumbers; // Line number pointer. Not supported yet.
+ llvm::yaml::Hex16 NumberOfRelocations;
+ llvm::yaml::Hex16 NumberOfLineNumbers; // Line number counts. Not supported yet.
+ uint32_t Flags;
+ yaml::BinaryRef SectionData;
+ std::vector<Relocation> Relocations;
+};
+
struct Symbol {
StringRef SymbolName;
- llvm::yaml::Hex32 Value; // Symbol value; storage class-dependent.
+ llvm::yaml::Hex64 Value; // Symbol value; storage class-dependent.
StringRef SectionName;
llvm::yaml::Hex16 Type;
XCOFF::StorageClass StorageClass;
- uint8_t NumberOfAuxEntries; // Number of auxiliary entries
+ uint8_t NumberOfAuxEntries;
};
struct Object {
FileHeader Header;
+ std::vector<Section> Sections;
std::vector<Symbol> Symbols;
Object();
};
} // namespace XCOFFYAML
} // namespace llvm
+
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol)
+LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Relocation)
+LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Section)
+
namespace llvm {
namespace yaml {
+template <> struct ScalarBitSetTraits<XCOFF::SectionTypeFlags> {
+ static void bitset(IO &IO, XCOFF::SectionTypeFlags &Value);
+};
+
template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
static void enumeration(IO &IO, XCOFF::StorageClass &Value);
};
@@ -57,14 +87,23 @@ template <> struct MappingTraits<XCOFFYAML::FileHeader> {
static void mapping(IO &IO, XCOFFYAML::FileHeader &H);
};
-template <> struct MappingTraits<XCOFFYAML::Object> {
- static void mapping(IO &IO, XCOFFYAML::Object &Obj);
-};
template <> struct MappingTraits<XCOFFYAML::Symbol> {
static void mapping(IO &IO, XCOFFYAML::Symbol &S);
};
+template <> struct MappingTraits<XCOFFYAML::Relocation> {
+ static void mapping(IO &IO, XCOFFYAML::Relocation &R);
+};
+
+template <> struct MappingTraits<XCOFFYAML::Section> {
+ static void mapping(IO &IO, XCOFFYAML::Section &Sec);
+};
+
+template <> struct MappingTraits<XCOFFYAML::Object> {
+ static void mapping(IO &IO, XCOFFYAML::Object &Obj);
+};
+
} // namespace yaml
} // namespace llvm
diff --git a/llvm/include/llvm/ObjectYAML/yaml2obj.h b/llvm/include/llvm/ObjectYAML/yaml2obj.h
index 21dabb8597d4c..468f673fd4510 100644
--- a/llvm/include/llvm/ObjectYAML/yaml2obj.h
+++ b/llvm/include/llvm/ObjectYAML/yaml2obj.h
@@ -40,6 +40,10 @@ namespace WasmYAML {
struct Object;
}
+namespace XCOFFYAML {
+struct Object;
+}
+
namespace ArchYAML {
struct Archive;
}
@@ -58,6 +62,7 @@ bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH);
bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out,
ErrorHandler EH);
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
+bool yaml2xcoff(XCOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
bool convertYAML(Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
unsigned DocNum = 1, uint64_t MaxSize = UINT64_MAX);
diff --git a/llvm/lib/ObjectYAML/CMakeLists.txt b/llvm/lib/ObjectYAML/CMakeLists.txt
index ee241f86d25b8..acb9f7cd11aea 100644
--- a/llvm/lib/ObjectYAML/CMakeLists.txt
+++ b/llvm/lib/ObjectYAML/CMakeLists.txt
@@ -18,6 +18,7 @@ add_llvm_component_library(LLVMObjectYAML
MinidumpYAML.cpp
WasmEmitter.cpp
WasmYAML.cpp
+ XCOFFEmitter.cpp
XCOFFYAML.cpp
YAML.cpp
yaml2obj.cpp
diff --git a/llvm/lib/ObjectYAML/ObjectYAML.cpp b/llvm/lib/ObjectYAML/ObjectYAML.cpp
index 4564b537c9a14..63769d2eba0e4 100644
--- a/llvm/lib/ObjectYAML/ObjectYAML.cpp
+++ b/llvm/lib/ObjectYAML/ObjectYAML.cpp
@@ -59,6 +59,9 @@ void MappingTraits<YamlObjectFile>::mapping(IO &IO,
} else if (IO.mapTag("!WASM")) {
ObjectFile.Wasm.reset(new WasmYAML::Object());
MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm);
+ } else if (IO.mapTag("!XCOFF")) {
+ ObjectFile.Xcoff.reset(new XCOFFYAML::Object());
+ MappingTraits<XCOFFYAML::Object>::mapping(IO, *ObjectFile.Xcoff);
} else if (const Node *N = In.getCurrentNode()) {
if (N->getRawTag().empty())
IO.setError("YAML Object File missing document type tag!");
diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
new file mode 100644
index 0000000000000..67c890eebd775
--- /dev/null
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -0,0 +1,315 @@
+//===- yaml2xcoff - Convert YAML to a xcoff object file -------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// The xcoff component of yaml2obj.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/ObjectYAML/ObjectYAML.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/LEB128.h"
+
+using namespace llvm;
+
+namespace {
+
+constexpr unsigned DefaultSectionAlign = 4;
+constexpr int16_t MaxSectionIndex = INT16_MAX;
+constexpr uint32_t MaxRawDataSize = UINT32_MAX;
+
+class XCOFFWriter {
+public:
+ XCOFFWriter(XCOFFYAML::Object &Obj, raw_ostream &OS, yaml::ErrorHandler EH)
+ : Obj(Obj), W(OS, support::big), ErrHandler(EH) {
+ Is64Bit = Obj.Header.Magic == XCOFF::XCOFF64;
+ }
+ bool writeXCOFF();
+
+private:
+ bool initFileHeader(uint64_t CurrentOffset);
+ bool initSectionHeader(uint64_t &CurrentOffset);
+ bool initRelocations(uint64_t &CurrentOffset);
+ bool assignAddressesAndIndices();
+ void writeFileHeader();
+ void writeSectionHeader();
+ bool writeSectionData();
+ bool writeRelocations();
+ bool writeSymbols();
+
+ XCOFFYAML::Object &Obj;
+ bool Is64Bit = false;
+ support::endian::Writer W;
+ yaml::ErrorHandler ErrHandler;
+ uint64_t StartOffset;
+ // Map the section name to its corrresponding section index.
+ DenseMap<StringRef, int16_t> SectionIndexMap = {
+ {StringRef("N_DEBUG"), XCOFF::N_DEBUG},
+ {StringRef("N_ABS"), XCOFF::N_ABS},
+ {StringRef("N_UNDEF"), XCOFF::N_UNDEF}};
+ XCOFFYAML::FileHeader InitFileHdr = Obj.Header;
+ std::vector<XCOFFYAML::Section> InitSections = Obj.Sections;
+};
+
+static void writeName(StringRef StrName, support::endian::Writer W) {
+ char Name[XCOFF::NameSize];
+ memset(Name, 0, XCOFF::NameSize);
+ memcpy(Name, StrName.data(), StrName.size());
+ ArrayRef<char> NameRef(Name, XCOFF::NameSize);
+ W.write(NameRef);
+}
+
+bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
+ for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
+ if (!InitSections[I].Relocations.empty()) {
+ InitSections[I].NumberOfRelocations = InitSections[I].Relocations.size();
+ InitSections[I].FileOffsetToRelocations = CurrentOffset;
+ CurrentOffset += InitSections[I].NumberOfRelocations *
+ XCOFF::RelocationSerializationSize32;
+ if (CurrentOffset > MaxRawDataSize) {
+ ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
+ "exceeded when writing relocation data");
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool XCOFFWriter::initSectionHeader(uint64_t &CurrentOffset) {
+ uint64_t CurrentSecAddr = 0;
+ for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
+ if (CurrentOffset > MaxRawDataSize) {
+ ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
+ "exceeded when writing section data");
+ return false;
+ }
+
+ // Assign indices for sections.
+ if (InitSections[I].SectionName.size() &&
+ !SectionIndexMap[InitSections[I].SectionName]) {
+ // The section index starts from 1.
+ SectionIndexMap[InitSections[I].SectionName] = I + 1;
+ if ((I + 1) > MaxSectionIndex) {
+ ErrHandler("exceeded the maximum permitted section index of " +
+ Twine(MaxSectionIndex));
+ return false;
+ }
+ }
+
+ // Calculate the physical/virtual address. This field should contain 0 for
+ // all sections except the text, data and bss sections.
+ if (InitSections[I].Flags != XCOFF::STYP_TEXT &&
+ InitSections[I].Flags != XCOFF::STYP_DATA &&
+ InitSections[I].Flags != XCOFF::STYP_BSS)
+ InitSections[I].Address = 0;
+ else
+ InitSections[I].Address = CurrentSecAddr;
+
+ // Calculate the FileOffsetToData and data size for sections.
+ if (InitSections[I].SectionData.binary_size()) {
+ InitSections[I].FileOffsetToData = CurrentOffset;
+ CurrentOffset += InitSections[I].SectionData.binary_size();
+ // Ensure the offset is aligned to DefaultSectionAlign.
+ CurrentOffset = alignTo(CurrentOffset, DefaultSectionAlign);
+ InitSections[I].Size = CurrentOffset - InitSections[I].FileOffsetToData;
+ CurrentSecAddr += InitSections[I].Size;
+ }
+ }
+ return initRelocations(CurrentOffset);
+}
+
+bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
+ // The default format of the object file is XCOFF32.
+ InitFileHdr.Magic = XCOFF::XCOFF32;
+ InitFileHdr.NumberOfSections = Obj.Sections.size();
+ InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();
+
+ for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
+ // Add the number of auxiliary symbols to the total number.
+ InitFileHdr.NumberOfSymTableEntries += YamlSym.NumberOfAuxEntries;
+ }
+
+ // Calculate SymbolTableOffset for the file header.
+ if (InitFileHdr.NumberOfSymTableEntries) {
+ InitFileHdr.SymbolTableOffset = CurrentOffset;
+ CurrentOffset +=
+ InitFileHdr.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize;
+ if (CurrentOffset > MaxRawDataSize) {
+ ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
+ "exceeded when writing symbols");
+ return false;
+ }
+ }
+ // TODO: Calculate FileOffsetToLineNumbers when line number supported.
+ return true;
+}
+
+bool XCOFFWriter::assignAddressesAndIndices() {
+ uint64_t CurrentOffset =
+ sizeof(XCOFF::FileHeader32) /* TODO: + auxiliaryHeaderSize() */ +
+ InitSections.size() * sizeof(XCOFF::SectionHeader32);
+
+ // Calculate section header info.
+ if (!initSectionHeader(CurrentOffset))
+ return false;
+ // Calculate file header info.
+ return initFileHeader(CurrentOffset);
+}
+
+void XCOFFWriter::writeFileHeader() {
+ W.write<uint16_t>(Obj.Header.Magic ? Obj.Header.Magic : InitFileHdr.Magic);
+ W.write<uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
+ : InitFileHdr.NumberOfSections);
+ W.write<int32_t>(Obj.Header.TimeStamp);
+ W.write<uint32_t>(Obj.Header.SymbolTableOffset
+ ? Obj.Header.SymbolTableOffset
+ : InitFileHdr.SymbolTableOffset);
+ W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
+ ? Obj.Header.NumberOfSymTableEntries
+ : InitFileHdr.NumberOfSymTableEntries);
+ W.write<uint16_t>(Obj.Header.AuxHeaderSize);
+ W.write<uint16_t>(Obj.Header.Flags);
+}
+
+void XCOFFWriter::writeSectionHeader() {
+ for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
+ XCOFFYAML::Section YamlSec = Obj.Sections[I];
+ XCOFFYAML::Section DerivedSec = InitSections[I];
+ writeName(YamlSec.SectionName, W);
+ // Virtual address is the same as physical address.
+ uint32_t SectionAddress =
+ YamlSec.Address ? YamlSec.Address : DerivedSec.Address;
+ W.write<uint32_t>(SectionAddress); // Physical address
+ W.write<uint32_t>(SectionAddress); // Virtual address
+ W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
+ W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
+ : DerivedSec.FileOffsetToData);
+ W.write<uint32_t>(YamlSec.FileOffsetToRelocations
+ ? YamlSec.FileOffsetToRelocations
+ : DerivedSec.FileOffsetToRelocations);
+ W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
+ W.write<uint16_t>(YamlSec.NumberOfRelocations
+ ? YamlSec.NumberOfRelocations
+ : DerivedSec.NumberOfRelocations);
+ W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
+ W.write<int32_t>(YamlSec.Flags);
+ }
+}
+
+bool XCOFFWriter::writeSectionData() {
+ for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
+ XCOFFYAML::Section YamlSec = Obj.Sections[I];
+ if (YamlSec.SectionData.binary_size()) {
+ // Fill the padding size with zeros.
+ int64_t PaddingSize =
+ InitSections[I].FileOffsetToData - (W.OS.tell() - StartOffset);
+ if (PaddingSize < 0) {
+ ErrHandler("redundant data was written before section data");
+ return false;
+ }
+ if (PaddingSize > 0)
+ W.OS.write_zeros(PaddingSize);
+ YamlSec.SectionData.writeAsBinary(W.OS);
+ }
+ }
+ return true;
+}
+
+bool XCOFFWriter::writeRelocations() {
+ for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
+ XCOFFYAML::Section YamlSec = Obj.Sections[I];
+ if (!YamlSec.Relocations.empty()) {
+ int64_t PaddingSize =
+ InitSections[I].FileOffsetToRelocations - (W.OS.tell() - StartOffset);
+ if (PaddingSize < 0) {
+ ErrHandler("redundant data was written before relocations");
+ return false;
+ }
+ if (PaddingSize > 0)
+ W.OS.write_zeros(PaddingSize);
+ for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) {
+ W.write<uint32_t>(YamlRel.VirtualAddress);
+ W.write<uint32_t>(YamlRel.SymbolIndex);
+ W.write<uint8_t>(YamlRel.Info);
+ W.write<uint8_t>(YamlRel.Type);
+ }
+ }
+ }
+ return true;
+}
+
+bool XCOFFWriter::writeSymbols() {
+ int64_t PaddingSize =
+ (uint64_t)InitFileHdr.SymbolTableOffset - (W.OS.tell() - StartOffset);
+ if (PaddingSize < 0) {
+ ErrHandler("redundant data was written before symbols");
+ return false;
+ }
+ if (PaddingSize > 0)
+ W.OS.write_zeros(PaddingSize);
+ for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
+ writeName(YamlSym.SymbolName, W);
+ W.write<uint32_t>(YamlSym.Value);
+ W.write<int16_t>(
+ YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0);
+ W.write<uint16_t>(YamlSym.Type);
+ W.write<uint8_t>(YamlSym.StorageClass);
+ W.write<uint8_t>(YamlSym.NumberOfAuxEntries);
+
+ // Now output the auxiliary entry.
+ for (uint8_t I = 0, E = YamlSym.NumberOfAuxEntries; I < E; ++I) {
+ // TODO: Auxiliary entry is not supported yet.
+ // The auxiliary entries for a symbol follow its symbol table entry. The
+ // length of each auxiliary entry is the same as a symbol table entry (18
+ // bytes). The format and quantity of auxiliary entries depend on the
+ // storage class (n_sclass) and type (n_type) of the symbol table entry.
+ W.OS.write_zeros(18);
+ }
+ }
+ return true;
+}
+
+bool XCOFFWriter::writeXCOFF() {
+ if (Is64Bit) {
+ ErrHandler("only XCOFF32 is currently supported");
+ return false;
+ }
+ if (!assignAddressesAndIndices())
+ return false;
+ StartOffset = W.OS.tell();
+ writeFileHeader();
+ if (!Obj.Sections.empty()) {
+ writeSectionHeader();
+ if (!writeSectionData())
+ return false;
+ if (!writeRelocations())
+ return false;
+ }
+ if (!Obj.Symbols.empty())
+ return writeSymbols();
+ return true;
+}
+
+} // end anonymous namespace
+
+namespace llvm {
+namespace yaml {
+
+bool yaml2xcoff(XCOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
+ XCOFFWriter Writer(Doc, Out, EH);
+ return Writer.writeXCOFF();
+}
+
+} // namespace yaml
+} // namespace llvm
diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
index 982e6aecbb987..73d188e274b12 100644
--- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp
@@ -23,6 +23,25 @@ Object::Object() { memset(&Header, 0, sizeof(Header)); }
namespace yaml {
+void ScalarBitSetTraits<XCOFF::SectionTypeFlags>::bitset(
+ IO &IO, XCOFF::SectionTypeFlags &Value) {
+#define ECase(X) IO.bitSetCase(Value, #X, XCOFF::X)
+ ECase(STYP_PAD);
+ ECase(STYP_DWARF);
+ ECase(STYP_TEXT);
+ ECase(STYP_DATA);
+ ECase(STYP_BSS);
+ ECase(STYP_EXCEPT);
+ ECase(STYP_INFO);
+ ECase(STYP_TDATA);
+ ECase(STYP_TBSS);
+ ECase(STYP_LOADER);
+ ECase(STYP_DEBUG);
+ ECase(STYP_TYPCHK);
+ ECase(STYP_OVRFLO);
+#undef ECase
+}
+
void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
IO &IO, XCOFF::StorageClass &Value) {
#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
@@ -79,30 +98,64 @@ void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
#undef ECase
}
+struct NSectionFlags {
+ NSectionFlags(IO &) : Flags(XCOFF::SectionTypeFlags(0)) {}
+ NSectionFlags(IO &, uint32_t C) : Flags(XCOFF::SectionTypeFlags(C)) {}
+
+ uint32_t denormalize(IO &) { return Flags; }
+
+ XCOFF::SectionTypeFlags Flags;
+};
+
void MappingTraits<XCOFFYAML::FileHeader>::mapping(
IO &IO, XCOFFYAML::FileHeader &FileHdr) {
- IO.mapRequired("MagicNumber", FileHdr.Magic);
- IO.mapRequired("NumberOfSections", FileHdr.NumberOfSections);
- IO.mapRequired("CreationTime", FileHdr.TimeStamp);
- IO.mapRequired("OffsetToSymbolTable", FileHdr.SymbolTableOffset);
- IO.mapRequired("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries);
- IO.mapRequired("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize);
- IO.mapRequired("Flags", FileHdr.Flags);
+ IO.mapOptional("MagicNumber", FileHdr.Magic);
+ IO.mapOptional("NumberOfSections", FileHdr.NumberOfSections);
+ IO.mapOptional("CreationTime", FileHdr.TimeStamp);
+ IO.mapOptional("OffsetToSymbolTable", FileHdr.SymbolTableOffset);
+ IO.mapOptional("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries);
+ IO.mapOptional("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize);
+ IO.mapOptional("Flags", FileHdr.Flags);
+}
+
+void MappingTraits<XCOFFYAML::Relocation>::mapping(IO &IO,
+ XCOFFYAML::Relocation &R) {
+ IO.mapOptional("Address", R.VirtualAddress);
+ IO.mapOptional("Symbol", R.SymbolIndex);
+ IO.mapOptional("Info", R.Info);
+ IO.mapOptional("Type", R.Type);
+}
+
+void MappingTraits<XCOFFYAML::Section>::mapping(IO &IO,
+ XCOFFYAML::Section &Sec) {
+ MappingNormalization<NSectionFlags, uint32_t> NC(IO, Sec.Flags);
+ IO.mapOptional("Name", Sec.SectionName);
+ IO.mapOptional("Address", Sec.Address);
+ IO.mapOptional("Size", Sec.Size);
+ IO.mapOptional("FileOffsetToData", Sec.FileOffsetToData);
+ IO.mapOptional("FileOffsetToRelocations", Sec.FileOffsetToRelocations);
+ IO.mapOptional("FileOffsetToLineNumbers", Sec.FileOffsetToLineNumbers);
+ IO.mapOptional("NumberOfRelocations", Sec.NumberOfRelocations);
+ IO.mapOptional("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
+ IO.mapOptional("Flags", NC->Flags);
+ IO.mapOptional("SectionData", Sec.SectionData);
+ IO.mapOptional("Relocations", Sec.Relocations);
}
void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
IO.mapRequired("Name", S.SymbolName);
- IO.mapRequired("Value", S.Value);
- IO.mapRequired("Section", S.SectionName);
- IO.mapRequired("Type", S.Type);
- IO.mapRequired("StorageClass", S.StorageClass);
- IO.mapRequired("NumberOfAuxEntries", S.NumberOfAuxEntries);
+ IO.mapOptional("Value", S.Value);
+ IO.mapOptional("Section", S.SectionName);
+ IO.mapOptional("Type", S.Type);
+ IO.mapOptional("StorageClass", S.StorageClass);
+ IO.mapOptional("NumberOfAuxEntries", S.NumberOfAuxEntries);
}
void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
IO.mapTag("!XCOFF", true);
IO.mapRequired("FileHeader", Obj.Header);
- IO.mapRequired("Symbols", Obj.Symbols);
+ IO.mapOptional("Sections", Obj.Sections);
+ IO.mapOptional("Symbols", Obj.Symbols);
}
} // namespace yaml
diff --git a/llvm/lib/ObjectYAML/yaml2obj.cpp b/llvm/lib/ObjectYAML/yaml2obj.cpp
index ef2ab83dcd24e..d19fa0a525302 100644
--- a/llvm/lib/ObjectYAML/yaml2obj.cpp
+++ b/llvm/lib/ObjectYAML/yaml2obj.cpp
@@ -44,6 +44,8 @@ bool convertYAML(yaml::Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
return yaml2minidump(*Doc.Minidump, Out, ErrHandler);
if (Doc.Wasm)
return yaml2wasm(*Doc.Wasm, Out, ErrHandler);
+ if (Doc.Xcoff)
+ return yaml2xcoff(*Doc.Xcoff, Out, ErrHandler);
ErrHandler("unknown document type");
return false;
diff --git a/llvm/test/tools/yaml2obj/XCOFF/basic-doc.yaml b/llvm/test/tools/yaml2obj/XCOFF/basic-doc.yaml
new file mode 100644
index 0000000000000..5d9ec19afa931
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/basic-doc.yaml
@@ -0,0 +1,164 @@
+## Check that yaml2obj automatically assigns omited fields with values.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --headers --symbols %t | FileCheck %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ SectionData: "9061FFF880820000"
+ - Name: .data
+ Flags: [ STYP_DATA ]
+ SectionData: "0000000000000FC0"
+ Relocations:
+ - Address: 0x08
+ - Name: .data
+ Relocations:
+ - Type: 0x02
+ - Name: .debug
+ Address: 0x0
+ Size: 0x60
+ Flags: [ STYP_DEBUG, STYP_DATA ]
+ SectionData: 01110103
+ - Flags: [ STYP_BSS, STYP_DWARF, STYP_EXCEPT, STYP_INFO, STYP_TDATA, STYP_TBSS, STYP_LOADER, STYP_TYPCHK, STYP_OVRFLO ]
+Symbols:
+ - Name: .file
+ Section: N_DEBUG
+ - Name: .undef
+ - Name: .abs
+ Section: N_ABS
+ - Name: .text
+ Value: 0x0
+ Section: .text
+ Type: 0x0
+ StorageClass: C_HIDEXT
+ NumberOfAuxEntries: 1
+
+# CHECK: AddressSize: 32bit
+# CHECK-NEXT: FileHeader {
+# CHECK-NEXT: Magic: 0x1DF
+# CHECK-NEXT: NumberOfSections: 5
+# CHECK-NEXT: TimeStamp: None (0x0)
+# CHECK-NEXT: SymbolTableOffset: 0x104
+# CHECK-NEXT: SymbolTableEntries: 5
+# CHECK-NEXT: OptionalHeaderSize: 0x0
+# CHECK-NEXT: Flags: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: Size: 0x8
+# CHECK-NEXT: RawDataOffset: 0xDC
+# CHECK-NEXT: RelocationPointer: 0x0
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 0
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: STYP_TEXT (0x20)
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: PhysicalAddress: 0x8
+# CHECK-NEXT: VirtualAddress: 0x8
+# CHECK-NEXT: Size: 0x8
+# CHECK-NEXT: RawDataOffset: 0xE4
+# CHECK-NEXT: RelocationPointer: 0xF0
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 1
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: STYP_DATA (0x40)
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: Size: 0x0
+# CHECK-NEXT: RawDataOffset: 0x0
+# CHECK-NEXT: RelocationPointer: 0xFA
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 1
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .debug
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: Size: 0x60
+# CHECK-NEXT: RawDataOffset: 0xEC
+# CHECK-NEXT: RelocationPointer: 0x0
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 0
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: 0x2040
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Name:
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: Size: 0x0
+# CHECK-NEXT: RawDataOffset: 0x0
+# CHECK-NEXT: RelocationPointer: 0x0
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 0
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: 0xDF90
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: .file
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Section: N_DEBUG
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_NULL (0x0)
+# CHECK-NEXT: NumberOfAuxEntries: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: Name: .undef
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Section: N_UNDEF
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_NULL (0x0)
+# CHECK-NEXT: NumberOfAuxEntries: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .abs
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Section: N_ABS
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_NULL (0x0)
+# CHECK-NEXT: NumberOfAuxEntries: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Value (RelocatableAddress): 0x0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_HIDEXT (0x6B)
+# CHECK-NEXT: NumberOfAuxEntries: 1
+# CHECK-NEXT: CSECT Auxiliary Entry {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: SectionLen: 0
+# CHECK-NEXT: ParameterHashIndex: 0x0
+# CHECK-NEXT: TypeChkSectNum: 0x0
+# CHECK-NEXT: SymbolAlignmentLog2: 0
+# CHECK-NEXT: SymbolType: XTY_ER (0x0)
+# CHECK-NEXT: StorageMappingClass: XMC_PR (0x0)
+# CHECK-NEXT: StabInfoIndex: 0x0
+# CHECK-NEXT: StabSectNum: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/llvm/test/tools/yaml2obj/XCOFF/full-contents.yaml b/llvm/test/tools/yaml2obj/XCOFF/full-contents.yaml
new file mode 100644
index 0000000000000..5fb17c7ac7e1e
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/full-contents.yaml
@@ -0,0 +1,122 @@
+## Test that we can explicitly specify all the fields.
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --headers --symbols %t | FileCheck %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+ NumberOfSections: 2
+ CreationTime: 0
+ OffsetToSymbolTable: 0x7A
+ EntriesInSymbolTable: 4
+ AuxiliaryHeaderSize: 0
+ Flags: 0x0
+Sections:
+ - Name: .text
+ Address: 0x0
+ Size: 0x8
+ FileOffsetToData: 0x64
+ FileOffsetToRelocations: 0x0
+ FileOffsetToLineNumbers: 0x0
+ NumberOfRelocations: 0x0
+ NumberOfLineNumbers: 0x0
+ Flags: [ STYP_TEXT ]
+ SectionData: "3860000048"
+ - Name: .data
+ Address: 0x8
+ Size: 0x4
+ FileOffsetToData: 0x6C
+ FileOffsetToRelocations: 0x70
+ FileOffsetToLineNumbers: 0x0
+ NumberOfRelocations: 0x1
+ NumberOfLineNumbers: 0x0
+ Flags: [ STYP_DATA ]
+ SectionData: "00000088"
+ Relocations:
+ - Address: 0x80
+ Symbol: 0x21
+ Info: 0x1F
+ Type: 0x0
+Symbols:
+ - Name: .text
+ Value: 0x0
+ Section: .text
+ Type: 0x0
+ StorageClass: C_STAT
+ NumberOfAuxEntries: 1
+ - Name: .data
+ Value: 0x80
+ Section: .data
+ Type: 0x0
+ StorageClass: C_STAT
+ NumberOfAuxEntries: 1
+
+# CHECK: FileHeader {
+# CHECK-NEXT: Magic: 0x1DF
+# CHECK-NEXT: NumberOfSections: 2
+# CHECK-NEXT: TimeStamp: None (0x0)
+# CHECK-NEXT: SymbolTableOffset: 0x7A
+# CHECK-NEXT: SymbolTableEntries: 4
+# CHECK-NEXT: OptionalHeaderSize: 0x0
+# CHECK-NEXT: Flags: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: Size: 0x8
+# CHECK-NEXT: RawDataOffset: 0x64
+# CHECK-NEXT: RelocationPointer: 0x0
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 0
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: STYP_TEXT (0x20)
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: PhysicalAddress: 0x8
+# CHECK-NEXT: VirtualAddress: 0x8
+# CHECK-NEXT: Size: 0x4
+# CHECK-NEXT: RawDataOffset: 0x6C
+# CHECK-NEXT: RelocationPointer: 0x70
+# CHECK-NEXT: LineNumberPointer: 0x0
+# CHECK-NEXT: NumberOfRelocations: 1
+# CHECK-NEXT: NumberOfLineNumbers: 0
+# CHECK-NEXT: Type: STYP_DATA (0x40)
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Value (RelocatableAddress): 0x0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_STAT (0x3)
+# CHECK-NEXT: NumberOfAuxEntries: 1
+# CHECK-NEXT: Sect Auxiliary Entry For Stat {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: SectionLength: 0
+# CHECK-NEXT: NumberOfRelocEnt: 0
+# CHECK-NEXT: NumberOfLineNum: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Value (RelocatableAddress): 0x80
+# CHECK-NEXT: Section: .data
+# CHECK-NEXT: Type: 0x0
+# CHECK-NEXT: StorageClass: C_STAT (0x3)
+# CHECK-NEXT: NumberOfAuxEntries: 1
+# CHECK-NEXT: Sect Auxiliary Entry For Stat {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: SectionLength: 0
+# CHECK-NEXT: NumberOfRelocEnt: 0
+# CHECK-NEXT: NumberOfLineNum: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/llvm/utils/gn/secondary/llvm/lib/ObjectYAML/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/ObjectYAML/BUILD.gn
index 0f6c2e8ea3cf7..9f80c4f4813cf 100644
--- a/llvm/utils/gn/secondary/llvm/lib/ObjectYAML/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/ObjectYAML/BUILD.gn
@@ -26,6 +26,7 @@ static_library("ObjectYAML") {
"ObjectYAML.cpp",
"WasmEmitter.cpp",
"WasmYAML.cpp",
+ "XCOFFEmitter.cpp"
"XCOFFYAML.cpp",
"YAML.cpp",
"yaml2obj.cpp",
More information about the llvm-commits
mailing list