XCOFFWriter.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //===- XCOFFWriter.cpp ----------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Support/Errc.h"
  9. #include "XCOFFWriter.h"
  10. namespace llvm {
  11. namespace objcopy {
  12. namespace xcoff {
  13. using namespace object;
  14. void XCOFFWriter::finalizeHeaders() {
  15. // File header.
  16. FileSize += sizeof(XCOFFFileHeader32);
  17. // Optional file header.
  18. FileSize += Obj.FileHeader.AuxHeaderSize;
  19. // Section headers.
  20. FileSize += sizeof(XCOFFSectionHeader32) * Obj.Sections.size();
  21. }
  22. void XCOFFWriter::finalizeSections() {
  23. for (const Section &Sec : Obj.Sections) {
  24. // Section data.
  25. FileSize += Sec.Contents.size();
  26. // Relocations.
  27. FileSize +=
  28. Sec.SectionHeader.NumberOfRelocations * sizeof(XCOFFRelocation32);
  29. }
  30. }
  31. void XCOFFWriter::finalizeSymbolStringTable() {
  32. assert(Obj.FileHeader.SymbolTableOffset >= FileSize);
  33. FileSize = Obj.FileHeader.SymbolTableOffset;
  34. // Symbols and auxiliary entries.
  35. FileSize +=
  36. Obj.FileHeader.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize;
  37. // String table.
  38. FileSize += Obj.StringTable.size();
  39. }
  40. void XCOFFWriter::finalize() {
  41. FileSize = 0;
  42. finalizeHeaders();
  43. finalizeSections();
  44. finalizeSymbolStringTable();
  45. }
  46. void XCOFFWriter::writeHeaders() {
  47. // Write the file header.
  48. uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
  49. memcpy(Ptr, &Obj.FileHeader, sizeof(XCOFFFileHeader32));
  50. Ptr += sizeof(XCOFFFileHeader32);
  51. // Write the optional header.
  52. if (Obj.FileHeader.AuxHeaderSize) {
  53. memcpy(Ptr, &Obj.OptionalFileHeader, Obj.FileHeader.AuxHeaderSize);
  54. Ptr += Obj.FileHeader.AuxHeaderSize;
  55. }
  56. // Write section headers.
  57. for (const Section &Sec : Obj.Sections) {
  58. memcpy(Ptr, &Sec.SectionHeader, sizeof(XCOFFSectionHeader32));
  59. Ptr += sizeof(XCOFFSectionHeader32);
  60. }
  61. }
  62. void XCOFFWriter::writeSections() {
  63. // Write section data.
  64. for (const Section &Sec : Obj.Sections) {
  65. uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
  66. Sec.SectionHeader.FileOffsetToRawData;
  67. Ptr = std::copy(Sec.Contents.begin(), Sec.Contents.end(), Ptr);
  68. }
  69. // Write relocations.
  70. for (const Section &Sec : Obj.Sections) {
  71. uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
  72. Sec.SectionHeader.FileOffsetToRelocationInfo;
  73. for (const XCOFFRelocation32 &Rel : Sec.Relocations) {
  74. memcpy(Ptr, &Rel, sizeof(XCOFFRelocation32));
  75. Ptr += sizeof(XCOFFRelocation32);
  76. }
  77. }
  78. }
  79. void XCOFFWriter::writeSymbolStringTable() {
  80. // Write symbols.
  81. uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
  82. Obj.FileHeader.SymbolTableOffset;
  83. for (const Symbol &Sym : Obj.Symbols) {
  84. memcpy(Ptr, &Sym.Sym, XCOFF::SymbolTableEntrySize);
  85. Ptr += XCOFF::SymbolTableEntrySize;
  86. // Auxiliary symbols.
  87. memcpy(Ptr, Sym.AuxSymbolEntries.data(), Sym.AuxSymbolEntries.size());
  88. Ptr += Sym.AuxSymbolEntries.size();
  89. }
  90. // Write the string table.
  91. memcpy(Ptr, Obj.StringTable.data(), Obj.StringTable.size());
  92. Ptr += Obj.StringTable.size();
  93. }
  94. Error XCOFFWriter::write() {
  95. finalize();
  96. Buf = WritableMemoryBuffer::getNewMemBuffer(FileSize);
  97. if (!Buf)
  98. return createStringError(errc::not_enough_memory,
  99. "failed to allocate memory buffer of " +
  100. Twine::utohexstr(FileSize) + " bytes");
  101. writeHeaders();
  102. writeSections();
  103. writeSymbolStringTable();
  104. Out.write(Buf->getBufferStart(), Buf->getBufferSize());
  105. return Error::success();
  106. }
  107. } // end namespace xcoff
  108. } // end namespace objcopy
  109. } // end namespace llvm