summaryrefslogtreecommitdiff
path: root/llvm/lib/ObjectYAML/ELFYAML.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFYAML.cpp')
-rw-r--r--llvm/lib/ObjectYAML/ELFYAML.cpp254
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 &sectionOrType) {
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)