Skip to content

Commit

Permalink
[XCOFF][yaml2obj] support for the auxiliary file header.
Browse files Browse the repository at this point in the history
Summary:
  This patch adds yaml2obj supporting for the auxiliary
  file header of XCOFF.

Reviewed By: DiggerLin, jhenderson

Differential Revision: https://reviews.llvm.org/D111487
  • Loading branch information
EsmeYi committed Nov 9, 2021
1 parent d85d57e commit e1eec76
Show file tree
Hide file tree
Showing 6 changed files with 536 additions and 4 deletions.
13 changes: 13 additions & 0 deletions llvm/include/llvm/BinaryFormat/XCOFF.h
Expand Up @@ -29,6 +29,8 @@ constexpr size_t FileNamePadSize = 6;
constexpr size_t NameSize = 8;
constexpr size_t FileHeaderSize32 = 20;
constexpr size_t FileHeaderSize64 = 24;
constexpr size_t AuxFileHeaderSize32 = 72;
constexpr size_t AuxFileHeaderSize64 = 110;
constexpr size_t SectionHeaderSize32 = 40;
constexpr size_t SectionHeaderSize64 = 72;
constexpr size_t SymbolTableEntrySize = 18;
Expand All @@ -41,6 +43,17 @@ enum ReservedSectionNum : int16_t { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };

enum MagicNumber : uint16_t { XCOFF32 = 0x01DF, XCOFF64 = 0x01F7 };

// This field only exists in the XCOFF64 definition.
enum AuxHeaderFlags64 : uint16_t {
SHR_SYMTAB = 0x8000, ///< At exec time, create shared symbol table for program
///< (main program only).
FORK_POLICY = 0x4000, ///< Forktree policy specified (main program only).
FORK_COR = 0x2000 ///< If _AOUT_FORK_POLICY is set, specify copy-on-reference
///< if this bit is set. Specify copy-on- write otherwise.
///< If _AOUT_FORK_POLICY is 0, this bit is reserved for
///< future use and should be set to 0.
};

