llvm.org GIT mirror llvm / 9c5b799
Add ELF dynamic symbol support to yaml2obj/obj2yaml Summary: This change introduces a `DynamicSymbols` field to the ELF specific YAML supported by `yaml2obj` and `obj2yaml`. This grouping of symbols provides a way to represent ELF dynamic symbols. The `DynamicSymbols` structure is identical to the existing `Symbols`. Reviewers: compnerd, jakehehrlich, silvas Reviewed By: silvas Subscribers: silvas, jakehehrlich, llvm-commits Differential Revision: https://reviews.llvm.org/D39582 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318433 91177308-0d34-0410-b5e6-96231b3b80d8 Dave Lee 3 years ago
6 changed file(s) with 136 addition(s) and 41 deletion(s). Raw diff Collapse all Expand all
206206 // top-level key, which automatically ensures that invariants like there
207207 // being a single SHT_SYMTAB section are upheld.
208208 LocalGlobalWeakSymbols Symbols;
209 LocalGlobalWeakSymbols DynamicSymbols;
209210 };
210211
211212 } // end namespace ELFYAML
932932 IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
933933 IO.mapOptional("Sections", Object.Sections);
934934 IO.mapOptional("Symbols", Object.Symbols);
935 IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
935936 IO.setContext(nullptr);
936937 }
937938
0 # Ensures that implicitly added sections can be ordered within Sections.
1 # RUN: yaml2obj %s -o %t
2 # RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=SECTION
3 # RUN: llvm-nm -dynamic %t | FileCheck %s --check-prefix=SYMBOL
4
5 !ELF
6 FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 Type: ET_DYN
10 Machine: EM_X86_64
11 Sections:
12 - Name: .data
13 Type: SHT_PROGBITS
14 Flags: [ SHF_ALLOC, SHF_WRITE ]
15 DynamicSymbols:
16 Global:
17 - Name: dynglobal
18 Type: STT_OBJECT
19 Section: .data
20 Weak:
21 - Name: dynweak
22 Type: STT_OBJECT
23 Section: .data
24 Local:
25 - Name: dynlocal
26 Type: STT_OBJECT
27 Section: .data
28
29 # SECTION: Name: .dynsym
30 # SECTION-NEXT: Type: SHT_DYNSYM
31 # SECTION-NEXT: Flags
32 # SECTION-NEXT: SHF_ALLOC
33 # SECTION: Name: .dynstr
34 # SECTION-NEXT: Type: SHT_STRTAB
35 # SECTION-NEXT: Flags
36 # SECTION-NEXT: SHF_ALLOC
37
38 # SYMBOL-DAG: D dynglobal
39 # SYMBOL-DAG: V dynweak
40 # SYMBOL-DAG: d dynlocal
13211321 DynSymRegion = createDRIFrom(&Sec);
13221322 // This is only used (if Elf_Shdr present)for naming section in GNU style
13231323 DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
1324 DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec));
13241325 break;
13251326 case ELF::SHT_SYMTAB_SHNDX:
13261327 ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
4141 const object::ELFFile &Obj;
4242 ArrayRef ShndxTable;
4343
44 std::error_code dumpSymbols(const Elf_Shdr *Symtab,
45 ELFYAML::LocalGlobalWeakSymbols &Symbols);
4446 std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
4547 StringRef StrTable, ELFYAML::Symbol &S);
4648 std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
118120 Y->Header.Entry = Obj.getHeader()->e_entry;
119121
120122 const Elf_Shdr *Symtab = nullptr;
123 const Elf_Shdr *DynSymtab = nullptr;
121124
122125 // Dump sections
123126 auto SectionsOrErr = Obj.sections();
128131 for (const Elf_Shdr &Sec : Sections) {
129132 switch (Sec.sh_type) {
130133 case ELF::SHT_NULL:
131 case ELF::SHT_DYNSYM:
132134 case ELF::SHT_STRTAB:
133135 // Do not dump these sections.
134136 break;
135137 case ELF::SHT_SYMTAB:
136138 Symtab = &Sec;
139 break;
140 case ELF::SHT_DYNSYM:
141 DynSymtab = &Sec;
137142 break;
138143 case ELF::SHT_SYMTAB_SHNDX: {
139144 auto TableOrErr = Obj.getSHNDXTable(Sec);
186191 }
187192 }
188193
189 // Dump symbols
194 if (auto EC = dumpSymbols(Symtab, Y->Symbols))
195 return EC;
196 if (auto EC = dumpSymbols(DynSymtab, Y->DynamicSymbols))
197 return EC;
198
199 return Y.release();
200 }
201
202 template
203 std::error_code
204 ELFDumper::dumpSymbols(const Elf_Shdr *Symtab,
205 ELFYAML::LocalGlobalWeakSymbols &Symbols) {
190206 if (!Symtab)
191 return Y.release(); // if the symbol table is missing return early
207 return std::error_code();
208
192209 auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab);
193210 if (!StrTableOrErr)
194211 return errorToErrorCode(StrTableOrErr.takeError());
195212 StringRef StrTable = *StrTableOrErr;
196213
197 bool IsFirstSym = true;
198214 auto SymtabOrErr = Obj.symbols(Symtab);
199215 if (!SymtabOrErr)
200216 return errorToErrorCode(SymtabOrErr.takeError());
201 for (const Elf_Sym &Sym : *SymtabOrErr) {
217
218 bool IsFirstSym = true;
219 for (const auto &Sym : *SymtabOrErr) {
202220 if (IsFirstSym) {
203221 IsFirstSym = false;
204222 continue;
205223 }
206224
207225 ELFYAML::Symbol S;
208 if (std::error_code EC =
209 ELFDumper::dumpSymbol(&Sym, Symtab, StrTable, S))
226 if (auto EC = dumpSymbol(&Sym, Symtab, StrTable, S))
210227 return EC;
211228
212 switch (Sym.getBinding())
213 {
229 switch (Sym.getBinding()) {
214230 case ELF::STB_LOCAL:
215 Y->Symbols.Local.push_back(S);
231 Symbols.Local.push_back(S);
216232 break;
217233 case ELF::STB_GLOBAL:
218 Y->Symbols.Global.push_back(S);
234 Symbols.Global.push_back(S);
219235 break;
220236 case ELF::STB_WEAK:
221 Y->Symbols.Weak.push_back(S);
237 Symbols.Weak.push_back(S);
222238 break;
223239 default:
224240 llvm_unreachable("Unknown ELF symbol binding");
225241 }
226242 }
227243
228 return Y.release();
244 return std::error_code();
229245 }
230246
231247 template
113113 typedef typename object::ELFFile::Elf_Rel Elf_Rel;
114114 typedef typename object::ELFFile::Elf_Rela Elf_Rela;
115115
116 enum class SymtabType { Static, Dynamic };
117
116118 /// \brief The future ".strtab" section.
117119 StringTableBuilder DotStrtab{StringTableBuilder::ELF};
118120
119121 /// \brief The future ".shstrtab" section.
120122 StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
123
124 /// \brief The future ".dynstr" section.
125 StringTableBuilder DotDynstr{StringTableBuilder::ELF};
121126
122127 NameToIdxMap SN2I;
123128 NameToIdxMap SymN2I;
130135 void initProgramHeaders(std::vector &PHeaders);
131136 bool initSectionHeaders(std::vector &SHeaders,
132137 ContiguousBlobAccumulator &CBA);
133 void initSymtabSectionHeader(Elf_Shdr &SHeader,
138 void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,
134139 ContiguousBlobAccumulator &CBA);
135140 void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
136141 StringTableBuilder &STB,
138143 void setProgramHeaderLayout(std::vector &PHeaders,
139144 std::vector &SHeaders);
140145 void addSymbols(const std::vector &Symbols,
141 std::vector &Syms, unsigned SymbolBinding);
146 std::vector &Syms, unsigned SymbolBinding,
147 const StringTableBuilder &Strtab);
142148 void writeSectionContent(Elf_Shdr &SHeader,
143149 const ELFYAML::RawContentSection &Section,
144150 ContiguousBlobAccumulator &CBA);
150156 bool writeSectionContent(Elf_Shdr &SHeader,
151157 const ELFYAML::MipsABIFlags &Section,
152158 ContiguousBlobAccumulator &CBA);
159 bool hasDynamicSymbols() const;
160 SmallVector implicitSectionNames() const;
153161
154162 // - SHT_NULL entry (placed first, i.e. 0'th entry)
155 // - symbol table (.symtab) (defaults to third to last)
156 // - string table (.strtab) (defaults to second to last)
157 // - section header string table (.shstrtab) (defaults to last)
163 // - symbol table (.symtab) (defaults to after last yaml section)
164 // - string table (.strtab) (defaults to after .symtab)
165 // - section header string table (.shstrtab) (defaults to after .strtab)
166 // - dynamic symbol table (.dynsym) (defaults to after .shstrtab)
167 // - dynamic string table (.dynstr) (defaults to after .dynsym)
158168 unsigned getDotSymTabSecNo() const { return SN2I.get(".symtab"); }
159169 unsigned getDotStrTabSecNo() const { return SN2I.get(".strtab"); }
160170 unsigned getDotShStrTabSecNo() const { return SN2I.get(".shstrtab"); }
171 unsigned getDotDynSymSecNo() const { return SN2I.get(".dynsym"); }
172 unsigned getDotDynStrSecNo() const { return SN2I.get(".dynstr"); }
161173 unsigned getSectionCount() const { return SN2I.size() + 1; }
162174
163175 ELFState(const ELFYAML::Object &D) : Doc(D) {}
165177 public:
166178 static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
167179 };
168
169 static const char * const ImplicitSecNames[] = {".symtab", ".strtab", ".shstrtab"};
170180 } // end anonymous namespace
171181
172182 template
287297
288298 template
289299 void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader,
300 SymtabType STType,
290301 ContiguousBlobAccumulator &CBA) {
291302 zero(SHeader);
292 SHeader.sh_name = DotShStrtab.getOffset(".symtab");
293 SHeader.sh_type = ELF::SHT_SYMTAB;
294 SHeader.sh_link = getDotStrTabSecNo();
303 bool IsStatic = STType == SymtabType::Static;
304 SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym");
305 SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM;
306 SHeader.sh_link = IsStatic ? getDotStrTabSecNo() : getDotDynStrSecNo();
307 const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols;
308 auto &Strtab = IsStatic ? DotStrtab : DotDynstr;
295309 // One greater than symbol table index of the last local symbol.
296 SHeader.sh_info = Doc.Symbols.Local.size() + 1;
310 SHeader.sh_info = Symbols.Local.size() + 1;
297311 SHeader.sh_entsize = sizeof(Elf_Sym);
298312 SHeader.sh_addralign = 8;
299313
305319 Syms.push_back(Sym);
306320 }
307321
308 // Add symbol names to .strtab.
309 for (const auto &Sym : Doc.Symbols.Local)
310 DotStrtab.add(Sym.Name);
311 for (const auto &Sym : Doc.Symbols.Global)
312 DotStrtab.add(Sym.Name);
313 for (const auto &Sym : Doc.Symbols.Weak)
314 DotStrtab.add(Sym.Name);
315 DotStrtab.finalize();
316
317 addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
318 addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
319 addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
322 // Add symbol names to .strtab or .dynstr.
323 for (const auto &Sym : Symbols.Local)
324 Strtab.add(Sym.Name);
325 for (const auto &Sym : Symbols.Global)
326 Strtab.add(Sym.Name);
327 for (const auto &Sym : Symbols.Weak)
328 Strtab.add(Sym.Name);
329 Strtab.finalize();
330
331 addSymbols(Symbols.Local, Syms, ELF::STB_LOCAL, Strtab);
332 addSymbols(Symbols.Global, Syms, ELF::STB_GLOBAL, Strtab);
333 addSymbols(Symbols.Weak, Syms, ELF::STB_WEAK, Strtab);
320334
321335 writeArrayData(
322336 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
404418 template
405419 void ELFState::addSymbols(const std::vector &Symbols,
406420 std::vector &Syms,
407 unsigned SymbolBinding) {
421 unsigned SymbolBinding,
422 const StringTableBuilder &Strtab) {
408423 for (const auto &Sym : Symbols) {
409424 Elf_Sym Symbol;
410425 zero(Symbol);
411426 if (!Sym.Name.empty())
412 Symbol.st_name = DotStrtab.getOffset(Sym.Name);
427 Symbol.st_name = Strtab.getOffset(Sym.Name);
413428 Symbol.setBindingAndType(SymbolBinding, Sym.Type);
414429 if (!Sym.Section.empty()) {
415430 unsigned Index;
566581
567582 auto SecNo = 1 + Doc.Sections.size();
568583 // Add special sections after input sections, if necessary.
569 for (const auto &Name : ImplicitSecNames)
584 for (const auto &Name : implicitSectionNames())
570585 if (!SN2I.addName(Name, SecNo)) {
571586 // Account for this section, since it wasn't in the Doc
572587 ++SecNo;
625640 return 1;
626641
627642 // Populate SHeaders with implicit sections not present in the Doc
628 for (const auto &Name : ImplicitSecNames)
643 for (const auto &Name : State.implicitSectionNames())
629644 if (State.SN2I.get(Name) >= SHeaders.size())
630645 SHeaders.push_back({});
631646
632647 // Initialize the implicit sections
633648 auto Index = State.SN2I.get(".symtab");
634 State.initSymtabSectionHeader(SHeaders[Index], CBA);
649 State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Static, CBA);
635650 Index = State.SN2I.get(".strtab");
636651 State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA);
637652 Index = State.SN2I.get(".shstrtab");
638653 State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA);
654 if (State.hasDynamicSymbols()) {
655 Index = State.SN2I.get(".dynsym");
656 State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Dynamic, CBA);
657 SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
658 Index = State.SN2I.get(".dynstr");
659 State.initStrtabSectionHeader(SHeaders[Index], ".dynstr", State.DotDynstr, CBA);
660 SHeaders[Index].sh_flags |= ELF::SHF_ALLOC;
661 }
639662
640663 // Now we can decide segment offsets
641664 State.setProgramHeaderLayout(PHeaders, SHeaders);
645668 writeArrayData(OS, makeArrayRef(SHeaders));
646669 CBA.writeBlobToStream(OS);
647670 return 0;
671 }
672
673 template bool ELFState::hasDynamicSymbols() const {
674 return Doc.DynamicSymbols.Global.size() > 0 ||
675 Doc.DynamicSymbols.Weak.size() > 0 ||
676 Doc.DynamicSymbols.Local.size() > 0;
677 }
678
679 template SmallVector ELFState::implicitSectionNames() const {
680 if (!hasDynamicSymbols())
681 return {".symtab", ".strtab", ".shstrtab"};
682 return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
648683 }
649684
650685 static bool is64Bit(const ELFYAML::Object &Doc) {