summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ObjectFile
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
commitc0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch)
treef42add1021b9f2ac6a69ac7cf6c4499962739a45 /lldb/source/Plugins/ObjectFile
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'lldb/source/Plugins/ObjectFile')
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp91
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h50
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp11
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h6
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp69
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h10
-rw-r--r--lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp17
-rw-r--r--lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h10
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp772
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h92
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp114
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h66
-rw-r--r--lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp5
-rw-r--r--lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h6
-rw-r--r--lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp5
-rw-r--r--lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h5
16 files changed, 1226 insertions, 103 deletions
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
index bd8eeedce57d..24941be515de 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
@@ -23,6 +23,8 @@ enum class Token {
CodeID,
File,
Func,
+ Inline,
+ InlineOrigin,
Public,
Stack,
CFI,
@@ -41,6 +43,8 @@ template <> Token stringTo<Token>(llvm::StringRef Str) {
.Case("CODE_ID", Token::CodeID)
.Case("FILE", Token::File)
.Case("FUNC", Token::Func)
+ .Case("INLINE", Token::Inline)
+ .Case("INLINE_ORIGIN", Token::InlineOrigin)
.Case("PUBLIC", Token::Public)
.Case("STACK", Token::Stack)
.Case("CFI", Token::CFI)
@@ -145,7 +149,10 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) {
default:
return llvm::None;
}
-
+ case Token::Inline:
+ return Record::Inline;
+ case Token::InlineOrigin:
+ return Record::InlineOrigin;
case Token::Unknown:
// Optimistically assume that any unrecognised token means this is a line
// record, those don't have a special keyword and start directly with a
@@ -216,9 +223,11 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
return OS << "INFO CODE_ID " << R.ID.GetAsString();
}
-llvm::Optional<FileRecord> FileRecord::parse(llvm::StringRef Line) {
- // FILE number name
- if (consume<Token>(Line) != Token::File)
+template <typename T>
+static llvm::Optional<T> parseNumberName(llvm::StringRef Line,
+ Token TokenType) {
+ // TOKEN number name
+ if (consume<Token>(Line) != TokenType)
return llvm::None;
llvm::StringRef Str;
@@ -231,7 +240,12 @@ llvm::Optional<FileRecord> FileRecord::parse(llvm::StringRef Line) {
if (Name.empty())
return llvm::None;
- return FileRecord(Number, Name);
+ return T(Number, Name);
+}
+
+llvm::Optional<FileRecord> FileRecord::parse(llvm::StringRef Line) {
+ // FILE number name
+ return parseNumberName<FileRecord>(Line, Token::File);
}
llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
@@ -239,6 +253,17 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
return OS << "FILE " << R.Number << " " << R.Name;
}
+llvm::Optional<InlineOriginRecord>
+InlineOriginRecord::parse(llvm::StringRef Line) {
+ // INLINE_ORIGIN number name
+ return parseNumberName<InlineOriginRecord>(Line, Token::InlineOrigin);
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const InlineOriginRecord &R) {
+ return OS << "INLINE_ORIGIN " << R.Number << " " << R.Name;
+}
+
static bool parsePublicOrFunc(llvm::StringRef Line, bool &Multiple,
lldb::addr_t &Address, lldb::addr_t *Size,
lldb::addr_t &ParamSize, llvm::StringRef &Name) {
@@ -299,6 +324,58 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
R.ParamSize, R.Name);
}
+llvm::Optional<InlineRecord> InlineRecord::parse(llvm::StringRef Line) {
+ // INLINE inline_nest_level call_site_line call_site_file_num origin_num
+ // [address size]+
+ if (consume<Token>(Line) != Token::Inline)
+ return llvm::None;
+
+ llvm::SmallVector<llvm::StringRef> Tokens;
+ SplitString(Line, Tokens, " ");
+ if (Tokens.size() < 6 || Tokens.size() % 2 == 1)
+ return llvm::None;
+
+ size_t InlineNestLevel;
+ uint32_t CallSiteLineNum;
+ size_t CallSiteFileNum;
+ size_t OriginNum;
+ if (!(to_integer(Tokens[0], InlineNestLevel) &&
+ to_integer(Tokens[1], CallSiteLineNum) &&
+ to_integer(Tokens[2], CallSiteFileNum) &&
+ to_integer(Tokens[3], OriginNum)))
+ return llvm::None;
+
+ InlineRecord Record = InlineRecord(InlineNestLevel, CallSiteLineNum,
+ CallSiteFileNum, OriginNum);
+ for (size_t i = 4; i < Tokens.size(); i += 2) {
+ lldb::addr_t Address;
+ if (!to_integer(Tokens[i], Address, 16))
+ return llvm::None;
+ lldb::addr_t Size;
+ if (!to_integer(Tokens[i + 1].trim(), Size, 16))
+ return llvm::None;
+ Record.Ranges.emplace_back(Address, Size);
+ }
+ return Record;
+}
+
+bool breakpad::operator==(const InlineRecord &L, const InlineRecord &R) {
+ return L.InlineNestLevel == R.InlineNestLevel &&
+ L.CallSiteLineNum == R.CallSiteLineNum &&
+ L.CallSiteFileNum == R.CallSiteFileNum && L.OriginNum == R.OriginNum &&
+ L.Ranges == R.Ranges;
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const InlineRecord &R) {
+ OS << llvm::formatv("INLINE {0} {1} {2} {3}", R.InlineNestLevel,
+ R.CallSiteLineNum, R.CallSiteFileNum, R.OriginNum);
+ for (const auto &range : R.Ranges) {
+ OS << llvm::formatv(" {0:x-} {1:x-}", range.first, range.second);
+ }
+ return OS;
+}
+
llvm::Optional<LineRecord> LineRecord::parse(llvm::StringRef Line) {
lldb::addr_t Address;
llvm::StringRef Str;
@@ -490,6 +567,10 @@ llvm::StringRef breakpad::toString(Record::Kind K) {
return "FILE";
case Record::Func:
return "FUNC";
+ case Record::Inline:
+ return "INLINE";
+ case Record::InlineOrigin:
+ return "INLINE_ORIGIN";
case Record::Line:
return "LINE";
case Record::Public:
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
index 1620a1210b84..8a11323d521c 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
@@ -20,7 +20,18 @@ namespace breakpad {
class Record {
public:
- enum Kind { Module, Info, File, Func, Line, Public, StackCFI, StackWin };
+ enum Kind {
+ Module,
+ Info,
+ File,
+ Func,
+ Inline,
+ InlineOrigin,
+ Line,
+ Public,
+ StackCFI,
+ StackWin
+ };
/// Attempt to guess the kind of the record present in the argument without
/// doing a full parse. The returned kind will always be correct for valid
@@ -89,6 +100,23 @@ inline bool operator==(const FileRecord &L, const FileRecord &R) {
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FileRecord &R);
+class InlineOriginRecord : public Record {
+public:
+ static llvm::Optional<InlineOriginRecord> parse(llvm::StringRef Line);
+ InlineOriginRecord(size_t Number, llvm::StringRef Name)
+ : Record(InlineOrigin), Number(Number), Name(Name) {}
+
+ size_t Number;
+ llvm::StringRef Name;
+};
+
+inline bool operator==(const InlineOriginRecord &L,
+ const InlineOriginRecord &R) {
+ return L.Number == R.Number && L.Name == R.Name;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const InlineOriginRecord &R);
+
class FuncRecord : public Record {
public:
static llvm::Optional<FuncRecord> parse(llvm::StringRef Line);
@@ -107,6 +135,26 @@ public:
bool operator==(const FuncRecord &L, const FuncRecord &R);
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FuncRecord &R);
+class InlineRecord : public Record {
+public:
+ static llvm::Optional<InlineRecord> parse(llvm::StringRef Line);
+ InlineRecord(size_t InlineNestLevel, uint32_t CallSiteLineNum,
+ size_t CallSiteFileNum, size_t OriginNum)
+ : Record(Inline), InlineNestLevel(InlineNestLevel),
+ CallSiteLineNum(CallSiteLineNum), CallSiteFileNum(CallSiteFileNum),
+ OriginNum(OriginNum) {}
+
+ size_t InlineNestLevel;
+ uint32_t CallSiteLineNum;
+ size_t CallSiteFileNum;
+ size_t OriginNum;
+ // A vector of address range covered by this inline
+ std::vector<std::pair<lldb::addr_t, lldb::addr_t>> Ranges;
+};
+
+bool operator==(const InlineRecord &L, const InlineRecord &R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InlineRecord &R);
+
class LineRecord : public Record {
public:
static llvm::Optional<LineRecord> parse(llvm::StringRef Line);
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
index 7a9163ddb880..bad730512ff4 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
@@ -56,11 +56,6 @@ void ObjectFileBreakpad::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-ConstString ObjectFileBreakpad::GetPluginNameStatic() {
- static ConstString g_name("breakpad");
- return g_name;
-}
-
ObjectFile *ObjectFileBreakpad::CreateInstance(
const ModuleSP &module_sp, DataBufferSP &data_sp, offset_t data_offset,
const FileSpec *file, offset_t file_offset, offset_t length) {
@@ -153,9 +148,9 @@ void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
std::tie(line, text) = text.split('\n');
llvm::Optional<Record::Kind> next_section = Record::classify(line);
- if (next_section == Record::Line) {
- // Line records logically belong to the preceding Func record, so we put
- // them in the same section.
+ if (next_section == Record::Line || next_section == Record::Inline) {
+ // Line/Inline records logically belong to the preceding Func record, so
+ // we put them in the same section.
next_section = Record::Func;
}
if (next_section == current_section)
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
index 8724feaa422d..c320c7ad3e2e 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
@@ -21,7 +21,7 @@ public:
static void Initialize();
static void Terminate();
- static ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "breakpad"; }
static const char *GetPluginDescriptionStatic() {
return "Breakpad object file reader.";
}
@@ -44,9 +44,7 @@ public:
ModuleSpecList &specs);
// PluginInterface protocol
- ConstString GetPluginName() override { return GetPluginNameStatic(); }
-
- uint32_t GetPluginVersion() override { return 1; }
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
// LLVM RTTI support
static char ID;
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index a5e86f0c2c1b..8e0f228a988f 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -55,36 +55,36 @@ using namespace llvm::ELF;
LLDB_PLUGIN_DEFINE(ObjectFileELF)
-namespace {
-
// ELF note owner definitions
-const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
-const char *const LLDB_NT_OWNER_GNU = "GNU";
-const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
-const char *const LLDB_NT_OWNER_NETBSDCORE = "NetBSD-CORE";
-const char *const LLDB_NT_OWNER_OPENBSD = "OpenBSD";
-const char *const LLDB_NT_OWNER_ANDROID = "Android";
-const char *const LLDB_NT_OWNER_CORE = "CORE";
-const char *const LLDB_NT_OWNER_LINUX = "LINUX";
+static const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
+static const char *const LLDB_NT_OWNER_GNU = "GNU";
+static const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
+static const char *const LLDB_NT_OWNER_NETBSDCORE = "NetBSD-CORE";
+static const char *const LLDB_NT_OWNER_OPENBSD = "OpenBSD";
+static const char *const LLDB_NT_OWNER_ANDROID = "Android";
+static const char *const LLDB_NT_OWNER_CORE = "CORE";
+static const char *const LLDB_NT_OWNER_LINUX = "LINUX";
// ELF note type definitions
-const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
-const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4;
+static const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
+static const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4;
-const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
-const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
+static const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
+static const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
-const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;
+static const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;
-const elf_word LLDB_NT_NETBSD_IDENT_TAG = 1;
-const elf_word LLDB_NT_NETBSD_IDENT_DESCSZ = 4;
-const elf_word LLDB_NT_NETBSD_IDENT_NAMESZ = 7;
-const elf_word LLDB_NT_NETBSD_PROCINFO = 1;
+static const elf_word LLDB_NT_NETBSD_IDENT_TAG = 1;
+static const elf_word LLDB_NT_NETBSD_IDENT_DESCSZ = 4;
+static const elf_word LLDB_NT_NETBSD_IDENT_NAMESZ = 7;
+static const elf_word LLDB_NT_NETBSD_PROCINFO = 1;
// GNU ABI note OS constants
-const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
-const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
-const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
+static const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
+static const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
+static const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
+
+namespace {
//===----------------------------------------------------------------------===//
/// \class ELFRelocation
@@ -125,6 +125,7 @@ private:
RelocUnion reloc;
};
+} // end anonymous namespace
ELFRelocation::ELFRelocation(unsigned type) {
if (type == DT_REL || type == SHT_REL)
@@ -208,8 +209,6 @@ unsigned ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
return rel.reloc.get<ELFRela *>()->r_addend;
}
-} // end anonymous namespace
-
static user_id_t SegmentID(size_t PHdrIndex) {
return ~user_id_t(PHdrIndex);
}
@@ -335,15 +334,6 @@ void ObjectFileELF::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString ObjectFileELF::GetPluginNameStatic() {
- static ConstString g_name("elf");
- return g_name;
-}
-
-const char *ObjectFileELF::GetPluginDescriptionStatic() {
- return "ELF object file reader.";
-}
-
ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
lldb::offset_t data_offset,
@@ -634,12 +624,6 @@ size_t ObjectFileELF::GetModuleSpecifications(
return specs.GetSize() - initial_count;
}
-// PluginInterface protocol
-lldb_private::ConstString ObjectFileELF::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t ObjectFileELF::GetPluginVersion() { return m_plugin_version; }
// ObjectFile protocol
ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
@@ -2708,9 +2692,6 @@ Symtab *ObjectFileELF::GetSymtab() {
if (!module_sp)
return nullptr;
- Progress progress(llvm::formatv("Parsing symbol table for {0}",
- m_file.GetFilename().AsCString("<Unknown>")));
-
// We always want to use the main object file so we (hopefully) only have one
// cached copy of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
@@ -2718,6 +2699,10 @@ Symtab *ObjectFileELF::GetSymtab() {
return module_obj_file->GetSymtab();
if (m_symtab_up == nullptr) {
+ Progress progress(
+ llvm::formatv("Parsing symbol table for {0}",
+ m_file.GetFilename().AsCString("<Unknown>")));
+ ElapsedTime elapsed(module_sp->GetSymtabParseTime());
SectionList *section_list = module_sp->GetSectionList();
if (!section_list)
return nullptr;
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index e678c2f5f011..5738e5cf60d5 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -61,9 +61,11 @@ public:
static void Terminate();
- static lldb_private::ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "elf"; }
- static const char *GetPluginDescriptionStatic();
+ static llvm::StringRef GetPluginDescriptionStatic() {
+ return "ELF object file reader.";
+ }
static lldb_private::ObjectFile *
CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
@@ -85,9 +87,7 @@ public:
lldb::addr_t length);
// PluginInterface protocol
- lldb_private::ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
// LLVM RTTI support
static char ID;
diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index f93ac9261afd..bec0099517c8 100644
--- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -53,15 +53,6 @@ void ObjectFileJIT::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString ObjectFileJIT::GetPluginNameStatic() {
- static ConstString g_name("jit");
- return g_name;
-}
-
-const char *ObjectFileJIT::GetPluginDescriptionStatic() {
- return "JIT code object file";
-}
-
ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
lldb::offset_t data_offset,
@@ -120,6 +111,7 @@ Symtab *ObjectFileJIT::GetSymtab() {
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_symtab_up == nullptr) {
+ ElapsedTime elapsed(module_sp->GetSymtabParseTime());
m_symtab_up = std::make_unique<Symtab>(this);
std::lock_guard<std::recursive_mutex> symtab_guard(
m_symtab_up->GetMutex());
@@ -199,13 +191,6 @@ ArchSpec ObjectFileJIT::GetArchitecture() {
return ArchSpec();
}
-// PluginInterface protocol
-lldb_private::ConstString ObjectFileJIT::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t ObjectFileJIT::GetPluginVersion() { return 1; }
-
bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
bool value_is_offset) {
size_t num_loaded_sections = 0;
diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index a3a1acea916a..03ac001988a0 100644
--- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -26,9 +26,11 @@ public:
static void Terminate();
- static lldb_private::ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "jit"; }
- static const char *GetPluginDescriptionStatic();
+ static llvm::StringRef GetPluginDescriptionStatic() {
+ return "JIT code object file";
+ }
static lldb_private::ObjectFile *
CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
@@ -96,9 +98,7 @@ public:
ObjectFile::Strata CalculateStrata() override;
// PluginInterface protocol
- lldb_private::ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
protected:
lldb::ObjectFileJITDelegateWP m_delegate_wp;
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
new file mode 100644
index 000000000000..a70e6a079f76
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
@@ -0,0 +1,772 @@
+//===-- MinidumpFileBuilder.cpp -------------------------------------------===//
+//
+// 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 "MinidumpFileBuilder.h"
+
+#include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Minidump.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Error.h"
+
+#include "Plugins/Process/minidump/MinidumpTypes.h"
+
+#include <cinttypes>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm::minidump;
+
+void MinidumpFileBuilder::AddDirectory(StreamType type, size_t stream_size) {
+ LocationDescriptor loc;
+ loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size);
+ // Stream will begin at the current end of data section
+ loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
+
+ Directory dir;
+ dir.Type = static_cast<llvm::support::little_t<StreamType>>(type);
+ dir.Location = loc;
+
+ m_directories.push_back(dir);
+}
+
+Status MinidumpFileBuilder::AddSystemInfo(const llvm::Triple &target_triple) {
+ Status error;
+ AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo));
+
+ llvm::minidump::ProcessorArchitecture arch;
+ switch (target_triple.getArch()) {
+ case llvm::Triple::ArchType::x86_64:
+ arch = ProcessorArchitecture::AMD64;
+ break;
+ case llvm::Triple::ArchType::x86:
+ arch = ProcessorArchitecture::X86;
+ break;
+ case llvm::Triple::ArchType::arm:
+ arch = ProcessorArchitecture::ARM;
+ break;
+ case llvm::Triple::ArchType::aarch64:
+ arch = ProcessorArchitecture::ARM64;
+ break;
+ case llvm::Triple::ArchType::mips64:
+ case llvm::Triple::ArchType::mips64el:
+ case llvm::Triple::ArchType::mips:
+ case llvm::Triple::ArchType::mipsel:
+ arch = ProcessorArchitecture::MIPS;
+ break;
+ case llvm::Triple::ArchType::ppc64:
+ case llvm::Triple::ArchType::ppc:
+ case llvm::Triple::ArchType::ppc64le:
+ arch = ProcessorArchitecture::PPC;
+ break;
+ default:
+ error.SetErrorStringWithFormat("Architecture %s not supported.",
+ target_triple.getArchName().str().c_str());
+ return error;
+ };
+
+ llvm::support::little_t<OSPlatform> platform_id;
+ switch (target_triple.getOS()) {
+ case llvm::Triple::OSType::Linux:
+ if (target_triple.getEnvironment() ==
+ llvm::Triple::EnvironmentType::Android)
+ platform_id = OSPlatform::Android;
+ else
+ platform_id = OSPlatform::Linux;
+ break;
+ case llvm::Triple::OSType::Win32:
+ platform_id = OSPlatform::Win32NT;
+ break;
+ case llvm::Triple::OSType::MacOSX:
+ platform_id = OSPlatform::MacOSX;
+ break;
+ case llvm::Triple::OSType::IOS:
+ platform_id = OSPlatform::IOS;
+ break;
+ default:
+ error.SetErrorStringWithFormat("OS %s not supported.",
+ target_triple.getOSName().str().c_str());
+ return error;
+ };
+
+ llvm::minidump::SystemInfo sys_info;
+ sys_info.ProcessorArch =
+ static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
+ // Global offset to beginning of a csd_string in a data section
+ sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
+ GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
+ sys_info.PlatformId = platform_id;
+ m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));
+
+ std::string csd_string = "";
+
+ error = WriteString(csd_string, &m_data);
+ if (error.Fail()) {
+ error.SetErrorString("Unable to convert the csd string to UTF16.");
+ return error;
+ }
+
+ return error;
+}
+
+Status WriteString(const std::string &to_write,
+ lldb_private::DataBufferHeap *buffer) {
+ Status error;
+ // let the StringRef eat also null termination char
+ llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
+ llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;
+
+ bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
+ if (!converted) {
+ error.SetErrorStringWithFormat(
+ "Unable to convert the string to UTF16. Failed to convert %s",
+ to_write.c_str());
+ return error;
+ }
+
+ // size of the UTF16 string should be written without the null termination
+ // character that is stored in 2 bytes
+ llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);
+
+ buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
+ buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());
+
+ return error;
+}
+
+llvm::Expected<uint64_t> getModuleFileSize(Target &target,
+ const ModuleSP &mod) {
+ SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();
+ uint64_t SizeOfImage = 0;
+
+ if (!sect_sp) {
+ return llvm::createStringError(std::errc::operation_not_supported,
+ "Couldn't obtain the section information.");
+ }
+ lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
+ // Use memory size since zero fill sections, like ".bss", will be smaller on
+ // disk.
+ lldb::addr_t sect_size = sect_sp->GetByteSize();
+ // This will usually be zero, but make sure to calculate the BaseOfImage
+ // offset.
+ const lldb::addr_t base_sect_offset =
+ mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
+ sect_addr;
+ SizeOfImage = sect_size - base_sect_offset;
+ lldb::addr_t next_sect_addr = sect_addr + sect_size;
+ Address sect_so_addr;
+ target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
+ lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
+ while (next_sect_sp &&
+ next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
+ sect_size = sect_sp->GetByteSize();
+ SizeOfImage += sect_size;
+ next_sect_addr += sect_size;
+ target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
+ next_sect_sp = sect_so_addr.GetSection();
+ }
+
+ return SizeOfImage;
+}
+
+// ModuleList stream consists of a number of modules, followed by an array
+// of llvm::minidump::Module's structures. Every structure informs about a
+// single module. Additional data of variable length, such as module's names,
+// are stored just after the ModuleList stream. The llvm::minidump::Module
+// structures point to this helper data by global offset.
+Status MinidumpFileBuilder::AddModuleList(Target &target) {
+ constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
+ Status error;
+
+ const ModuleList &modules = target.GetImages();
+ llvm::support::ulittle32_t modules_count =
+ static_cast<llvm::support::ulittle32_t>(modules.GetSize());
+
+ // This helps us with getting the correct global offset in minidump
+ // file later, when we will be setting up offsets from the
+ // the llvm::minidump::Module's structures into helper data
+ size_t size_before = GetCurrentDataEndOffset();
+
+ // This is the size of the main part of the ModuleList stream.
+ // It consists of a module number and corresponding number of
+ // structs describing individual modules
+ size_t module_stream_size =
+ sizeof(llvm::support::ulittle32_t) + modules_count * minidump_module_size;
+
+ // Adding directory describing this stream.
+ AddDirectory(StreamType::ModuleList, module_stream_size);
+
+ m_data.AppendData(&modules_count, sizeof(llvm::support::ulittle32_t));
+
+ // Temporary storage for the helper data (of variable length)
+ // as these cannot be dumped to m_data before dumping entire
+ // array of module structures.
+ DataBufferHeap helper_data;
+
+ for (size_t i = 0; i < modules_count; ++i) {
+ ModuleSP mod = modules.GetModuleAtIndex(i);
+ std::string module_name = mod->GetSpecificationDescription();
+ auto maybe_mod_size = getModuleFileSize(target, mod);
+ if (!maybe_mod_size) {
+ error.SetErrorStringWithFormat("Unable to get the size of module %s.",
+ module_name.c_str());
+ return error;
+ }
+
+ uint64_t mod_size = std::move(*maybe_mod_size);
+
+ llvm::support::ulittle32_t signature =
+ static_cast<llvm::support::ulittle32_t>(
+ static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
+ auto uuid = mod->GetUUID().GetBytes();
+
+ VSFixedFileInfo info;
+ info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
+ info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
+ info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
+ info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
+ info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);
+
+ LocationDescriptor ld;
+ ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
+ ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);
+
+ // Setting up LocationDescriptor for uuid string. The global offset into
+ // minidump file is calculated.
+ LocationDescriptor ld_cv;
+ ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
+ sizeof(llvm::support::ulittle32_t) + uuid.size());
+ ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
+ size_before + module_stream_size + helper_data.GetByteSize());
+
+ helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
+ helper_data.AppendData(uuid.begin(), uuid.size());
+
+ llvm::minidump::Module m;
+ m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
+ mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
+ m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size);
+ m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
+ m.TimeDateStamp = static_cast<llvm::support::ulittle32_t>(std::time(0));
+ m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
+ size_before + module_stream_size + helper_data.GetByteSize());
+ m.VersionInfo = info;
+ m.CvRecord = ld_cv;
+ m.MiscRecord = ld;
+
+ error = WriteString(module_name, &helper_data);
+
+ if (error.Fail())
+ return error;
+
+ m_data.AppendData(&m, sizeof(llvm::minidump::Module));
+ }
+
+ m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
+ return error;
+}
+
+uint16_t read_register_u16_raw(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
+ if (!reg_info)
+ return 0;
+ lldb_private::RegisterValue reg_value;
+ bool success = reg_ctx->ReadRegister(reg_info, reg_value);
+ if (!success)
+ return 0;
+ return reg_value.GetAsUInt16();
+}
+
+uint32_t read_register_u32_raw(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
+ if (!reg_info)
+ return 0;
+ lldb_private::RegisterValue reg_value;
+ bool success = reg_ctx->ReadRegister(reg_info, reg_value);
+ if (!success)
+ return 0;
+ return reg_value.GetAsUInt32();
+}
+
+uint64_t read_register_u64_raw(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
+ if (!reg_info)
+ return 0;
+ lldb_private::RegisterValue reg_value;
+ bool success = reg_ctx->ReadRegister(reg_info, reg_value);
+ if (!success)
+ return 0;
+ return reg_value.GetAsUInt64();
+}
+
+llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ return static_cast<llvm::support::ulittle16_t>(
+ read_register_u16_raw(reg_ctx, reg_name));
+}
+
+llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ return static_cast<llvm::support::ulittle32_t>(
+ read_register_u32_raw(reg_ctx, reg_name));
+}
+
+llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
+ const std::string &reg_name) {
+ return static_cast<llvm::support::ulittle64_t>(
+ read_register_u64_raw(reg_ctx, reg_name));
+}
+
+lldb_private::minidump::MinidumpContext_x86_64
+GetThreadContext_64(RegisterContext *reg_ctx) {
+ lldb_private::minidump::MinidumpContext_x86_64 thread_context;
+ thread_context.context_flags = static_cast<uint32_t>(
+ lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag |
+ lldb_private::minidump::MinidumpContext_x86_64_Flags::Control |
+ lldb_private::minidump::MinidumpContext_x86_64_Flags::Segments |
+ lldb_private::minidump::MinidumpContext_x86_64_Flags::Integer);
+ thread_context.rax = read_register_u64(reg_ctx, "rax");
+ thread_context.rbx = read_register_u64(reg_ctx, "rbx");
+ thread_context.rcx = read_register_u64(reg_ctx, "rcx");
+ thread_context.rdx = read_register_u64(reg_ctx, "rdx");
+ thread_context.rdi = read_register_u64(reg_ctx, "rdi");
+ thread_context.rsi = read_register_u64(reg_ctx, "rsi");
+ thread_context.rbp = read_register_u64(reg_ctx, "rbp");
+ thread_context.rsp = read_register_u64(reg_ctx, "rsp");
+ thread_context.r8 = read_register_u64(reg_ctx, "r8");
+ thread_context.r9 = read_register_u64(reg_ctx, "r9");
+ thread_context.r10 = read_register_u64(reg_ctx, "r10");
+ thread_context.r11 = read_register_u64(reg_ctx, "r11");
+ thread_context.r12 = read_register_u64(reg_ctx, "r12");
+ thread_context.r13 = read_register_u64(reg_ctx, "r13");
+ thread_context.r14 = read_register_u64(reg_ctx, "r14");
+ thread_context.r15 = read_register_u64(reg_ctx, "r15");
+ thread_context.rip = read_register_u64(reg_ctx, "rip");
+ thread_context.eflags = read_register_u32(reg_ctx, "rflags");
+ thread_context.cs = read_register_u16(reg_ctx, "cs");
+ thread_context.fs = read_register_u16(reg_ctx, "fs");
+ thread_context.gs = read_register_u16(reg_ctx, "gs");
+ thread_context.ss = read_register_u16(reg_ctx, "ss");
+ thread_context.ds = read_register_u16(reg_ctx, "ds");
+ return thread_context;
+}
+
+// Function returns start and size of the memory region that contains
+// memory location pointed to by the current stack pointer.
+llvm::Expected<std::pair<addr_t, addr_t>>
+findStackHelper(const lldb::ProcessSP &process_sp, uint64_t rsp) {
+ MemoryRegionInfo range_info;
+ Status error = process_sp->GetMemoryRegionInfo(rsp, range_info);
+ // Skip failed memory region requests or any regions with no permissions.
+ if (error.Fail() || range_info.GetLLDBPermissions() == 0)
+ return llvm::createStringError(
+ std::errc::not_supported,
+ "unable to load stack segment of the process");
+
+ const addr_t addr = range_info.GetRange().GetRangeBase();
+ const addr_t size = range_info.GetRange().GetByteSize();
+
+ if (size == 0)
+ return llvm::createStringError(std::errc::not_supported,
+ "stack segment of the process is empty");
+
+ return std::make_pair(addr, size);
+}
+
+Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) {
+ constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
+ lldb_private::ThreadList thread_list = process_sp->GetThreadList();
+
+ // size of the entire thread stream consists of:
+ // number of threads and threads array
+ size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
+ thread_list.GetSize() * minidump_thread_size;
+ // save for the ability to set up RVA
+ size_t size_before = GetCurrentDataEndOffset();
+
+ AddDirectory(StreamType::ThreadList, thread_stream_size);
+
+ llvm::support::ulittle32_t thread_count =
+ static_cast<llvm::support::ulittle32_t>(thread_list.GetSize());
+ m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));
+
+ DataBufferHeap helper_data;
+
+ const uint32_t num_threads = thread_list.GetSize();
+
+ for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
+ ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ Status error;
+
+ if (!reg_ctx_sp) {
+ error.SetErrorString("Unable to get the register context.");
+ return error;
+ }
+ RegisterContext *reg_ctx = reg_ctx_sp.get();
+ auto thread_context = GetThreadContext_64(reg_ctx);
+ uint64_t rsp = read_register_u64_raw(reg_ctx, "rsp");
+ auto expected_address_range = findStackHelper(process_sp, rsp);
+
+ if (!expected_address_range) {
+ error.SetErrorString("Unable to get the stack address.");
+ return error;
+ }
+
+ std::pair<uint64_t, uint64_t> range = std::move(*expected_address_range);
+ uint64_t addr = range.first;
+ uint64_t size = range.second;
+
+ auto data_up = std::make_unique<DataBufferHeap>(size, 0);
+ const size_t stack_bytes_read =
+ process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
+
+ if (error.Fail())
+ return error;
+
+ LocationDescriptor stack_memory;
+ stack_memory.DataSize =
+ static_cast<llvm::support::ulittle32_t>(stack_bytes_read);
+ stack_memory.RVA = static_cast<llvm::support::ulittle32_t>(
+ size_before + thread_stream_size + helper_data.GetByteSize());
+
+ MemoryDescriptor stack;
+ stack.StartOfMemoryRange = static_cast<llvm::support::ulittle64_t>(addr);
+ stack.Memory = stack_memory;
+
+ helper_data.AppendData(data_up->GetBytes(), stack_bytes_read);
+
+ LocationDescriptor thread_context_memory_locator;
+ thread_context_memory_locator.DataSize =
+ static_cast<llvm::support::ulittle32_t>(sizeof(thread_context));
+ thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
+ size_before + thread_stream_size + helper_data.GetByteSize());
+
+ helper_data.AppendData(
+ &thread_context,
+ sizeof(lldb_private::minidump::MinidumpContext_x86_64));
+
+ llvm::minidump::Thread t;
+ t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
+ t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
+ (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
+ t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
+ t.Priority = static_cast<llvm::support::ulittle32_t>(0);
+ t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
+ t.Stack = stack, t.Context = thread_context_memory_locator;
+
+ m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
+ }
+
+ m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
+ return Status();
+}
+
+Status MinidumpFileBuilder::AddException(const lldb::ProcessSP &process_sp) {
+ Status error;
+ lldb_private::ThreadList thread_list = process_sp->GetThreadList();
+
+ const uint32_t num_threads = thread_list.GetSize();
+ uint32_t stop_reason_thread_idx = 0;
+ for (stop_reason_thread_idx = 0; stop_reason_thread_idx < num_threads;
+ ++stop_reason_thread_idx) {
+ ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx));
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
+
+ if (stop_info_sp && stop_info_sp->IsValid())
+ break;
+ }
+
+ if (stop_reason_thread_idx == num_threads) {
+ error.SetErrorString("No stop reason thread found.");
+ return error;
+ }
+
+ constexpr size_t minidump_exception_size =
+ sizeof(llvm::minidump::ExceptionStream);
+ AddDirectory(StreamType::Exception, minidump_exception_size);
+ size_t size_before = GetCurrentDataEndOffset();
+
+ ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx));
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ RegisterContext *reg_ctx = reg_ctx_sp.get();
+ auto thread_context = GetThreadContext_64(reg_ctx);
+ StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
+
+ DataBufferHeap helper_data;
+
+ LocationDescriptor thread_context_memory_locator;
+ thread_context_memory_locator.DataSize =
+ static_cast<llvm::support::ulittle32_t>(sizeof(thread_context));
+ thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
+ size_before + minidump_exception_size + helper_data.GetByteSize());
+
+ helper_data.AppendData(
+ &thread_context, sizeof(lldb_private::minidump::MinidumpContext_x86_64));
+
+ Exception exp_record;
+ exp_record.ExceptionCode =
+ static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
+ exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0);
+ exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
+ exp_record.ExceptionAddress = read_register_u64(reg_ctx, "rip");
+ exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0);
+ exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
+ // exp_record.ExceptionInformation;
+
+ ExceptionStream exp_stream;
+ exp_stream.ThreadId =
+ static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
+ exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
+ exp_stream.ExceptionRecord = exp_record;
+ exp_stream.ThreadContext = thread_context_memory_locator;
+
+ m_data.AppendData(&exp_stream, minidump_exception_size);
+ m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
+ return error;
+}
+
+lldb_private::Status
+MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp) {
+ Status error;
+
+ if (error.Fail()) {
+ error.SetErrorString("Process doesn't support getting memory region info.");
+ return error;
+ }
+
+ // Get interesting addresses
+ std::vector<size_t> interesting_addresses;
+ auto thread_list = process_sp->GetThreadList();
+ for (size_t i = 0; i < thread_list.GetSize(); ++i) {
+ ThreadSP thread_sp(thread_list.GetThreadAtIndex(i));
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ RegisterContext *reg_ctx = reg_ctx_sp.get();
+
+ interesting_addresses.push_back(read_register_u64(reg_ctx, "rsp"));
+ interesting_addresses.push_back(read_register_u64(reg_ctx, "rip"));
+ }
+
+ DataBufferHeap helper_data;
+ std::vector<MemoryDescriptor> mem_descriptors;
+
+ std::set<addr_t> visited_region_base_addresses;
+ for (size_t interesting_address : interesting_addresses) {
+ MemoryRegionInfo range_info;
+ error = process_sp->GetMemoryRegionInfo(interesting_address, range_info);
+ // Skip failed memory region requests or any regions with no permissions.
+ if (error.Fail() || range_info.GetLLDBPermissions() == 0)
+ continue;
+ const addr_t addr = range_info.GetRange().GetRangeBase();
+ // Skip any regions we have already saved out.
+ if (visited_region_base_addresses.insert(addr).second == false)
+ continue;
+ const addr_t size = range_info.GetRange().GetByteSize();
+ if (size == 0)
+ continue;
+ auto data_up = std::make_unique<DataBufferHeap>(size, 0);
+ const size_t bytes_read =
+ process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
+ if (bytes_read == 0)
+ continue;
+ // We have a good memory region with valid bytes to store.
+ LocationDescriptor memory_dump;
+ memory_dump.DataSize = static_cast<llvm::support::ulittle32_t>(bytes_read);
+ memory_dump.RVA =
+ static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
+ MemoryDescriptor memory_desc;
+ memory_desc.StartOfMemoryRange =
+ static_cast<llvm::support::ulittle64_t>(addr);
+ memory_desc.Memory = memory_dump;
+ mem_descriptors.push_back(memory_desc);
+ m_data.AppendData(data_up->GetBytes(), bytes_read);
+ }
+
+ AddDirectory(StreamType::MemoryList,
+ sizeof(llvm::support::ulittle32_t) +
+ mem_descriptors.size() *
+ sizeof(llvm::minidump::MemoryDescriptor));
+ llvm::support::ulittle32_t memory_ranges_num(mem_descriptors.size());
+
+ m_data.AppendData(&memory_ranges_num, sizeof(llvm::support::ulittle32_t));
+ for (auto memory_descriptor : mem_descriptors) {
+ m_data.AppendData(&memory_descriptor,
+ sizeof(llvm::minidump::MemoryDescriptor));
+ }
+
+ return error;
+}
+
+void MinidumpFileBuilder::AddMiscInfo(const lldb::ProcessSP &process_sp) {
+ AddDirectory(StreamType::MiscInfo,
+ sizeof(lldb_private::minidump::MinidumpMiscInfo));
+
+ lldb_private::minidump::MinidumpMiscInfo misc_info;
+ misc_info.size = static_cast<llvm::support::ulittle32_t>(
+ sizeof(lldb_private::minidump::MinidumpMiscInfo));
+ // Default set flags1 to 0, in case that we will not be able to
+ // get any information
+ misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);
+
+ lldb_private::ProcessInstanceInfo process_info;
+ process_sp->GetProcessInfo(process_info);
+ if (process_info.ProcessIDIsValid()) {
+ // Set flags1 to reflect that PID is filled in
+ misc_info.flags1 =
+ static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
+ lldb_private::minidump::MinidumpMiscInfoFlags::ProcessID));
+ misc_info.process_id =
+ static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
+ }
+
+ m_data.AppendData(&misc_info,
+ sizeof(lldb_private::minidump::MinidumpMiscInfo));
+}
+
+std::unique_ptr<llvm::MemoryBuffer>
+getFileStreamHelper(const std::string &path) {
+ auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
+ if (!maybe_stream)
+ return nullptr;
+ return std::move(maybe_stream.get());
+}
+
+void MinidumpFileBuilder::AddLinuxFileStreams(
+ const lldb::ProcessSP &process_sp) {
+ std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
+ {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
+ {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
+ };
+
+ lldb_private::ProcessInstanceInfo process_info;
+ process_sp->GetProcessInfo(process_info);
+ if (process_info.ProcessIDIsValid()) {
+ lldb::pid_t pid = process_info.GetProcessID();
+ std::string pid_str = std::to_string(pid);
+ files_with_stream_types.push_back(
+ {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
+ files_with_stream_types.push_back(
+ {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
+ }
+
+ for (const auto &entry : files_with_stream_types) {
+ StreamType stream = entry.first;
+ std::string path = entry.second;
+ auto memory_buffer = getFileStreamHelper(path);
+
+ if (memory_buffer) {
+ size_t size = memory_buffer->getBufferSize();
+ if (size == 0)
+ continue;
+ AddDirectory(stream, size);
+ m_data.AppendData(memory_buffer->getBufferStart(), size);
+ }
+ }
+}
+
+Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const {
+ constexpr size_t header_size = sizeof(llvm::minidump::Header);
+ constexpr size_t directory_size = sizeof(llvm::minidump::Directory);
+
+ // write header
+ llvm::minidump::Header header;
+ header.Signature = static_cast<llvm::support::ulittle32_t>(
+ llvm::minidump::Header::MagicSignature);
+ header.Version = static_cast<llvm::support::ulittle32_t>(
+ llvm::minidump::Header::MagicVersion);
+ header.NumberOfStreams =
+ static_cast<llvm::support::ulittle32_t>(GetDirectoriesNum());
+ header.StreamDirectoryRVA =
+ static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());
+ header.Checksum = static_cast<llvm::support::ulittle32_t>(
+ 0u), // not used in most of the writers
+ header.TimeDateStamp =
+ static_cast<llvm::support::ulittle32_t>(std::time(0));
+ header.Flags =
+ static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag
+
+ Status error;
+ size_t bytes_written;
+
+ bytes_written = header_size;
+ error = core_file->Write(&header, bytes_written);
+ if (error.Fail() || bytes_written != header_size) {
+ if (bytes_written != header_size)
+ error.SetErrorStringWithFormat(
+ "unable to write the header (written %zd/%zd)", bytes_written,
+ header_size);
+ return error;
+ }
+
+ // write data
+ bytes_written = m_data.GetByteSize();
+ error = core_file->Write(m_data.GetBytes(), bytes_written);
+ if (error.Fail() || bytes_written != m_data.GetByteSize()) {
+ if (bytes_written != m_data.GetByteSize())
+ error.SetErrorStringWithFormat(
+ "unable to write the data (written %zd/%" PRIu64 ")", bytes_written,
+ m_data.GetByteSize());
+ return error;
+ }
+
+ // write directories
+ for (const Directory &dir : m_directories) {
+ bytes_written = directory_size;
+ error = core_file->Write(&dir, bytes_written);
+ if (error.Fail() || bytes_written != directory_size) {
+ if (bytes_written != directory_size)
+ error.SetErrorStringWithFormat(
+ "unable to write the directory (written %zd/%zd)", bytes_written,
+ directory_size);
+ return error;
+ }
+ }
+
+ return error;
+}
+
+size_t MinidumpFileBuilder::GetDirectoriesNum() const {
+ return m_directories.size();
+}
+
+size_t MinidumpFileBuilder::GetCurrentDataEndOffset() const {
+ return sizeof(llvm::minidump::Header) + m_data.GetByteSize();
+}
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
new file mode 100644
index 000000000000..f4017fb66384
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
@@ -0,0 +1,92 @@
+//===-- MinidumpFileBuilder.h ---------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Structure holding data neccessary for minidump file creation.
+///
+/// The class MinidumpFileWriter is used to hold the data that will eventually
+/// be dumped to the file.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H
+
+#include <cstddef>
+
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Status.h"
+
+#include "llvm/Object/Minidump.h"
+
+// Write std::string to minidump in the UTF16 format(with null termination char)
+// with the size(without null termination char) preceding the UTF16 string.
+// Empty strings are also printed with zero length and just null termination
+// char.
+lldb_private::Status WriteString(const std::string &to_write,
+ lldb_private::DataBufferHeap *buffer);
+
+/// \class MinidumpFileBuilder
+/// Minidump writer for Linux
+///
+/// This class provides a Minidump writer that is able to
+/// snapshot the current process state. For the whole time, it stores all
+/// the data on heap.
+class MinidumpFileBuilder {
+public:
+ MinidumpFileBuilder() = default;
+
+ MinidumpFileBuilder(const MinidumpFileBuilder &) = delete;
+ MinidumpFileBuilder &operator=(const MinidumpFileBuilder &) = delete;
+
+ MinidumpFileBuilder(MinidumpFileBuilder &&other) = default;
+ MinidumpFileBuilder &operator=(MinidumpFileBuilder &&other) = default;
+
+ ~MinidumpFileBuilder() = default;
+
+ // Add SystemInfo stream, used for storing the most basic information
+ // about the system, platform etc...
+ lldb_private::Status AddSystemInfo(const llvm::Triple &target_triple);
+ // Add ModuleList stream, containing information about all loaded modules
+ // at the time of saving minidump.
+ lldb_private::Status AddModuleList(lldb_private::Target &target);
+ // Add ThreadList stream, containing information about all threads running
+ // at the moment of core saving. Contains information about thread
+ // contexts.
+ lldb_private::Status AddThreadList(const lldb::ProcessSP &process_sp);
+ // Add Exception stream, this contains information about the exception
+ // that stopped the process. In case no thread made exception it return
+ // failed status.
+ lldb_private::Status AddException(const lldb::ProcessSP &process_sp);
+ // Add MemoryList stream, containing dumps of important memory segments
+ lldb_private::Status AddMemoryList(const lldb::ProcessSP &process_sp);
+ // Add MiscInfo stream, mainly providing ProcessId
+ void AddMiscInfo(const lldb::ProcessSP &process_sp);
+ // Add informative files about a Linux process
+ void AddLinuxFileStreams(const lldb::ProcessSP &process_sp);
+ // Dump the prepared data into file. In case of the failure data are
+ // intact.
+ lldb_private::Status Dump(lldb::FileUP &core_file) const;
+ // Returns the current number of directories(streams) that have been so far
+ // created. This number of directories will be dumped when calling Dump()
+ size_t GetDirectoriesNum() const;
+
+private:
+ // Add directory of StreamType pointing to the current end of the prepared
+ // file with the specified size.
+ void AddDirectory(llvm::minidump::StreamType type, size_t stream_size);
+ size_t GetCurrentDataEndOffset() const;
+
+ // Stores directories to later put them at the end of minidump file
+ std::vector<llvm::minidump::Directory> m_directories;
+ // Main data buffer consisting of data without the minidump header and
+ // directories
+ lldb_private::DataBufferHeap m_data;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
new file mode 100644
index 000000000000..715ccd311dee
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
@@ -0,0 +1,114 @@
+//===-- ObjectFileMinidump.cpp --------------------------------------------===//
+//
+// 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 "ObjectFileMinidump.h"
+
+#include "MinidumpFileBuilder.h"
+
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/Process.h"
+
+#include "llvm/Support/FileSystem.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ObjectFileMinidump)
+
+void ObjectFileMinidump::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications, SaveCore);
+}
+
+void ObjectFileMinidump::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ObjectFile *ObjectFileMinidump::CreateInstance(
+ const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length) {
+ return nullptr;
+}
+
+ObjectFile *ObjectFileMinidump::CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ const ProcessSP &process_sp, lldb::addr_t header_addr) {
+ return nullptr;
+}
+
+size_t ObjectFileMinidump::GetModuleSpecifications(
+ const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, lldb::offset_t file_offset,
+ lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
+ specs.Clear();
+ return 0;
+}
+
+bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp,
+ const lldb_private::FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style,
+ lldb_private::Status &error) {
+ if (core_style != SaveCoreStyle::eSaveCoreStackOnly) {
+ error.SetErrorString("Only stack minidumps supported yet.");
+ return false;
+ }
+
+ if (!process_sp)
+ return false;
+
+ MinidumpFileBuilder builder;
+
+ Target &target = process_sp->GetTarget();
+
+ error = builder.AddSystemInfo(target.GetArchitecture().GetTriple());
+ if (error.Fail())
+ return false;
+
+ error = builder.AddModuleList(target);
+ if (error.Fail())
+ return false;
+
+ builder.AddMiscInfo(process_sp);
+
+ if (target.GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86_64) {
+ error = builder.AddThreadList(process_sp);
+ if (error.Fail())
+ return false;
+
+ error = builder.AddException(process_sp);
+ if (error.Fail())
+ return false;
+
+ error = builder.AddMemoryList(process_sp);
+ if (error.Fail())
+ return false;
+ }
+
+ if (target.GetArchitecture().GetTriple().getOS() ==
+ llvm::Triple::OSType::Linux) {
+ builder.AddLinuxFileStreams(process_sp);
+ }
+
+ llvm::Expected<lldb::FileUP> maybe_core_file = FileSystem::Instance().Open(
+ outfile, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
+ if (!maybe_core_file) {
+ error = maybe_core_file.takeError();
+ return false;
+ }
+ lldb::FileUP core_file = std::move(maybe_core_file.get());
+
+ error = builder.Dump(core_file);
+ if (error.Fail())
+ return false;
+
+ return true;
+}
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
new file mode 100644
index 000000000000..3e4d55dc6c8c
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
@@ -0,0 +1,66 @@
+//===-- ObjectFileMinidump.h ---------------------------------- -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Placeholder plugin for the save core functionality.
+///
+/// ObjectFileMinidump is created only to be able to save minidump core files
+/// from existing processes with the ObjectFileMinidump::SaveCore function.
+/// Minidump files are not ObjectFile objects, but they are core files and
+/// currently LLDB's ObjectFile plug-ins handle emitting core files. If the
+/// core file saving ever moves into a new plug-in type within LLDB, this code
+/// should move as well, but for now this is the best place architecturally.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_OBJECTFILEMINIDUMP_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_OBJECTFILEMINIDUMP_H
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+
+class ObjectFileMinidump : public lldb_private::PluginInterface {
+public:
+ // Static Functions
+ static void Initialize();
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "minidump"; }
+ static const char *GetPluginDescriptionStatic() {
+ return "Minidump object file.";
+ }
+
+ // PluginInterface protocol
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+ static lldb_private::ObjectFile *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ static lldb_private::ObjectFile *CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+ static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ // Saves dump in Minidump file format
+ static bool SaveCore(const lldb::ProcessSP &process_sp,
+ const lldb_private::FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style,
+ lldb_private::Status &error);
+
+private:
+ ObjectFileMinidump() = default;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_OBJECTFILEMINIDUMP_H
diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
index cb7bbeeca054..b63cd8e70899 100644
--- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
+++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
@@ -46,11 +46,6 @@ void ObjectFilePDB::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-ConstString ObjectFilePDB::GetPluginNameStatic() {
- static ConstString g_name("pdb");
- return g_name;
-}
-
ArchSpec ObjectFilePDB::GetArchitecture() {
auto dbi_stream = m_file_up->getPDBDbiStream();
if (!dbi_stream) {
diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
index 19dd46b31406..36e71e21332f 100644
--- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
+++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
@@ -22,7 +22,7 @@ public:
static void Initialize();
static void Terminate();
- static ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "pdb"; }
static const char *GetPluginDescriptionStatic() {
return "PDB object file reader.";
}
@@ -48,9 +48,7 @@ public:
ModuleSpecList &specs);
// PluginInterface protocol
- ConstString GetPluginName() override { return GetPluginNameStatic(); }
-
- uint32_t GetPluginVersion() override { return 1; }
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
// LLVM RTTI support
static char ID;
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 5272da9ab33a..0e6329885528 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -86,11 +86,6 @@ void ObjectFileWasm::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-ConstString ObjectFileWasm::GetPluginNameStatic() {
- static ConstString g_name("wasm");
- return g_name;
-}
-
ObjectFile *
ObjectFileWasm::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp,
offset_t data_offset, const FileSpec *file,
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
index b6e906a7b15f..44939b6d4ea0 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
@@ -24,7 +24,7 @@ public:
static void Initialize();
static void Terminate();
- static ConstString GetPluginNameStatic();
+ static llvm::StringRef GetPluginNameStatic() { return "wasm"; }
static const char *GetPluginDescriptionStatic() {
return "WebAssembly object file reader.";
}
@@ -48,8 +48,7 @@ public:
/// PluginInterface protocol.
/// \{
- ConstString GetPluginName() override { return GetPluginNameStatic(); }
- uint32_t GetPluginVersion() override { return 1; }
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
/// \}
/// LLVM RTTI support