// x_smclas field of x_csect from system header: /usr/include/syms.h
/// Storage Mapping Class definitions.
enum StorageMappingClass : uint8_t {
Expand Down
36 changes: 36 additions & 0 deletions llvm/include/llvm/ObjectYAML/XCOFFYAML.h
Expand Up @@ -29,6 +29,38 @@ struct FileHeader {
llvm::yaml::Hex16 Flags;
};

struct AuxiliaryHeader {
Optional<llvm::yaml::Hex16> Magic;
Optional<llvm::yaml::Hex16> Version;
Optional<llvm::yaml::Hex64> TextStartAddr;
Optional<llvm::yaml::Hex64> DataStartAddr;
Optional<llvm::yaml::Hex64> TOCAnchorAddr;
Optional<uint16_t> SecNumOfEntryPoint;
Optional<uint16_t> SecNumOfText;
Optional<uint16_t> SecNumOfData;
Optional<uint16_t> SecNumOfTOC;
Optional<uint16_t> SecNumOfLoader;
Optional<uint16_t> SecNumOfBSS;
Optional<llvm::yaml::Hex16> MaxAlignOfText;
Optional<llvm::yaml::Hex16> MaxAlignOfData;
Optional<llvm::yaml::Hex16> ModuleType;
Optional<llvm::yaml::Hex8> CpuFlag;
Optional<llvm::yaml::Hex8> CpuType;
Optional<llvm::yaml::Hex8> TextPageSize;
Optional<llvm::yaml::Hex8> DataPageSize;
Optional<llvm::yaml::Hex8> StackPageSize;
Optional<llvm::yaml::Hex8> FlagAndTDataAlignment;
Optional<llvm::yaml::Hex64> TextSize;
Optional<llvm::yaml::Hex64> InitDataSize;
Optional<llvm::yaml::Hex64> BssDataSize;
Optional<llvm::yaml::Hex64> EntryPointAddr;
Optional<llvm::yaml::Hex64> MaxStackSize;
Optional<llvm::yaml::Hex64> MaxDataSize;
Optional<uint16_t> SecNumOfTData;
Optional<uint16_t> SecNumOfTBSS;
Optional<llvm::yaml::Hex16> Flag;
};

struct Relocation {
llvm::yaml::Hex64 VirtualAddress;
llvm::yaml::Hex64 SymbolIndex;
Expand Down Expand Up @@ -70,6 +102,7 @@ struct StringTable {

struct Object {
FileHeader Header;
Optional<AuxiliaryHeader> AuxHeader;
std::vector<Section> Sections;
std::vector<Symbol> Symbols;
StringTable StrTbl;
Expand Down Expand Up @@ -97,6 +130,9 @@ template <> struct MappingTraits<XCOFFYAML::FileHeader> {
static void mapping(IO &IO, XCOFFYAML::FileHeader &H);
};

template <> struct MappingTraits<XCOFFYAML::AuxiliaryHeader> {
static void mapping(IO &IO, XCOFFYAML::AuxiliaryHeader &AuxHdr);
};

template <> struct MappingTraits<XCOFFYAML::Symbol> {
static void mapping(IO &IO, XCOFFYAML::Symbol &S);
Expand Down
137 changes: 133 additions & 4 deletions llvm/lib/ObjectYAML/XCOFFEmitter.cpp
Expand Up @@ -42,11 +42,13 @@ class XCOFFWriter {
private:
bool nameShouldBeInStringTable(StringRef SymbolName);
bool initFileHeader(uint64_t CurrentOffset);
void initAuxFileHeader();
bool initSectionHeader(uint64_t &CurrentOffset);
bool initRelocations(uint64_t &CurrentOffset);
bool initStringTable();
bool assignAddressesAndIndices();
void writeFileHeader();
void writeAuxFileHeader();
void writeSectionHeader();
bool writeSectionData();
bool writeRelocations();
Expand All @@ -65,6 +67,7 @@ class XCOFFWriter {
{StringRef("N_ABS"), XCOFF::N_ABS},
{StringRef("N_UNDEF"), XCOFF::N_UNDEF}};
XCOFFYAML::FileHeader InitFileHdr = Obj.Header;
XCOFFYAML::AuxiliaryHeader InitAuxFileHdr;
std::vector<XCOFFYAML::Section> InitSections = Obj.Sections;
};

Expand Down Expand Up @@ -232,22 +235,85 @@ bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
return true;
}

void XCOFFWriter::initAuxFileHeader() {
InitAuxFileHdr = *Obj.AuxHeader;
// In general, an object file might contain multiple sections of a given type,
// but in a loadable module, there must be exactly one .text, .data, .bss, and
// .loader section. A loadable object might also have one .tdata section and
// one .tbss section.
// Set these section-related values if not set explicitly. We assume that the
// input YAML matches the format of the loadable object, but if multiple input
// sections still have the same type, the first section with that type
// prevails.
for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
switch (InitSections[I].Flags) {
case XCOFF::STYP_TEXT:
if (!InitAuxFileHdr.TextSize)
InitAuxFileHdr.TextSize = InitSections[I].Size;
if (!InitAuxFileHdr.TextStartAddr)
InitAuxFileHdr.TextStartAddr = InitSections[I].Address;
if (!InitAuxFileHdr.SecNumOfText)
InitAuxFileHdr.SecNumOfText = I + 1;
break;
case XCOFF::STYP_DATA:
if (!InitAuxFileHdr.InitDataSize)
InitAuxFileHdr.InitDataSize = InitSections[I].Size;
if (!InitAuxFileHdr.DataStartAddr)
InitAuxFileHdr.DataStartAddr = InitSections[I].Address;
if (!InitAuxFileHdr.SecNumOfData)
InitAuxFileHdr.SecNumOfData = I + 1;
break;
case XCOFF::STYP_BSS:
if (!InitAuxFileHdr.BssDataSize)
InitAuxFileHdr.BssDataSize = InitSections[I].Size;
if (!InitAuxFileHdr.SecNumOfBSS)
InitAuxFileHdr.SecNumOfBSS = I + 1;
break;
case XCOFF::STYP_TDATA:
if (!InitAuxFileHdr.SecNumOfTData)
InitAuxFileHdr.SecNumOfTData = I + 1;
break;
case XCOFF::STYP_TBSS:
if (!InitAuxFileHdr.SecNumOfTBSS)
InitAuxFileHdr.SecNumOfTBSS = I + 1;
break;
case XCOFF::STYP_LOADER:
if (!InitAuxFileHdr.SecNumOfLoader)
InitAuxFileHdr.SecNumOfLoader = I + 1;
break;
default:
break;
}
}
}

bool XCOFFWriter::assignAddressesAndIndices() {
uint64_t FileHdrSize =
Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32;
uint64_t AuxFileHdrSize = 0;
if (Obj.AuxHeader)
AuxFileHdrSize = Obj.Header.AuxHeaderSize
? Obj.Header.AuxHeaderSize
: (Is64Bit ? XCOFF::AuxFileHeaderSize64
: XCOFF::AuxFileHeaderSize32);
uint64_t SecHdrSize =
Is64Bit ? XCOFF::SectionHeaderSize64 : XCOFF::SectionHeaderSize32;
uint64_t CurrentOffset = FileHdrSize /* TODO: + auxiliaryHeaderSize() */ +
InitSections.size() * SecHdrSize;
uint64_t CurrentOffset =
FileHdrSize + AuxFileHdrSize + InitSections.size() * SecHdrSize;

// Calculate section header info.
if (!initSectionHeader(CurrentOffset))
return false;
InitFileHdr.AuxHeaderSize = AuxFileHdrSize;

// Calculate file header info.
if (!initFileHeader(CurrentOffset))
return false;

// Initialize the auxiliary file header.
if (Obj.AuxHeader)
initAuxFileHeader();

// Initialize the string table.
return initStringTable();
}
Expand All @@ -261,7 +327,7 @@ void XCOFFWriter::writeFileHeader() {
W.write<uint64_t>(Obj.Header.SymbolTableOffset
? Obj.Header.SymbolTableOffset
: InitFileHdr.SymbolTableOffset);
W.write<uint16_t>(Obj.Header.AuxHeaderSize);
W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
W.write<uint16_t>(Obj.Header.Flags);
W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
? Obj.Header.NumberOfSymTableEntries
Expand All @@ -273,11 +339,72 @@ void XCOFFWriter::writeFileHeader() {
W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
? Obj.Header.NumberOfSymTableEntries
: InitFileHdr.NumberOfSymTableEntries);
W.write<uint16_t>(Obj.Header.AuxHeaderSize);
W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
W.write<uint16_t>(Obj.Header.Flags);
}
}

void XCOFFWriter::writeAuxFileHeader() {
W.write<uint16_t>(InitAuxFileHdr.Magic.getValueOr(yaml::Hex16(1)));
W.write<uint16_t>(InitAuxFileHdr.Version.getValueOr(yaml::Hex16(1)));
if (Is64Bit) {
W.OS.write_zeros(4); // Reserved for debugger.
W.write<uint64_t>(InitAuxFileHdr.TextStartAddr.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.DataStartAddr.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.TOCAnchorAddr.getValueOr(yaml::Hex64(0)));
} else {
W.write<uint32_t>(InitAuxFileHdr.TextSize.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.InitDataSize.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.BssDataSize.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.EntryPointAddr.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.TextStartAddr.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.DataStartAddr.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.TOCAnchorAddr.getValueOr(yaml::Hex32(0)));
}
W.write<uint16_t>(InitAuxFileHdr.SecNumOfEntryPoint.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfText.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfData.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfTOC.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfLoader.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfBSS.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfText.getValueOr(yaml::Hex16(0)));
W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfData.getValueOr(yaml::Hex16(0)));
W.write<uint16_t>(InitAuxFileHdr.ModuleType.getValueOr(yaml::Hex16(0)));
W.write<uint8_t>(InitAuxFileHdr.CpuFlag.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(0); // Reserved for CPU type.
if (Is64Bit) {
W.write<uint8_t>(InitAuxFileHdr.TextPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(InitAuxFileHdr.DataPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(InitAuxFileHdr.StackPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(
InitAuxFileHdr.FlagAndTDataAlignment.getValueOr(yaml::Hex8(0x80)));
W.write<uint64_t>(InitAuxFileHdr.TextSize.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.InitDataSize.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.BssDataSize.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.EntryPointAddr.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.MaxStackSize.getValueOr(yaml::Hex64(0)));
W.write<uint64_t>(InitAuxFileHdr.MaxDataSize.getValueOr(yaml::Hex64(0)));
} else {
W.write<uint32_t>(InitAuxFileHdr.MaxStackSize.getValueOr(yaml::Hex32(0)));
W.write<uint32_t>(InitAuxFileHdr.MaxDataSize.getValueOr(yaml::Hex32(0)));
W.OS.write_zeros(4); // Reserved for debugger.
W.write<uint8_t>(InitAuxFileHdr.TextPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(InitAuxFileHdr.DataPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(InitAuxFileHdr.StackPageSize.getValueOr(yaml::Hex8(0)));
W.write<uint8_t>(
InitAuxFileHdr.FlagAndTDataAlignment.getValueOr(yaml::Hex8(0)));
}
W.write<uint16_t>(InitAuxFileHdr.SecNumOfTData.getValueOr(0));
W.write<uint16_t>(InitAuxFileHdr.SecNumOfTBSS.getValueOr(0));
if (Is64Bit) {
W.write<uint16_t>(InitAuxFileHdr.Flag.getValueOr(yaml::Hex16(XCOFF::SHR_SYMTAB)));
if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize64)
W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize64);
} else if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize32) {
W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize32);
}
}

void XCOFFWriter::writeSectionHeader() {
for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
XCOFFYAML::Section YamlSec = Obj.Sections[I];
Expand Down Expand Up @@ -468,6 +595,8 @@ bool XCOFFWriter::writeXCOFF() {
return false;
StartOffset = W.OS.tell();
writeFileHeader();
if (Obj.AuxHeader)
writeAuxFileHeader();
if (!Obj.Sections.empty()) {
writeSectionHeader();
if (!writeSectionData())
Expand Down
32 changes: 32 additions & 0 deletions llvm/lib/ObjectYAML/XCOFFYAML.cpp
Expand Up @@ -118,6 +118,37 @@ void MappingTraits<XCOFFYAML::FileHeader>::mapping(
IO.mapOptional("Flags", FileHdr.Flags);
}

void MappingTraits<XCOFFYAML::AuxiliaryHeader>::mapping(
IO &IO, XCOFFYAML::AuxiliaryHeader &AuxHdr) {
IO.mapOptional("Magic", AuxHdr.Magic);
IO.mapOptional("Version", AuxHdr.Version);
IO.mapOptional("TextStartAddr", AuxHdr.TextStartAddr);
IO.mapOptional("DataStartAddr", AuxHdr.DataStartAddr);
IO.mapOptional("TOCAnchorAddr", AuxHdr.TOCAnchorAddr);
IO.mapOptional("TextSectionSize", AuxHdr.TextSize);
IO.mapOptional("DataSectionSize", AuxHdr.InitDataSize);
IO.mapOptional("BssSectionSize", AuxHdr.BssDataSize);
IO.mapOptional("SecNumOfEntryPoint", AuxHdr.SecNumOfEntryPoint);
IO.mapOptional("SecNumOfText", AuxHdr.SecNumOfText);
IO.mapOptional("SecNumOfData", AuxHdr.SecNumOfData);
IO.mapOptional("SecNumOfTOC", AuxHdr.SecNumOfTOC);
IO.mapOptional("SecNumOfLoader", AuxHdr.SecNumOfLoader);
IO.mapOptional("SecNumOfBSS", AuxHdr.SecNumOfBSS);
IO.mapOptional("MaxAlignOfText", AuxHdr.MaxAlignOfText);
IO.mapOptional("MaxAlignOfData", AuxHdr.MaxAlignOfData);
IO.mapOptional("ModuleType", AuxHdr.CpuFlag);
IO.mapOptional("TextPageSize", AuxHdr.TextPageSize);
IO.mapOptional("DataPageSize", AuxHdr.DataPageSize);
IO.mapOptional("StackPageSize", AuxHdr.StackPageSize);
IO.mapOptional("FlagAndTDataAlignment", AuxHdr.FlagAndTDataAlignment);
IO.mapOptional("EntryPointAddr", AuxHdr.EntryPointAddr);
IO.mapOptional("MaxStackSize", AuxHdr.MaxStackSize);
IO.mapOptional("MaxDataSize", AuxHdr.MaxDataSize);
IO.mapOptional("SecNumOfTData", AuxHdr.SecNumOfTData);
IO.mapOptional("SecNumOfTBSS", AuxHdr.SecNumOfTBSS);
IO.mapOptional("Flag", AuxHdr.Flag);
}

void MappingTraits<XCOFFYAML::Relocation>::mapping(IO &IO,
XCOFFYAML::Relocation &R) {
IO.mapOptional("Address", R.VirtualAddress);
Expand Down Expand Up @@ -162,6 +193,7 @@ void MappingTraits<XCOFFYAML::StringTable>::mapping(IO &IO, XCOFFYAML::StringTab
void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
IO.mapTag("!XCOFF", true);
IO.mapRequired("FileHeader", Obj.Header);
IO.mapOptional("AuxiliaryHeader", Obj.AuxHeader);
IO.mapOptional("Sections", Obj.Sections);
IO.mapOptional("Symbols", Obj.Symbols);
IO.mapOptional("StringTable", Obj.StrTbl);
Expand Down

0 comments on commit e1eec76

Please sign in to comment.