1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[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
This commit is contained in:
Esme-Yi 2021-06-07 04:14:44 +00:00
parent 779c968967
commit 4a3c52750c
12 changed files with 729 additions and 20 deletions

View File

@ -33,6 +33,8 @@ constexpr uint8_t AllocRegNo = 31;
enum ReservedSectionNum : int16_t { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 }; 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 // x_smclas field of x_csect from system header: /usr/include/syms.h
/// Storage Mapping Class definitions. /// Storage Mapping Class definitions.
enum StorageMappingClass : uint8_t { enum StorageMappingClass : uint8_t {

View File

@ -15,6 +15,7 @@
#include "llvm/ObjectYAML/MachOYAML.h" #include "llvm/ObjectYAML/MachOYAML.h"
#include "llvm/ObjectYAML/MinidumpYAML.h" #include "llvm/ObjectYAML/MinidumpYAML.h"
#include "llvm/ObjectYAML/WasmYAML.h" #include "llvm/ObjectYAML/WasmYAML.h"
#include "llvm/ObjectYAML/XCOFFYAML.h"
#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/YAMLTraits.h"
#include <memory> #include <memory>
@ -31,6 +32,7 @@ struct YamlObjectFile {
std::unique_ptr<MachOYAML::UniversalBinary> FatMachO; std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
std::unique_ptr<MinidumpYAML::Object> Minidump; std::unique_ptr<MinidumpYAML::Object> Minidump;
std::unique_ptr<WasmYAML::Object> Wasm; std::unique_ptr<WasmYAML::Object> Wasm;
std::unique_ptr<XCOFFYAML::Object> Xcoff;
}; };
template <> struct MappingTraits<YamlObjectFile> { template <> struct MappingTraits<YamlObjectFile> {

View File

@ -23,32 +23,62 @@ struct FileHeader {
llvm::yaml::Hex16 Magic; llvm::yaml::Hex16 Magic;
uint16_t NumberOfSections; uint16_t NumberOfSections;
int32_t TimeStamp; int32_t TimeStamp;
llvm::yaml::Hex32 SymbolTableOffset; // File offset to symbol table. llvm::yaml::Hex64 SymbolTableOffset;
int32_t NumberOfSymTableEntries; uint32_t NumberOfSymTableEntries;
uint16_t AuxHeaderSize; uint16_t AuxHeaderSize;
llvm::yaml::Hex16 Flags; 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 { struct Symbol {
StringRef SymbolName; StringRef SymbolName;
llvm::yaml::Hex32 Value; // Symbol value; storage class-dependent. llvm::yaml::Hex64 Value; // Symbol value; storage class-dependent.
StringRef SectionName; StringRef SectionName;
llvm::yaml::Hex16 Type; llvm::yaml::Hex16 Type;
XCOFF::StorageClass StorageClass; XCOFF::StorageClass StorageClass;
uint8_t NumberOfAuxEntries; // Number of auxiliary entries uint8_t NumberOfAuxEntries;
}; };
struct Object { struct Object {
FileHeader Header; FileHeader Header;
std::vector<Section> Sections;
std::vector<Symbol> Symbols; std::vector<Symbol> Symbols;
Object(); Object();
}; };
} // namespace XCOFFYAML } // namespace XCOFFYAML
} // namespace llvm } // namespace llvm
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol)
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Relocation)
LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Section)
namespace llvm { namespace llvm {
namespace yaml { namespace yaml {
template <> struct ScalarBitSetTraits<XCOFF::SectionTypeFlags> {
static void bitset(IO &IO, XCOFF::SectionTypeFlags &Value);
};
template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> { template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
static void enumeration(IO &IO, XCOFF::StorageClass &Value); 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); 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> { template <> struct MappingTraits<XCOFFYAML::Symbol> {
static void mapping(IO &IO, XCOFFYAML::Symbol &S); 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 yaml
} // namespace llvm } // namespace llvm

View File

@ -40,6 +40,10 @@ namespace WasmYAML {
struct Object; struct Object;
} }
namespace XCOFFYAML {
struct Object;
}
namespace ArchYAML { namespace ArchYAML {
struct Archive; struct Archive;
} }
@ -58,6 +62,7 @@ bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH);
bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out, bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out,
ErrorHandler EH); ErrorHandler EH);
bool yaml2wasm(WasmYAML::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, bool convertYAML(Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
unsigned DocNum = 1, uint64_t MaxSize = UINT64_MAX); unsigned DocNum = 1, uint64_t MaxSize = UINT64_MAX);

View File

@ -18,6 +18,7 @@ add_llvm_component_library(LLVMObjectYAML
MinidumpYAML.cpp MinidumpYAML.cpp
WasmEmitter.cpp WasmEmitter.cpp
WasmYAML.cpp WasmYAML.cpp
XCOFFEmitter.cpp
XCOFFYAML.cpp XCOFFYAML.cpp
YAML.cpp YAML.cpp
yaml2obj.cpp yaml2obj.cpp

View File

@ -59,6 +59,9 @@ void MappingTraits<YamlObjectFile>::mapping(IO &IO,
} else if (IO.mapTag("!WASM")) { } else if (IO.mapTag("!WASM")) {
ObjectFile.Wasm.reset(new WasmYAML::Object()); ObjectFile.Wasm.reset(new WasmYAML::Object());
MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm); 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()) { } else if (const Node *N = In.getCurrentNode()) {
if (N->getRawTag().empty()) if (N->getRawTag().empty())
IO.setError("YAML Object File missing document type tag!"); IO.setError("YAML Object File missing document type tag!");

View File

@ -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

View File

@ -23,6 +23,25 @@ Object::Object() { memset(&Header, 0, sizeof(Header)); }
namespace yaml { 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( void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
IO &IO, XCOFF::StorageClass &Value) { IO &IO, XCOFF::StorageClass &Value) {
#define ECase(X) IO.enumCase(Value, #X, XCOFF::X) #define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
@ -79,30 +98,64 @@ void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
#undef ECase #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( void MappingTraits<XCOFFYAML::FileHeader>::mapping(
IO &IO, XCOFFYAML::FileHeader &FileHdr) { IO &IO, XCOFFYAML::FileHeader &FileHdr) {
IO.mapRequired("MagicNumber", FileHdr.Magic); IO.mapOptional("MagicNumber", FileHdr.Magic);
IO.mapRequired("NumberOfSections", FileHdr.NumberOfSections); IO.mapOptional("NumberOfSections", FileHdr.NumberOfSections);
IO.mapRequired("CreationTime", FileHdr.TimeStamp); IO.mapOptional("CreationTime", FileHdr.TimeStamp);
IO.mapRequired("OffsetToSymbolTable", FileHdr.SymbolTableOffset); IO.mapOptional("OffsetToSymbolTable", FileHdr.SymbolTableOffset);
IO.mapRequired("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries); IO.mapOptional("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries);
IO.mapRequired("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize); IO.mapOptional("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize);
IO.mapRequired("Flags", FileHdr.Flags); 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) { void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
IO.mapRequired("Name", S.SymbolName); IO.mapRequired("Name", S.SymbolName);
IO.mapRequired("Value", S.Value); IO.mapOptional("Value", S.Value);
IO.mapRequired("Section", S.SectionName); IO.mapOptional("Section", S.SectionName);
IO.mapRequired("Type", S.Type); IO.mapOptional("Type", S.Type);
IO.mapRequired("StorageClass", S.StorageClass); IO.mapOptional("StorageClass", S.StorageClass);
IO.mapRequired("NumberOfAuxEntries", S.NumberOfAuxEntries); IO.mapOptional("NumberOfAuxEntries", S.NumberOfAuxEntries);
} }
void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) { void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
IO.mapTag("!XCOFF", true); IO.mapTag("!XCOFF", true);
IO.mapRequired("FileHeader", Obj.Header); IO.mapRequired("FileHeader", Obj.Header);
IO.mapRequired("Symbols", Obj.Symbols); IO.mapOptional("Sections", Obj.Sections);
IO.mapOptional("Symbols", Obj.Symbols);
} }
} // namespace yaml } // namespace yaml

View File

@ -44,6 +44,8 @@ bool convertYAML(yaml::Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
return yaml2minidump(*Doc.Minidump, Out, ErrHandler); return yaml2minidump(*Doc.Minidump, Out, ErrHandler);
if (Doc.Wasm) if (Doc.Wasm)
return yaml2wasm(*Doc.Wasm, Out, ErrHandler); return yaml2wasm(*Doc.Wasm, Out, ErrHandler);
if (Doc.Xcoff)
return yaml2xcoff(*Doc.Xcoff, Out, ErrHandler);
ErrHandler("unknown document type"); ErrHandler("unknown document type");
return false; return false;

View File

@ -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: ]

View File

@ -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: ]

View File

@ -26,6 +26,7 @@ static_library("ObjectYAML") {
"ObjectYAML.cpp", "ObjectYAML.cpp",
"WasmEmitter.cpp", "WasmEmitter.cpp",
"WasmYAML.cpp", "WasmYAML.cpp",
"XCOFFEmitter.cpp"
"XCOFFYAML.cpp", "XCOFFYAML.cpp",
"YAML.cpp", "YAML.cpp",
"yaml2obj.cpp", "yaml2obj.cpp",