diff options
Diffstat (limited to 'lib/ObjectYAML')
| -rw-r--r-- | lib/ObjectYAML/COFFYAML.cpp | 16 | ||||
| -rw-r--r-- | lib/ObjectYAML/CodeViewYAMLDebugSections.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/CodeViewYAMLSymbols.cpp | 17 | ||||
| -rw-r--r-- | lib/ObjectYAML/CodeViewYAMLTypeHashing.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/CodeViewYAMLTypes.cpp | 11 | ||||
| -rw-r--r-- | lib/ObjectYAML/DWARFEmitter.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/DWARFVisitor.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/DWARFVisitor.h | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/DWARFYAML.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/ELFYAML.cpp | 244 | ||||
| -rw-r--r-- | lib/ObjectYAML/MachOYAML.cpp | 7 | ||||
| -rw-r--r-- | lib/ObjectYAML/MinidumpYAML.cpp | 673 | ||||
| -rw-r--r-- | lib/ObjectYAML/ObjectYAML.cpp | 22 | ||||
| -rw-r--r-- | lib/ObjectYAML/WasmYAML.cpp | 80 | ||||
| -rw-r--r-- | lib/ObjectYAML/XCOFFYAML.cpp | 109 | ||||
| -rw-r--r-- | lib/ObjectYAML/YAML.cpp | 14 |
16 files changed, 1133 insertions, 102 deletions
diff --git a/lib/ObjectYAML/COFFYAML.cpp b/lib/ObjectYAML/COFFYAML.cpp index fdd94f4054e15..b5154467f11ac 100644 --- a/lib/ObjectYAML/COFFYAML.cpp +++ b/lib/ObjectYAML/COFFYAML.cpp @@ -1,9 +1,8 @@ //===- COFFYAML.cpp - COFF YAMLIO implementation --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -188,6 +187,7 @@ void ScalarEnumerationTraits<COFF::RelocationTypesARM>::enumeration( ECase(IMAGE_REL_ARM_TOKEN); ECase(IMAGE_REL_ARM_BLX24); ECase(IMAGE_REL_ARM_BLX11); + ECase(IMAGE_REL_ARM_REL32); ECase(IMAGE_REL_ARM_SECTION); ECase(IMAGE_REL_ARM_SECREL); ECase(IMAGE_REL_ARM_MOV32A); @@ -195,6 +195,7 @@ void ScalarEnumerationTraits<COFF::RelocationTypesARM>::enumeration( ECase(IMAGE_REL_ARM_BRANCH20T); ECase(IMAGE_REL_ARM_BRANCH24T); ECase(IMAGE_REL_ARM_BLX23T); + ECase(IMAGE_REL_ARM_PAIR); } void ScalarEnumerationTraits<COFF::RelocationTypesARM64>::enumeration( @@ -216,6 +217,7 @@ void ScalarEnumerationTraits<COFF::RelocationTypesARM64>::enumeration( ECase(IMAGE_REL_ARM64_ADDR64); ECase(IMAGE_REL_ARM64_BRANCH19); ECase(IMAGE_REL_ARM64_BRANCH14); + ECase(IMAGE_REL_ARM64_REL32); } void ScalarEnumerationTraits<COFF::WindowsSubsystem>::enumeration( @@ -576,6 +578,12 @@ void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { else if (Sec.Name == ".debug$H") IO.mapOptional("GlobalHashes", Sec.DebugH); + // Uninitialized sections, such as .bss, typically have no data, but the size + // is carried in SizeOfRawData, even though PointerToRawData is zero. + if (Sec.SectionData.binary_size() == 0 && + NC->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + IO.mapOptional("SizeOfRawData", Sec.Header.SizeOfRawData); + IO.mapOptional("Relocations", Sec.Relocations); } diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index 4deeae878013a..eeebb694589b2 100644 --- a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -1,9 +1,8 @@ //===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index 713e9a710e945..227107c051ddc 100644 --- a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -1,9 +1,8 @@ //===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -148,7 +147,7 @@ void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) { } void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) { - auto RegNames = getRegisterNames(); + auto RegNames = getRegisterNames(CPUType::X64); for (const auto &E : RegNames) { io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value)); } @@ -249,7 +248,7 @@ struct UnknownSymbolRecord : public SymbolRecordBase { uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen); ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix)); ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size()); - return CVSymbol(Kind, ArrayRef<uint8_t>(Buffer, TotalLen)); + return CVSymbol(ArrayRef<uint8_t>(Buffer, TotalLen)); } Error fromCodeViewSymbol(CVSymbol CVS) override { @@ -554,6 +553,12 @@ template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) { IO.mapRequired("Namespace", Symbol.Name); } +template <> void SymbolRecordImpl<AnnotationSym>::map(IO &IO) { + IO.mapOptional("Offset", Symbol.CodeOffset, 0U); + IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); + IO.mapRequired("Strings", Symbol.Strings); +} + } // end namespace detail } // end namespace CodeViewYAML } // end namespace llvm diff --git a/lib/ObjectYAML/CodeViewYAMLTypeHashing.cpp b/lib/ObjectYAML/CodeViewYAMLTypeHashing.cpp index ed117059560fd..e921ae1e7d8d3 100644 --- a/lib/ObjectYAML/CodeViewYAMLTypeHashing.cpp +++ b/lib/ObjectYAML/CodeViewYAMLTypeHashing.cpp @@ -1,9 +1,8 @@ //===- CodeViewYAMLTypeHashing.cpp - CodeView YAMLIO type hashing ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/lib/ObjectYAML/CodeViewYAMLTypes.cpp index 791b115dc4929..a5e3ce1e71e88 100644 --- a/lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ b/lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -1,9 +1,8 @@ //===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types implementation -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -99,7 +98,7 @@ template <typename T> struct LeafRecordImpl : public LeafRecordBase { CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override { TS.writeLeafType(Record); - return CVType(Kind, TS.records().back()); + return CVType(TS.records().back()); } mutable T Record; @@ -497,7 +496,7 @@ CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord( Member.Member->writeTo(CRB); } TS.insertRecord(CRB); - return CVType(Kind, TS.records().back()); + return CVType(TS.records().back()); } void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) { diff --git a/lib/ObjectYAML/DWARFEmitter.cpp b/lib/ObjectYAML/DWARFEmitter.cpp index f23fa12376004..2ae66997cf597 100644 --- a/lib/ObjectYAML/DWARFEmitter.cpp +++ b/lib/ObjectYAML/DWARFEmitter.cpp @@ -1,9 +1,8 @@ //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/lib/ObjectYAML/DWARFVisitor.cpp b/lib/ObjectYAML/DWARFVisitor.cpp index e6114c85ac0b9..ecb5967ac532d 100644 --- a/lib/ObjectYAML/DWARFVisitor.cpp +++ b/lib/ObjectYAML/DWARFVisitor.cpp @@ -1,9 +1,8 @@ //===--- DWARFVisitor.cpp ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/DWARFVisitor.h b/lib/ObjectYAML/DWARFVisitor.h index 5489031dc3319..50e88aa7a26bf 100644 --- a/lib/ObjectYAML/DWARFVisitor.h +++ b/lib/ObjectYAML/DWARFVisitor.h @@ -1,9 +1,8 @@ //===--- DWARFVisitor.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/DWARFYAML.cpp b/lib/ObjectYAML/DWARFYAML.cpp index d6c09e1a35d73..bb3b1422eb62d 100644 --- a/lib/ObjectYAML/DWARFYAML.cpp +++ b/lib/ObjectYAML/DWARFYAML.cpp @@ -1,9 +1,8 @@ //===- DWARFYAML.cpp - DWARF YAMLIO implementation ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp index 215d6bdd091eb..7497154c757d3 100644 --- a/lib/ObjectYAML/ELFYAML.cpp +++ b/lib/ObjectYAML/ELFYAML.cpp @@ -1,9 +1,8 @@ //===- ELFYAML.cpp - ELF YAMLIO implementation ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -233,8 +232,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS>::enumeration( void ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA>::enumeration( IO &IO, ELFYAML::ELF_ELFDATA &Value) { #define ECase(X) IO.enumCase(Value, #X, ELF::X) - // Since the semantics of ELFDATANONE is "invalid", just don't accept it - // here. + // ELFDATANONE is an invalid data encoding, but we accept it because + // we want to be able to produce invalid binaries for the tests. + ECase(ELFDATANONE); ECase(ELFDATA2LSB); ECase(ELFDATA2MSB); #undef ECase @@ -410,7 +410,11 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX902, EF_AMDGPU_MACH); BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX904, EF_AMDGPU_MACH); BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX906, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX908, EF_AMDGPU_MACH); BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX909, EF_AMDGPU_MACH); + 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); BCase(EF_AMDGPU_XNACK); BCase(EF_AMDGPU_SRAM_ECC); break; @@ -447,7 +451,6 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( ECase(SHT_GROUP); ECase(SHT_SYMTAB_SHNDX); ECase(SHT_RELR); - ECase(SHT_LOOS); ECase(SHT_ANDROID_REL); ECase(SHT_ANDROID_RELA); ECase(SHT_ANDROID_RELR); @@ -455,13 +458,12 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( ECase(SHT_LLVM_LINKER_OPTIONS); ECase(SHT_LLVM_CALL_GRAPH_PROFILE); ECase(SHT_LLVM_ADDRSIG); + ECase(SHT_LLVM_DEPENDENT_LIBRARIES); ECase(SHT_GNU_ATTRIBUTES); ECase(SHT_GNU_HASH); ECase(SHT_GNU_verdef); ECase(SHT_GNU_verneed); ECase(SHT_GNU_versym); - ECase(SHT_HIOS); - ECase(SHT_LOPROC); switch (Object->Header.Machine) { case ELF::EM_ARM: ECase(SHT_ARM_EXIDX); @@ -479,6 +481,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( case ELF::EM_MIPS: ECase(SHT_MIPS_REGINFO); ECase(SHT_MIPS_OPTIONS); + ECase(SHT_MIPS_DWARF); ECase(SHT_MIPS_ABIFLAGS); break; default: @@ -486,6 +489,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( break; } #undef ECase + IO.enumFallback<Hex32>(Value); } void ScalarBitSetTraits<ELFYAML::ELF_PF>::bitset(IO &IO, @@ -552,6 +556,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHN>::enumeration( ECase(SHN_COMMON); ECase(SHN_XINDEX); ECase(SHN_HIRESERVE); + ECase(SHN_AMDGPU_LDS); ECase(SHN_HEXAGON_SCOMMON); ECase(SHN_HEXAGON_SCOMMON_1); ECase(SHN_HEXAGON_SCOMMON_2); @@ -561,6 +566,17 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHN>::enumeration( IO.enumFallback<Hex32>(Value); } +void ScalarEnumerationTraits<ELFYAML::ELF_STB>::enumeration( + IO &IO, ELFYAML::ELF_STB &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X) + ECase(STB_LOCAL); + ECase(STB_GLOBAL); + ECase(STB_WEAK); + ECase(STB_GNU_UNIQUE); +#undef ECase + IO.enumFallback<Hex8>(Value); +} + void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration( IO &IO, ELFYAML::ELF_STT &Value) { #define ECase(X) IO.enumCase(Value, #X, ELF::X) @@ -573,6 +589,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration( ECase(STT_TLS); ECase(STT_GNU_IFUNC); #undef ECase + IO.enumFallback<Hex8>(Value); } void ScalarEnumerationTraits<ELFYAML::ELF_STV>::enumeration( @@ -661,6 +678,74 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( IO.enumFallback<Hex32>(Value); } +void ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG>::enumeration( + IO &IO, ELFYAML::ELF_DYNTAG &Value) { + const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); + assert(Object && "The IO context is not initialized"); + +// Disable architecture specific tags by default. We might enable them below. +#define AARCH64_DYNAMIC_TAG(name, value) +#define MIPS_DYNAMIC_TAG(name, value) +#define HEXAGON_DYNAMIC_TAG(name, value) +#define PPC_DYNAMIC_TAG(name, value) +#define PPC64_DYNAMIC_TAG(name, value) +// Ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. +#define DYNAMIC_TAG_MARKER(name, value) + +#define STRINGIFY(X) (#X) +#define DYNAMIC_TAG(X, Y) IO.enumCase(Value, STRINGIFY(DT_##X), ELF::DT_##X); + switch (Object->Header.Machine) { + case ELF::EM_AARCH64: +#undef AARCH64_DYNAMIC_TAG +#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef AARCH64_DYNAMIC_TAG +#define AARCH64_DYNAMIC_TAG(name, value) + break; + case ELF::EM_MIPS: +#undef MIPS_DYNAMIC_TAG +#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef MIPS_DYNAMIC_TAG +#define MIPS_DYNAMIC_TAG(name, value) + break; + case ELF::EM_HEXAGON: +#undef HEXAGON_DYNAMIC_TAG +#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef HEXAGON_DYNAMIC_TAG +#define HEXAGON_DYNAMIC_TAG(name, value) + break; + case ELF::EM_PPC: +#undef PPC_DYNAMIC_TAG +#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef PPC_DYNAMIC_TAG +#define PPC_DYNAMIC_TAG(name, value) + break; + case ELF::EM_PPC64: +#undef PPC64_DYNAMIC_TAG +#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef PPC64_DYNAMIC_TAG +#define PPC64_DYNAMIC_TAG(name, value) + break; + default: +#include "llvm/BinaryFormat/DynamicTags.def" + break; + } +#undef AARCH64_DYNAMIC_TAG +#undef MIPS_DYNAMIC_TAG +#undef HEXAGON_DYNAMIC_TAG +#undef PPC_DYNAMIC_TAG +#undef PPC64_DYNAMIC_TAG +#undef DYNAMIC_TAG_MARKER +#undef STRINGIFY +#undef DYNAMIC_TAG + + IO.enumFallback<Hex64>(Value); +} + void ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG>::enumeration( IO &IO, ELFYAML::MIPS_AFL_REG &Value) { #define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X) @@ -758,6 +843,11 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, IO.mapRequired("Machine", FileHdr.Machine); IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0)); IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); + + IO.mapOptional("SHEntSize", FileHdr.SHEntSize); + IO.mapOptional("SHOffset", FileHdr.SHOffset); + IO.mapOptional("SHNum", FileHdr.SHNum); + IO.mapOptional("SHStrNdx", FileHdr.SHStrNdx); } void MappingTraits<ELFYAML::ProgramHeader>::mapping( @@ -768,6 +858,9 @@ void MappingTraits<ELFYAML::ProgramHeader>::mapping( IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0)); IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0)); IO.mapOptional("Align", Phdr.Align); + IO.mapOptional("FileSize", Phdr.FileSize); + IO.mapOptional("MemSize", Phdr.MemSize); + IO.mapOptional("Offset", Phdr.Offset); } namespace { @@ -788,12 +881,13 @@ struct NormalizedOther { void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); + IO.mapOptional("NameIndex", Symbol.NameIndex); IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Index", Symbol.Index); + IO.mapOptional("Binding", Symbol.Binding, ELFYAML::ELF_STB(0)); IO.mapOptional("Value", Symbol.Value, Hex64(0)); IO.mapOptional("Size", Symbol.Size, Hex64(0)); - MappingNormalization<NormalizedOther, uint8_t> Keys(IO, Symbol.Other); IO.mapOptional("Visibility", Keys->Visibility, ELFYAML::ELF_STV(0)); IO.mapOptional("Other", Keys->Other, ELFYAML::ELF_STO(0)); @@ -801,40 +895,44 @@ void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO, ELFYAML::Symbol &Symbol) { - if (Symbol.Index && Symbol.Section.data()) { + if (Symbol.Index && Symbol.Section.data()) return "Index and Section cannot both be specified for Symbol"; - } - if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX)) { + if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX)) return "Large indexes are not supported"; - } - if (Symbol.Index && *Symbol.Index < ELFYAML::ELF_SHN(ELF::SHN_LORESERVE)) { - return "Use a section name to define which section a symbol is defined in"; - } + if (Symbol.NameIndex && !Symbol.Name.empty()) + return "Name and NameIndex cannot both be specified for Symbol"; return StringRef(); } -void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping( - IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) { - IO.mapOptional("Local", Symbols.Local); - IO.mapOptional("Global", Symbols.Global); - IO.mapOptional("Weak", Symbols.Weak); -} - static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { IO.mapOptional("Name", Section.Name, StringRef()); IO.mapRequired("Type", Section.Type); - IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0)); + IO.mapOptional("Flags", Section.Flags); IO.mapOptional("Address", Section.Address, Hex64(0)); IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); IO.mapOptional("EntSize", Section.EntSize); - IO.mapOptional("Info", Section.Info, StringRef()); + + // obj2yaml does not dump these fields. They are expected to be empty when we + // are producing YAML, because yaml2obj sets appropriate values for sh_offset + // and sh_size automatically when they are not explicitly defined. + assert(!IO.outputting() || + (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue())); + IO.mapOptional("ShOffset", Section.ShOffset); + IO.mapOptional("ShSize", Section.ShSize); +} + +static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Content", Section.Content); - IO.mapOptional("Size", Section.Size, Hex64(Section.Content.binary_size())); + IO.mapOptional("Size", Section.Size); + IO.mapOptional("Info", Section.Info); } static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { @@ -842,14 +940,33 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { IO.mapOptional("Size", Section.Size, Hex64(0)); } +static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Info", Section.Info); + IO.mapRequired("Entries", Section.Entries); +} + +static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Entries", Section.Entries); +} + +static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Info", Section.Info); + IO.mapRequired("Dependencies", Section.VerneedV); +} + static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { commonSectionMapping(IO, Section); + IO.mapOptional("Info", Section.RelocatableSec, StringRef()); IO.mapOptional("Relocations", Section.Relocations); } -static void groupSectionMapping(IO &IO, ELFYAML::Group &group) { - commonSectionMapping(IO, group); - IO.mapRequired("Members", group.Members); +static void groupSectionMapping(IO &IO, ELFYAML::Group &Group) { + commonSectionMapping(IO, Group); + IO.mapOptional("Info", Group.Signature, StringRef()); + IO.mapRequired("Members", Group.Members); } void MappingTraits<ELFYAML::SectionOrType>::mapping( @@ -891,6 +1008,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( IO.mapRequired("Type", sectionType); switch (sectionType) { + case ELF::SHT_DYNAMIC: + if (!IO.outputting()) + Section.reset(new ELFYAML::DynamicSection()); + sectionMapping(IO, *cast<ELFYAML::DynamicSection>(Section.get())); + break; case ELF::SHT_REL: case ELF::SHT_RELA: if (!IO.outputting()) @@ -912,6 +1034,21 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::MipsABIFlags()); sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get())); break; + case ELF::SHT_GNU_verdef: + if (!IO.outputting()) + Section.reset(new ELFYAML::VerdefSection()); + sectionMapping(IO, *cast<ELFYAML::VerdefSection>(Section.get())); + break; + case ELF::SHT_GNU_versym: + if (!IO.outputting()) + Section.reset(new ELFYAML::SymverSection()); + sectionMapping(IO, *cast<ELFYAML::SymverSection>(Section.get())); + break; + case ELF::SHT_GNU_verneed: + if (!IO.outputting()) + Section.reset(new ELFYAML::VerneedSection()); + sectionMapping(IO, *cast<ELFYAML::VerneedSection>(Section.get())); + break; default: if (!IO.outputting()) Section.reset(new ELFYAML::RawContentSection()); @@ -922,9 +1059,12 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( IO &io, std::unique_ptr<ELFYAML::Section> &Section) { const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(Section.get()); - if (!RawSection || RawSection->Size >= RawSection->Content.binary_size()) - return StringRef(); - return "Section size must be greater or equal to the content size"; + if (!RawSection) + return {}; + 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"; + return {}; } namespace { @@ -952,6 +1092,44 @@ struct NormalizedMips64RelType { } // end anonymous namespace +void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, + ELFYAML::DynamicEntry &Rel) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapRequired("Tag", Rel.Tag); + IO.mapRequired("Value", Rel.Val); +} + +void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO, + ELFYAML::VerdefEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapRequired("Version", E.Version); + IO.mapRequired("Flags", E.Flags); + IO.mapRequired("VersionNdx", E.VersionNdx); + IO.mapRequired("Hash", E.Hash); + IO.mapRequired("Names", E.VerNames); +} + +void MappingTraits<ELFYAML::VerneedEntry>::mapping(IO &IO, + ELFYAML::VerneedEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapRequired("Version", E.Version); + IO.mapRequired("File", E.File); + IO.mapRequired("Entries", E.AuxV); +} + +void MappingTraits<ELFYAML::VernauxEntry>::mapping(IO &IO, + ELFYAML::VernauxEntry &E) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapRequired("Name", E.Name); + IO.mapRequired("Hash", E.Hash); + IO.mapRequired("Flags", E.Flags); + IO.mapRequired("Other", E.Other); +} + void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, ELFYAML::Relocation &Rel) { const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); diff --git a/lib/ObjectYAML/MachOYAML.cpp b/lib/ObjectYAML/MachOYAML.cpp index e00a4ea93074a..d12f12cf44350 100644 --- a/lib/ObjectYAML/MachOYAML.cpp +++ b/lib/ObjectYAML/MachOYAML.cpp @@ -1,9 +1,8 @@ //===- MachOYAML.cpp - MachO YAMLIO implementation ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/ObjectYAML/MinidumpYAML.cpp b/lib/ObjectYAML/MinidumpYAML.cpp new file mode 100644 index 0000000000000..f5f2acd0cc4bd --- /dev/null +++ b/lib/ObjectYAML/MinidumpYAML.cpp @@ -0,0 +1,673 @@ +//===- MinidumpYAML.cpp - Minidump YAMLIO implementation ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ObjectYAML/MinidumpYAML.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ConvertUTF.h" + +using namespace llvm; +using namespace llvm::MinidumpYAML; +using namespace llvm::minidump; + +namespace { +/// A helper class to manage the placement of various structures into the final +/// minidump binary. Space for objects can be allocated via various allocate*** +/// methods, while the final minidump file is written by calling the writeTo +/// method. The plain versions of allocation functions take a reference to the +/// data which is to be written (and hence the data must be available until +/// writeTo is called), while the "New" versions allocate the data in an +/// allocator-managed buffer, which is available until the allocator object is +/// destroyed. For both kinds of functions, it is possible to modify the +/// data for which the space has been "allocated" until the final writeTo call. +/// This is useful for "linking" the allocated structures via their offsets. +class BlobAllocator { +public: + size_t tell() const { return NextOffset; } + + size_t allocateCallback(size_t Size, + std::function<void(raw_ostream &)> Callback) { + size_t Offset = NextOffset; + NextOffset += Size; + Callbacks.push_back(std::move(Callback)); + return Offset; + } + + size_t allocateBytes(ArrayRef<uint8_t> Data) { + return allocateCallback( + Data.size(), [Data](raw_ostream &OS) { OS << toStringRef(Data); }); + } + + size_t allocateBytes(yaml::BinaryRef Data) { + return allocateCallback(Data.binary_size(), [Data](raw_ostream &OS) { + Data.writeAsBinary(OS); + }); + } + + template <typename T> size_t allocateArray(ArrayRef<T> Data) { + return allocateBytes({reinterpret_cast<const uint8_t *>(Data.data()), + sizeof(T) * Data.size()}); + } + + template <typename T, typename RangeType> + std::pair<size_t, MutableArrayRef<T>> + allocateNewArray(const iterator_range<RangeType> &Range); + + template <typename T> size_t allocateObject(const T &Data) { + return allocateArray(makeArrayRef(Data)); + } + + template <typename T, typename... Types> + std::pair<size_t, T *> allocateNewObject(Types &&... Args) { + T *Object = new (Temporaries.Allocate<T>()) T(std::forward<Types>(Args)...); + return {allocateObject(*Object), Object}; + } + + size_t allocateString(StringRef Str); + + void writeTo(raw_ostream &OS) const; + +private: + size_t NextOffset = 0; + + BumpPtrAllocator Temporaries; + std::vector<std::function<void(raw_ostream &)>> Callbacks; +}; +} // namespace + +template <typename T, typename RangeType> +std::pair<size_t, MutableArrayRef<T>> +BlobAllocator::allocateNewArray(const iterator_range<RangeType> &Range) { + size_t Num = std::distance(Range.begin(), Range.end()); + MutableArrayRef<T> Array(Temporaries.Allocate<T>(Num), Num); + std::uninitialized_copy(Range.begin(), Range.end(), Array.begin()); + return {allocateArray(Array), Array}; +} + +size_t BlobAllocator::allocateString(StringRef Str) { + SmallVector<UTF16, 32> WStr; + bool OK = convertUTF8ToUTF16String(Str, WStr); + assert(OK && "Invalid UTF8 in Str?"); + (void)OK; + + // The utf16 string is null-terminated, but the terminator is not counted in + // the string size. + WStr.push_back(0); + size_t Result = + allocateNewObject<support::ulittle32_t>(2 * (WStr.size() - 1)).first; + allocateNewArray<support::ulittle16_t>(make_range(WStr.begin(), WStr.end())); + return Result; +} + +void BlobAllocator::writeTo(raw_ostream &OS) const { + size_t BeginOffset = OS.tell(); + for (const auto &Callback : Callbacks) + Callback(OS); + assert(OS.tell() == BeginOffset + NextOffset && + "Callbacks wrote an unexpected number of bytes."); + (void)BeginOffset; +} + +/// Perform an optional yaml-mapping of an endian-aware type EndianType. The +/// only purpose of this function is to avoid casting the Default value to the +/// endian type; +template <typename EndianType> +static inline void mapOptional(yaml::IO &IO, const char *Key, EndianType &Val, + typename EndianType::value_type Default) { + IO.mapOptional(Key, Val, EndianType(Default)); +} + +/// Yaml-map an endian-aware type EndianType as some other type MapType. +template <typename MapType, typename EndianType> +static inline void mapRequiredAs(yaml::IO &IO, const char *Key, + EndianType &Val) { + MapType Mapped = static_cast<typename EndianType::value_type>(Val); + IO.mapRequired(Key, Mapped); + Val = static_cast<typename EndianType::value_type>(Mapped); +} + +/// Perform an optional yaml-mapping of an endian-aware type EndianType as some +/// other type MapType. +template <typename MapType, typename EndianType> +static inline void mapOptionalAs(yaml::IO &IO, const char *Key, EndianType &Val, + MapType Default) { + MapType Mapped = static_cast<typename EndianType::value_type>(Val); + IO.mapOptional(Key, Mapped, Default); + Val = static_cast<typename EndianType::value_type>(Mapped); +} + +namespace { +/// Return the appropriate yaml Hex type for a given endian-aware type. +template <typename EndianType> struct HexType; +template <> struct HexType<support::ulittle16_t> { using type = yaml::Hex16; }; +template <> struct HexType<support::ulittle32_t> { using type = yaml::Hex32; }; +template <> struct HexType<support::ulittle64_t> { using type = yaml::Hex64; }; +} // namespace + +/// Yaml-map an endian-aware type as an appropriately-sized hex value. +template <typename EndianType> +static inline void mapRequiredHex(yaml::IO &IO, const char *Key, + EndianType &Val) { + mapRequiredAs<typename HexType<EndianType>::type>(IO, Key, Val); +} + +/// Perform an optional yaml-mapping of an endian-aware type as an +/// appropriately-sized hex value. +template <typename EndianType> +static inline void mapOptionalHex(yaml::IO &IO, const char *Key, + EndianType &Val, + typename EndianType::value_type Default) { + mapOptionalAs<typename HexType<EndianType>::type>(IO, Key, Val, Default); +} + +Stream::~Stream() = default; + +Stream::StreamKind Stream::getKind(StreamType Type) { + switch (Type) { + case StreamType::MemoryList: + return StreamKind::MemoryList; + case StreamType::ModuleList: + return StreamKind::ModuleList; + case StreamType::SystemInfo: + return StreamKind::SystemInfo; + case StreamType::LinuxCPUInfo: + case StreamType::LinuxProcStatus: + case StreamType::LinuxLSBRelease: + case StreamType::LinuxCMDLine: + case StreamType::LinuxMaps: + case StreamType::LinuxProcStat: + case StreamType::LinuxProcUptime: + return StreamKind::TextContent; + case StreamType::ThreadList: + return StreamKind::ThreadList; + default: + return StreamKind::RawContent; + } +} + +std::unique_ptr<Stream> Stream::create(StreamType Type) { + StreamKind Kind = getKind(Type); + switch (Kind) { + case StreamKind::MemoryList: + return llvm::make_unique<MemoryListStream>(); + case StreamKind::ModuleList: + return llvm::make_unique<ModuleListStream>(); + case StreamKind::RawContent: + return llvm::make_unique<RawContentStream>(Type); + case StreamKind::SystemInfo: + return llvm::make_unique<SystemInfoStream>(); + case StreamKind::TextContent: + return llvm::make_unique<TextContentStream>(Type); + case StreamKind::ThreadList: + return llvm::make_unique<ThreadListStream>(); + } + llvm_unreachable("Unhandled stream kind!"); +} + +void yaml::ScalarEnumerationTraits<ProcessorArchitecture>::enumeration( + IO &IO, ProcessorArchitecture &Arch) { +#define HANDLE_MDMP_ARCH(CODE, NAME) \ + IO.enumCase(Arch, #NAME, ProcessorArchitecture::NAME); +#include "llvm/BinaryFormat/MinidumpConstants.def" + IO.enumFallback<Hex16>(Arch); +} + +void yaml::ScalarEnumerationTraits<OSPlatform>::enumeration(IO &IO, + OSPlatform &Plat) { +#define HANDLE_MDMP_PLATFORM(CODE, NAME) \ + IO.enumCase(Plat, #NAME, OSPlatform::NAME); +#include "llvm/BinaryFormat/MinidumpConstants.def" + IO.enumFallback<Hex32>(Plat); +} + +void yaml::ScalarEnumerationTraits<StreamType>::enumeration(IO &IO, + StreamType &Type) { +#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) \ + IO.enumCase(Type, #NAME, StreamType::NAME); +#include "llvm/BinaryFormat/MinidumpConstants.def" + IO.enumFallback<Hex32>(Type); +} + +void yaml::MappingTraits<CPUInfo::ArmInfo>::mapping(IO &IO, + CPUInfo::ArmInfo &Info) { + mapRequiredHex(IO, "CPUID", Info.CPUID); + mapOptionalHex(IO, "ELF hwcaps", Info.ElfHWCaps, 0); +} + +namespace { +template <std::size_t N> struct FixedSizeHex { + FixedSizeHex(uint8_t (&Storage)[N]) : Storage(Storage) {} + + uint8_t (&Storage)[N]; +}; +} // namespace + +namespace llvm { +namespace yaml { +template <std::size_t N> struct ScalarTraits<FixedSizeHex<N>> { + static void output(const FixedSizeHex<N> &Fixed, void *, raw_ostream &OS) { + OS << toHex(makeArrayRef(Fixed.Storage)); + } + + static StringRef input(StringRef Scalar, void *, FixedSizeHex<N> &Fixed) { + if (!all_of(Scalar, isHexDigit)) + return "Invalid hex digit in input"; + if (Scalar.size() < 2 * N) + return "String too short"; + if (Scalar.size() > 2 * N) + return "String too long"; + copy(fromHex(Scalar), Fixed.Storage); + return ""; + } + + static QuotingType mustQuote(StringRef S) { return QuotingType::None; } +}; +} // namespace yaml +} // namespace llvm +void yaml::MappingTraits<CPUInfo::OtherInfo>::mapping( + IO &IO, CPUInfo::OtherInfo &Info) { + FixedSizeHex<sizeof(Info.ProcessorFeatures)> Features(Info.ProcessorFeatures); + IO.mapRequired("Features", Features); +} + +namespace { +/// A type which only accepts strings of a fixed size for yaml conversion. +template <std::size_t N> struct FixedSizeString { + FixedSizeString(char (&Storage)[N]) : Storage(Storage) {} + + char (&Storage)[N]; +}; +} // namespace + +namespace llvm { +namespace yaml { +template <std::size_t N> struct ScalarTraits<FixedSizeString<N>> { + static void output(const FixedSizeString<N> &Fixed, void *, raw_ostream &OS) { + OS << StringRef(Fixed.Storage, N); + } + + static StringRef input(StringRef Scalar, void *, FixedSizeString<N> &Fixed) { + if (Scalar.size() < N) + return "String too short"; + if (Scalar.size() > N) + return "String too long"; + copy(Scalar, Fixed.Storage); + return ""; + } + + static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } +}; +} // namespace yaml +} // namespace llvm + +void yaml::MappingTraits<CPUInfo::X86Info>::mapping(IO &IO, + CPUInfo::X86Info &Info) { + FixedSizeString<sizeof(Info.VendorID)> VendorID(Info.VendorID); + IO.mapRequired("Vendor ID", VendorID); + + mapRequiredHex(IO, "Version Info", Info.VersionInfo); + mapRequiredHex(IO, "Feature Info", Info.FeatureInfo); + mapOptionalHex(IO, "AMD Extended Features", Info.AMDExtendedFeatures, 0); +} + +void yaml::MappingTraits<VSFixedFileInfo>::mapping(IO &IO, + VSFixedFileInfo &Info) { + mapOptionalHex(IO, "Signature", Info.Signature, 0); + mapOptionalHex(IO, "Struct Version", Info.StructVersion, 0); + mapOptionalHex(IO, "File Version High", Info.FileVersionHigh, 0); + mapOptionalHex(IO, "File Version Low", Info.FileVersionLow, 0); + mapOptionalHex(IO, "Product Version High", Info.ProductVersionHigh, 0); + mapOptionalHex(IO, "Product Version Low", Info.ProductVersionLow, 0); + mapOptionalHex(IO, "File Flags Mask", Info.FileFlagsMask, 0); + mapOptionalHex(IO, "File Flags", Info.FileFlags, 0); + mapOptionalHex(IO, "File OS", Info.FileOS, 0); + mapOptionalHex(IO, "File Type", Info.FileType, 0); + mapOptionalHex(IO, "File Subtype", Info.FileSubtype, 0); + mapOptionalHex(IO, "File Date High", Info.FileDateHigh, 0); + mapOptionalHex(IO, "File Date Low", Info.FileDateLow, 0); +} + +void yaml::MappingTraits<ModuleListStream::entry_type>::mapping( + IO &IO, ModuleListStream::entry_type &M) { + mapRequiredHex(IO, "Base of Image", M.Entry.BaseOfImage); + mapRequiredHex(IO, "Size of Image", M.Entry.SizeOfImage); + mapOptionalHex(IO, "Checksum", M.Entry.Checksum, 0); + IO.mapOptional("Time Date Stamp", M.Entry.TimeDateStamp, + support::ulittle32_t(0)); + IO.mapRequired("Module Name", M.Name); + IO.mapOptional("Version Info", M.Entry.VersionInfo, VSFixedFileInfo()); + IO.mapRequired("CodeView Record", M.CvRecord); + IO.mapOptional("Misc Record", M.MiscRecord, yaml::BinaryRef()); + mapOptionalHex(IO, "Reserved0", M.Entry.Reserved0, 0); + mapOptionalHex(IO, "Reserved1", M.Entry.Reserved1, 0); +} + +static void streamMapping(yaml::IO &IO, RawContentStream &Stream) { + IO.mapOptional("Content", Stream.Content); + IO.mapOptional("Size", Stream.Size, Stream.Content.binary_size()); +} + +static StringRef streamValidate(RawContentStream &Stream) { + if (Stream.Size.value < Stream.Content.binary_size()) + return "Stream size must be greater or equal to the content size"; + return ""; +} + +void yaml::MappingTraits<MemoryListStream::entry_type>::mapping( + IO &IO, MemoryListStream::entry_type &Range) { + MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping( + IO, Range.Entry, Range.Content); +} + +static void streamMapping(yaml::IO &IO, MemoryListStream &Stream) { + IO.mapRequired("Memory Ranges", Stream.Entries); +} + +static void streamMapping(yaml::IO &IO, ModuleListStream &Stream) { + IO.mapRequired("Modules", Stream.Entries); +} + +static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) { + SystemInfo &Info = Stream.Info; + IO.mapRequired("Processor Arch", Info.ProcessorArch); + mapOptional(IO, "Processor Level", Info.ProcessorLevel, 0); + mapOptional(IO, "Processor Revision", Info.ProcessorRevision, 0); + IO.mapOptional("Number of Processors", Info.NumberOfProcessors, 0); + IO.mapOptional("Product type", Info.ProductType, 0); + mapOptional(IO, "Major Version", Info.MajorVersion, 0); + mapOptional(IO, "Minor Version", Info.MinorVersion, 0); + mapOptional(IO, "Build Number", Info.BuildNumber, 0); + IO.mapRequired("Platform ID", Info.PlatformId); + IO.mapOptional("CSD Version", Stream.CSDVersion, ""); + mapOptionalHex(IO, "Suite Mask", Info.SuiteMask, 0); + mapOptionalHex(IO, "Reserved", Info.Reserved, 0); + switch (static_cast<ProcessorArchitecture>(Info.ProcessorArch)) { + case ProcessorArchitecture::X86: + case ProcessorArchitecture::AMD64: + IO.mapOptional("CPU", Info.CPU.X86); + break; + case ProcessorArchitecture::ARM: + case ProcessorArchitecture::ARM64: + IO.mapOptional("CPU", Info.CPU.Arm); + break; + default: + IO.mapOptional("CPU", Info.CPU.Other); + break; + } +} + +static void streamMapping(yaml::IO &IO, TextContentStream &Stream) { + IO.mapOptional("Text", Stream.Text); +} + +void yaml::MappingContextTraits<MemoryDescriptor, yaml::BinaryRef>::mapping( + IO &IO, MemoryDescriptor &Memory, BinaryRef &Content) { + mapRequiredHex(IO, "Start of Memory Range", Memory.StartOfMemoryRange); + IO.mapRequired("Content", Content); +} + +void yaml::MappingTraits<ThreadListStream::entry_type>::mapping( + IO &IO, ThreadListStream::entry_type &T) { + mapRequiredHex(IO, "Thread Id", T.Entry.ThreadId); + mapOptionalHex(IO, "Suspend Count", T.Entry.SuspendCount, 0); + mapOptionalHex(IO, "Priority Class", T.Entry.PriorityClass, 0); + mapOptionalHex(IO, "Priority", T.Entry.Priority, 0); + mapOptionalHex(IO, "Environment Block", T.Entry.EnvironmentBlock, 0); + IO.mapRequired("Context", T.Context); + IO.mapRequired("Stack", T.Entry.Stack, T.Stack); +} + +static void streamMapping(yaml::IO &IO, ThreadListStream &Stream) { + IO.mapRequired("Threads", Stream.Entries); +} + +void yaml::MappingTraits<std::unique_ptr<Stream>>::mapping( + yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) { + StreamType Type; + if (IO.outputting()) + Type = S->Type; + IO.mapRequired("Type", Type); + + if (!IO.outputting()) + S = MinidumpYAML::Stream::create(Type); + switch (S->Kind) { + case MinidumpYAML::Stream::StreamKind::MemoryList: + streamMapping(IO, llvm::cast<MemoryListStream>(*S)); + break; + case MinidumpYAML::Stream::StreamKind::ModuleList: + streamMapping(IO, llvm::cast<ModuleListStream>(*S)); + break; + case MinidumpYAML::Stream::StreamKind::RawContent: + streamMapping(IO, llvm::cast<RawContentStream>(*S)); + break; + case MinidumpYAML::Stream::StreamKind::SystemInfo: + streamMapping(IO, llvm::cast<SystemInfoStream>(*S)); + break; + case MinidumpYAML::Stream::StreamKind::TextContent: + streamMapping(IO, llvm::cast<TextContentStream>(*S)); + break; + case MinidumpYAML::Stream::StreamKind::ThreadList: + streamMapping(IO, llvm::cast<ThreadListStream>(*S)); + break; + } +} + +StringRef yaml::MappingTraits<std::unique_ptr<Stream>>::validate( + yaml::IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S) { + switch (S->Kind) { + case MinidumpYAML::Stream::StreamKind::RawContent: + return streamValidate(cast<RawContentStream>(*S)); + case MinidumpYAML::Stream::StreamKind::MemoryList: + case MinidumpYAML::Stream::StreamKind::ModuleList: + case MinidumpYAML::Stream::StreamKind::SystemInfo: + case MinidumpYAML::Stream::StreamKind::TextContent: + case MinidumpYAML::Stream::StreamKind::ThreadList: + return ""; + } + llvm_unreachable("Fully covered switch above!"); +} + +void yaml::MappingTraits<Object>::mapping(IO &IO, Object &O) { + IO.mapTag("!minidump", true); + mapOptionalHex(IO, "Signature", O.Header.Signature, Header::MagicSignature); + mapOptionalHex(IO, "Version", O.Header.Version, Header::MagicVersion); + mapOptionalHex(IO, "Flags", O.Header.Flags, 0); + IO.mapRequired("Streams", O.Streams); +} + +static LocationDescriptor layout(BlobAllocator &File, yaml::BinaryRef Data) { + return {support::ulittle32_t(Data.binary_size()), + support::ulittle32_t(File.allocateBytes(Data))}; +} + +static void layout(BlobAllocator &File, MemoryListStream::entry_type &Range) { + Range.Entry.Memory = layout(File, Range.Content); +} + +static void layout(BlobAllocator &File, ModuleListStream::entry_type &M) { + M.Entry.ModuleNameRVA = File.allocateString(M.Name); + + M.Entry.CvRecord = layout(File, M.CvRecord); + M.Entry.MiscRecord = layout(File, M.MiscRecord); +} + +static void layout(BlobAllocator &File, ThreadListStream::entry_type &T) { + T.Entry.Stack.Memory = layout(File, T.Stack); + T.Entry.Context = layout(File, T.Context); +} + +template <typename EntryT> +static size_t layout(BlobAllocator &File, + MinidumpYAML::detail::ListStream<EntryT> &S) { + + File.allocateNewObject<support::ulittle32_t>(S.Entries.size()); + for (auto &E : S.Entries) + File.allocateObject(E.Entry); + + size_t DataEnd = File.tell(); + + // Lay out the auxiliary data, (which is not a part of the stream). + DataEnd = File.tell(); + for (auto &E : S.Entries) + layout(File, E); + + return DataEnd; +} + +static Directory layout(BlobAllocator &File, Stream &S) { + Directory Result; + Result.Type = S.Type; + Result.Location.RVA = File.tell(); + Optional<size_t> DataEnd; + switch (S.Kind) { + case Stream::StreamKind::MemoryList: + DataEnd = layout(File, cast<MemoryListStream>(S)); + break; + case Stream::StreamKind::ModuleList: + DataEnd = layout(File, cast<ModuleListStream>(S)); + break; + case Stream::StreamKind::RawContent: { + RawContentStream &Raw = cast<RawContentStream>(S); + File.allocateCallback(Raw.Size, [&Raw](raw_ostream &OS) { + Raw.Content.writeAsBinary(OS); + assert(Raw.Content.binary_size() <= Raw.Size); + OS << std::string(Raw.Size - Raw.Content.binary_size(), '\0'); + }); + break; + } + case Stream::StreamKind::SystemInfo: { + SystemInfoStream &SystemInfo = cast<SystemInfoStream>(S); + File.allocateObject(SystemInfo.Info); + // The CSD string is not a part of the stream. + DataEnd = File.tell(); + SystemInfo.Info.CSDVersionRVA = File.allocateString(SystemInfo.CSDVersion); + break; + } + case Stream::StreamKind::TextContent: + File.allocateArray(arrayRefFromStringRef(cast<TextContentStream>(S).Text)); + break; + case Stream::StreamKind::ThreadList: + DataEnd = layout(File, cast<ThreadListStream>(S)); + break; + } + // If DataEnd is not set, we assume everything we generated is a part of the + // stream. + Result.Location.DataSize = + DataEnd.getValueOr(File.tell()) - Result.Location.RVA; + return Result; +} + +void MinidumpYAML::writeAsBinary(Object &Obj, raw_ostream &OS) { + BlobAllocator File; + File.allocateObject(Obj.Header); + + std::vector<Directory> StreamDirectory(Obj.Streams.size()); + Obj.Header.StreamDirectoryRVA = + File.allocateArray(makeArrayRef(StreamDirectory)); + Obj.Header.NumberOfStreams = StreamDirectory.size(); + + for (auto &Stream : enumerate(Obj.Streams)) + StreamDirectory[Stream.index()] = layout(File, *Stream.value()); + + File.writeTo(OS); +} + +Error MinidumpYAML::writeAsBinary(StringRef Yaml, raw_ostream &OS) { + yaml::Input Input(Yaml); + Object Obj; + Input >> Obj; + if (std::error_code EC = Input.error()) + return errorCodeToError(EC); + + writeAsBinary(Obj, OS); + return Error::success(); +} + +Expected<std::unique_ptr<Stream>> +Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) { + StreamKind Kind = getKind(StreamDesc.Type); + switch (Kind) { + case StreamKind::MemoryList: { + auto ExpectedList = File.getMemoryList(); + if (!ExpectedList) + return ExpectedList.takeError(); + std::vector<MemoryListStream::entry_type> Ranges; + for (const MemoryDescriptor &MD : *ExpectedList) { + auto ExpectedContent = File.getRawData(MD.Memory); + if (!ExpectedContent) + return ExpectedContent.takeError(); + Ranges.push_back({MD, *ExpectedContent}); + } + return llvm::make_unique<MemoryListStream>(std::move(Ranges)); + } + case StreamKind::ModuleList: { + auto ExpectedList = File.getModuleList(); + if (!ExpectedList) + return ExpectedList.takeError(); + std::vector<ModuleListStream::entry_type> Modules; + for (const Module &M : *ExpectedList) { + auto ExpectedName = File.getString(M.ModuleNameRVA); + if (!ExpectedName) + return ExpectedName.takeError(); + auto ExpectedCv = File.getRawData(M.CvRecord); + if (!ExpectedCv) + return ExpectedCv.takeError(); + auto ExpectedMisc = File.getRawData(M.MiscRecord); + if (!ExpectedMisc) + return ExpectedMisc.takeError(); + Modules.push_back( + {M, std::move(*ExpectedName), *ExpectedCv, *ExpectedMisc}); + } + return llvm::make_unique<ModuleListStream>(std::move(Modules)); + } + case StreamKind::RawContent: + return llvm::make_unique<RawContentStream>(StreamDesc.Type, + File.getRawStream(StreamDesc)); + case StreamKind::SystemInfo: { + auto ExpectedInfo = File.getSystemInfo(); + if (!ExpectedInfo) + return ExpectedInfo.takeError(); + auto ExpectedCSDVersion = File.getString(ExpectedInfo->CSDVersionRVA); + if (!ExpectedCSDVersion) + return ExpectedInfo.takeError(); + return llvm::make_unique<SystemInfoStream>(*ExpectedInfo, + std::move(*ExpectedCSDVersion)); + } + case StreamKind::TextContent: + return llvm::make_unique<TextContentStream>( + StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc))); + case StreamKind::ThreadList: { + auto ExpectedList = File.getThreadList(); + if (!ExpectedList) + return ExpectedList.takeError(); + std::vector<ThreadListStream::entry_type> Threads; + for (const Thread &T : *ExpectedList) { + auto ExpectedStack = File.getRawData(T.Stack.Memory); + if (!ExpectedStack) + return ExpectedStack.takeError(); + auto ExpectedContext = File.getRawData(T.Context); + if (!ExpectedContext) + return ExpectedContext.takeError(); + Threads.push_back({T, *ExpectedStack, *ExpectedContext}); + } + return llvm::make_unique<ThreadListStream>(std::move(Threads)); + } + } + llvm_unreachable("Unhandled stream kind!"); +} + +Expected<Object> Object::create(const object::MinidumpFile &File) { + std::vector<std::unique_ptr<Stream>> Streams; + Streams.reserve(File.streams().size()); + for (const Directory &StreamDesc : File.streams()) { + auto ExpectedStream = Stream::create(StreamDesc, File); + if (!ExpectedStream) + return ExpectedStream.takeError(); + Streams.push_back(std::move(*ExpectedStream)); + } + return Object(File.header(), std::move(Streams)); +} diff --git a/lib/ObjectYAML/ObjectYAML.cpp b/lib/ObjectYAML/ObjectYAML.cpp index 850c1a5a06c02..7f636f4eabac4 100644 --- a/lib/ObjectYAML/ObjectYAML.cpp +++ b/lib/ObjectYAML/ObjectYAML.cpp @@ -1,9 +1,8 @@ //===- ObjectYAML.cpp - YAML utilities for object files -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -33,6 +32,7 @@ void MappingTraits<YamlObjectFile>::mapping(IO &IO, MappingTraits<MachOYAML::UniversalBinary>::mapping(IO, *ObjectFile.FatMachO); } else { + Input &In = (Input &)IO; if (IO.mapTag("!ELF")) { ObjectFile.Elf.reset(new ELFYAML::Object()); MappingTraits<ELFYAML::Object>::mapping(IO, *ObjectFile.Elf); @@ -46,18 +46,18 @@ void MappingTraits<YamlObjectFile>::mapping(IO &IO, ObjectFile.FatMachO.reset(new MachOYAML::UniversalBinary()); MappingTraits<MachOYAML::UniversalBinary>::mapping(IO, *ObjectFile.FatMachO); + } else if (IO.mapTag("!minidump")) { + ObjectFile.Minidump.reset(new MinidumpYAML::Object()); + MappingTraits<MinidumpYAML::Object>::mapping(IO, *ObjectFile.Minidump); } else if (IO.mapTag("!WASM")) { ObjectFile.Wasm.reset(new WasmYAML::Object()); MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm); - } else { - Input &In = (Input &)IO; - std::string Tag = In.getCurrentNode()->getRawTag(); - if (Tag.empty()) + } else if (const Node *N = In.getCurrentNode()) { + if (N->getRawTag().empty()) IO.setError("YAML Object File missing document type tag!"); else - IO.setError( - Twine("YAML Object File unsupported document type tag '") + - Twine(Tag) + Twine("'!")); + IO.setError("YAML Object File unsupported document type tag '" + + N->getRawTag() + "'!"); } } } diff --git a/lib/ObjectYAML/WasmYAML.cpp b/lib/ObjectYAML/WasmYAML.cpp index 47bf853e0d3e2..88491d955c497 100644 --- a/lib/ObjectYAML/WasmYAML.cpp +++ b/lib/ObjectYAML/WasmYAML.cpp @@ -1,9 +1,8 @@ //===- WasmYAML.cpp - Wasm YAMLIO implementation --------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -74,6 +73,20 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) { IO.mapOptional("Comdats", Section.Comdats); } +static void sectionMapping(IO &IO, WasmYAML::ProducersSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Name", Section.Name); + IO.mapOptional("Languages", Section.Languages); + IO.mapOptional("Tools", Section.Tools); + IO.mapOptional("SDKs", Section.SDKs); +} + +static void sectionMapping(IO &IO, WasmYAML::TargetFeaturesSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Name", Section.Name); + IO.mapRequired("Features", Section.Features); +} + static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Name", Section.Name); @@ -140,6 +153,11 @@ static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) { IO.mapRequired("Segments", Section.Segments); } +static void sectionMapping(IO &IO, WasmYAML::DataCountSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Count", Section.Count); +} + void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping( IO &IO, std::unique_ptr<WasmYAML::Section> &Section) { WasmYAML::SectionType SectionType; @@ -169,6 +187,14 @@ void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping( if (!IO.outputting()) Section.reset(new WasmYAML::NameSection()); sectionMapping(IO, *cast<WasmYAML::NameSection>(Section.get())); + } else if (SectionName == "producers") { + if (!IO.outputting()) + Section.reset(new WasmYAML::ProducersSection()); + sectionMapping(IO, *cast<WasmYAML::ProducersSection>(Section.get())); + } else if (SectionName == "target_features") { + if (!IO.outputting()) + Section.reset(new WasmYAML::TargetFeaturesSection()); + sectionMapping(IO, *cast<WasmYAML::TargetFeaturesSection>(Section.get())); } else { if (!IO.outputting()) Section.reset(new WasmYAML::CustomSection(SectionName)); @@ -236,6 +262,11 @@ void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping( Section.reset(new WasmYAML::DataSection()); sectionMapping(IO, *cast<WasmYAML::DataSection>(Section.get())); break; + case wasm::WASM_SEC_DATACOUNT: + if (!IO.outputting()) + Section.reset(new WasmYAML::DataCountSection()); + sectionMapping(IO, *cast<WasmYAML::DataCountSection>(Section.get())); + break; default: llvm_unreachable("Unknown section type"); } @@ -257,6 +288,7 @@ void ScalarEnumerationTraits<WasmYAML::SectionType>::enumeration( ECase(ELEM); ECase(CODE); ECase(DATA); + ECase(DATACOUNT); #undef ECase } @@ -293,6 +325,27 @@ void MappingTraits<WasmYAML::NameEntry>::mapping( IO.mapRequired("Name", NameEntry.Name); } +void MappingTraits<WasmYAML::ProducerEntry>::mapping( + IO &IO, WasmYAML::ProducerEntry &ProducerEntry) { + IO.mapRequired("Name", ProducerEntry.Name); + IO.mapRequired("Version", ProducerEntry.Version); +} + +void ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix>::enumeration( + IO &IO, WasmYAML::FeaturePolicyPrefix &Kind) { +#define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_FEATURE_PREFIX_##X); + ECase(USED); + ECase(REQUIRED); + ECase(DISALLOWED); +#undef ECase +} + +void MappingTraits<WasmYAML::FeatureEntry>::mapping( + IO &IO, WasmYAML::FeatureEntry &FeatureEntry) { + IO.mapRequired("Prefix", FeatureEntry.Prefix); + IO.mapRequired("Name", FeatureEntry.Name); +} + void MappingTraits<WasmYAML::SegmentInfo>::mapping( IO &IO, WasmYAML::SegmentInfo &SegmentInfo) { IO.mapRequired("Index", SegmentInfo.Index); @@ -386,8 +439,18 @@ void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO, void MappingTraits<WasmYAML::DataSegment>::mapping( IO &IO, WasmYAML::DataSegment &Segment) { IO.mapOptional("SectionOffset", Segment.SectionOffset); - IO.mapRequired("MemoryIndex", Segment.MemoryIndex); - IO.mapRequired("Offset", Segment.Offset); + IO.mapRequired("InitFlags", Segment.InitFlags); + if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX) { + IO.mapRequired("MemoryIndex", Segment.MemoryIndex); + } else { + Segment.MemoryIndex = 0; + } + if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) { + IO.mapRequired("Offset", Segment.Offset); + } else { + Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Offset.Value.Int32 = 0; + } IO.mapRequired("Content", Segment.Content); } @@ -421,7 +484,8 @@ void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO, WasmYAML::SymbolInfo &Info) { IO.mapRequired("Index", Info.Index); IO.mapRequired("Kind", Info.Kind); - IO.mapRequired("Name", Info.Name); + if (Info.Kind != wasm::WASM_SYMBOL_TYPE_SECTION) + IO.mapRequired("Name", Info.Name); IO.mapRequired("Flags", Info.Flags); if (Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION) { IO.mapRequired("Function", Info.ElementIndex); @@ -469,6 +533,8 @@ void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset( // BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT); BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN); BCaseMask(UNDEFINED, UNDEFINED); + BCaseMask(EXPORTED, EXPORTED); + BCaseMask(EXPLICIT_NAME, EXPLICIT_NAME); #undef BCaseMask } diff --git a/lib/ObjectYAML/XCOFFYAML.cpp b/lib/ObjectYAML/XCOFFYAML.cpp new file mode 100644 index 0000000000000..982e6aecbb987 --- /dev/null +++ b/lib/ObjectYAML/XCOFFYAML.cpp @@ -0,0 +1,109 @@ +//===-- XCOFFYAML.cpp - XCOFF YAMLIO implementation -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines classes for handling the YAML representation of XCOFF. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ObjectYAML/XCOFFYAML.h" +#include "llvm/BinaryFormat/XCOFF.h" +#include <string.h> + +namespace llvm { +namespace XCOFFYAML { + +Object::Object() { memset(&Header, 0, sizeof(Header)); } + +} // namespace XCOFFYAML + +namespace yaml { + +void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration( + IO &IO, XCOFF::StorageClass &Value) { +#define ECase(X) IO.enumCase(Value, #X, XCOFF::X) + ECase(C_NULL); + ECase(C_AUTO); + ECase(C_EXT); + ECase(C_STAT); + ECase(C_REG); + ECase(C_EXTDEF); + ECase(C_LABEL); + ECase(C_ULABEL); + ECase(C_MOS); + ECase(C_ARG); + ECase(C_STRTAG); + ECase(C_MOU); + ECase(C_UNTAG); + ECase(C_TPDEF); + ECase(C_USTATIC); + ECase(C_ENTAG); + ECase(C_MOE); + ECase(C_REGPARM); + ECase(C_FIELD); + ECase(C_BLOCK); + ECase(C_FCN); + ECase(C_EOS); + ECase(C_FILE); + ECase(C_LINE); + ECase(C_ALIAS); + ECase(C_HIDDEN); + ECase(C_HIDEXT); + ECase(C_BINCL); + ECase(C_EINCL); + ECase(C_INFO); + ECase(C_WEAKEXT); + ECase(C_DWARF); + ECase(C_GSYM); + ECase(C_LSYM); + ECase(C_PSYM); + ECase(C_RSYM); + ECase(C_RPSYM); + ECase(C_STSYM); + ECase(C_TCSYM); + ECase(C_BCOMM); + ECase(C_ECOML); + ECase(C_ECOMM); + ECase(C_DECL); + ECase(C_ENTRY); + ECase(C_FUN); + ECase(C_BSTAT); + ECase(C_ESTAT); + ECase(C_GTLS); + ECase(C_STTLS); + ECase(C_EFCN); +#undef ECase +} + +void MappingTraits<XCOFFYAML::FileHeader>::mapping( + IO &IO, XCOFFYAML::FileHeader &FileHdr) { + IO.mapRequired("MagicNumber", FileHdr.Magic); + IO.mapRequired("NumberOfSections", FileHdr.NumberOfSections); + IO.mapRequired("CreationTime", FileHdr.TimeStamp); + IO.mapRequired("OffsetToSymbolTable", FileHdr.SymbolTableOffset); + IO.mapRequired("EntriesInSymbolTable", FileHdr.NumberOfSymTableEntries); + IO.mapRequired("AuxiliaryHeaderSize", FileHdr.AuxHeaderSize); + IO.mapRequired("Flags", FileHdr.Flags); +} + +void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) { + IO.mapRequired("Name", S.SymbolName); + IO.mapRequired("Value", S.Value); + IO.mapRequired("Section", S.SectionName); + IO.mapRequired("Type", S.Type); + IO.mapRequired("StorageClass", S.StorageClass); + IO.mapRequired("NumberOfAuxEntries", S.NumberOfAuxEntries); +} + +void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) { + IO.mapTag("!XCOFF", true); + IO.mapRequired("FileHeader", Obj.Header); + IO.mapRequired("Symbols", Obj.Symbols); +} + +} // namespace yaml +} // namespace llvm diff --git a/lib/ObjectYAML/YAML.cpp b/lib/ObjectYAML/YAML.cpp index 67b5764eadaa4..6eba16e36c2a2 100644 --- a/lib/ObjectYAML/YAML.cpp +++ b/lib/ObjectYAML/YAML.cpp @@ -1,9 +1,8 @@ //===- YAML.cpp - YAMLIO utilities for object files -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -32,7 +31,7 @@ StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *, // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? // (e.g. a caret pointing to the offending character). for (unsigned I = 0, N = Scalar.size(); I != N; ++I) - if (!isxdigit(Scalar[I])) + if (!llvm::isHexDigit(Scalar[I])) return "BinaryRef hex string must contain only hex digits."; Val = yaml::BinaryRef(Scalar); return {}; @@ -44,8 +43,9 @@ void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const { return; } for (unsigned I = 0, N = Data.size(); I != N; I += 2) { - uint8_t Byte; - StringRef((const char *)&Data[I], 2).getAsInteger(16, Byte); + uint8_t Byte = llvm::hexDigitValue(Data[I]); + Byte <<= 4; + Byte |= llvm::hexDigitValue(Data[I + 1]); OS.write(Byte); } } |
