+FragmentWriter::FragmentWriter(bool IsLittleEndian)
+ : IsLittleEndian(IsLittleEndian) {}
+
+template <typename T> void FragmentWriter::write(MCDataFragment &F, T Val) {
+ if (IsLittleEndian)
+ Val = support::endian::byte_swap<T, support::little>(Val);
+ else
+ Val = support::endian::byte_swap<T, support::big>(Val);
+ const char *Start = (const char *)&Val;
+ F.getContents().append(Start, Start + sizeof(T));
+}
+
+void SymbolTableWriter::createSymtabShndx() {
+ if (ShndxF)
+ return;
+
+ MCContext &Ctx = Asm.getContext();
+ const MCSectionELF *SymtabShndxSection =
+ Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, "");
+ MCSectionData *SymtabShndxSD =
+ &Asm.getOrCreateSectionData(*SymtabShndxSection);
+ SymtabShndxSD->setAlignment(4);
+ ShndxF = new MCDataFragment(SymtabShndxSD);
+ unsigned Index = SectionIndexMap.size() + 1;
+ SectionIndexMap[SymtabShndxSection] = Index;
+
+ for (unsigned I = 0; I < NumWritten; ++I)
+ write(*ShndxF, uint32_t(0));
+}
+
+template <typename T>
+void SymbolTableWriter::write(MCDataFragment &F, T Value) {
+ FWriter.write(F, Value);
+}
+
+SymbolTableWriter::SymbolTableWriter(MCAssembler &Asm, FragmentWriter &FWriter,
+ bool Is64Bit,
+ SectionIndexMapTy &SectionIndexMap,
+ MCDataFragment *SymtabF)
+ : Asm(Asm), FWriter(FWriter), Is64Bit(Is64Bit),
+ SectionIndexMap(SectionIndexMap), SymtabF(SymtabF), ShndxF(nullptr),
+ NumWritten(0) {}
+
+void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
+ uint64_t size, uint8_t other,
+ uint32_t shndx, bool Reserved) {
+ bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
+
+ if (LargeIndex)
+ createSymtabShndx();
+
+ if (ShndxF) {
+ if (LargeIndex)
+ write(*ShndxF, shndx);
+ else
+ write(*ShndxF, uint32_t(0));
+ }
+
+ uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
+
+ raw_svector_ostream OS(SymtabF->getContents());
+
+ if (Is64Bit) {
+ write(*SymtabF, name); // st_name
+ write(*SymtabF, info); // st_info
+ write(*SymtabF, other); // st_other
+ write(*SymtabF, Index); // st_shndx
+ write(*SymtabF, value); // st_value
+ write(*SymtabF, size); // st_size
+ } else {
+ write(*SymtabF, name); // st_name
+ write(*SymtabF, uint32_t(value)); // st_value
+ write(*SymtabF, uint32_t(size)); // st_size
+ write(*SymtabF, info); // st_info
+ write(*SymtabF, other); // st_other
+ write(*SymtabF, Index); // st_shndx
+ }
+
+ ++NumWritten;
+}
+