diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /llvm/lib/ObjectYAML/ELFYAML.cpp | |
parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) |
Notes
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFYAML.cpp')
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 254 |
1 files changed, 233 insertions, 21 deletions
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 29585abe6e80..efa7ecb4728b 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -24,7 +24,7 @@ namespace llvm { -ELFYAML::Section::~Section() = default; +ELFYAML::Chunk::~Chunk() = default; namespace yaml { @@ -54,6 +54,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_PT>::enumeration( ECase(PT_GNU_EH_FRAME); ECase(PT_GNU_STACK); ECase(PT_GNU_RELRO); + ECase(PT_GNU_PROPERTY); #undef ECase IO.enumFallback<Hex32>(Value); } @@ -252,6 +253,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( ECase(ELFOSABI_HPUX); ECase(ELFOSABI_NETBSD); ECase(ELFOSABI_GNU); + ECase(ELFOSABI_LINUX); ECase(ELFOSABI_HURD); ECase(ELFOSABI_SOLARIS); ECase(ELFOSABI_AIX); @@ -273,6 +275,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( ECase(ELFOSABI_C6000_LINUX); ECase(ELFOSABI_STANDALONE); #undef ECase + IO.enumFallback<Hex8>(Value); } void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, @@ -863,6 +866,24 @@ template <> struct SequenceElementTraits<StOtherPiece> { static const bool flow = true; }; +template <> struct ScalarTraits<ELFYAML::YAMLFlowString> { + static void output(const ELFYAML::YAMLFlowString &Val, void *, + raw_ostream &Out) { + Out << Val; + } + static StringRef input(StringRef Scalar, void *, + ELFYAML::YAMLFlowString &Val) { + Val = Scalar; + return {}; + } + static QuotingType mustQuote(StringRef S) { + return ScalarTraits<StringRef>::mustQuote(S); + } +}; +template <> struct SequenceElementTraits<ELFYAML::YAMLFlowString> { + static const bool flow = true; +}; + namespace { struct NormalizedOther { @@ -998,10 +1019,12 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { // are producing YAML, because yaml2obj sets appropriate values for them // automatically when they are not explicitly defined. assert(!IO.outputting() || - (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue())); + (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue() && + !Section.ShName.hasValue() && !Section.ShFlags.hasValue())); IO.mapOptional("ShName", Section.ShName); IO.mapOptional("ShOffset", Section.ShOffset); IO.mapOptional("ShSize", Section.ShSize); + IO.mapOptional("ShFlags", Section.ShFlags); } static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { @@ -1032,6 +1055,22 @@ static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) { IO.mapOptional("Size", Section.Size); } +static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Size", Section.Size); + IO.mapOptional("Notes", Section.Notes); +} + + +static void sectionMapping(IO &IO, ELFYAML::GnuHashSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Header", Section.Header); + IO.mapOptional("BloomFilter", Section.BloomFilter); + IO.mapOptional("HashBuckets", Section.HashBuckets); + IO.mapOptional("HashValues", Section.HashValues); +} static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Size", Section.Size, Hex64(0)); @@ -1040,7 +1079,8 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); - IO.mapRequired("Entries", Section.Entries); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { @@ -1051,7 +1091,8 @@ static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); - IO.mapRequired("Dependencies", Section.VerneedV); + IO.mapOptional("Dependencies", Section.VerneedV); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { @@ -1060,9 +1101,15 @@ static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { IO.mapOptional("Relocations", Section.Relocations); } +static void sectionMapping(IO &IO, ELFYAML::RelrSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); +} + static void groupSectionMapping(IO &IO, ELFYAML::Group &Group) { commonSectionMapping(IO, Group); - IO.mapOptional("Info", Group.Signature, StringRef()); + IO.mapOptional("Info", Group.Signature); IO.mapRequired("Members", Group.Members); } @@ -1078,6 +1125,25 @@ static void sectionMapping(IO &IO, ELFYAML::AddrsigSection &Section) { IO.mapOptional("Symbols", Section.Symbols); } +static void fillMapping(IO &IO, ELFYAML::Fill &Fill) { + IO.mapOptional("Name", Fill.Name, StringRef()); + IO.mapOptional("Pattern", Fill.Pattern); + IO.mapRequired("Size", Fill.Size); +} + +static void sectionMapping(IO &IO, ELFYAML::LinkerOptionsSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Options", Section.Options); + IO.mapOptional("Content", Section.Content); +} + +static void sectionMapping(IO &IO, + ELFYAML::DependentLibrariesSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Libraries", Section.Libs); + IO.mapOptional("Content", Section.Content); +} + void MappingTraits<ELFYAML::SectionOrType>::mapping( IO &IO, ELFYAML::SectionOrType §ionOrType) { IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); @@ -1108,15 +1174,27 @@ static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { IO.mapOptional("Flags2", Section.Flags2, Hex32(0)); } -void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( - IO &IO, std::unique_ptr<ELFYAML::Section> &Section) { - ELFYAML::ELF_SHT sectionType; - if (IO.outputting()) - sectionType = Section->Type; - else - IO.mapRequired("Type", sectionType); +void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping( + IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) { + ELFYAML::ELF_SHT Type; + if (IO.outputting()) { + Type = cast<ELFYAML::Section>(Section.get())->Type; + } else { + // When the Type string does not have a "SHT_" prefix, we know it is not a + // description of a regular ELF output section. Currently, we have one + // special type named "Fill". See comments for Fill. + StringRef StrType; + IO.mapRequired("Type", StrType); + if (StrType == "Fill") { + Section.reset(new ELFYAML::Fill()); + fillMapping(IO, *cast<ELFYAML::Fill>(Section.get())); + return; + } + + IO.mapRequired("Type", Type); + } - switch (sectionType) { + switch (Type) { case ELF::SHT_DYNAMIC: if (!IO.outputting()) Section.reset(new ELFYAML::DynamicSection()); @@ -1128,6 +1206,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::RelocationSection()); sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get())); break; + case ELF::SHT_RELR: + if (!IO.outputting()) + Section.reset(new ELFYAML::RelrSection()); + sectionMapping(IO, *cast<ELFYAML::RelrSection>(Section.get())); + break; case ELF::SHT_GROUP: if (!IO.outputting()) Section.reset(new ELFYAML::Group()); @@ -1143,6 +1226,16 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::HashSection()); sectionMapping(IO, *cast<ELFYAML::HashSection>(Section.get())); break; + case ELF::SHT_NOTE: + if (!IO.outputting()) + Section.reset(new ELFYAML::NoteSection()); + sectionMapping(IO, *cast<ELFYAML::NoteSection>(Section.get())); + break; + case ELF::SHT_GNU_HASH: + if (!IO.outputting()) + Section.reset(new ELFYAML::GnuHashSection()); + sectionMapping(IO, *cast<ELFYAML::GnuHashSection>(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1173,6 +1266,17 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::AddrsigSection()); sectionMapping(IO, *cast<ELFYAML::AddrsigSection>(Section.get())); break; + case ELF::SHT_LLVM_LINKER_OPTIONS: + if (!IO.outputting()) + Section.reset(new ELFYAML::LinkerOptionsSection()); + sectionMapping(IO, *cast<ELFYAML::LinkerOptionsSection>(Section.get())); + break; + case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: + if (!IO.outputting()) + Section.reset(new ELFYAML::DependentLibrariesSection()); + sectionMapping(IO, + *cast<ELFYAML::DependentLibrariesSection>(Section.get())); + break; default: if (!IO.outputting()) { StringRef Name; @@ -1192,17 +1296,18 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( } } -StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( - IO &io, std::unique_ptr<ELFYAML::Section> &Section) { - if (const auto *RawSection = - dyn_cast<ELFYAML::RawContentSection>(Section.get())) { +StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate( + IO &io, std::unique_ptr<ELFYAML::Chunk> &C) { + if (const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(C.get())) { if (RawSection->Size && RawSection->Content && (uint64_t)(*RawSection->Size) < RawSection->Content->binary_size()) return "Section size must be greater than or equal to the content size"; + if (RawSection->Flags && RawSection->ShFlags) + return "ShFlags and Flags cannot be used together"; return {}; } - if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(Section.get())) { + if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(C.get())) { if (!SS->Entries && !SS->Content && !SS->Size) return ".stack_sizes: one of Content, Entries and Size must be specified"; @@ -1222,7 +1327,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } - if (const auto *HS = dyn_cast<ELFYAML::HashSection>(Section.get())) { + if (const auto *HS = dyn_cast<ELFYAML::HashSection>(C.get())) { if (!HS->Content && !HS->Bucket && !HS->Chain && !HS->Size) return "one of \"Content\", \"Size\", \"Bucket\" or \"Chain\" must be " "specified"; @@ -1245,7 +1350,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } - if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(Section.get())) { + if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(C.get())) { if (!Sec->Symbols && !Sec->Content && !Sec->Size) return "one of \"Content\", \"Size\" or \"Symbols\" must be specified"; @@ -1270,6 +1375,89 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } + if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(C.get())) { + if (!NS->Content && !NS->Size && !NS->Notes) + return "one of \"Content\", \"Size\" or \"Notes\" must be " + "specified"; + + if (!NS->Content && !NS->Size) + return {}; + + if (NS->Size && NS->Content && + (uint64_t)*NS->Size < NS->Content->binary_size()) + return "\"Size\" must be greater than or equal to the content " + "size"; + + if (NS->Notes) + return "\"Notes\" cannot be used with \"Content\" or \"Size\""; + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(C.get())) { + if (!Sec->Content && !Sec->Header && !Sec->BloomFilter && + !Sec->HashBuckets && !Sec->HashValues) + return "either \"Content\" or \"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashBuckets\" must be specified"; + + if (Sec->Header || Sec->BloomFilter || Sec->HashBuckets || + Sec->HashValues) { + if (!Sec->Header || !Sec->BloomFilter || !Sec->HashBuckets || + !Sec->HashValues) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" must be used together"; + if (Sec->Content) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" can't be used together with " + "\"Content\""; + return {}; + } + + // Only Content is specified. + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::LinkerOptionsSection>(C.get())) { + if (Sec->Options && Sec->Content) + return "\"Options\" and \"Content\" can't be used together"; + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::DependentLibrariesSection>(C.get())) { + if (Sec->Libs && Sec->Content) + return "SHT_LLVM_DEPENDENT_LIBRARIES: \"Libraries\" and \"Content\" " + "can't " + "be used together"; + return {}; + } + + if (const auto *F = dyn_cast<ELFYAML::Fill>(C.get())) { + if (!F->Pattern) + return {}; + if (F->Pattern->binary_size() != 0 && !F->Size) + return "\"Size\" can't be 0 when \"Pattern\" is not empty"; + return {}; + } + + if (const auto *VD = dyn_cast<ELFYAML::VerdefSection>(C.get())) { + if (VD->Entries && VD->Content) + return "SHT_GNU_verdef: \"Entries\" and \"Content\" can't be used " + "together"; + return {}; + } + + if (const auto *VD = dyn_cast<ELFYAML::VerneedSection>(C.get())) { + if (VD->VerneedV && VD->Content) + return "SHT_GNU_verneed: \"Dependencies\" and \"Content\" can't be used " + "together"; + return {}; + } + + if (const auto *RS = dyn_cast<ELFYAML::RelrSection>(C.get())) { + if (RS->Entries && RS->Content) + return "\"Entries\" and \"Content\" can't be used together"; + return {}; + } + return {}; } @@ -1305,6 +1493,15 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping( IO.mapRequired("Size", E.Size); } +void MappingTraits<ELFYAML::GnuHashHeader>::mapping(IO &IO, + ELFYAML::GnuHashHeader &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapOptional("NBuckets", E.NBuckets); + IO.mapRequired("SymNdx", E.SymNdx); + IO.mapOptional("MaskWords", E.MaskWords); + IO.mapRequired("Shift2", E.Shift2); +} + void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, ELFYAML::DynamicEntry &Rel) { assert(IO.getContext() && "The IO context is not initialized"); @@ -1313,6 +1510,14 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, IO.mapRequired("Value", Rel.Val); } +void MappingTraits<ELFYAML::NoteEntry>::mapping(IO &IO, ELFYAML::NoteEntry &N) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapOptional("Name", N.Name); + IO.mapOptional("Desc", N.Desc); + IO.mapRequired("Type", N.Type); +} + void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO, ELFYAML::VerdefEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); @@ -1371,7 +1576,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { IO.mapTag("!ELF", true); IO.mapRequired("FileHeader", Object.Header); IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); - IO.mapOptional("Sections", Object.Sections); + IO.mapOptional("Sections", Object.Chunks); IO.mapOptional("Symbols", Object.Symbols); IO.mapOptional("DynamicSymbols", Object.DynamicSymbols); IO.setContext(nullptr); @@ -1383,6 +1588,13 @@ void MappingTraits<ELFYAML::AddrsigSymbol>::mapping(IO &IO, ELFYAML::AddrsigSymb IO.mapOptional("Index", Sym.Index); } +void MappingTraits<ELFYAML::LinkerOption>::mapping(IO &IO, + ELFYAML::LinkerOption &Opt) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapRequired("Name", Opt.Key); + IO.mapRequired("Value", Opt.Value); +} + 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) |