29constexpr unsigned DefaultSectionAlign = 4;
30constexpr int16_t MaxSectionIndex = INT16_MAX;
31constexpr uint32_t MaxRawDataSize = UINT32_MAX;
43 bool nameShouldBeInStringTable(
StringRef SymbolName);
44 bool initFileHeader(
uint64_t CurrentOffset);
45 void initAuxFileHeader();
46 bool initSectionHeader(
uint64_t &CurrentOffset);
48 bool initStringTable();
49 bool assignAddressesAndIndices();
51 void writeFileHeader();
52 void writeAuxFileHeader();
53 void writeSectionHeader();
54 bool writeSectionData();
55 bool writeRelocations();
57 void writeStringTable();
66 void writeAuxSymbol(
const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym);
81 std::vector<XCOFFYAML::Section> InitSections = Obj.
Sections;
93bool XCOFFWriter::nameShouldBeInStringTable(
StringRef SymbolName) {
98bool XCOFFWriter::initRelocations(
uint64_t &CurrentOffset) {
100 if (!InitSection.Relocations.empty()) {
101 InitSection.NumberOfRelocations = InitSection.Relocations.size();
102 InitSection.FileOffsetToRelocations = CurrentOffset;
105 CurrentOffset += InitSection.NumberOfRelocations * RelSize;
106 if (CurrentOffset > MaxRawDataSize) {
107 ErrHandler(
"maximum object size of" +
Twine(MaxRawDataSize) +
108 "exceeded when writing relocation data");
116bool XCOFFWriter::initSectionHeader(
uint64_t &CurrentOffset) {
119 if (CurrentOffset > MaxRawDataSize) {
120 ErrHandler(
"maximum object size of" +
Twine(MaxRawDataSize) +
121 "exceeded when writing section data");
127 !SectionIndexMap[InitSections[
I].SectionName]) {
129 SectionIndexMap[InitSections[
I].SectionName] =
I + 1;
130 if ((
I + 1) > MaxSectionIndex) {
131 ErrHandler(
"exceeded the maximum permitted section index of " +
132 Twine(MaxSectionIndex));
142 InitSections[
I].Address = 0;
144 InitSections[
I].Address = CurrentSecAddr;
147 if (InitSections[
I].SectionData.binary_size()) {
148 InitSections[
I].FileOffsetToData = CurrentOffset;
149 CurrentOffset += InitSections[
I].SectionData.binary_size();
151 CurrentOffset =
alignTo(CurrentOffset, DefaultSectionAlign);
152 InitSections[
I].Size = CurrentOffset - InitSections[
I].FileOffsetToData;
153 CurrentSecAddr += InitSections[
I].Size;
159bool XCOFFWriter::initStringTable() {
160 if (Obj.StrTbl.RawContent) {
161 size_t RawSize = Obj.StrTbl.RawContent->binary_size();
162 if (Obj.StrTbl.Strings || Obj.StrTbl.Length) {
164 "can't specify Strings or Length when RawContent is specified");
167 if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < RawSize) {
168 ErrHandler(
"specified ContentSize (" +
Twine(*Obj.StrTbl.ContentSize) +
169 ") is less than the RawContent data size (" +
Twine(RawSize) +
175 if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize <= 3) {
176 ErrHandler(
"ContentSize shouldn't be less than 4 without RawContent");
181 StrTblBuilder.clear();
183 if (Obj.StrTbl.Strings) {
185 for (
StringRef StringEnt : *Obj.StrTbl.Strings)
186 StrTblBuilder.add(StringEnt);
188 size_t StrTblIdx = 0;
189 size_t NumOfStrings = Obj.StrTbl.Strings->size();
191 if (nameShouldBeInStringTable(YamlSym.
SymbolName)) {
192 if (StrTblIdx < NumOfStrings) {
194 YamlSym.
SymbolName = (*Obj.StrTbl.Strings)[StrTblIdx];
204 if (nameShouldBeInStringTable(YamlSym.
SymbolName))
212 for (
const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
214 if (
auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
215 if (nameShouldBeInStringTable(AS->FileNameOrString.value_or(
"")))
216 StrTblBuilder.add(AS->FileNameOrString.value_or(
""));
220 StrTblBuilder.finalize();
222 size_t StrTblSize = StrTblBuilder.getSize();
223 if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < StrTblSize) {
224 ErrHandler(
"specified ContentSize (" +
Twine(*Obj.StrTbl.ContentSize) +
225 ") is less than the size of the data that would otherwise be "
227 Twine(StrTblSize) +
")");
234bool XCOFFWriter::initFileHeader(
uint64_t CurrentOffset) {
237 InitFileHdr.NumberOfSections = Obj.Sections.size();
238 InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();
243 ErrHandler(
"specified NumberOfAuxEntries " +
245 " is less than the actual number "
246 "of auxiliary entries " +
256 if (InitFileHdr.NumberOfSymTableEntries) {
257 InitFileHdr.SymbolTableOffset = CurrentOffset;
260 if (CurrentOffset > MaxRawDataSize) {
261 ErrHandler(
"maximum object size of" +
Twine(MaxRawDataSize) +
262 "exceeded when writing symbols");
270void XCOFFWriter::initAuxFileHeader() {
271 InitAuxFileHdr = *Obj.AuxHeader;
281 switch (InitSections[
I].Flags) {
283 if (!InitAuxFileHdr.TextSize)
284 InitAuxFileHdr.TextSize = InitSections[
I].Size;
285 if (!InitAuxFileHdr.TextStartAddr)
286 InitAuxFileHdr.TextStartAddr = InitSections[
I].Address;
287 if (!InitAuxFileHdr.SecNumOfText)
288 InitAuxFileHdr.SecNumOfText =
I + 1;
291 if (!InitAuxFileHdr.InitDataSize)
292 InitAuxFileHdr.InitDataSize = InitSections[
I].Size;
293 if (!InitAuxFileHdr.DataStartAddr)
294 InitAuxFileHdr.DataStartAddr = InitSections[
I].Address;
295 if (!InitAuxFileHdr.SecNumOfData)
296 InitAuxFileHdr.SecNumOfData =
I + 1;
299 if (!InitAuxFileHdr.BssDataSize)
300 InitAuxFileHdr.BssDataSize = InitSections[
I].Size;
301 if (!InitAuxFileHdr.SecNumOfBSS)
302 InitAuxFileHdr.SecNumOfBSS =
I + 1;
305 if (!InitAuxFileHdr.SecNumOfTData)
306 InitAuxFileHdr.SecNumOfTData =
I + 1;
309 if (!InitAuxFileHdr.SecNumOfTBSS)
310 InitAuxFileHdr.SecNumOfTBSS =
I + 1;
313 if (!InitAuxFileHdr.SecNumOfLoader)
314 InitAuxFileHdr.SecNumOfLoader =
I + 1;
322bool XCOFFWriter::assignAddressesAndIndices() {
327 AuxFileHdrSize = Obj.Header.AuxHeaderSize
328 ? Obj.Header.AuxHeaderSize
334 FileHdrSize + AuxFileHdrSize + InitSections.size() * SecHdrSize;
337 if (!initSectionHeader(CurrentOffset))
339 InitFileHdr.AuxHeaderSize = AuxFileHdrSize;
342 if (!initFileHeader(CurrentOffset))
350 return initStringTable();
353void XCOFFWriter::writeFileHeader() {
354 W.write<
uint16_t>(Obj.Header.Magic ? Obj.Header.Magic : InitFileHdr.Magic);
355 W.write<
uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
356 : InitFileHdr.NumberOfSections);
357 W.write<int32_t>(Obj.Header.TimeStamp);
359 W.write<
uint64_t>(Obj.Header.SymbolTableOffset
360 ? Obj.Header.SymbolTableOffset
361 : InitFileHdr.SymbolTableOffset);
362 W.write<
uint16_t>(InitFileHdr.AuxHeaderSize);
364 W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
365 ? Obj.Header.NumberOfSymTableEntries
366 : InitFileHdr.NumberOfSymTableEntries);
368 W.write<
uint32_t>(Obj.Header.SymbolTableOffset
369 ? Obj.Header.SymbolTableOffset
370 : InitFileHdr.SymbolTableOffset);
371 W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
372 ? Obj.Header.NumberOfSymTableEntries
373 : InitFileHdr.NumberOfSymTableEntries);
374 W.write<
uint16_t>(InitFileHdr.AuxHeaderSize);
379void XCOFFWriter::writeAuxFileHeader() {
380 W.write<
uint16_t>(InitAuxFileHdr.Magic.value_or(yaml::Hex16(1)));
381 W.write<
uint16_t>(InitAuxFileHdr.Version.value_or(yaml::Hex16(1)));
384 W.write<
uint64_t>(InitAuxFileHdr.TextStartAddr.value_or(yaml::Hex64(0)));
385 W.write<
uint64_t>(InitAuxFileHdr.DataStartAddr.value_or(yaml::Hex64(0)));
386 W.write<
uint64_t>(InitAuxFileHdr.TOCAnchorAddr.value_or(yaml::Hex64(0)));
388 W.write<
uint32_t>(InitAuxFileHdr.TextSize.value_or(yaml::Hex64(0)));
389 W.write<
uint32_t>(InitAuxFileHdr.InitDataSize.value_or(yaml::Hex64(0)));
390 W.write<
uint32_t>(InitAuxFileHdr.BssDataSize.value_or(yaml::Hex64(0)));
391 W.write<
uint32_t>(InitAuxFileHdr.EntryPointAddr.value_or(yaml::Hex64(0)));
392 W.write<
uint32_t>(InitAuxFileHdr.TextStartAddr.value_or(yaml::Hex64(0)));
393 W.write<
uint32_t>(InitAuxFileHdr.DataStartAddr.value_or(yaml::Hex64(0)));
394 W.write<
uint32_t>(InitAuxFileHdr.TOCAnchorAddr.value_or(yaml::Hex64(0)));
396 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfEntryPoint.value_or(0));
397 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfText.value_or(0));
398 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfData.value_or(0));
399 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfTOC.value_or(0));
400 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfLoader.value_or(0));
401 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfBSS.value_or(0));
402 W.write<
uint16_t>(InitAuxFileHdr.MaxAlignOfText.value_or(yaml::Hex16(0)));
403 W.write<
uint16_t>(InitAuxFileHdr.MaxAlignOfData.value_or(yaml::Hex16(0)));
404 W.write<
uint16_t>(InitAuxFileHdr.ModuleType.value_or(yaml::Hex16(0)));
405 W.write<uint8_t>(InitAuxFileHdr.CpuFlag.value_or(yaml::Hex8(0)));
408 W.write<uint8_t>(InitAuxFileHdr.TextPageSize.value_or(yaml::Hex8(0)));
409 W.write<uint8_t>(InitAuxFileHdr.DataPageSize.value_or(yaml::Hex8(0)));
410 W.write<uint8_t>(InitAuxFileHdr.StackPageSize.value_or(yaml::Hex8(0)));
412 InitAuxFileHdr.FlagAndTDataAlignment.value_or(yaml::Hex8(0x80)));
413 W.write<
uint64_t>(InitAuxFileHdr.TextSize.value_or(yaml::Hex64(0)));
414 W.write<
uint64_t>(InitAuxFileHdr.InitDataSize.value_or(yaml::Hex64(0)));
415 W.write<
uint64_t>(InitAuxFileHdr.BssDataSize.value_or(yaml::Hex64(0)));
416 W.write<
uint64_t>(InitAuxFileHdr.EntryPointAddr.value_or(yaml::Hex64(0)));
417 W.write<
uint64_t>(InitAuxFileHdr.MaxStackSize.value_or(yaml::Hex64(0)));
418 W.write<
uint64_t>(InitAuxFileHdr.MaxDataSize.value_or(yaml::Hex64(0)));
420 W.write<
uint32_t>(InitAuxFileHdr.MaxStackSize.value_or(yaml::Hex64(0)));
421 W.write<
uint32_t>(InitAuxFileHdr.MaxDataSize.value_or(yaml::Hex64(0)));
423 W.write<uint8_t>(InitAuxFileHdr.TextPageSize.value_or(yaml::Hex8(0)));
424 W.write<uint8_t>(InitAuxFileHdr.DataPageSize.value_or(yaml::Hex8(0)));
425 W.write<uint8_t>(InitAuxFileHdr.StackPageSize.value_or(yaml::Hex8(0)));
427 InitAuxFileHdr.FlagAndTDataAlignment.value_or(yaml::Hex8(0)));
429 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfTData.value_or(0));
430 W.write<
uint16_t>(InitAuxFileHdr.SecNumOfTBSS.value_or(0));
441void XCOFFWriter::writeSectionHeader() {
463 W.write<int32_t>(YamlSec.
Flags);
479 W.write<int32_t>(YamlSec.
Flags);
484bool XCOFFWriter::writeSectionData() {
489 int64_t PaddingSize =
491 if (PaddingSize < 0) {
492 ErrHandler(
"redundant data was written before section data");
495 W.OS.write_zeros(PaddingSize);
502bool XCOFFWriter::writeRelocations() {
506 int64_t PaddingSize =
508 if (PaddingSize < 0) {
509 ErrHandler(
"redundant data was written before relocations");
512 W.OS.write_zeros(PaddingSize);
519 W.write<uint8_t>(YamlRel.
Info);
520 W.write<uint8_t>(YamlRel.
Type);
549 assert(Is64Bit &&
"can't write the exception auxiliary symbol for XCOFF32");
575 if (nameShouldBeInStringTable(FileName)) {
577 W.write<
uint32_t>(StrTblBuilder.getOffset(FileName));
579 writeName(FileName, W);
594 W.OS.write_zeros(13);
600 W.OS.write_zeros(12);
619 assert(!Is64Bit &&
"can't write the stat auxiliary symbol for XCOFF64");
623 W.OS.write_zeros(10);
626void XCOFFWriter::writeAuxSymbol(
627 const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
628 if (
auto AS = dyn_cast<XCOFFYAML::CsectAuxEnt>(AuxSym.get()))
630 else if (
auto AS = dyn_cast<XCOFFYAML::FunctionAuxEnt>(AuxSym.get()))
632 else if (
auto AS = dyn_cast<XCOFFYAML::ExcpetionAuxEnt>(AuxSym.get()))
634 else if (
auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
636 else if (
auto AS = dyn_cast<XCOFFYAML::BlockAuxEnt>(AuxSym.get()))
638 else if (
auto AS = dyn_cast<XCOFFYAML::SectAuxEntForDWARF>(AuxSym.get()))
640 else if (
auto AS = dyn_cast<XCOFFYAML::SectAuxEntForStat>(AuxSym.get()))
646bool XCOFFWriter::writeSymbols() {
647 int64_t PaddingSize =
648 (
uint64_t)InitFileHdr.SymbolTableOffset - (
W.OS.tell() - StartOffset);
649 if (PaddingSize < 0) {
650 ErrHandler(
"redundant data was written before symbols");
653 W.OS.write_zeros(PaddingSize);
659 if (nameShouldBeInStringTable(YamlSym.
SymbolName)) {
670 if (!SectionIndexMap.count(*YamlSym.
SectionName)) {
671 ErrHandler(
"the SectionName " + *YamlSym.
SectionName +
672 " specified in the symbol does not exist");
677 ErrHandler(
"the SectionName " + *YamlSym.
SectionName +
679 ") refer to different sections");
682 W.write<int16_t>(SectionIndexMap[*YamlSym.
SectionName]);
690 W.write<uint8_t>(NumOfAuxSym);
692 if (!NumOfAuxSym && !YamlSym.
AuxEntries.size())
699 for (
const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
701 writeAuxSymbol(AuxSym);
712void XCOFFWriter::writeStringTable() {
713 if (Obj.StrTbl.RawContent) {
714 Obj.StrTbl.RawContent->writeAsBinary(
W.OS);
715 if (Obj.StrTbl.ContentSize) {
716 assert(*Obj.StrTbl.ContentSize >= Obj.StrTbl.RawContent->binary_size() &&
717 "Specified ContentSize is less than the RawContent size.");
718 W.OS.write_zeros(*Obj.StrTbl.ContentSize -
719 Obj.StrTbl.RawContent->binary_size());
724 size_t StrTblBuilderSize = StrTblBuilder.getSize();
727 if (!Obj.StrTbl.Length && !Obj.StrTbl.ContentSize) {
728 if (StrTblBuilderSize <= 4)
730 StrTblBuilder.write(
W.OS);
735 std::unique_ptr<WritableMemoryBuffer> Buf =
737 uint8_t *
Ptr =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart());
738 StrTblBuilder.write(
Ptr);
743 : *Obj.StrTbl.ContentSize);
745 W.OS.write(Buf->getBufferStart(), Buf->getBufferSize());
747 if (Obj.StrTbl.ContentSize) {
748 assert(*Obj.StrTbl.ContentSize >= StrTblBuilderSize &&
749 "Specified ContentSize is less than the StringTableBuilder size.");
750 W.OS.write_zeros(*Obj.StrTbl.ContentSize - StrTblBuilderSize);
754bool XCOFFWriter::writeXCOFF() {
755 if (!assignAddressesAndIndices())
757 StartOffset =
W.OS.tell();
760 writeAuxFileHeader();
761 if (!Obj.Sections.empty()) {
762 writeSectionHeader();
763 if (!writeSectionData())
765 if (!writeRelocations())
768 if (!Obj.Symbols.empty() && !writeSymbols())
780 XCOFFWriter Writer(Doc, Out, EH);
781 return Writer.writeXCOFF();
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
static Error initRelocations(RelocationSection *Relocs, T RelRange)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Utility for building string tables with deduplicated suffixes.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
ArrayRef< uint8_t >::size_type binary_size() const
The number of bytes that are represented by this BinaryRef.
void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ SHR_SYMTAB
At exec time, create shared symbol table for program (main program only).
constexpr size_t RelocationSerializationSize32
constexpr size_t RelocationSerializationSize64
constexpr size_t FileHeaderSize64
constexpr size_t AuxFileHeaderSize64
constexpr size_t SectionHeaderSize64
@ AUX_SECT
Identifies a SECT auxiliary entry.
@ AUX_FILE
Identifies a file auxiliary entry.
@ AUX_EXCEPT
Identifies an exception auxiliary entry.
@ AUX_FCN
Identifies a function auxiliary entry.
@ AUX_SYM
Identifies a symbol auxiliary entry.
@ AUX_CSECT
Identifies a csect auxiliary entry.
constexpr size_t NameSize
constexpr size_t AuxFileHeaderSize32
@ XFT_FN
Specifies the source-file name.
constexpr size_t FileHeaderSize32
constexpr size_t SectionHeaderSize32
constexpr size_t SymbolTableEntrySize
constexpr size_t FileNamePadSize
void write32be(void *P, uint32_t V)
bool yaml2xcoff(XCOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
This is an optimization pass for GlobalISel generic memory operations.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
std::optional< uint32_t > LineNum
std::optional< uint16_t > LineNumHi
std::optional< uint16_t > LineNumLo
std::optional< uint16_t > TypeChkSectNum
std::optional< uint32_t > ParameterHashIndex
std::optional< uint32_t > SectionOrLength
std::optional< uint32_t > SectionOrLengthHi
std::optional< uint8_t > SymbolAlignmentAndType
std::optional< uint32_t > SectionOrLengthLo
std::optional< uint16_t > StabSectNum
std::optional< XCOFF::StorageMappingClass > StorageMappingClass
std::optional< uint32_t > StabInfoIndex
std::optional< int32_t > SymIdxOfNextBeyond
std::optional< uint32_t > SizeOfFunction
std::optional< uint64_t > OffsetToExceptionTbl
std::optional< XCOFF::CFileStringType > FileStringType
std::optional< StringRef > FileNameOrString
std::optional< int32_t > SymIdxOfNextBeyond
std::optional< uint32_t > OffsetToExceptionTbl
std::optional< uint64_t > PtrToLineNum
std::optional< uint32_t > SizeOfFunction
std::vector< Section > Sections
llvm::yaml::Hex64 SymbolIndex
llvm::yaml::Hex64 VirtualAddress
std::optional< uint32_t > NumberOfRelocEnt
std::optional< uint32_t > LengthOfSectionPortion
std::optional< uint16_t > NumberOfRelocEnt
std::optional< uint16_t > NumberOfLineNum
std::optional< uint32_t > SectionLength
llvm::yaml::Hex64 FileOffsetToRelocations
llvm::yaml::Hex64 Address
llvm::yaml::Hex64 FileOffsetToData
yaml::BinaryRef SectionData
std::vector< Relocation > Relocations
llvm::yaml::Hex16 NumberOfLineNumbers
llvm::yaml::Hex16 NumberOfRelocations
llvm::yaml::Hex64 FileOffsetToLineNumbers
std::vector< std::unique_ptr< AuxSymbolEnt > > AuxEntries
std::optional< uint16_t > SectionIndex
std::optional< uint8_t > NumberOfAuxEntries
XCOFF::StorageClass StorageClass
std::optional< StringRef > SectionName
Adapter to write values to a stream in a particular byte order.
Common declarations for yaml2obj.