diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/ObjectYAML/ELFYAML.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFYAML.cpp')
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 157 |
1 files changed, 135 insertions, 22 deletions
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index efa7ecb4728b2..2353b34f188b1 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -221,6 +221,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration( ECase(EM_RISCV); ECase(EM_LANAI); ECase(EM_BPF); + ECase(EM_VE); #undef ECase IO.enumFallback<Hex16>(Value); } @@ -349,6 +350,9 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, BCase(EF_HEXAGON_MACH_V60); BCase(EF_HEXAGON_MACH_V62); BCase(EF_HEXAGON_MACH_V65); + BCase(EF_HEXAGON_MACH_V66); + BCase(EF_HEXAGON_MACH_V67); + BCase(EF_HEXAGON_MACH_V67T); BCase(EF_HEXAGON_ISA_V2); BCase(EF_HEXAGON_ISA_V3); BCase(EF_HEXAGON_ISA_V4); @@ -357,6 +361,8 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, BCase(EF_HEXAGON_ISA_V60); BCase(EF_HEXAGON_ISA_V62); BCase(EF_HEXAGON_ISA_V65); + BCase(EF_HEXAGON_ISA_V66); + BCase(EF_HEXAGON_ISA_V67); break; case ELF::EM_AVR: BCase(EF_AVR_ARCH_AVR1); @@ -423,6 +429,7 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1010, EF_AMDGPU_MACH); BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1011, EF_AMDGPU_MACH); BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1012, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1030, EF_AMDGPU_MACH); BCase(EF_AMDGPU_XNACK); BCase(EF_AMDGPU_SRAM_ECC); break; @@ -495,6 +502,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( ECase(SHT_MIPS_DWARF); ECase(SHT_MIPS_ABIFLAGS); break; + case ELF::EM_RISCV: + ECase(SHT_RISCV_ATTRIBUTES); + break; default: // Nothing to do. break; @@ -654,6 +664,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( case ELF::EM_BPF: #include "llvm/BinaryFormat/ELFRelocs/BPF.def" break; + case ELF::EM_VE: +#include "llvm/BinaryFormat/ELFRelocs/VE.def" + break; case ELF::EM_PPC64: #include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def" break; @@ -820,6 +833,28 @@ void ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1>::bitset( #undef BCase } +void MappingTraits<ELFYAML::SectionHeader>::mapping( + IO &IO, ELFYAML::SectionHeader &SHdr) { + IO.mapRequired("Name", SHdr.Name); +} + +void MappingTraits<ELFYAML::SectionHeaderTable>::mapping( + IO &IO, ELFYAML::SectionHeaderTable &SectionHeader) { + IO.mapOptional("Sections", SectionHeader.Sections); + IO.mapOptional("Excluded", SectionHeader.Excluded); + IO.mapOptional("NoHeaders", SectionHeader.NoHeaders); +} + +StringRef MappingTraits<ELFYAML::SectionHeaderTable>::validate( + IO &IO, ELFYAML::SectionHeaderTable &SecHdrTable) { + if (SecHdrTable.NoHeaders && (SecHdrTable.Sections || SecHdrTable.Excluded)) + return "NoHeaders can't be used together with Sections/Excluded"; + if (!SecHdrTable.NoHeaders && !SecHdrTable.Sections && !SecHdrTable.Excluded) + return "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the " + "section header table"; + return StringRef(); +} + void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, ELFYAML::FileHeader &FileHdr) { IO.mapRequired("Class", FileHdr.Class); @@ -831,10 +866,16 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0)); IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); - IO.mapOptional("SHEntSize", FileHdr.SHEntSize); - IO.mapOptional("SHOff", FileHdr.SHOff); - IO.mapOptional("SHNum", FileHdr.SHNum); - IO.mapOptional("SHStrNdx", FileHdr.SHStrNdx); + // obj2yaml does not dump these fields. + assert(!IO.outputting() || + (!FileHdr.EPhOff && !FileHdr.EPhEntSize && !FileHdr.EPhNum)); + IO.mapOptional("EPhOff", FileHdr.EPhOff); + IO.mapOptional("EPhEntSize", FileHdr.EPhEntSize); + IO.mapOptional("EPhNum", FileHdr.EPhNum); + IO.mapOptional("EShEntSize", FileHdr.EShEntSize); + IO.mapOptional("EShOff", FileHdr.EShOff); + IO.mapOptional("EShNum", FileHdr.EShNum); + IO.mapOptional("EShStrNdx", FileHdr.EShStrNdx); } void MappingTraits<ELFYAML::ProgramHeader>::mapping( @@ -843,7 +884,7 @@ void MappingTraits<ELFYAML::ProgramHeader>::mapping( IO.mapOptional("Flags", Phdr.Flags, ELFYAML::ELF_PF(0)); IO.mapOptional("Sections", Phdr.Sections); IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0)); - IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0)); + IO.mapOptional("PAddr", Phdr.PAddr, Phdr.VAddr); IO.mapOptional("Align", Phdr.Align); IO.mapOptional("FileSize", Phdr.FileSize); IO.mapOptional("MemSize", Phdr.MemSize); @@ -977,9 +1018,41 @@ struct NormalizedOther { } // end anonymous namespace +void ScalarTraits<ELFYAML::YAMLIntUInt>::output(const ELFYAML::YAMLIntUInt &Val, + void *Ctx, raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits<ELFYAML::YAMLIntUInt>::input(StringRef Scalar, void *Ctx, + ELFYAML::YAMLIntUInt &Val) { + const bool Is64 = static_cast<ELFYAML::Object *>(Ctx)->Header.Class == + ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); + StringRef ErrMsg = "invalid number"; + // We do not accept negative hex numbers because their meaning is ambiguous. + // For example, would -0xfffffffff mean 1 or INT32_MIN? + if (Scalar.empty() || Scalar.startswith("-0x")) + return ErrMsg; + + if (Scalar.startswith("-")) { + const int64_t MinVal = Is64 ? INT64_MIN : INT32_MIN; + long long Int; + if (getAsSignedInteger(Scalar, /*Radix=*/0, Int) || (Int < MinVal)) + return ErrMsg; + Val = Int; + return ""; + } + + const uint64_t MaxVal = Is64 ? UINT64_MAX : UINT32_MAX; + unsigned long long UInt; + if (getAsUnsignedInteger(Scalar, /*Radix=*/0, UInt) || (UInt > MaxVal)) + return ErrMsg; + Val = UInt; + return ""; +} + void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); - IO.mapOptional("NameIndex", Symbol.NameIndex); + IO.mapOptional("StName", Symbol.StName); IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Index", Symbol.Index); @@ -1001,8 +1074,6 @@ StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO, ELFYAML::Symbol &Symbol) { if (Symbol.Index && Symbol.Section.data()) return "Index and Section cannot both be specified for Symbol"; - if (Symbol.NameIndex && !Symbol.Name.empty()) - return "Name and NameIndex cannot both be specified for Symbol"; return StringRef(); } @@ -1010,10 +1081,11 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { IO.mapOptional("Name", Section.Name, StringRef()); IO.mapRequired("Type", Section.Type); IO.mapOptional("Flags", Section.Flags); - IO.mapOptional("Address", Section.Address, Hex64(0)); + IO.mapOptional("Address", Section.Address); IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); IO.mapOptional("EntSize", Section.EntSize); + IO.mapOptional("Offset", Section.Offset); // obj2yaml does not dump these fields. They are expected to be empty when we // are producing YAML, because yaml2obj sets appropriate values for them @@ -1036,6 +1108,17 @@ static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Content", Section.Content); + + // We also support reading a content as array of bytes using the ContentArray + // key. obj2yaml never prints this field. + assert(!IO.outputting() || !Section.ContentBuf.hasValue()); + IO.mapOptional("ContentArray", Section.ContentBuf); + if (Section.ContentBuf) { + if (Section.Content) + IO.setError("Content and ContentArray can't be used together"); + Section.Content = yaml::BinaryRef(*Section.ContentBuf); + } + IO.mapOptional("Size", Section.Size); IO.mapOptional("Info", Section.Info); } @@ -1053,6 +1136,13 @@ static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) { IO.mapOptional("Bucket", Section.Bucket); IO.mapOptional("Chain", Section.Chain); IO.mapOptional("Size", Section.Size); + + // obj2yaml does not dump these fields. They can be used to override nchain + // and nbucket values for creating broken sections. + assert(!IO.outputting() || + (!Section.NBucket.hasValue() && !Section.NChain.hasValue())); + IO.mapOptional("NChain", Section.NChain); + IO.mapOptional("NBucket", Section.NBucket); } static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { @@ -1128,6 +1218,7 @@ static void sectionMapping(IO &IO, ELFYAML::AddrsigSection &Section) { static void fillMapping(IO &IO, ELFYAML::Fill &Fill) { IO.mapOptional("Name", Fill.Name, StringRef()); IO.mapOptional("Pattern", Fill.Pattern); + IO.mapOptional("Offset", Fill.Offset); IO.mapRequired("Size", Fill.Size); } @@ -1144,6 +1235,12 @@ static void sectionMapping(IO &IO, IO.mapOptional("Content", Section.Content); } +static void sectionMapping(IO &IO, ELFYAML::CallGraphProfileSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); +} + void MappingTraits<ELFYAML::SectionOrType>::mapping( IO &IO, ELFYAML::SectionOrType §ionOrType) { IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); @@ -1277,6 +1374,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping( sectionMapping(IO, *cast<ELFYAML::DependentLibrariesSection>(Section.get())); break; + case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + if (!IO.outputting()) + Section.reset(new ELFYAML::CallGraphProfileSection()); + sectionMapping(IO, *cast<ELFYAML::CallGraphProfileSection>(Section.get())); + break; default: if (!IO.outputting()) { StringRef Name; @@ -1367,11 +1469,6 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate( if (!Sec->Symbols) return {}; - - for (const ELFYAML::AddrsigSymbol &AS : *Sec->Symbols) - if (AS.Index && AS.Name) - return "\"Index\" and \"Name\" cannot be used together when defining a " - "symbol"; return {}; } @@ -1458,6 +1555,12 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate( return {}; } + if (const auto *CGP = dyn_cast<ELFYAML::CallGraphProfileSection>(C.get())) { + if (CGP->Entries && CGP->Content) + return "\"Entries\" and \"Content\" can't be used together"; + return {}; + } + return {}; } @@ -1553,7 +1656,7 @@ void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); assert(Object && "The IO context is not initialized"); - IO.mapRequired("Offset", Rel.Offset); + IO.mapOptional("Offset", Rel.Offset, (Hex64)0); IO.mapOptional("Symbol", Rel.Symbol); if (Object->Header.Machine == ELFYAML::ELF_EM(ELF::EM_MIPS) && @@ -1567,7 +1670,7 @@ void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, } else IO.mapRequired("Type", Rel.Type); - IO.mapOptional("Addend", Rel.Addend, (int64_t)0); + IO.mapOptional("Addend", Rel.Addend, (ELFYAML::YAMLIntUInt)0); } void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { @@ -1575,19 +1678,21 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { IO.setContext(&Object); IO.mapTag("!ELF", true); IO.mapRequired("FileHeader", Object.Header); + IO.mapOptional("SectionHeaderTable", Object.SectionHeaders); IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); IO.mapOptional("Sections", Object.Chunks); IO.mapOptional("Symbols", Object.Symbols); IO.mapOptional("DynamicSymbols", Object.DynamicSymbols); + IO.mapOptional("DWARF", Object.DWARF); + if (Object.DWARF) { + Object.DWARF->IsLittleEndian = + Object.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); + Object.DWARF->Is64BitAddrSize = + Object.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); + } IO.setContext(nullptr); } -void MappingTraits<ELFYAML::AddrsigSymbol>::mapping(IO &IO, ELFYAML::AddrsigSymbol &Sym) { - assert(IO.getContext() && "The IO context is not initialized"); - IO.mapOptional("Name", Sym.Name); - IO.mapOptional("Index", Sym.Index); -} - void MappingTraits<ELFYAML::LinkerOption>::mapping(IO &IO, ELFYAML::LinkerOption &Opt) { assert(IO.getContext() && "The IO context is not initialized"); @@ -1595,6 +1700,14 @@ void MappingTraits<ELFYAML::LinkerOption>::mapping(IO &IO, IO.mapRequired("Value", Opt.Value); } +void MappingTraits<ELFYAML::CallGraphEntry>::mapping( + IO &IO, ELFYAML::CallGraphEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapRequired("From", E.From); + IO.mapRequired("To", E.To); + IO.mapRequired("Weight", E.Weight); +} + LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) |