diff --git a/llvm/include/llvm/ObjectYAML/MinidumpYAML.h b/llvm/include/llvm/ObjectYAML/MinidumpYAML.h --- a/llvm/include/llvm/ObjectYAML/MinidumpYAML.h +++ b/llvm/include/llvm/ObjectYAML/MinidumpYAML.h @@ -10,6 +10,7 @@ #define LLVM_OBJECTYAML_MINIDUMPYAML_H #include "llvm/BinaryFormat/Minidump.h" +#include "llvm/Object/Minidump.h" #include "llvm/ObjectYAML/YAML.h" #include "llvm/Support/YAMLTraits.h" @@ -41,6 +42,11 @@ /// Create an empty stream of the given Type. static std::unique_ptr create(minidump::StreamType Type); + + /// Create a stream from the given stream directory entry. + static Expected> + create(const minidump::Directory &StreamDesc, + const object::MinidumpFile &File); }; /// A minidump stream represented as a sequence of hex bytes. This is used as a @@ -103,11 +109,17 @@ Object(Object &&) = default; Object &operator=(Object &&) = default; + Object(const minidump::Header &Header, + std::vector> Streams) + : Header(Header), Streams(std::move(Streams)) {} + /// The minidump header. minidump::Header Header; /// The list of streams in this minidump object. std::vector> Streams; + + static Expected create(const object::MinidumpFile &File); }; /// Serialize the minidump file represented by Obj to OS in binary form. diff --git a/llvm/lib/ObjectYAML/MinidumpYAML.cpp b/llvm/lib/ObjectYAML/MinidumpYAML.cpp --- a/llvm/lib/ObjectYAML/MinidumpYAML.cpp +++ b/llvm/lib/ObjectYAML/MinidumpYAML.cpp @@ -383,3 +383,35 @@ writeAsBinary(Obj, OS); return Error::success(); } + +Expected> +Stream::create(const Directory &StreamDesc, const object::MinidumpFile &File) { + StreamKind Kind = getKind(StreamDesc.Type); + switch (Kind) { + case StreamKind::RawContent: + return make_unique(StreamDesc.Type, + File.getRawStream(StreamDesc)); + case StreamKind::SystemInfo: { + auto ExpectedInfo = File.getSystemInfo(); + if (!ExpectedInfo) + return ExpectedInfo.takeError(); + return make_unique(*ExpectedInfo); + } + case StreamKind::TextContent: + return make_unique( + StreamDesc.Type, toStringRef(File.getRawStream(StreamDesc))); + } + llvm_unreachable("Unhandled stream kind!"); +} + +Expected Object::create(const object::MinidumpFile &File) { + std::vector> 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/llvm/test/tools/obj2yaml/basic-minidump.yaml b/llvm/test/tools/obj2yaml/basic-minidump.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/obj2yaml/basic-minidump.yaml @@ -0,0 +1,35 @@ +# RUN: yaml2obj %s | obj2yaml - | FileCheck %s + +--- !minidump +Streams: + - Type: SystemInfo + Processor Arch: ARM64 + Platform ID: Linux + CSD Version RVA: 0x01020304 + CPU: + CPUID: 0x05060708 + - Type: LinuxAuxv + Content: DEADBEEFBAADF00D + - Type: LinuxMaps + Text: | + 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process + 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process + +... + +# CHECK: --- !minidump +# CHECK-NEXT: Streams: +# CHECK-NEXT: - Type: SystemInfo +# CHECK-NEXT: Processor Arch: ARM64 +# CHECK-NEXT: Platform ID: Linux +# CHECK-NEXT: CSD Version RVA: 0x01020304 +# CHECK-NEXT: CPU: +# CHECK-NEXT: CPUID: 0x05060708 +# CHECK-NEXT: - Type: LinuxAuxv +# CHECK-NEXT: Content: DEADBEEFBAADF00D +# CHECK-NEXT: - Type: LinuxMaps +# CHECK-NEXT: Text: | +# CHECK-NEXT: 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process +# CHECK-NEXT: 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process +# CHECK-EMPTY: +# CHECK-NEXT: ... diff --git a/llvm/tools/obj2yaml/CMakeLists.txt b/llvm/tools/obj2yaml/CMakeLists.txt --- a/llvm/tools/obj2yaml/CMakeLists.txt +++ b/llvm/tools/obj2yaml/CMakeLists.txt @@ -13,6 +13,7 @@ dwarf2yaml.cpp elf2yaml.cpp macho2yaml.cpp + minidump2yaml.cpp wasm2yaml.cpp Error.cpp ) diff --git a/llvm/tools/obj2yaml/minidump2yaml.cpp b/llvm/tools/obj2yaml/minidump2yaml.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/obj2yaml/minidump2yaml.cpp @@ -0,0 +1,24 @@ +//===- minidump2yaml.cpp - Minidump to yaml conversion tool -----*- 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 +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "obj2yaml.h" +#include "llvm/Object/Minidump.h" +#include "llvm/ObjectYAML/MinidumpYAML.h" +#include "llvm/Support/YAMLTraits.h" + +using namespace llvm; + +Error minidump2yaml(raw_ostream &Out, const object::MinidumpFile &Obj) { + auto ExpectedObject = MinidumpYAML::Object::create(Obj); + if (!ExpectedObject) + return ExpectedObject.takeError(); + yaml::Output Output(Out); + Output << *ExpectedObject; + return llvm::Error::success(); +} diff --git a/llvm/tools/obj2yaml/obj2yaml.h b/llvm/tools/obj2yaml/obj2yaml.h --- a/llvm/tools/obj2yaml/obj2yaml.h +++ b/llvm/tools/obj2yaml/obj2yaml.h @@ -13,6 +13,7 @@ #define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H #include "llvm/Object/COFF.h" +#include "llvm/Object/Minidump.h" #include "llvm/Object/Wasm.h" #include "llvm/Support/raw_ostream.h" #include @@ -23,6 +24,8 @@ const llvm::object::ObjectFile &Obj); std::error_code macho2yaml(llvm::raw_ostream &Out, const llvm::object::Binary &Obj); +llvm::Error minidump2yaml(llvm::raw_ostream &Out, + const llvm::object::MinidumpFile &Obj); std::error_code wasm2yaml(llvm::raw_ostream &Out, const llvm::object::WasmObjectFile &Obj); diff --git a/llvm/tools/obj2yaml/obj2yaml.cpp b/llvm/tools/obj2yaml/obj2yaml.cpp --- a/llvm/tools/obj2yaml/obj2yaml.cpp +++ b/llvm/tools/obj2yaml/obj2yaml.cpp @@ -10,6 +10,7 @@ #include "Error.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/Minidump.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" @@ -40,6 +41,8 @@ // TODO: If this is an archive, then burst it and dump each entry if (ObjectFile *Obj = dyn_cast(&Binary)) return errorCodeToError(dumpObject(*Obj)); + if (MinidumpFile *Minidump = dyn_cast(&Binary)) + return minidump2yaml(outs(), *Minidump); return Error::success(); }