+/// EmitSymbolTable - If the current symbol table is non-empty, emit the string
+/// table for it and then the symbol table itself.
+void ELFWriter::EmitSymbolTable() {
+ if (SymbolTable.size() == 1) return; // Only the null entry.
+
+ // FIXME: compact all local symbols to the start of the symtab.
+ unsigned FirstNonLocalSymbol = 1;
+
+ ELFSection &StrTab = getSection(".strtab", ELFSection::SHT_STRTAB, 0);
+ StrTab.Align = 1;
+
+ DataBuffer &StrTabBuf = StrTab.SectionData;
+ OutputBuffer StrTabOut(StrTabBuf, is64Bit, isLittleEndian);
+
+ // Set the zero'th symbol to a null byte, as required.
+ StrTabOut.outbyte(0);
+ SymbolTable[0].NameIdx = 0;
+ unsigned Index = 1;
+ for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) {
+ // Use the name mangler to uniquify the LLVM symbol.
+ std::string Name = Mang->getValueName(SymbolTable[i].GV);
+
+ if (Name.empty()) {
+ SymbolTable[i].NameIdx = 0;
+ } else {
+ SymbolTable[i].NameIdx = Index;
+
+ // Add the name to the output buffer, including the null terminator.
+ StrTabBuf.insert(StrTabBuf.end(), Name.begin(), Name.end());
+
+ // Add a null terminator.
+ StrTabBuf.push_back(0);
+
+ // Keep track of the number of bytes emitted to this section.
+ Index += Name.size()+1;
+ }
+ }
+ assert(Index == StrTabBuf.size());
+ StrTab.Size = Index;
+
+ // Now that we have emitted the string table and know the offset into the
+ // string table of each symbol, emit the symbol table itself.
+ ELFSection &SymTab = getSection(".symtab", ELFSection::SHT_SYMTAB, 0);
+ SymTab.Align = is64Bit ? 8 : 4;
+ SymTab.Link = SymTab.SectionIdx; // Section Index of .strtab.
+ SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol.
+ SymTab.EntSize = 16; // Size of each symtab entry. FIXME: wrong for ELF64
+ DataBuffer &SymTabBuf = SymTab.SectionData;
+ OutputBuffer SymTabOut(SymTabBuf, is64Bit, isLittleEndian);
+
+ if (!is64Bit) { // 32-bit and 64-bit formats are shuffled a bit.
+ for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i) {
+ ELFSym &Sym = SymbolTable[i];
+ SymTabOut.outword(Sym.NameIdx);
+ SymTabOut.outaddr32(Sym.Value);
+ SymTabOut.outword(Sym.Size);
+ SymTabOut.outbyte(Sym.Info);
+ SymTabOut.outbyte(Sym.Other);
+ SymTabOut.outhalf(Sym.SectionIdx);
+ }
+ } else {
+ for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i) {
+ ELFSym &Sym = SymbolTable[i];
+ SymTabOut.outword(Sym.NameIdx);
+ SymTabOut.outbyte(Sym.Info);
+ SymTabOut.outbyte(Sym.Other);
+ SymTabOut.outhalf(Sym.SectionIdx);
+ SymTabOut.outaddr64(Sym.Value);
+ SymTabOut.outxword(Sym.Size);
+ }
+ }
+
+ SymTab.Size = SymTabBuf.size();
+}
+