1 //===------ utils/elf2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/DenseSet.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Object/ELFObjectFile.h"
13 #include "llvm/ObjectYAML/ELFYAML.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/YAMLTraits.h"
23 typedef object::Elf_Sym_Impl
<ELFT
> Elf_Sym
;
24 typedef typename
ELFT::Dyn Elf_Dyn
;
25 typedef typename
ELFT::Shdr Elf_Shdr
;
26 typedef typename
ELFT::Word Elf_Word
;
27 typedef typename
ELFT::Rel Elf_Rel
;
28 typedef typename
ELFT::Rela Elf_Rela
;
30 ArrayRef
<Elf_Shdr
> Sections
;
32 // If the file has multiple sections with the same name, we add a
33 // suffix to make them unique.
35 DenseSet
<StringRef
> UsedSectionNames
;
36 std::vector
<std::string
> SectionNames
;
37 Expected
<StringRef
> getUniquedSectionName(const Elf_Shdr
*Sec
);
38 Expected
<StringRef
> getSymbolName(const Elf_Sym
*Sym
, StringRef StrTable
,
39 const Elf_Shdr
*SymTab
);
41 const object::ELFFile
<ELFT
> &Obj
;
42 ArrayRef
<Elf_Word
> ShndxTable
;
44 std::error_code
dumpSymbols(const Elf_Shdr
*Symtab
,
45 ELFYAML::LocalGlobalWeakSymbols
&Symbols
);
46 std::error_code
dumpSymbol(const Elf_Sym
*Sym
, const Elf_Shdr
*SymTab
,
47 StringRef StrTable
, ELFYAML::Symbol
&S
);
48 std::error_code
dumpCommonSection(const Elf_Shdr
*Shdr
, ELFYAML::Section
&S
);
49 std::error_code
dumpCommonRelocationSection(const Elf_Shdr
*Shdr
,
50 ELFYAML::RelocationSection
&S
);
52 std::error_code
dumpRelocation(const RelT
*Rel
, const Elf_Shdr
*SymTab
,
53 ELFYAML::Relocation
&R
);
55 ErrorOr
<ELFYAML::DynamicSection
*> dumpDynamicSection(const Elf_Shdr
*Shdr
);
56 ErrorOr
<ELFYAML::RelocationSection
*> dumpRelocSection(const Elf_Shdr
*Shdr
);
57 ErrorOr
<ELFYAML::RawContentSection
*>
58 dumpContentSection(const Elf_Shdr
*Shdr
);
59 ErrorOr
<ELFYAML::NoBitsSection
*> dumpNoBitsSection(const Elf_Shdr
*Shdr
);
60 ErrorOr
<ELFYAML::Group
*> dumpGroup(const Elf_Shdr
*Shdr
);
61 ErrorOr
<ELFYAML::MipsABIFlags
*> dumpMipsABIFlags(const Elf_Shdr
*Shdr
);
64 ELFDumper(const object::ELFFile
<ELFT
> &O
);
65 ErrorOr
<ELFYAML::Object
*> dump();
71 ELFDumper
<ELFT
>::ELFDumper(const object::ELFFile
<ELFT
> &O
)
76 ELFDumper
<ELFT
>::getUniquedSectionName(const Elf_Shdr
*Sec
) {
77 unsigned SecIndex
= Sec
- &Sections
[0];
78 assert(&Sections
[SecIndex
] == Sec
);
79 if (!SectionNames
[SecIndex
].empty())
80 return SectionNames
[SecIndex
];
82 auto NameOrErr
= Obj
.getSectionName(Sec
);
85 StringRef Name
= *NameOrErr
;
86 std::string
&Ret
= SectionNames
[SecIndex
];
88 while (!UsedSectionNames
.insert(Ret
).second
)
89 Ret
= (Name
+ to_string(++Suffix
)).str();
94 Expected
<StringRef
> ELFDumper
<ELFT
>::getSymbolName(const Elf_Sym
*Sym
,
96 const Elf_Shdr
*SymTab
) {
97 Expected
<StringRef
> SymbolNameOrErr
= Sym
->getName(StrTable
);
99 return SymbolNameOrErr
;
100 StringRef Name
= *SymbolNameOrErr
;
101 if (Name
.empty() && Sym
->getType() == ELF::STT_SECTION
) {
102 auto ShdrOrErr
= Obj
.getSection(Sym
, SymTab
, ShndxTable
);
104 return ShdrOrErr
.takeError();
105 return getUniquedSectionName(*ShdrOrErr
);
110 template <class ELFT
> ErrorOr
<ELFYAML::Object
*> ELFDumper
<ELFT
>::dump() {
111 auto Y
= make_unique
<ELFYAML::Object
>();
114 Y
->Header
.Class
= ELFYAML::ELF_ELFCLASS(Obj
.getHeader()->getFileClass());
115 Y
->Header
.Data
= ELFYAML::ELF_ELFDATA(Obj
.getHeader()->getDataEncoding());
116 Y
->Header
.OSABI
= Obj
.getHeader()->e_ident
[ELF::EI_OSABI
];
117 Y
->Header
.ABIVersion
= Obj
.getHeader()->e_ident
[ELF::EI_ABIVERSION
];
118 Y
->Header
.Type
= Obj
.getHeader()->e_type
;
119 Y
->Header
.Machine
= Obj
.getHeader()->e_machine
;
120 Y
->Header
.Flags
= Obj
.getHeader()->e_flags
;
121 Y
->Header
.Entry
= Obj
.getHeader()->e_entry
;
123 const Elf_Shdr
*Symtab
= nullptr;
124 const Elf_Shdr
*DynSymtab
= nullptr;
127 auto SectionsOrErr
= Obj
.sections();
129 return errorToErrorCode(SectionsOrErr
.takeError());
130 Sections
= *SectionsOrErr
;
131 SectionNames
.resize(Sections
.size());
132 for (const Elf_Shdr
&Sec
: Sections
) {
133 switch (Sec
.sh_type
) {
134 case ELF::SHT_DYNAMIC
: {
135 ErrorOr
<ELFYAML::DynamicSection
*> S
= dumpDynamicSection(&Sec
);
136 if (std::error_code EC
= S
.getError())
138 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(S
.get()));
142 case ELF::SHT_STRTAB
:
143 // Do not dump these sections.
145 case ELF::SHT_SYMTAB
:
148 case ELF::SHT_DYNSYM
:
151 case ELF::SHT_SYMTAB_SHNDX
: {
152 auto TableOrErr
= Obj
.getSHNDXTable(Sec
);
154 return errorToErrorCode(TableOrErr
.takeError());
155 ShndxTable
= *TableOrErr
;
159 case ELF::SHT_RELA
: {
160 ErrorOr
<ELFYAML::RelocationSection
*> S
= dumpRelocSection(&Sec
);
161 if (std::error_code EC
= S
.getError())
163 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(S
.get()));
166 case ELF::SHT_GROUP
: {
167 ErrorOr
<ELFYAML::Group
*> G
= dumpGroup(&Sec
);
168 if (std::error_code EC
= G
.getError())
170 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(G
.get()));
173 case ELF::SHT_MIPS_ABIFLAGS
: {
174 ErrorOr
<ELFYAML::MipsABIFlags
*> G
= dumpMipsABIFlags(&Sec
);
175 if (std::error_code EC
= G
.getError())
177 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(G
.get()));
180 case ELF::SHT_NOBITS
: {
181 ErrorOr
<ELFYAML::NoBitsSection
*> S
= dumpNoBitsSection(&Sec
);
182 if (std::error_code EC
= S
.getError())
184 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(S
.get()));
188 ErrorOr
<ELFYAML::RawContentSection
*> S
= dumpContentSection(&Sec
);
189 if (std::error_code EC
= S
.getError())
191 Y
->Sections
.push_back(std::unique_ptr
<ELFYAML::Section
>(S
.get()));
196 if (auto EC
= dumpSymbols(Symtab
, Y
->Symbols
))
198 if (auto EC
= dumpSymbols(DynSymtab
, Y
->DynamicSymbols
))
204 template <class ELFT
>
206 ELFDumper
<ELFT
>::dumpSymbols(const Elf_Shdr
*Symtab
,
207 ELFYAML::LocalGlobalWeakSymbols
&Symbols
) {
209 return std::error_code();
211 auto StrTableOrErr
= Obj
.getStringTableForSymtab(*Symtab
);
213 return errorToErrorCode(StrTableOrErr
.takeError());
214 StringRef StrTable
= *StrTableOrErr
;
216 auto SymtabOrErr
= Obj
.symbols(Symtab
);
218 return errorToErrorCode(SymtabOrErr
.takeError());
220 bool IsFirstSym
= true;
221 for (const auto &Sym
: *SymtabOrErr
) {
228 if (auto EC
= dumpSymbol(&Sym
, Symtab
, StrTable
, S
))
231 switch (Sym
.getBinding()) {
233 Symbols
.Local
.push_back(S
);
235 case ELF::STB_GLOBAL
:
236 Symbols
.Global
.push_back(S
);
239 Symbols
.Weak
.push_back(S
);
242 llvm_unreachable("Unknown ELF symbol binding");
246 return std::error_code();
249 template <class ELFT
>
251 ELFDumper
<ELFT
>::dumpSymbol(const Elf_Sym
*Sym
, const Elf_Shdr
*SymTab
,
252 StringRef StrTable
, ELFYAML::Symbol
&S
) {
253 S
.Type
= Sym
->getType();
254 S
.Value
= Sym
->st_value
;
255 S
.Size
= Sym
->st_size
;
256 S
.Other
= Sym
->st_other
;
258 Expected
<StringRef
> SymbolNameOrErr
= getSymbolName(Sym
, StrTable
, SymTab
);
259 if (!SymbolNameOrErr
)
260 return errorToErrorCode(SymbolNameOrErr
.takeError());
261 S
.Name
= SymbolNameOrErr
.get();
263 auto ShdrOrErr
= Obj
.getSection(Sym
, SymTab
, ShndxTable
);
265 return errorToErrorCode(ShdrOrErr
.takeError());
266 const Elf_Shdr
*Shdr
= *ShdrOrErr
;
268 return obj2yaml_error::success
;
270 auto NameOrErr
= getUniquedSectionName(Shdr
);
272 return errorToErrorCode(NameOrErr
.takeError());
273 S
.Section
= NameOrErr
.get();
275 return obj2yaml_error::success
;
278 template <class ELFT
>
279 template <class RelT
>
280 std::error_code ELFDumper
<ELFT
>::dumpRelocation(const RelT
*Rel
,
281 const Elf_Shdr
*SymTab
,
282 ELFYAML::Relocation
&R
) {
283 R
.Type
= Rel
->getType(Obj
.isMips64EL());
284 R
.Offset
= Rel
->r_offset
;
287 auto SymOrErr
= Obj
.getRelocationSymbol(Rel
, SymTab
);
289 return errorToErrorCode(SymOrErr
.takeError());
290 const Elf_Sym
*Sym
= *SymOrErr
;
291 auto StrTabSec
= Obj
.getSection(SymTab
->sh_link
);
293 return errorToErrorCode(StrTabSec
.takeError());
294 auto StrTabOrErr
= Obj
.getStringTable(*StrTabSec
);
296 return errorToErrorCode(StrTabOrErr
.takeError());
297 StringRef StrTab
= *StrTabOrErr
;
300 Expected
<StringRef
> NameOrErr
= getSymbolName(Sym
, StrTab
, SymTab
);
302 return errorToErrorCode(NameOrErr
.takeError());
303 R
.Symbol
= NameOrErr
.get();
305 // We have some edge cases of relocations without a symbol associated,
306 // e.g. an object containing the invalid (according to the System V
307 // ABI) R_X86_64_NONE reloc. Create a symbol with an empty name instead
312 return obj2yaml_error::success
;
315 template <class ELFT
>
316 std::error_code ELFDumper
<ELFT
>::dumpCommonSection(const Elf_Shdr
*Shdr
,
317 ELFYAML::Section
&S
) {
318 S
.Type
= Shdr
->sh_type
;
319 S
.Flags
= Shdr
->sh_flags
;
320 S
.Address
= Shdr
->sh_addr
;
321 S
.AddressAlign
= Shdr
->sh_addralign
;
322 if (Shdr
->sh_entsize
)
323 S
.EntSize
= static_cast<llvm::yaml::Hex64
>(Shdr
->sh_entsize
);
325 auto NameOrErr
= getUniquedSectionName(Shdr
);
327 return errorToErrorCode(NameOrErr
.takeError());
328 S
.Name
= NameOrErr
.get();
330 if (Shdr
->sh_link
!= ELF::SHN_UNDEF
) {
331 auto LinkSection
= Obj
.getSection(Shdr
->sh_link
);
332 if (LinkSection
.takeError())
333 return errorToErrorCode(LinkSection
.takeError());
334 NameOrErr
= getUniquedSectionName(*LinkSection
);
336 return errorToErrorCode(NameOrErr
.takeError());
337 S
.Link
= NameOrErr
.get();
340 return obj2yaml_error::success
;
343 template <class ELFT
>
345 ELFDumper
<ELFT
>::dumpCommonRelocationSection(const Elf_Shdr
*Shdr
,
346 ELFYAML::RelocationSection
&S
) {
347 if (std::error_code EC
= dumpCommonSection(Shdr
, S
))
350 auto InfoSection
= Obj
.getSection(Shdr
->sh_info
);
352 return errorToErrorCode(InfoSection
.takeError());
354 auto NameOrErr
= getUniquedSectionName(*InfoSection
);
356 return errorToErrorCode(NameOrErr
.takeError());
357 S
.RelocatableSec
= NameOrErr
.get();
359 return obj2yaml_error::success
;
362 template <class ELFT
>
363 ErrorOr
<ELFYAML::DynamicSection
*>
364 ELFDumper
<ELFT
>::dumpDynamicSection(const Elf_Shdr
*Shdr
) {
365 auto S
= make_unique
<ELFYAML::DynamicSection
>();
366 if (std::error_code EC
= dumpCommonSection(Shdr
, *S
))
369 auto DynTagsOrErr
= Obj
.template getSectionContentsAsArray
<Elf_Dyn
>(Shdr
);
371 return errorToErrorCode(DynTagsOrErr
.takeError());
373 for (const Elf_Dyn
&Dyn
: *DynTagsOrErr
)
374 S
->Entries
.push_back({(ELFYAML::ELF_DYNTAG
)Dyn
.getTag(), Dyn
.getVal()});
379 template <class ELFT
>
380 ErrorOr
<ELFYAML::RelocationSection
*>
381 ELFDumper
<ELFT
>::dumpRelocSection(const Elf_Shdr
*Shdr
) {
382 auto S
= make_unique
<ELFYAML::RelocationSection
>();
383 if (std::error_code EC
= dumpCommonRelocationSection(Shdr
, *S
))
386 auto SymTabOrErr
= Obj
.getSection(Shdr
->sh_link
);
388 return errorToErrorCode(SymTabOrErr
.takeError());
389 const Elf_Shdr
*SymTab
= *SymTabOrErr
;
391 if (Shdr
->sh_type
== ELF::SHT_REL
) {
392 auto Rels
= Obj
.rels(Shdr
);
394 return errorToErrorCode(Rels
.takeError());
395 for (const Elf_Rel
&Rel
: *Rels
) {
396 ELFYAML::Relocation R
;
397 if (std::error_code EC
= dumpRelocation(&Rel
, SymTab
, R
))
399 S
->Relocations
.push_back(R
);
402 auto Rels
= Obj
.relas(Shdr
);
404 return errorToErrorCode(Rels
.takeError());
405 for (const Elf_Rela
&Rel
: *Rels
) {
406 ELFYAML::Relocation R
;
407 if (std::error_code EC
= dumpRelocation(&Rel
, SymTab
, R
))
409 R
.Addend
= Rel
.r_addend
;
410 S
->Relocations
.push_back(R
);
417 template <class ELFT
>
418 ErrorOr
<ELFYAML::RawContentSection
*>
419 ELFDumper
<ELFT
>::dumpContentSection(const Elf_Shdr
*Shdr
) {
420 auto S
= make_unique
<ELFYAML::RawContentSection
>();
422 if (std::error_code EC
= dumpCommonSection(Shdr
, *S
))
425 auto ContentOrErr
= Obj
.getSectionContents(Shdr
);
427 return errorToErrorCode(ContentOrErr
.takeError());
428 S
->Content
= yaml::BinaryRef(ContentOrErr
.get());
429 S
->Size
= S
->Content
.binary_size();
434 template <class ELFT
>
435 ErrorOr
<ELFYAML::NoBitsSection
*>
436 ELFDumper
<ELFT
>::dumpNoBitsSection(const Elf_Shdr
*Shdr
) {
437 auto S
= make_unique
<ELFYAML::NoBitsSection
>();
439 if (std::error_code EC
= dumpCommonSection(Shdr
, *S
))
441 S
->Size
= Shdr
->sh_size
;
446 template <class ELFT
>
447 ErrorOr
<ELFYAML::Group
*> ELFDumper
<ELFT
>::dumpGroup(const Elf_Shdr
*Shdr
) {
448 auto S
= make_unique
<ELFYAML::Group
>();
450 if (std::error_code EC
= dumpCommonSection(Shdr
, *S
))
452 // Get sh_info which is the signature.
453 auto SymtabOrErr
= Obj
.getSection(Shdr
->sh_link
);
455 return errorToErrorCode(SymtabOrErr
.takeError());
456 const Elf_Shdr
*Symtab
= *SymtabOrErr
;
457 auto SymOrErr
= Obj
.getSymbol(Symtab
, Shdr
->sh_info
);
459 return errorToErrorCode(SymOrErr
.takeError());
460 const Elf_Sym
*symbol
= *SymOrErr
;
461 auto StrTabOrErr
= Obj
.getStringTableForSymtab(*Symtab
);
463 return errorToErrorCode(StrTabOrErr
.takeError());
464 StringRef StrTab
= *StrTabOrErr
;
465 auto sectionContents
= Obj
.getSectionContents(Shdr
);
466 if (!sectionContents
)
467 return errorToErrorCode(sectionContents
.takeError());
468 Expected
<StringRef
> symbolName
= getSymbolName(symbol
, StrTab
, Symtab
);
470 return errorToErrorCode(symbolName
.takeError());
471 S
->Signature
= *symbolName
;
472 const Elf_Word
*groupMembers
=
473 reinterpret_cast<const Elf_Word
*>(sectionContents
->data());
474 const long count
= (Shdr
->sh_size
) / sizeof(Elf_Word
);
475 ELFYAML::SectionOrType s
;
476 for (int i
= 0; i
< count
; i
++) {
477 if (groupMembers
[i
] == llvm::ELF::GRP_COMDAT
) {
478 s
.sectionNameOrType
= "GRP_COMDAT";
480 auto sHdr
= Obj
.getSection(groupMembers
[i
]);
482 return errorToErrorCode(sHdr
.takeError());
483 auto sectionName
= getUniquedSectionName(*sHdr
);
485 return errorToErrorCode(sectionName
.takeError());
486 s
.sectionNameOrType
= *sectionName
;
488 S
->Members
.push_back(s
);
493 template <class ELFT
>
494 ErrorOr
<ELFYAML::MipsABIFlags
*>
495 ELFDumper
<ELFT
>::dumpMipsABIFlags(const Elf_Shdr
*Shdr
) {
496 assert(Shdr
->sh_type
== ELF::SHT_MIPS_ABIFLAGS
&&
497 "Section type is not SHT_MIPS_ABIFLAGS");
498 auto S
= make_unique
<ELFYAML::MipsABIFlags
>();
499 if (std::error_code EC
= dumpCommonSection(Shdr
, *S
))
502 auto ContentOrErr
= Obj
.getSectionContents(Shdr
);
504 return errorToErrorCode(ContentOrErr
.takeError());
506 auto *Flags
= reinterpret_cast<const object::Elf_Mips_ABIFlags
<ELFT
> *>(
507 ContentOrErr
.get().data());
508 S
->Version
= Flags
->version
;
509 S
->ISALevel
= Flags
->isa_level
;
510 S
->ISARevision
= Flags
->isa_rev
;
511 S
->GPRSize
= Flags
->gpr_size
;
512 S
->CPR1Size
= Flags
->cpr1_size
;
513 S
->CPR2Size
= Flags
->cpr2_size
;
514 S
->FpABI
= Flags
->fp_abi
;
515 S
->ISAExtension
= Flags
->isa_ext
;
516 S
->ASEs
= Flags
->ases
;
517 S
->Flags1
= Flags
->flags1
;
518 S
->Flags2
= Flags
->flags2
;
522 template <class ELFT
>
523 static std::error_code
elf2yaml(raw_ostream
&Out
,
524 const object::ELFFile
<ELFT
> &Obj
) {
525 ELFDumper
<ELFT
> Dumper(Obj
);
526 ErrorOr
<ELFYAML::Object
*> YAMLOrErr
= Dumper
.dump();
527 if (std::error_code EC
= YAMLOrErr
.getError())
530 std::unique_ptr
<ELFYAML::Object
> YAML(YAMLOrErr
.get());
531 yaml::Output
Yout(Out
);
534 return std::error_code();
537 std::error_code
elf2yaml(raw_ostream
&Out
, const object::ObjectFile
&Obj
) {
538 if (const auto *ELFObj
= dyn_cast
<object::ELF32LEObjectFile
>(&Obj
))
539 return elf2yaml(Out
, *ELFObj
->getELFFile());
541 if (const auto *ELFObj
= dyn_cast
<object::ELF32BEObjectFile
>(&Obj
))
542 return elf2yaml(Out
, *ELFObj
->getELFFile());
544 if (const auto *ELFObj
= dyn_cast
<object::ELF64LEObjectFile
>(&Obj
))
545 return elf2yaml(Out
, *ELFObj
->getELFFile());
547 if (const auto *ELFObj
= dyn_cast
<object::ELF64BEObjectFile
>(&Obj
))
548 return elf2yaml(Out
, *ELFObj
->getELFFile());
550 return obj2yaml_error::unsupported_obj_file_format
;