Skip to content

Commit

Permalink
[ObjectYAML][DWARF] Add DWARF entry in ELFYAML.
Browse files Browse the repository at this point in the history
This patch adds a new DWARF entry in ELF YAML file.

Reviewed By: grimar

Differential Revision: https://reviews.llvm.org/D80203
  • Loading branch information
higuoxing committed May 29, 2020
1 parent 4cd3f4b commit 373e98a
Show file tree
Hide file tree
Showing 6 changed files with 332 additions and 1 deletion.
3 changes: 3 additions & 0 deletions llvm/include/llvm/ObjectYAML/DWARFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef LLVM_OBJECTYAML_DWARFYAML_H
#define LLVM_OBJECTYAML_DWARFYAML_H

#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/YAMLTraits.h"
Expand Down Expand Up @@ -171,6 +172,8 @@ struct Data {
std::vector<LineTable> DebugLines;

bool isEmpty() const;

SetVector<StringRef> getUsedSectionNames() const;
};

} // end namespace DWARFYAML
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/ObjectYAML/ELFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define LLVM_OBJECTYAML_ELFYAML_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/YAMLTraits.h"
#include <cstdint>
Expand Down Expand Up @@ -529,6 +530,7 @@ struct Object {
// being a single SHT_SYMTAB section are upheld.
Optional<std::vector<Symbol>> Symbols;
Optional<std::vector<Symbol>> DynamicSymbols;
Optional<DWARFYAML::Data> DWARF;

std::vector<Section *> getSections() {
std::vector<Section *> Ret;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/ObjectYAML/DWARFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ bool DWARFYAML::Data::isEmpty() const {
DebugLines.empty();
}

SetVector<StringRef> DWARFYAML::Data::getUsedSectionNames() const {
SetVector<StringRef> SecNames;
if (!DebugStrings.empty())
SecNames.insert("debug_str");
return SecNames;
}

namespace yaml {

void MappingTraits<DWARFYAML::Data>::mapping(IO &IO, DWARFYAML::Data &DWARF) {
Expand Down
82 changes: 81 additions & 1 deletion llvm/lib/ObjectYAML/ELFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/EndianStream.h"
Expand Down Expand Up @@ -149,6 +152,9 @@ template <class ELFT> class ELFState {
StringTableBuilder &STB,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec);
void initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec);
void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
std::vector<Elf_Shdr> &SHeaders);

Expand Down Expand Up @@ -274,6 +280,11 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
if (Doc.Symbols)
ImplicitSections.push_back(".symtab");
if (Doc.DWARF)
for (StringRef DebugSecName : Doc.DWARF->getUsedSectionNames()) {
std::string SecName = ("." + DebugSecName).str();
ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
}
ImplicitSections.insert(ImplicitSections.end(), {".strtab", ".shstrtab"});

// Insert placeholders for implicit sections that are not
Expand Down Expand Up @@ -447,7 +458,13 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
else if (SecName == ".dynstr")
initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
else
else if (SecName.startswith(".debug_")) {
// If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
// will not treat it as a debug section.
if (YAMLSec && !isa<ELFYAML::RawContentSection>(YAMLSec))
return false;
initDWARFSectionHeader(Header, SecName, CBA, YAMLSec);
} else
return false;

LocationCounter += Header.sh_size;
Expand Down Expand Up @@ -791,6 +808,69 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
assignSectionAddress(SHeader, YAMLSec);
}

static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) {
SetVector<StringRef> DebugSecNames = DWARF.getUsedSectionNames();
return Name.consume_front(".") && DebugSecNames.count(Name);
}

template <class ELFT>
uint64_t emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name,
const DWARFYAML::Data &DWARF, raw_ostream &OS) {
uint64_t BeginOffset = OS.tell();
if (Name == ".debug_str")
DWARFYAML::EmitDebugStr(OS, DWARF);
else
llvm_unreachable("unexpected emitDWARF() call");

return OS.tell() - BeginOffset;
}

template <class ELFT>
void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec) {
zero(SHeader);
SHeader.sh_name = DotShStrtab.getOffset(ELFYAML::dropUniqueSuffix(Name));
SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS;
SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,
YAMLSec ? YAMLSec->Offset : None);

ELFYAML::RawContentSection *RawSec =
dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);
if (Doc.DWARF && shouldEmitDWARF(*Doc.DWARF, Name)) {
if (RawSec && (RawSec->Content || RawSec->Size))
reportError("cannot specify section '" + Name +
"' contents in the 'DWARF' entry and the 'Content' "
"or 'Size' in the 'Sections' entry at the same time");
else
SHeader.sh_size = emitDWARF<ELFT>(SHeader, Name, *Doc.DWARF, CBA.getOS());
} else if (RawSec)
SHeader.sh_size = writeContent(CBA.getOS(), RawSec->Content, RawSec->Size);
else
llvm_unreachable("debug sections can only be initialized via the 'DWARF' "
"entry or a RawContentSection");

if (YAMLSec && YAMLSec->EntSize)
SHeader.sh_entsize = *YAMLSec->EntSize;
else if (Name == ".debug_str")
SHeader.sh_entsize = 1;

if (RawSec && RawSec->Info)
SHeader.sh_info = *RawSec->Info;

if (YAMLSec && YAMLSec->Flags)
SHeader.sh_flags = *YAMLSec->Flags;
else if (Name == ".debug_str")
SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS;

unsigned Link = 0;
if (YAMLSec && !YAMLSec->Link.empty() && SN2I.lookup(YAMLSec->Link, Link))
SHeader.sh_link = Link;

assignSectionAddress(SHeader, YAMLSec);
}

template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
ErrHandler(Msg);
HasError = true;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ObjectYAML/ELFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1653,6 +1653,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
IO.mapOptional("Sections", Object.Chunks);
IO.mapOptional("Symbols", Object.Symbols);
IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
IO.mapOptional("DWARF", Object.DWARF);
IO.setContext(nullptr);
}

Expand Down
Loading

0 comments on commit 373e98a

Please sign in to comment.