From c47e98d58f870f862e454c8b498b24848dba93c6 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Tue, 2 Apr 2019 11:58:37 +0000 Subject: [PATCH] Add minidump support to obj2yaml Summary: This patch adds the code needed to parse a minidump file into the MinidumpYAML model, and the necessary glue code so that obj2yaml can recognise the minidump files and process them. Reviewers: jhenderson, zturner, clayborg Subscribers: mgorny, lldb-commits, amccarth, markmentovai, aprantl, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59634 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357469 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ObjectYAML/MinidumpYAML.h | 12 +++++++++ lib/ObjectYAML/MinidumpYAML.cpp | 32 ++++++++++++++++++++++ test/tools/obj2yaml/basic-minidump.yaml | 35 +++++++++++++++++++++++++ tools/obj2yaml/CMakeLists.txt | 1 + tools/obj2yaml/minidump2yaml.cpp | 24 +++++++++++++++++ tools/obj2yaml/obj2yaml.cpp | 3 +++ tools/obj2yaml/obj2yaml.h | 3 +++ 7 files changed, 110 insertions(+) create mode 100644 test/tools/obj2yaml/basic-minidump.yaml create mode 100644 tools/obj2yaml/minidump2yaml.cpp diff --git a/include/llvm/ObjectYAML/MinidumpYAML.h b/include/llvm/ObjectYAML/MinidumpYAML.h index 641b9b67cb1..98c918b1e37 100644 --- a/include/llvm/ObjectYAML/MinidumpYAML.h +++ b/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 @@ struct Stream { /// 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 @@ struct Object { 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/lib/ObjectYAML/MinidumpYAML.cpp b/lib/ObjectYAML/MinidumpYAML.cpp index bd017c82fb4..a2e0b209da5 100644 --- a/lib/ObjectYAML/MinidumpYAML.cpp +++ b/lib/ObjectYAML/MinidumpYAML.cpp @@ -383,3 +383,35 @@ Error MinidumpYAML::writeAsBinary(StringRef Yaml, raw_ostream &OS) { 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/test/tools/obj2yaml/basic-minidump.yaml b/test/tools/obj2yaml/basic-minidump.yaml new file mode 100644 index 00000000000..ce2c1b197e1 --- /dev/null +++ b/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/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt index c59fe650952..5bac7c02465 100644 --- a/tools/obj2yaml/CMakeLists.txt +++ b/tools/obj2yaml/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_tool(obj2yaml dwarf2yaml.cpp elf2yaml.cpp macho2yaml.cpp + minidump2yaml.cpp wasm2yaml.cpp Error.cpp ) diff --git a/tools/obj2yaml/minidump2yaml.cpp b/tools/obj2yaml/minidump2yaml.cpp new file mode 100644 index 00000000000..50c883edb27 --- /dev/null +++ b/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/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp index 1350970096f..9ae861dd13e 100644 --- a/tools/obj2yaml/obj2yaml.cpp +++ b/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 @@ static Error dumpInput(StringRef File) { // 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(); } diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h index c7c4956d6bf..c34a6814c5e 100644 --- a/tools/obj2yaml/obj2yaml.h +++ b/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 @@ std::error_code elf2yaml(llvm::raw_ostream &Out, 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); -- 2.50.1