summaryrefslogtreecommitdiff
path: root/source/Plugins/ObjectFile
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ObjectFile')
-rw-r--r--source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp411
-rw-r--r--source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h163
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp197
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h16
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp47
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.h99
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp410
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h36
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp61
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.h17
10 files changed, 863 insertions, 594 deletions
diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
new file mode 100644
index 0000000000000..d489eaf11115a
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
@@ -0,0 +1,411 @@
+//===-- BreakpadRecords.cpp ----------------------------------- -*- 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 "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace lldb_private;
+using namespace lldb_private::breakpad;
+
+namespace {
+enum class Token { Unknown, Module, Info, CodeID, File, Func, Public, Stack, CFI, Init };
+}
+
+template<typename T>
+static T stringTo(llvm::StringRef Str);
+
+template <> Token stringTo<Token>(llvm::StringRef Str) {
+ return llvm::StringSwitch<Token>(Str)
+ .Case("MODULE", Token::Module)
+ .Case("INFO", Token::Info)
+ .Case("CODE_ID", Token::CodeID)
+ .Case("FILE", Token::File)
+ .Case("FUNC", Token::Func)
+ .Case("PUBLIC", Token::Public)
+ .Case("STACK", Token::Stack)
+ .Case("CFI", Token::CFI)
+ .Case("INIT", Token::Init)
+ .Default(Token::Unknown);
+}
+
+template <>
+llvm::Triple::OSType stringTo<llvm::Triple::OSType>(llvm::StringRef Str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::OSType>(Str)
+ .Case("Linux", Triple::Linux)
+ .Case("mac", Triple::MacOSX)
+ .Case("windows", Triple::Win32)
+ .Default(Triple::UnknownOS);
+}
+
+template <>
+llvm::Triple::ArchType stringTo<llvm::Triple::ArchType>(llvm::StringRef Str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::ArchType>(Str)
+ .Case("arm", Triple::arm)
+ .Cases("arm64", "arm64e", Triple::aarch64)
+ .Case("mips", Triple::mips)
+ .Case("ppc", Triple::ppc)
+ .Case("ppc64", Triple::ppc64)
+ .Case("s390", Triple::systemz)
+ .Case("sparc", Triple::sparc)
+ .Case("sparcv9", Triple::sparcv9)
+ .Case("x86", Triple::x86)
+ .Case("x86_64", Triple::x86_64)
+ .Default(Triple::UnknownArch);
+}
+
+template<typename T>
+static T consume(llvm::StringRef &Str) {
+ llvm::StringRef Token;
+ std::tie(Token, Str) = getToken(Str);
+ return stringTo<T>(Token);
+}
+
+/// Return the number of hex digits needed to encode an (POD) object of a given
+/// type.
+template <typename T> static constexpr size_t hex_digits() {
+ return 2 * sizeof(T);
+}
+
+static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) {
+ struct data_t {
+ using uuid_t = uint8_t[16];
+ uuid_t uuid;
+ llvm::support::ubig32_t age;
+ } data;
+ static_assert(sizeof(data) == 20, "");
+ // The textual module id encoding should be between 33 and 40 bytes long,
+ // depending on the size of the age field, which is of variable length.
+ // The first three chunks of the id are encoded in big endian, so we need to
+ // byte-swap those.
+ if (str.size() <= hex_digits<data_t::uuid_t>() ||
+ str.size() > hex_digits<data_t>())
+ return UUID();
+ if (!all_of(str, llvm::isHexDigit))
+ return UUID();
+
+ llvm::StringRef uuid_str = str.take_front(hex_digits<data_t::uuid_t>());
+ llvm::StringRef age_str = str.drop_front(hex_digits<data_t::uuid_t>());
+
+ llvm::copy(fromHex(uuid_str), data.uuid);
+ uint32_t age;
+ bool success = to_integer(age_str, age, 16);
+ assert(success);
+ (void)success;
+ data.age = age;
+
+ // On non-windows, the age field should always be zero, so we don't include to
+ // match the native uuid format of these platforms.
+ return UUID::fromData(&data, os == llvm::Triple::Win32 ? sizeof(data)
+ : sizeof(data.uuid));
+}
+
+llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) {
+ Token Tok = consume<Token>(Line);
+ switch (Tok) {
+ case Token::Module:
+ return Record::Module;
+ case Token::Info:
+ return Record::Info;
+ case Token::File:
+ return Record::File;
+ case Token::Func:
+ return Record::Func;
+ case Token::Public:
+ return Record::Public;
+ case Token::Stack:
+ Tok = consume<Token>(Line);
+ switch (Tok) {
+ case Token::CFI:
+ return Record::StackCFI;
+ default:
+ return llvm::None;
+ }
+
+ 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
+ // hex number. CODE_ID should never be at the start of a line, but if it
+ // is, it can be treated the same way as a garbled line record.
+ return Record::Line;
+
+ case Token::CodeID:
+ case Token::CFI:
+ case Token::Init:
+ // These should never appear at the start of a valid record.
+ return llvm::None;
+ }
+ llvm_unreachable("Fully covered switch above!");
+}
+
+llvm::Optional<ModuleRecord> ModuleRecord::parse(llvm::StringRef Line) {
+ // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out
+ if (consume<Token>(Line) != Token::Module)
+ return llvm::None;
+
+ llvm::Triple::OSType OS = consume<llvm::Triple::OSType>(Line);
+ if (OS == llvm::Triple::UnknownOS)
+ return llvm::None;
+
+ llvm::Triple::ArchType Arch = consume<llvm::Triple::ArchType>(Line);
+ if (Arch == llvm::Triple::UnknownArch)
+ return llvm::None;
+
+ llvm::StringRef Str;
+ std::tie(Str, Line) = getToken(Line);
+ UUID ID = parseModuleId(OS, Str);
+ if (!ID)
+ return llvm::None;
+
+ return ModuleRecord(OS, Arch, std::move(ID));
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const ModuleRecord &R) {
+ return OS << "MODULE " << llvm::Triple::getOSTypeName(R.OS) << " "
+ << llvm::Triple::getArchTypeName(R.Arch) << " "
+ << R.ID.GetAsString();
+}
+
+llvm::Optional<InfoRecord> InfoRecord::parse(llvm::StringRef Line) {
+ // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe]
+ if (consume<Token>(Line) != Token::Info)
+ return llvm::None;
+
+ if (consume<Token>(Line) != Token::CodeID)
+ return llvm::None;
+
+ llvm::StringRef Str;
+ std::tie(Str, Line) = getToken(Line);
+ // If we don't have any text following the code ID (e.g. on linux), we should
+ // use this as the UUID. Otherwise, we should revert back to the module ID.
+ UUID ID;
+ if (Line.trim().empty()) {
+ if (Str.empty() || ID.SetFromStringRef(Str, Str.size() / 2) != Str.size())
+ return llvm::None;
+ }
+ return InfoRecord(std::move(ID));
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const InfoRecord &R) {
+ 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)
+ return llvm::None;
+
+ llvm::StringRef Str;
+ size_t Number;
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, Number))
+ return llvm::None;
+
+ llvm::StringRef Name = Line.trim();
+ if (Name.empty())
+ return llvm::None;
+
+ return FileRecord(Number, Name);
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const FileRecord &R) {
+ return OS << "FILE " << 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) {
+ // PUBLIC [m] address param_size name
+ // or
+ // FUNC [m] address size param_size name
+
+ Token Tok = Size ? Token::Func : Token::Public;
+
+ if (consume<Token>(Line) != Tok)
+ return false;
+
+ llvm::StringRef Str;
+ std::tie(Str, Line) = getToken(Line);
+ Multiple = Str == "m";
+
+ if (Multiple)
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, Address, 16))
+ return false;
+
+ if (Tok == Token::Func) {
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, *Size, 16))
+ return false;
+ }
+
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, ParamSize, 16))
+ return false;
+
+ Name = Line.trim();
+ if (Name.empty())
+ return false;
+
+ return true;
+}
+
+llvm::Optional<FuncRecord> FuncRecord::parse(llvm::StringRef Line) {
+ bool Multiple;
+ lldb::addr_t Address, Size, ParamSize;
+ llvm::StringRef Name;
+
+ if (parsePublicOrFunc(Line, Multiple, Address, &Size, ParamSize, Name))
+ return FuncRecord(Multiple, Address, Size, ParamSize, Name);
+
+ return llvm::None;
+}
+
+bool breakpad::operator==(const FuncRecord &L, const FuncRecord &R) {
+ return L.Multiple == R.Multiple && L.Address == R.Address &&
+ L.Size == R.Size && L.ParamSize == R.ParamSize && L.Name == R.Name;
+}
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const FuncRecord &R) {
+ return OS << llvm::formatv("FUNC {0}{1:x-} {2:x-} {3:x-} {4}",
+ R.Multiple ? "m " : "", R.Address, R.Size,
+ R.ParamSize, R.Name);
+}
+
+llvm::Optional<LineRecord> LineRecord::parse(llvm::StringRef Line) {
+ lldb::addr_t Address;
+ llvm::StringRef Str;
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, Address, 16))
+ return llvm::None;
+
+ lldb::addr_t Size;
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, Size, 16))
+ return llvm::None;
+
+ uint32_t LineNum;
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, LineNum))
+ return llvm::None;
+
+ size_t FileNum;
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, FileNum))
+ return llvm::None;
+
+ return LineRecord(Address, Size, LineNum, FileNum);
+}
+
+bool breakpad::operator==(const LineRecord &L, const LineRecord &R) {
+ return L.Address == R.Address && L.Size == R.Size && L.LineNum == R.LineNum &&
+ L.FileNum == R.FileNum;
+}
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const LineRecord &R) {
+ return OS << llvm::formatv("{0:x-} {1:x-} {2} {3}", R.Address, R.Size,
+ R.LineNum, R.FileNum);
+}
+
+llvm::Optional<PublicRecord> PublicRecord::parse(llvm::StringRef Line) {
+ bool Multiple;
+ lldb::addr_t Address, ParamSize;
+ llvm::StringRef Name;
+
+ if (parsePublicOrFunc(Line, Multiple, Address, nullptr, ParamSize, Name))
+ return PublicRecord(Multiple, Address, ParamSize, Name);
+
+ return llvm::None;
+}
+
+bool breakpad::operator==(const PublicRecord &L, const PublicRecord &R) {
+ return L.Multiple == R.Multiple && L.Address == R.Address &&
+ L.ParamSize == R.ParamSize && L.Name == R.Name;
+}
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const PublicRecord &R) {
+ return OS << llvm::formatv("PUBLIC {0}{1:x-} {2:x-} {3}",
+ R.Multiple ? "m " : "", R.Address, R.ParamSize,
+ R.Name);
+}
+
+llvm::Optional<StackCFIRecord> StackCFIRecord::parse(llvm::StringRef Line) {
+ // STACK CFI INIT address size reg1: expr1 reg2: expr2 ...
+ // or
+ // STACK CFI address reg1: expr1 reg2: expr2 ...
+ // No token in exprN ends with a colon.
+
+ if (consume<Token>(Line) != Token::Stack)
+ return llvm::None;
+ if (consume<Token>(Line) != Token::CFI)
+ return llvm::None;
+
+ llvm::StringRef Str;
+ std::tie(Str, Line) = getToken(Line);
+
+ bool IsInitRecord = stringTo<Token>(Str) == Token::Init;
+ if (IsInitRecord)
+ std::tie(Str, Line) = getToken(Line);
+
+ lldb::addr_t Address;
+ if (!to_integer(Str, Address, 16))
+ return llvm::None;
+
+ llvm::Optional<lldb::addr_t> Size;
+ if (IsInitRecord) {
+ Size.emplace();
+ std::tie(Str, Line) = getToken(Line);
+ if (!to_integer(Str, *Size, 16))
+ return llvm::None;
+ }
+
+ return StackCFIRecord(Address, Size, Line.trim());
+}
+
+bool breakpad::operator==(const StackCFIRecord &L, const StackCFIRecord &R) {
+ return L.Address == R.Address && L.Size == R.Size &&
+ L.UnwindRules == R.UnwindRules;
+}
+
+llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS,
+ const StackCFIRecord &R) {
+ OS << "STACK CFI ";
+ if (R.Size)
+ OS << "INIT ";
+ OS << llvm::formatv("{0:x-} ", R.Address);
+ if (R.Size)
+ OS << llvm::formatv("{0:x-} ", *R.Size);
+ return OS << " " << R.UnwindRules;
+}
+
+llvm::StringRef breakpad::toString(Record::Kind K) {
+ switch (K) {
+ case Record::Module:
+ return "MODULE";
+ case Record::Info:
+ return "INFO";
+ case Record::File:
+ return "FILE";
+ case Record::Func:
+ return "FUNC";
+ case Record::Line:
+ return "LINE";
+ case Record::Public:
+ return "PUBLIC";
+ case Record::StackCFI:
+ return "STACK CFI";
+ }
+ llvm_unreachable("Unknown record kind!");
+}
diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
new file mode 100644
index 0000000000000..5d5cdb319c10e
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
@@ -0,0 +1,163 @@
+//===-- BreakpadRecords.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_OBJECTFILE_BREAKPAD_BREAKPADRECORDS_H
+#define LLDB_PLUGINS_OBJECTFILE_BREAKPAD_BREAKPADRECORDS_H
+
+#include "lldb/Utility/UUID.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/FormatProviders.h"
+
+namespace lldb_private {
+namespace breakpad {
+
+class Record {
+public:
+ enum Kind { Module, Info, File, Func, Line, Public, StackCFI };
+
+ /// 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
+ /// records, but the full parse can still fail in case of corrupted input.
+ static llvm::Optional<Kind> classify(llvm::StringRef Line);
+
+protected:
+ Record(Kind K) : TheKind(K) {}
+
+ ~Record() = default;
+
+public:
+ Kind getKind() { return TheKind; }
+
+private:
+ Kind TheKind;
+};
+
+llvm::StringRef toString(Record::Kind K);
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Record::Kind K) {
+ OS << toString(K);
+ return OS;
+}
+
+class ModuleRecord : public Record {
+public:
+ static llvm::Optional<ModuleRecord> parse(llvm::StringRef Line);
+ ModuleRecord(llvm::Triple::OSType OS, llvm::Triple::ArchType Arch, UUID ID)
+ : Record(Module), OS(OS), Arch(Arch), ID(std::move(ID)) {}
+
+ llvm::Triple::OSType OS;
+ llvm::Triple::ArchType Arch;
+ UUID ID;
+};
+
+inline bool operator==(const ModuleRecord &L, const ModuleRecord &R) {
+ return L.OS == R.OS && L.Arch == R.Arch && L.ID == R.ID;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ModuleRecord &R);
+
+class InfoRecord : public Record {
+public:
+ static llvm::Optional<InfoRecord> parse(llvm::StringRef Line);
+ InfoRecord(UUID ID) : Record(Info), ID(std::move(ID)) {}
+
+ UUID ID;
+};
+
+inline bool operator==(const InfoRecord &L, const InfoRecord &R) {
+ return L.ID == R.ID;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InfoRecord &R);
+
+class FileRecord : public Record {
+public:
+ static llvm::Optional<FileRecord> parse(llvm::StringRef Line);
+ FileRecord(size_t Number, llvm::StringRef Name)
+ : Record(File), Number(Number), Name(Name) {}
+
+ size_t Number;
+ llvm::StringRef Name;
+};
+
+inline bool operator==(const FileRecord &L, const FileRecord &R) {
+ return L.Number == R.Number && L.Name == R.Name;
+}
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FileRecord &R);
+
+class FuncRecord : public Record {
+public:
+ static llvm::Optional<FuncRecord> parse(llvm::StringRef Line);
+ FuncRecord(bool Multiple, lldb::addr_t Address, lldb::addr_t Size,
+ lldb::addr_t ParamSize, llvm::StringRef Name)
+ : Record(Module), Multiple(Multiple), Address(Address), Size(Size),
+ ParamSize(ParamSize), Name(Name) {}
+
+ bool Multiple;
+ lldb::addr_t Address;
+ lldb::addr_t Size;
+ lldb::addr_t ParamSize;
+ llvm::StringRef Name;
+};
+
+bool operator==(const FuncRecord &L, const FuncRecord &R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FuncRecord &R);
+
+class LineRecord : public Record {
+public:
+ static llvm::Optional<LineRecord> parse(llvm::StringRef Line);
+ LineRecord(lldb::addr_t Address, lldb::addr_t Size, uint32_t LineNum,
+ size_t FileNum)
+ : Record(Line), Address(Address), Size(Size), LineNum(LineNum),
+ FileNum(FileNum) {}
+
+ lldb::addr_t Address;
+ lldb::addr_t Size;
+ uint32_t LineNum;
+ size_t FileNum;
+};
+
+bool operator==(const LineRecord &L, const LineRecord &R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LineRecord &R);
+
+class PublicRecord : public Record {
+public:
+ static llvm::Optional<PublicRecord> parse(llvm::StringRef Line);
+ PublicRecord(bool Multiple, lldb::addr_t Address, lldb::addr_t ParamSize,
+ llvm::StringRef Name)
+ : Record(Module), Multiple(Multiple), Address(Address),
+ ParamSize(ParamSize), Name(Name) {}
+
+ bool Multiple;
+ lldb::addr_t Address;
+ lldb::addr_t ParamSize;
+ llvm::StringRef Name;
+};
+
+bool operator==(const PublicRecord &L, const PublicRecord &R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PublicRecord &R);
+
+class StackCFIRecord : public Record {
+public:
+ static llvm::Optional<StackCFIRecord> parse(llvm::StringRef Line);
+ StackCFIRecord(lldb::addr_t Address, llvm::Optional<lldb::addr_t> Size,
+ llvm::StringRef UnwindRules)
+ : Record(StackCFI), Address(Address), Size(Size),
+ UnwindRules(UnwindRules) {}
+
+ lldb::addr_t Address;
+ llvm::Optional<lldb::addr_t> Size;
+ llvm::StringRef UnwindRules;
+};
+
+bool operator==(const StackCFIRecord &L, const StackCFIRecord &R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackCFIRecord &R);
+
+} // namespace breakpad
+} // namespace lldb_private
+
+#endif // LLDB_PLUGINS_OBJECTFILE_BREAKPAD_BREAKPADRECORDS_H
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
index 917025030ada4..60dd9f9cecf0f 100644
--- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
@@ -1,18 +1,16 @@
//===-- ObjectFileBreakpad.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
//
//===----------------------------------------------------------------------===//
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
+#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Utility/DataBuffer.h"
-#include "llvm/ADT/StringExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -24,164 +22,24 @@ struct Header {
UUID uuid;
static llvm::Optional<Header> parse(llvm::StringRef text);
};
-
-enum class Token { Unknown, Module, Info, File, Func, Public, Stack };
} // namespace
-static Token toToken(llvm::StringRef str) {
- return llvm::StringSwitch<Token>(str)
- .Case("MODULE", Token::Module)
- .Case("INFO", Token::Info)
- .Case("FILE", Token::File)
- .Case("FUNC", Token::Func)
- .Case("PUBLIC", Token::Public)
- .Case("STACK", Token::Stack)
- .Default(Token::Unknown);
-}
-
-static llvm::StringRef toString(Token t) {
- switch (t) {
- case Token::Unknown:
- return "";
- case Token::Module:
- return "MODULE";
- case Token::Info:
- return "INFO";
- case Token::File:
- return "FILE";
- case Token::Func:
- return "FUNC";
- case Token::Public:
- return "PUBLIC";
- case Token::Stack:
- return "STACK";
- }
- llvm_unreachable("Unknown token!");
-}
-
-static llvm::Triple::OSType toOS(llvm::StringRef str) {
- using llvm::Triple;
- return llvm::StringSwitch<Triple::OSType>(str)
- .Case("Linux", Triple::Linux)
- .Case("mac", Triple::MacOSX)
- .Case("windows", Triple::Win32)
- .Default(Triple::UnknownOS);
-}
-
-static llvm::Triple::ArchType toArch(llvm::StringRef str) {
- using llvm::Triple;
- return llvm::StringSwitch<Triple::ArchType>(str)
- .Case("arm", Triple::arm)
- .Case("arm64", Triple::aarch64)
- .Case("mips", Triple::mips)
- .Case("ppc", Triple::ppc)
- .Case("ppc64", Triple::ppc64)
- .Case("s390", Triple::systemz)
- .Case("sparc", Triple::sparc)
- .Case("sparcv9", Triple::sparcv9)
- .Case("x86", Triple::x86)
- .Case("x86_64", Triple::x86_64)
- .Default(Triple::UnknownArch);
-}
-
-static llvm::StringRef consume_front(llvm::StringRef &str, size_t n) {
- llvm::StringRef result = str.take_front(n);
- str = str.drop_front(n);
- return result;
-}
-
-static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) {
- struct uuid_data {
- llvm::support::ulittle32_t uuid1;
- llvm::support::ulittle16_t uuid2[2];
- uint8_t uuid3[8];
- llvm::support::ulittle32_t age;
- } data;
- static_assert(sizeof(data) == 20, "");
- // The textual module id encoding should be between 33 and 40 bytes long,
- // depending on the size of the age field, which is of variable length.
- // The first three chunks of the id are encoded in big endian, so we need to
- // byte-swap those.
- if (str.size() < 33 || str.size() > 40)
- return UUID();
- uint32_t t;
- if (to_integer(consume_front(str, 8), t, 16))
- data.uuid1 = t;
- else
- return UUID();
- for (int i = 0; i < 2; ++i) {
- if (to_integer(consume_front(str, 4), t, 16))
- data.uuid2[i] = t;
- else
- return UUID();
- }
- for (int i = 0; i < 8; ++i) {
- if (!to_integer(consume_front(str, 2), data.uuid3[i], 16))
- return UUID();
- }
- if (to_integer(str, t, 16))
- data.age = t;
- else
- return UUID();
-
- // On non-windows, the age field should always be zero, so we don't include to
- // match the native uuid format of these platforms.
- return UUID::fromData(&data, os == llvm::Triple::Win32 ? 20 : 16);
-}
-
llvm::Optional<Header> Header::parse(llvm::StringRef text) {
- // A valid module should start with something like:
- // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out
- // optionally followed by
- // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe]
- llvm::StringRef token, line;
+ llvm::StringRef line;
std::tie(line, text) = text.split('\n');
- std::tie(token, line) = getToken(line);
- if (toToken(token) != Token::Module)
+ auto Module = ModuleRecord::parse(line);
+ if (!Module)
return llvm::None;
- std::tie(token, line) = getToken(line);
llvm::Triple triple;
- triple.setOS(toOS(token));
- if (triple.getOS() == llvm::Triple::UnknownOS)
- return llvm::None;
-
- std::tie(token, line) = getToken(line);
- triple.setArch(toArch(token));
- if (triple.getArch() == llvm::Triple::UnknownArch)
- return llvm::None;
-
- llvm::StringRef module_id;
- std::tie(module_id, line) = getToken(line);
+ triple.setArch(Module->Arch);
+ triple.setOS(Module->OS);
std::tie(line, text) = text.split('\n');
- std::tie(token, line) = getToken(line);
- if (token == "INFO") {
- std::tie(token, line) = getToken(line);
- if (token != "CODE_ID")
- return llvm::None;
- std::tie(token, line) = getToken(line);
- // If we don't have any text following the code id (e.g. on linux), we
- // should use the module id as UUID. Otherwise, we revert back to the module
- // id.
- if (line.trim().empty()) {
- UUID uuid;
- if (uuid.SetFromStringRef(token, token.size() / 2) != token.size())
- return llvm::None;
-
- return Header{ArchSpec(triple), uuid};
- }
- }
-
- // We reach here if we don't have a INFO CODE_ID section, or we chose not to
- // use it. In either case, we need to properly decode the module id, whose
- // fields are encoded in big-endian.
- UUID uuid = parseModuleId(triple.getOS(), module_id);
- if (!uuid)
- return llvm::None;
-
- return Header{ArchSpec(triple), uuid};
+ auto Info = InfoRecord::parse(line);
+ UUID uuid = Info && Info->ID ? Info->ID : Module->ID;
+ return Header{ArchSpec(triple), std::move(uuid)};
}
void ObjectFileBreakpad::Initialize() {
@@ -264,50 +122,45 @@ Symtab *ObjectFileBreakpad::GetSymtab() {
return nullptr;
}
-bool ObjectFileBreakpad::GetUUID(UUID *uuid) {
- *uuid = m_uuid;
- return true;
-}
-
void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
- if (m_sections_ap)
+ if (m_sections_up)
return;
- m_sections_ap = llvm::make_unique<SectionList>();
+ m_sections_up = llvm::make_unique<SectionList>();
- Token current_section = Token::Unknown;
+ llvm::Optional<Record::Kind> current_section;
offset_t section_start;
llvm::StringRef text = toStringRef(m_data.GetData());
uint32_t next_section_id = 1;
auto maybe_add_section = [&](const uint8_t *end_ptr) {
- if (current_section == Token::Unknown)
+ if (!current_section)
return; // We have been called before parsing the first line.
offset_t end_offset = end_ptr - m_data.GetDataStart();
auto section_sp = std::make_shared<Section>(
GetModule(), this, next_section_id++,
- ConstString(toString(current_section)), eSectionTypeOther,
+ ConstString(toString(*current_section)), eSectionTypeOther,
/*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
- m_sections_ap->AddSection(section_sp);
+ m_sections_up->AddSection(section_sp);
unified_section_list.AddSection(section_sp);
};
while (!text.empty()) {
llvm::StringRef line;
std::tie(line, text) = text.split('\n');
- Token token = toToken(getToken(line).first);
- if (token == Token::Unknown) {
- // We assume this is a line record, which logically belongs to the Func
- // section. Errors will be handled when parsing the Func section.
- token = Token::Func;
+ 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.
+ next_section = Record::Func;
}
- if (token == current_section)
+ if (next_section == current_section)
continue;
// Changing sections, finish off the previous one, if there was any.
maybe_add_section(line.bytes_begin());
// And start a new one.
- current_section = token;
+ current_section = next_section;
section_start = line.bytes_begin() - m_data.GetDataStart();
}
// Finally, add the last section.
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
index ba2a3ad30e5f9..e8885e0cc8982 100644
--- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
@@ -1,9 +1,8 @@
//===-- ObjectFileBreakpad.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
//
//===----------------------------------------------------------------------===//
@@ -12,16 +11,13 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/ArchSpec.h"
-#include "llvm/ADT/Triple.h"
namespace lldb_private {
namespace breakpad {
class ObjectFileBreakpad : public ObjectFile {
public:
- //------------------------------------------------------------------
// Static Functions
- //------------------------------------------------------------------
static void Initialize();
static void Terminate();
@@ -47,16 +43,12 @@ public:
lldb::offset_t length,
ModuleSpecList &specs);
- //------------------------------------------------------------------
// PluginInterface protocol
- //------------------------------------------------------------------
ConstString GetPluginName() override { return GetPluginNameStatic(); }
uint32_t GetPluginVersion() override { return 1; }
- //------------------------------------------------------------------
// ObjectFile Protocol.
- //------------------------------------------------------------------
bool ParseHeader() override;
@@ -84,7 +76,7 @@ public:
ArchSpec GetArchitecture() override { return m_arch; }
- bool GetUUID(UUID *uuid) override;
+ UUID GetUUID() override { return m_uuid; }
FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); }
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index 3d4735286bf2a..aa9871071b0e0 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -1,9 +1,8 @@
//===-- ELFHeader.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
//
//===----------------------------------------------------------------------===//
@@ -19,7 +18,6 @@ using namespace elf;
using namespace lldb;
using namespace llvm::ELF;
-//------------------------------------------------------------------------------
// Static utility functions.
//
// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
@@ -68,7 +66,6 @@ static bool GetMaxS64(const lldb_private::DataExtractor &data,
return true;
}
-//------------------------------------------------------------------------------
// ELFHeader
ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
@@ -117,7 +114,7 @@ void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) {
bool ELFHeader::Parse(lldb_private::DataExtractor &data,
lldb::offset_t *offset) {
// Read e_ident. This provides byte order and address size info.
- if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
+ if (data.GetU8(offset, &e_ident, EI_NIDENT) == nullptr)
return false;
const unsigned byte_size = Is32Bit() ? 4 : 8;
@@ -125,11 +122,11 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
data.SetAddressByteSize(byte_size);
// Read e_type and e_machine.
- if (data.GetU16(offset, &e_type, 2) == NULL)
+ if (data.GetU16(offset, &e_type, 2) == nullptr)
return false;
// Read e_version.
- if (data.GetU32(offset, &e_version, 1) == NULL)
+ if (data.GetU32(offset, &e_version, 1) == nullptr)
return false;
// Read e_entry, e_phoff and e_shoff.
@@ -137,11 +134,11 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
return false;
// Read e_flags.
- if (data.GetU32(offset, &e_flags, 1) == NULL)
+ if (data.GetU32(offset, &e_flags, 1) == nullptr)
return false;
// Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
- if (data.GetU16(offset, &e_ehsize, 6) == NULL)
+ if (data.GetU16(offset, &e_ehsize, 6) == nullptr)
return false;
// Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
@@ -216,7 +213,6 @@ unsigned ELFHeader::GetRelocationJumpSlotType() const {
return slot;
}
-//------------------------------------------------------------------------------
// ELFSectionHeader
ELFSectionHeader::ELFSectionHeader() {
@@ -228,7 +224,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
const unsigned byte_size = data.GetAddressByteSize();
// Read sh_name and sh_type.
- if (data.GetU32(offset, &sh_name, 2) == NULL)
+ if (data.GetU32(offset, &sh_name, 2) == nullptr)
return false;
// Read sh_flags.
@@ -240,7 +236,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read sh_link and sh_info.
- if (data.GetU32(offset, &sh_link, 2) == NULL)
+ if (data.GetU32(offset, &sh_link, 2) == nullptr)
return false;
// Read sh_addralign and sh_entsize.
@@ -250,7 +246,6 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return true;
}
-//------------------------------------------------------------------------------
// ELFSymbol
ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
@@ -327,7 +322,7 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
const bool parsing_32 = byte_size == 4;
// Read st_name.
- if (data.GetU32(offset, &st_name, 1) == NULL)
+ if (data.GetU32(offset, &st_name, 1) == nullptr)
return false;
if (parsing_32) {
@@ -336,29 +331,28 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
return false;
// Read st_info and st_other.
- if (data.GetU8(offset, &st_info, 2) == NULL)
+ if (data.GetU8(offset, &st_info, 2) == nullptr)
return false;
// Read st_shndx.
- if (data.GetU16(offset, &st_shndx, 1) == NULL)
+ if (data.GetU16(offset, &st_shndx, 1) == nullptr)
return false;
} else {
// Read st_info and st_other.
- if (data.GetU8(offset, &st_info, 2) == NULL)
+ if (data.GetU8(offset, &st_info, 2) == nullptr)
return false;
// Read st_shndx.
- if (data.GetU16(offset, &st_shndx, 1) == NULL)
+ if (data.GetU16(offset, &st_shndx, 1) == nullptr)
return false;
// Read st_value and st_size.
- if (data.GetU64(offset, &st_value, 2) == NULL)
+ if (data.GetU64(offset, &st_value, 2) == nullptr)
return false;
}
return true;
}
-//------------------------------------------------------------------------------
// ELFProgramHeader
ELFProgramHeader::ELFProgramHeader() {
@@ -371,7 +365,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
const bool parsing_32 = byte_size == 4;
// Read p_type;
- if (data.GetU32(offset, &p_type, 1) == NULL)
+ if (data.GetU32(offset, &p_type, 1) == nullptr)
return false;
if (parsing_32) {
@@ -380,7 +374,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read p_flags.
- if (data.GetU32(offset, &p_flags, 1) == NULL)
+ if (data.GetU32(offset, &p_flags, 1) == nullptr)
return false;
// Read p_align.
@@ -388,7 +382,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
} else {
// Read p_flags.
- if (data.GetU32(offset, &p_flags, 1) == NULL)
+ if (data.GetU32(offset, &p_flags, 1) == nullptr)
return false;
// Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
@@ -399,7 +393,6 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return true;
}
-//------------------------------------------------------------------------------
// ELFDynamic
ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
@@ -410,7 +403,6 @@ bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
return GetMaxS64(data, offset, &d_tag, byte_size, 2);
}
-//------------------------------------------------------------------------------
// ELFRel
ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
@@ -423,7 +415,6 @@ bool ELFRel::Parse(const lldb_private::DataExtractor &data,
return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
}
-//------------------------------------------------------------------------------
// ELFRela
ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h
index faaf8be99d687..bb228e269d406 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -1,13 +1,12 @@
//===-- ELFHeader.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
//
//===----------------------------------------------------------------------===//
//
-/// @file
+/// \file
/// Generic structures and typedefs for ELF files.
///
/// This file provides definitions for the various entities comprising an ELF
@@ -32,8 +31,7 @@ class DataExtractor;
namespace elf {
-//------------------------------------------------------------------------------
-/// @name ELF type definitions.
+/// \name ELF type definitions.
///
/// Types used to represent the various components of ELF structures. All
/// types are signed or unsigned integral types wide enough to hold values
@@ -50,8 +48,7 @@ typedef uint64_t elf_xword;
typedef int64_t elf_sxword;
//@}
-//------------------------------------------------------------------------------
-/// @class ELFHeader
+/// \class ELFHeader
/// Generic representation of an ELF file header.
///
/// This object is used to identify the general attributes on an ELF file and
@@ -81,93 +78,83 @@ struct ELFHeader {
ELFHeader();
- //--------------------------------------------------------------------------
/// Returns true if this is a 32 bit ELF file header.
///
- /// @return
+ /// \return
/// True if this is a 32 bit ELF file header.
bool Is32Bit() const {
return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32;
}
- //--------------------------------------------------------------------------
/// Returns true if this is a 64 bit ELF file header.
///
- /// @return
+ /// \return
/// True if this is a 64 bit ELF file header.
bool Is64Bit() const {
return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;
}
- //--------------------------------------------------------------------------
/// The byte order of this ELF file header.
///
- /// @return
+ /// \return
/// The byte order of this ELF file as described by the header.
lldb::ByteOrder GetByteOrder() const;
- //--------------------------------------------------------------------------
/// The jump slot relocation type of this ELF.
unsigned GetRelocationJumpSlotType() const;
- //--------------------------------------------------------------------------
/// Check if there should be header extension in section header #0
///
- /// @return
+ /// \return
/// True if parsing the ELFHeader requires reading header extension
/// and false otherwise.
bool HasHeaderExtension() const;
- //--------------------------------------------------------------------------
/// Parse an ELFHeader entry starting at position \p offset and update the
/// data extractor with the address size and byte order attributes as
/// defined by the header.
///
- /// @param[in,out] data
+ /// \param[in,out] data
/// The DataExtractor to read from. Updated with the address size and
/// byte order attributes appropriate to this header.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFHeader was successfully read and false
/// otherwise.
bool Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
- //--------------------------------------------------------------------------
/// Examines at most EI_NIDENT bytes starting from the given pointer and
/// determines if the magic ELF identification exists.
///
- /// @return
+ /// \return
/// True if the given sequence of bytes identifies an ELF file.
static bool MagicBytesMatch(const uint8_t *magic);
- //--------------------------------------------------------------------------
/// Examines at most EI_NIDENT bytes starting from the given address and
/// determines the address size of the underlying ELF file. This function
/// should only be called on an pointer for which MagicBytesMatch returns
/// true.
///
- /// @return
+ /// \return
/// The number of bytes forming an address in the ELF file (either 4 or
/// 8), else zero if the address size could not be determined.
static unsigned AddressSizeInBytes(const uint8_t *magic);
private:
- //--------------------------------------------------------------------------
/// Parse an ELFHeader header extension entry. This method is called by
/// Parse().
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from.
void ParseHeaderExtension(lldb_private::DataExtractor &data);
};
-//------------------------------------------------------------------------------
-/// @class ELFSectionHeader
+/// \class ELFSectionHeader
/// Generic representation of an ELF section header.
struct ELFSectionHeader {
elf_word sh_name; ///< Section name string index.
@@ -183,26 +170,24 @@ struct ELFSectionHeader {
ELFSectionHeader();
- //--------------------------------------------------------------------------
/// Parse an ELFSectionHeader entry from the given DataExtracter starting at
/// position \p offset.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFSectionHeader was successfully read and false
/// otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
-//------------------------------------------------------------------------------
-/// @class ELFProgramHeader
+/// \class ELFProgramHeader
/// Generic representation of an ELF program header.
struct ELFProgramHeader {
elf_word p_type; ///< Type of program segment.
@@ -220,22 +205,21 @@ struct ELFProgramHeader {
/// position \p offset. The address size of the DataExtractor determines if
/// a 32 or 64 bit object is to be parsed.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFProgramHeader was successfully read and false
/// otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
-//------------------------------------------------------------------------------
-/// @class ELFSymbol
+/// \class ELFSymbol
/// Represents a symbol within an ELF symbol table.
struct ELFSymbol {
elf_addr st_value; ///< Absolute or relocatable address.
@@ -270,15 +254,15 @@ struct ELFSymbol {
/// position \p offset. The address size of the DataExtractor determines if
/// a 32 or 64 bit object is to be parsed.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFSymbol was successfully read and false otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
@@ -287,8 +271,7 @@ struct ELFSymbol {
const lldb_private::SectionList *section_list);
};
-//------------------------------------------------------------------------------
-/// @class ELFDynamic
+/// \class ELFDynamic
/// Represents an entry in an ELF dynamic table.
struct ELFDynamic {
elf_sxword d_tag; ///< Type of dynamic table entry.
@@ -303,22 +286,21 @@ struct ELFDynamic {
/// position \p offset. The address size of the DataExtractor determines if
/// a 32 or 64 bit object is to be parsed.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFDynamic entry was successfully read and false
/// otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
-//------------------------------------------------------------------------------
-/// @class ELFRel
+/// \class ELFRel
/// Represents a relocation entry with an implicit addend.
struct ELFRel {
elf_addr r_offset; ///< Address of reference.
@@ -330,15 +312,15 @@ struct ELFRel {
/// \p offset. The address size of the DataExtractor determines if a 32 or
/// 64 bit object is to be parsed.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFRel entry was successfully read and false otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
@@ -359,8 +341,7 @@ struct ELFRel {
static unsigned RelocSymbol64(const ELFRel &rel) { return rel.r_info >> 32; }
};
-//------------------------------------------------------------------------------
-/// @class ELFRela
+/// \class ELFRela
/// Represents a relocation entry with an explicit addend.
struct ELFRela {
elf_addr r_offset; ///< Address of reference.
@@ -373,15 +354,15 @@ struct ELFRela {
/// \p offset. The address size of the DataExtractor determines if a 32 or
/// 64 bit object is to be parsed.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from. The address size of the extractor
/// determines if a 32 or 64 bit object should be read.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFRela entry was successfully read and false otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 9a6563afa0a01..d62afa34bbe81 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1,9 +1,8 @@
//===-- ObjectFileELF.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
//
//===----------------------------------------------------------------------===//
@@ -17,7 +16,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
@@ -27,6 +25,7 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
@@ -56,8 +55,8 @@ namespace {
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_CSR = "csr";
const char *const LLDB_NT_OWNER_ANDROID = "Android";
const char *const LLDB_NT_OWNER_CORE = "CORE";
const char *const LLDB_NT_OWNER_LINUX = "LINUX";
@@ -71,8 +70,10 @@ const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;
-const elf_word LLDB_NT_NETBSD_ABI_TAG = 0x01;
-const elf_word LLDB_NT_NETBSD_ABI_SIZE = 4;
+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;
// GNU ABI note OS constants
const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
@@ -115,7 +116,7 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
#define NT_METAG_TLS 0x502
//===----------------------------------------------------------------------===//
-/// @class ELFRelocation
+/// \class ELFRelocation
/// Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
@@ -125,7 +126,7 @@ public:
/// Constructs an ELFRelocation entry with a personality as given by @p
/// type.
///
- /// @param type Either DT_REL or DT_RELA. Any other value is invalid.
+ /// \param type Either DT_REL or DT_RELA. Any other value is invalid.
ELFRelocation(unsigned type);
~ELFRelocation();
@@ -161,7 +162,7 @@ ELFRelocation::ELFRelocation(unsigned type) {
reloc = new ELFRela();
else {
assert(false && "unexpected relocation type");
- reloc = static_cast<ELFRel *>(NULL);
+ reloc = static_cast<ELFRel *>(nullptr);
}
}
@@ -242,7 +243,7 @@ static user_id_t SegmentID(size_t PHdrIndex) { return ~PHdrIndex; }
bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
// Read all fields.
- if (data.GetU32(offset, &n_namesz, 3) == NULL)
+ if (data.GetU32(offset, &n_namesz, 3) == nullptr)
return false;
// The name field is required to be nul-terminated, and n_namesz includes the
@@ -261,7 +262,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
}
const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4));
- if (cstr == NULL) {
+ if (cstr == nullptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));
if (log)
log->Printf("Failed to parse note name lacking nul terminator");
@@ -272,27 +273,6 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
return true;
}
-static uint32_t kalimbaVariantFromElfFlags(const elf::elf_word e_flags) {
- const uint32_t dsp_rev = e_flags & 0xFF;
- uint32_t kal_arch_variant = LLDB_INVALID_CPUTYPE;
- switch (dsp_rev) {
- // TODO(mg11) Support more variants
- case 10:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v3;
- break;
- case 14:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v4;
- break;
- case 17:
- case 20:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v5;
- break;
- default:
- break;
- }
- return kal_arch_variant;
-}
-
static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH;
uint32_t endian = header.e_ident[EI_DATA];
@@ -350,40 +330,13 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) {
if (header.e_machine == llvm::ELF::EM_MIPS)
return mipsVariantFromElfFlags(header);
- return llvm::ELF::EM_CSR_KALIMBA == header.e_machine
- ? kalimbaVariantFromElfFlags(header.e_flags)
- : LLDB_INVALID_CPUTYPE;
-}
-
-//! The kalimba toolchain identifies a code section as being
-//! one with the SHT_PROGBITS set in the section sh_type and the top
-//! bit in the 32-bit address field set.
-static lldb::SectionType
-kalimbaSectionType(const elf::ELFHeader &header,
- const elf::ELFSectionHeader &sect_hdr) {
- if (llvm::ELF::EM_CSR_KALIMBA != header.e_machine) {
- return eSectionTypeOther;
- }
-
- if (llvm::ELF::SHT_NOBITS == sect_hdr.sh_type) {
- return eSectionTypeZeroFill;
- }
-
- if (llvm::ELF::SHT_PROGBITS == sect_hdr.sh_type) {
- const lldb::addr_t KAL_CODE_BIT = 1 << 31;
- return KAL_CODE_BIT & sect_hdr.sh_addr ? eSectionTypeCode
- : eSectionTypeData;
- }
-
- return eSectionTypeOther;
+ return LLDB_INVALID_CPUTYPE;
}
// Arbitrary constant used as UUID prefix for core files.
const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C);
-//------------------------------------------------------------------
// Static methods.
-//------------------------------------------------------------------
void ObjectFileELF::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
@@ -436,14 +389,14 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8) {
- std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(
+ std::unique_ptr<ObjectFileELF> objfile_up(new ObjectFileELF(
module_sp, data_sp, data_offset, file, file_offset, length));
- ArchSpec spec = objfile_ap->GetArchitecture();
- if (spec && objfile_ap->SetModulesArchitecture(spec))
- return objfile_ap.release();
+ ArchSpec spec = objfile_up->GetArchitecture();
+ if (spec && objfile_up->SetModulesArchitecture(spec))
+ return objfile_up.release();
}
- return NULL;
+ return nullptr;
}
ObjectFile *ObjectFileELF::CreateMemoryInstance(
@@ -454,15 +407,15 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance(
if (ELFHeader::MagicBytesMatch(magic)) {
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8) {
- std::unique_ptr<ObjectFileELF> objfile_ap(
+ std::unique_ptr<ObjectFileELF> objfile_up(
new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
- ArchSpec spec = objfile_ap->GetArchitecture();
- if (spec && objfile_ap->SetModulesArchitecture(spec))
- return objfile_ap.release();
+ ArchSpec spec = objfile_up->GetArchitecture();
+ if (spec && objfile_up->SetModulesArchitecture(spec))
+ return objfile_up.release();
}
}
}
- return NULL;
+ return nullptr;
}
bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp,
@@ -756,17 +709,13 @@ 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,
DataBufferSP &data_sp, lldb::offset_t data_offset,
@@ -775,7 +724,7 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
: ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0),
m_program_headers(), m_section_headers(), m_dynamic_symbols(),
- m_filespec_ap(), m_entry_point_address(), m_arch_spec() {
+ m_filespec_up(), m_entry_point_address(), m_arch_spec() {
if (file)
m_file = *file;
::memset(&m_header, 0, sizeof(m_header));
@@ -788,7 +737,7 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
: ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0),
m_program_headers(), m_section_headers(), m_dynamic_symbols(),
- m_filespec_ap(), m_entry_point_address(), m_arch_spec() {
+ m_filespec_up(), m_entry_point_address(), m_arch_spec() {
::memset(&m_header, 0, sizeof(m_header));
}
@@ -897,49 +846,43 @@ bool ObjectFileELF::ParseHeader() {
return m_header.Parse(m_data, &offset);
}
-bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
+UUID ObjectFileELF::GetUUID() {
// Need to parse the section list to get the UUIDs, so make sure that's been
// done.
if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
- return false;
+ return UUID();
- using u32le = llvm::support::ulittle32_t;
- if (m_uuid.IsValid()) {
- // We have the full build id uuid.
- *uuid = m_uuid;
- return true;
- } else if (GetType() == ObjectFile::eTypeCoreFile) {
- uint32_t core_notes_crc = 0;
+ if (!m_uuid) {
+ using u32le = llvm::support::ulittle32_t;
+ if (GetType() == ObjectFile::eTypeCoreFile) {
+ uint32_t core_notes_crc = 0;
- if (!ParseProgramHeaders())
- return false;
+ if (!ParseProgramHeaders())
+ return UUID();
- core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
+ core_notes_crc =
+ CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
- if (core_notes_crc) {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look
- // different form .gnu_debuglink crc - followed by 4 bytes of note
- // segments crc.
- u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
- m_uuid = UUID::fromData(data, sizeof(data));
- }
- } else {
- if (!m_gnu_debuglink_crc)
- m_gnu_debuglink_crc =
- calc_gnu_debuglink_crc32(m_data.GetDataStart(), m_data.GetByteSize());
- if (m_gnu_debuglink_crc) {
- // Use 4 bytes of crc from the .gnu_debuglink section.
- u32le data(m_gnu_debuglink_crc);
- m_uuid = UUID::fromData(&data, sizeof(data));
+ if (core_notes_crc) {
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
+ // look different form .gnu_debuglink crc - followed by 4 bytes of note
+ // segments crc.
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ m_uuid = UUID::fromData(data, sizeof(data));
+ }
+ } else {
+ if (!m_gnu_debuglink_crc)
+ m_gnu_debuglink_crc = calc_gnu_debuglink_crc32(m_data.GetDataStart(),
+ m_data.GetByteSize());
+ if (m_gnu_debuglink_crc) {
+ // Use 4 bytes of crc from the .gnu_debuglink section.
+ u32le data(m_gnu_debuglink_crc);
+ m_uuid = UUID::fromData(&data, sizeof(data));
+ }
}
}
- if (m_uuid.IsValid()) {
- *uuid = m_uuid;
- return true;
- }
-
- return false;
+ return m_uuid;
}
lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() {
@@ -957,7 +900,7 @@ uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) {
uint32_t num_specs = 0;
for (unsigned i = 0; i < num_modules; ++i) {
- if (files.AppendIfUnique(m_filespec_ap->GetFileSpecAtIndex(i)))
+ if (files.AppendIfUnique(m_filespec_up->GetFileSpecAtIndex(i)))
num_specs++;
}
@@ -1060,14 +1003,12 @@ Address ObjectFileELF::GetBaseAddress() {
return LLDB_INVALID_ADDRESS;
}
-//----------------------------------------------------------------------
// ParseDependentModules
-//----------------------------------------------------------------------
size_t ObjectFileELF::ParseDependentModules() {
- if (m_filespec_ap.get())
- return m_filespec_ap->GetSize();
+ if (m_filespec_up)
+ return m_filespec_up->GetSize();
- m_filespec_ap.reset(new FileSpecList());
+ m_filespec_up.reset(new FileSpecList());
if (!ParseSectionHeaders())
return 0;
@@ -1114,16 +1055,14 @@ size_t ObjectFileELF::ParseDependentModules() {
const char *lib_name = dynstr_data.PeekCStr(str_index);
FileSpec file_spec(lib_name);
FileSystem::Instance().Resolve(file_spec);
- m_filespec_ap->Append(file_spec);
+ m_filespec_up->Append(file_spec);
}
}
- return m_filespec_ap->GetSize();
+ return m_filespec_up->GetSize();
}
-//----------------------------------------------------------------------
// GetProgramHeaderInfo
-//----------------------------------------------------------------------
size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
DataExtractor &object_data,
const ELFHeader &header) {
@@ -1158,9 +1097,7 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
return program_headers.size();
}
-//----------------------------------------------------------------------
// ParseProgramHeaders
-//----------------------------------------------------------------------
bool ObjectFileELF::ParseProgramHeaders() {
return GetProgramHeaderInfo(m_program_headers, m_data, m_header) != 0;
}
@@ -1301,46 +1238,45 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// The note.n_name == LLDB_NT_OWNER_GNU is valid for Linux platform
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
- // Process NetBSD ELF notes.
+ // Process NetBSD ELF executables and shared libraries
else if ((note.n_name == LLDB_NT_OWNER_NETBSD) &&
- (note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
- (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE)) {
- // Pull out the min version info.
+ (note.n_type == LLDB_NT_NETBSD_IDENT_TAG) &&
+ (note.n_descsz == LLDB_NT_NETBSD_IDENT_DESCSZ) &&
+ (note.n_namesz == LLDB_NT_NETBSD_IDENT_NAMESZ)) {
+ // Pull out the version info.
uint32_t version_info;
if (data.GetU32(&offset, &version_info, 1) == nullptr) {
error.SetErrorString("failed to read NetBSD ABI note payload");
return error;
}
-
+ // Convert the version info into a major/minor/patch number.
+ // #define __NetBSD_Version__ MMmmrrpp00
+ //
+ // M = major version
+ // m = minor version; a minor number of 99 indicates current.
+ // r = 0 (since NetBSD 3.0 not used)
+ // p = patchlevel
+ const uint32_t version_major = version_info / 100000000;
+ const uint32_t version_minor = (version_info % 100000000) / 1000000;
+ const uint32_t version_patch = (version_info % 10000) / 100;
+ // Set the elf OS version to NetBSD. Also clear the vendor.
+ arch_spec.GetTriple().setOSName(
+ llvm::formatv("netbsd{0}.{1}.{2}", version_major, version_minor,
+ version_patch).str());
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
+ }
+ // Process NetBSD ELF core(5) notes
+ else if ((note.n_name == LLDB_NT_OWNER_NETBSDCORE) &&
+ (note.n_type == LLDB_NT_NETBSD_PROCINFO)) {
// Set the elf OS version to NetBSD. Also clear the vendor.
arch_spec.GetTriple().setOS(llvm::Triple::OSType::NetBSD);
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
-
- if (log)
- log->Printf(
- "ObjectFileELF::%s detected NetBSD, min version constant %" PRIu32,
- __FUNCTION__, version_info);
}
// Process OpenBSD ELF notes.
else if (note.n_name == LLDB_NT_OWNER_OPENBSD) {
// Set the elf OS version to OpenBSD. Also clear the vendor.
arch_spec.GetTriple().setOS(llvm::Triple::OSType::OpenBSD);
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
- }
- // Process CSR kalimba notes
- else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
- (note.n_name == LLDB_NT_OWNER_CSR)) {
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
- arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
-
- // TODO At some point the description string could be processed.
- // It could provide a steer towards the kalimba variant which this ELF
- // targets.
- if (note.n_descsz) {
- const char *cstr =
- data.GetCStr(&offset, llvm::alignTo(note.n_descsz, 4));
- (void)cstr;
- }
} else if (note.n_name == LLDB_NT_OWNER_ANDROID) {
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
arch_spec.GetTriple().setEnvironment(
@@ -1354,8 +1290,6 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// the contents look like this in a 64 bit ELF core file: count =
// 0x000000000000000a (10) page_size = 0x0000000000001000 (4096) Index
// start end file_ofs path =====
- // ------------------ ------------------ ------------------
- // ------------------------------------- [ 0] 0x0000000000400000
// 0x0000000000401000 0x0000000000000000 /tmp/a.out [ 1]
// 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
// 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
@@ -1479,9 +1413,7 @@ void ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length,
}
}
-//----------------------------------------------------------------------
// GetSectionHeaderInfo
-//----------------------------------------------------------------------
size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
DataExtractor &object_data,
const elf::ELFHeader &header,
@@ -1714,9 +1646,7 @@ ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
return symbol_name.substr(0, pos);
}
-//----------------------------------------------------------------------
// ParseSectionHeaders
-//----------------------------------------------------------------------
size_t ObjectFileELF::ParseSectionHeaders() {
return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid,
m_gnu_debuglink_file, m_gnu_debuglink_crc,
@@ -1726,12 +1656,12 @@ size_t ObjectFileELF::ParseSectionHeaders() {
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
if (!ParseSectionHeaders())
- return NULL;
+ return nullptr;
if (id < m_section_headers.size())
return &m_section_headers[id];
- return NULL;
+ return nullptr;
}
lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
@@ -1744,37 +1674,40 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
}
static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
+ if (Name.consume_front(".debug_") || Name.consume_front(".zdebug_")) {
+ return llvm::StringSwitch<SectionType>(Name)
+ .Case("abbrev", eSectionTypeDWARFDebugAbbrev)
+ .Case("abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)
+ .Case("addr", eSectionTypeDWARFDebugAddr)
+ .Case("aranges", eSectionTypeDWARFDebugAranges)
+ .Case("cu_index", eSectionTypeDWARFDebugCuIndex)
+ .Case("frame", eSectionTypeDWARFDebugFrame)
+ .Case("info", eSectionTypeDWARFDebugInfo)
+ .Case("info.dwo", eSectionTypeDWARFDebugInfoDwo)
+ .Cases("line", "line.dwo", eSectionTypeDWARFDebugLine)
+ .Cases("line_str", "line_str.dwo", eSectionTypeDWARFDebugLineStr)
+ .Cases("loc", "loc.dwo", eSectionTypeDWARFDebugLoc)
+ .Cases("loclists", "loclists.dwo", eSectionTypeDWARFDebugLocLists)
+ .Case("macinfo", eSectionTypeDWARFDebugMacInfo)
+ .Cases("macro", "macro.dwo", eSectionTypeDWARFDebugMacro)
+ .Case("names", eSectionTypeDWARFDebugNames)
+ .Case("pubnames", eSectionTypeDWARFDebugPubNames)
+ .Case("pubtypes", eSectionTypeDWARFDebugPubTypes)
+ .Case("ranges", eSectionTypeDWARFDebugRanges)
+ .Case("rnglists", eSectionTypeDWARFDebugRngLists)
+ .Case("str", eSectionTypeDWARFDebugStr)
+ .Case("str.dwo", eSectionTypeDWARFDebugStrDwo)
+ .Case("str_offsets", eSectionTypeDWARFDebugStrOffsets)
+ .Case("str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
+ .Case("types", eSectionTypeDWARFDebugTypes)
+ .Case("types.dwo", eSectionTypeDWARFDebugTypesDwo)
+ .Default(eSectionTypeOther);
+ }
return llvm::StringSwitch<SectionType>(Name)
.Case(".ARM.exidx", eSectionTypeARMexidx)
.Case(".ARM.extab", eSectionTypeARMextab)
.Cases(".bss", ".tbss", eSectionTypeZeroFill)
.Cases(".data", ".tdata", eSectionTypeData)
- .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
- .Case(".debug_abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)
- .Case(".debug_addr", eSectionTypeDWARFDebugAddr)
- .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
- .Case(".debug_cu_index", eSectionTypeDWARFDebugCuIndex)
- .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
- .Case(".debug_info", eSectionTypeDWARFDebugInfo)
- .Case(".debug_info.dwo", eSectionTypeDWARFDebugInfoDwo)
- .Cases(".debug_line", ".debug_line.dwo", eSectionTypeDWARFDebugLine)
- .Cases(".debug_line_str", ".debug_line_str.dwo",
- eSectionTypeDWARFDebugLineStr)
- .Cases(".debug_loc", ".debug_loc.dwo", eSectionTypeDWARFDebugLoc)
- .Cases(".debug_loclists", ".debug_loclists.dwo",
- eSectionTypeDWARFDebugLocLists)
- .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
- .Cases(".debug_macro", ".debug_macro.dwo", eSectionTypeDWARFDebugMacro)
- .Case(".debug_names", eSectionTypeDWARFDebugNames)
- .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
- .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
- .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
- .Case(".debug_rnglists", eSectionTypeDWARFDebugRngLists)
- .Case(".debug_str", eSectionTypeDWARFDebugStr)
- .Case(".debug_str.dwo", eSectionTypeDWARFDebugStrDwo)
- .Case(".debug_str_offsets", eSectionTypeDWARFDebugStrOffsets)
- .Case(".debug_str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
- .Case(".debug_types", eSectionTypeDWARFDebugTypes)
.Case(".eh_frame", eSectionTypeEHFrame)
.Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
.Case(".gosymtab", eSectionTypeGoSymtab)
@@ -1798,14 +1731,7 @@ SectionType ObjectFileELF::GetSectionType(const ELFSectionHeaderInfo &H) const {
case SHT_DYNAMIC:
return eSectionTypeELFDynamicLinkInfo;
}
- SectionType Type = GetSectionTypeFromName(H.section_name.GetStringRef());
- if (Type == eSectionTypeOther) {
- // the kalimba toolchain assumes that ELF section names are free-form.
- // It does support linkscripts which (can) give rise to various
- // arbitrarily named sections being "Code" or "Data".
- Type = kalimbaSectionType(m_header, H);
- }
- return Type;
+ return GetSectionTypeFromName(H.section_name.GetStringRef());
}
static uint32_t GetTargetByteSize(SectionType Type, const ArchSpec &arch) {
@@ -1938,11 +1864,11 @@ public:
}
void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
- if (m_sections_ap)
+ if (m_sections_up)
return;
- m_sections_ap = llvm::make_unique<SectionList>();
- VMAddressProvider address_provider(CalculateType());
+ m_sections_up = llvm::make_unique<SectionList>();
+ VMAddressProvider address_provider(GetType());
size_t LoadID = 0;
for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
@@ -1961,7 +1887,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(),
PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0);
Segment->SetPermissions(GetPermissions(PHdr));
- m_sections_ap->AddSection(Segment);
+ m_sections_up->AddSection(Segment);
address_provider.AddSegment(*InfoOr, std::move(Segment));
}
@@ -2007,7 +1933,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
section_sp->SetPermissions(GetPermissions(header));
section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS);
- (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_ap)
+ (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_up)
.AddSection(section_sp);
address_provider.AddSection(std::move(*InfoOr), std::move(section_sp));
}
@@ -2015,7 +1941,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
// For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
// unified section list.
if (GetType() != eTypeDebugInfo)
- unified_section_list = *m_sections_ap;
+ unified_section_list = *m_sections_up;
}
// Find the arm/aarch64 mapping symbol character in the given symbol name.
@@ -2073,8 +1999,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
// custom extension and file name makes it highly unlikely that this will
// collide with anything else.
ConstString file_extension = m_file.GetFileNameExtension();
- bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
- file_extension == ConstString(".odex");
+ bool skip_oatdata_oatexec =
+ file_extension == ".oat" || file_extension == ".odex";
ArchSpec arch = GetArchitecture();
ModuleSP module_sp(GetModule());
@@ -2166,7 +2092,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION) {
if (symbol_section_sp) {
- const ConstString &sect_name = symbol_section_sp->GetName();
+ ConstString sect_name = symbol_section_sp->GetName();
if (sect_name == text_section_name || sect_name == init_section_name ||
sect_name == fini_section_name || sect_name == ctors_section_name ||
sect_name == dtors_section_name) {
@@ -2262,11 +2188,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
* class
* accordingly.
*/
- const llvm::Triple::ArchType llvm_arch = arch.GetMachine();
- if (llvm_arch == llvm::Triple::mips ||
- llvm_arch == llvm::Triple::mipsel ||
- llvm_arch == llvm::Triple::mips64 ||
- llvm_arch == llvm::Triple::mips64el) {
+ if (arch.IsMIPS()) {
if (IS_MICROMIPS(symbol.st_other))
m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
@@ -2310,7 +2232,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (symbol_section_sp && module_section_list &&
module_section_list != section_list) {
- const ConstString &sect_name = symbol_section_sp->GetName();
+ ConstString sect_name = symbol_section_sp->GetName();
auto section_it = section_name_to_section.find(sect_name.GetCString());
if (section_it == section_name_to_section.end())
section_it =
@@ -2391,7 +2313,7 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
}
// Get section list for this object file.
- SectionList *section_list = m_sections_ap.get();
+ SectionList *section_list = m_sections_up.get();
if (!section_list)
return 0;
@@ -2457,7 +2379,7 @@ size_t ObjectFileELF::ParseDynamicSymbols() {
const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) {
if (!ParseDynamicSymbols())
- return NULL;
+ return nullptr;
DynamicSymbolCollIter I = m_dynamic_symbols.begin();
DynamicSymbolCollIter E = m_dynamic_symbols.end();
@@ -2468,7 +2390,7 @@ const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) {
return symbol;
}
- return NULL;
+ return nullptr;
}
unsigned ObjectFileELF::PLTRelocationType() {
@@ -2619,7 +2541,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
if (!sym_hdr)
return 0;
- SectionList *section_list = m_sections_ap.get();
+ SectionList *section_list = m_sections_up.get();
if (!section_list)
return 0;
@@ -2685,7 +2607,7 @@ unsigned ObjectFileELF::ApplyRelocations(
if (!rel.Parse(rel_data, &offset))
break;
- Symbol *symbol = NULL;
+ Symbol *symbol = nullptr;
if (hdr->Is32Bit()) {
switch (reloc_type(rel)) {
@@ -2804,7 +2726,7 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
Symtab *ObjectFileELF::GetSymtab() {
ModuleSP module_sp(GetModule());
if (!module_sp)
- return NULL;
+ return nullptr;
// We always want to use the main object file so we (hopefully) only have one
// cached copy of our symtab, dynamic sections, etc.
@@ -2812,10 +2734,10 @@ Symtab *ObjectFileELF::GetSymtab() {
if (module_obj_file && module_obj_file != this)
return module_obj_file->GetSymtab();
- if (m_symtab_ap.get() == NULL) {
+ if (m_symtab_up == nullptr) {
SectionList *section_list = module_sp->GetSectionList();
if (!section_list)
- return NULL;
+ return nullptr;
uint64_t symbol_id = 0;
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
@@ -2836,8 +2758,8 @@ Symtab *ObjectFileELF::GetSymtab() {
.get();
}
if (symtab) {
- m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));
- symbol_id += ParseSymbolTable(m_symtab_ap.get(), symbol_id, symtab);
+ m_symtab_up.reset(new Symtab(symtab->GetObjectFile()));
+ symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab);
}
// DT_JMPREL
@@ -2861,30 +2783,30 @@ Symtab *ObjectFileELF::GetSymtab() {
GetSectionHeaderByIndex(reloc_id);
assert(reloc_header);
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));
+ if (m_symtab_up == nullptr)
+ m_symtab_up.reset(new Symtab(reloc_section->GetObjectFile()));
- ParseTrampolineSymbols(m_symtab_ap.get(), symbol_id, reloc_header,
+ ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
reloc_id);
}
}
- DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo();
- if (eh_frame) {
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(this));
- ParseUnwindSymbols(m_symtab_ap.get(), eh_frame);
+ if (DWARFCallFrameInfo *eh_frame =
+ GetModule()->GetUnwindTable().GetEHFrameInfo()) {
+ if (m_symtab_up == nullptr)
+ m_symtab_up.reset(new Symtab(this));
+ ParseUnwindSymbols(m_symtab_up.get(), eh_frame);
}
// If we still don't have any symtab then create an empty instance to avoid
// do the section lookup next time.
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(this));
+ if (m_symtab_up == nullptr)
+ m_symtab_up.reset(new Symtab(this));
- m_symtab_ap->CalculateSymbolSizes();
+ m_symtab_up->CalculateSymbolSizes();
}
- return m_symtab_ap.get();
+ return m_symtab_up.get();
}
void ObjectFileELF::RelocateSection(lldb_private::Section *section)
@@ -2991,7 +2913,6 @@ bool ObjectFileELF::IsStripped() {
//
// Dump the specifics of the runtime file container (such as any headers
// segments, sections, etc).
-//----------------------------------------------------------------------
void ObjectFileELF::Dump(Stream *s) {
ModuleSP module_sp(GetModule());
if (!module_sp) {
@@ -3016,20 +2937,18 @@ void ObjectFileELF::Dump(Stream *s) {
s->EOL();
SectionList *section_list = GetSectionList();
if (section_list)
- section_list->Dump(s, NULL, true, UINT32_MAX);
+ section_list->Dump(s, nullptr, true, UINT32_MAX);
Symtab *symtab = GetSymtab();
if (symtab)
- symtab->Dump(s, NULL, eSortOrderNone);
+ symtab->Dump(s, nullptr, eSortOrderNone);
s->EOL();
DumpDependentModules(s);
s->EOL();
}
-//----------------------------------------------------------------------
// DumpELFHeader
//
// Dump the ELF header to the specified output stream
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header) {
s->PutCString("ELF Header\n");
s->Printf("e_ident[EI_MAG0 ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
@@ -3062,11 +2981,9 @@ void ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header) {
s->Printf("e_shstrndx = 0x%8.8x\n", header.e_shstrndx);
}
-//----------------------------------------------------------------------
// DumpELFHeader_e_type
//
// Dump an token value for the ELF header member e_type
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type) {
switch (e_type) {
case ET_NONE:
@@ -3089,11 +3006,9 @@ void ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type) {
}
}
-//----------------------------------------------------------------------
// DumpELFHeader_e_ident_EI_DATA
//
// Dump an token value for the ELF header member e_ident[EI_DATA]
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s,
unsigned char ei_data) {
switch (ei_data) {
@@ -3111,11 +3026,9 @@ void ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s,
}
}
-//----------------------------------------------------------------------
// DumpELFProgramHeader
//
// Dump a single ELF program header to the specified output stream
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader(Stream *s,
const ELFProgramHeader &ph) {
DumpELFProgramHeader_p_type(s, ph.p_type);
@@ -3128,12 +3041,10 @@ void ObjectFileELF::DumpELFProgramHeader(Stream *s,
s->Printf(") %8.8" PRIx64, ph.p_align);
}
-//----------------------------------------------------------------------
// DumpELFProgramHeader_p_type
//
// Dump an token value for the ELF program header member p_type which describes
// the type of the program header
-// ----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
const int kStrWidth = 15;
switch (p_type) {
@@ -3152,11 +3063,9 @@ void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
}
}
-//----------------------------------------------------------------------
// DumpELFProgramHeader_p_flags
//
// Dump an token value for the ELF program header member p_flags
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags) {
*s << ((p_flags & PF_X) ? "PF_X" : " ")
<< (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
@@ -3165,11 +3074,9 @@ void ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags) {
<< ((p_flags & PF_R) ? "PF_R" : " ");
}
-//----------------------------------------------------------------------
// DumpELFProgramHeaders
//
// Dump all of the ELF program header to the specified output stream
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
if (!ParseProgramHeaders())
return;
@@ -3187,11 +3094,9 @@ void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
}
}
-//----------------------------------------------------------------------
// DumpELFSectionHeader
//
// Dump a single ELF section header to the specified output stream
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFSectionHeader(Stream *s,
const ELFSectionHeaderInfo &sh) {
s->Printf("%8.8x ", sh.sh_name);
@@ -3204,12 +3109,10 @@ void ObjectFileELF::DumpELFSectionHeader(Stream *s,
s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
}
-//----------------------------------------------------------------------
// DumpELFSectionHeader_sh_type
//
// Dump an token value for the ELF section header member sh_type which
// describes the type of the section
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type) {
const int kStrWidth = 12;
switch (sh_type) {
@@ -3235,11 +3138,9 @@ void ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type) {
}
}
-//----------------------------------------------------------------------
// DumpELFSectionHeader_sh_flags
//
// Dump an token value for the ELF section header member sh_flags
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s,
elf_xword sh_flags) {
*s << ((sh_flags & SHF_WRITE) ? "WRITE" : " ")
@@ -3249,11 +3150,9 @@ void ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s,
<< ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : " ");
}
-//----------------------------------------------------------------------
// DumpELFSectionHeaders
//
// Dump all of the ELF section header to the specified output stream
-//----------------------------------------------------------------------
void ObjectFileELF::DumpELFSectionHeaders(Stream *s) {
if (!ParseSectionHeaders())
return;
@@ -3283,7 +3182,7 @@ void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
if (num_modules > 0) {
s->PutCString("Dependent Modules:\n");
for (unsigned i = 0; i < num_modules; ++i) {
- const FileSpec &spec = m_filespec_ap->GetFileSpecAtIndex(i);
+ const FileSpec &spec = m_filespec_up->GetFileSpecAtIndex(i);
s->Printf(" %s\n", spec.GetFilename().GetCString());
}
}
@@ -3299,7 +3198,7 @@ ArchSpec ObjectFileELF::GetArchitecture() {
}
if (CalculateType() == eTypeCoreFile &&
- m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
+ !m_arch_spec.TripleOSWasSpecified()) {
// Core files don't have section headers yet they have PT_NOTE program
// headers that might shed more light on the architecture
for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
@@ -3405,7 +3304,8 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
return section->GetObjectFile()->ReadSectionData(section, section_data);
size_t result = ObjectFile::ReadSectionData(section, section_data);
- if (result == 0 || !section->Test(SHF_COMPRESSED))
+ if (result == 0 || !llvm::object::Decompressor::isCompressedELFSection(
+ section->Get(), section->GetName().GetStringRef()))
return result;
auto Decompressor = llvm::object::Decompressor::create(
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 08fd5bdc60a97..b63a5d14d4f5d 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -1,9 +1,8 @@
//===-- ObjectFileELF.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
//
//===----------------------------------------------------------------------===//
@@ -34,14 +33,14 @@ struct ELFNote {
/// Parse an ELFNote entry from the given DataExtractor starting at position
/// \p offset.
///
- /// @param[in] data
+ /// \param[in] data
/// The DataExtractor to read from.
///
- /// @param[in,out] offset
+ /// \param[in,out] offset
/// Pointer to an offset in the data. On return the offset will be
/// advanced by the number of bytes read.
///
- /// @return
+ /// \return
/// True if the ELFRel entry was successfully read and false otherwise.
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
@@ -50,8 +49,7 @@ struct ELFNote {
}
};
-//------------------------------------------------------------------------------
-/// @class ObjectFileELF
+/// \class ObjectFileELF
/// Generic ELF object file reader.
///
/// This class provides a generic ELF (32/64 bit) reader plugin implementing
@@ -60,9 +58,7 @@ class ObjectFileELF : public lldb_private::ObjectFile {
public:
~ObjectFileELF() override;
- //------------------------------------------------------------------
// Static Functions
- //------------------------------------------------------------------
static void Initialize();
static void Terminate();
@@ -90,16 +86,12 @@ public:
static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
lldb::addr_t length);
- //------------------------------------------------------------------
// PluginInterface protocol
- //------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
- //------------------------------------------------------------------
// ObjectFile Protocol.
- //------------------------------------------------------------------
bool ParseHeader() override;
bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
@@ -123,7 +115,7 @@ public:
lldb_private::ArchSpec GetArchitecture() override;
- bool GetUUID(lldb_private::UUID *uuid) override;
+ lldb_private::UUID GetUUID() override;
lldb_private::FileSpecList GetDebugSymbolFilePaths() override;
@@ -211,7 +203,7 @@ private:
/// List of file specifications corresponding to the modules (shared
/// libraries) on which this object file depends.
- mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
+ mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up;
/// Cached value of the entry point for this module.
lldb_private::Address m_entry_point_address;
@@ -265,7 +257,7 @@ private:
lldb_private::ArchSpec &arch_spec);
/// Scans the dynamic section and locates all dependent modules (shared
- /// libraries) populating m_filespec_ap. This method will compute the
+ /// libraries) populating m_filespec_up. This method will compute the
/// dependent module list only once. Returns the number of dependent
/// modules parsed.
size_t ParseDependentModules();
@@ -275,7 +267,7 @@ private:
/// number of dynamic symbols parsed.
size_t ParseDynamicSymbols();
- /// Populates m_symtab_ap will all non-dynamic linker symbols. This method
+ /// Populates m_symtab_up will all non-dynamic linker symbols. This method
/// will parse the symbols only once. Returns the number of symbols parsed.
unsigned ParseSymbolTable(lldb_private::Symtab *symbol_table,
lldb::user_id_t start_id,
@@ -331,7 +323,7 @@ private:
/// Returns the section header with the given id or NULL.
const ELFSectionHeaderInfo *GetSectionHeaderByIndex(lldb::user_id_t id);
- /// @name ELF header dump routines
+ /// \name ELF header dump routines
//@{
static void DumpELFHeader(lldb_private::Stream *s,
const elf::ELFHeader &header);
@@ -343,7 +335,7 @@ private:
elf::elf_half e_type);
//@}
- /// @name ELF program header dump routines
+ /// \name ELF program header dump routines
//@{
void DumpELFProgramHeaders(lldb_private::Stream *s);
@@ -357,7 +349,7 @@ private:
elf::elf_word p_flags);
//@}
- /// @name ELF section header dump routines
+ /// \name ELF section header dump routines
//@{
void DumpELFSectionHeaders(lldb_private::Stream *s);
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index cfe61992be0d2..eaf973da38355 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -1,9 +1,8 @@
//===-- ObjectFileJIT.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
//
//===----------------------------------------------------------------------===//
@@ -15,7 +14,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
@@ -29,6 +27,7 @@
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
@@ -67,7 +66,7 @@ ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
lldb::offset_t length) {
// JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
// a file
- return NULL;
+ return nullptr;
}
ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
@@ -76,7 +75,7 @@ ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
lldb::addr_t header_addr) {
// JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
// memory
- return NULL;
+ return nullptr;
}
size_t ObjectFileJIT::GetModuleSpecifications(
@@ -89,7 +88,7 @@ size_t ObjectFileJIT::GetModuleSpecifications(
ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp,
const ObjectFileJITDelegateSP &delegate_sp)
- : ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0), m_delegate_wp() {
+ : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() {
if (delegate_sp) {
m_delegate_wp = delegate_sp;
m_data.SetByteOrder(delegate_sp->GetByteOrder());
@@ -116,18 +115,18 @@ Symtab *ObjectFileJIT::GetSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- if (m_symtab_ap.get() == NULL) {
- m_symtab_ap.reset(new Symtab(this));
+ if (m_symtab_up == nullptr) {
+ m_symtab_up.reset(new Symtab(this));
std::lock_guard<std::recursive_mutex> symtab_guard(
- m_symtab_ap->GetMutex());
+ m_symtab_up->GetMutex());
ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
if (delegate_sp)
- delegate_sp->PopulateSymtab(this, *m_symtab_ap);
+ delegate_sp->PopulateSymtab(this, *m_symtab_up);
// TODO: get symbols from delegate
- m_symtab_ap->Finalize();
+ m_symtab_up->Finalize();
}
}
- return m_symtab_ap.get();
+ return m_symtab_up.get();
}
bool ObjectFileJIT::IsStripped() {
@@ -135,12 +134,12 @@ bool ObjectFileJIT::IsStripped() {
}
void ObjectFileJIT::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get()) {
- m_sections_ap.reset(new SectionList());
+ if (!m_sections_up) {
+ m_sections_up.reset(new SectionList());
ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
if (delegate_sp) {
- delegate_sp->PopulateSectionList(this, *m_sections_ap);
- unified_section_list = *m_sections_ap;
+ delegate_sp->PopulateSectionList(this, *m_sections_up);
+ unified_section_list = *m_sections_up;
}
}
}
@@ -160,16 +159,16 @@ void ObjectFileJIT::Dump(Stream *s) {
SectionList *sections = GetSectionList();
if (sections)
- sections->Dump(s, NULL, true, UINT32_MAX);
+ sections->Dump(s, nullptr, true, UINT32_MAX);
- if (m_symtab_ap.get())
- m_symtab_ap->Dump(s, NULL, eSortOrderNone);
+ if (m_symtab_up)
+ m_symtab_up->Dump(s, nullptr, eSortOrderNone);
}
}
-bool ObjectFileJIT::GetUUID(lldb_private::UUID *uuid) {
+UUID ObjectFileJIT::GetUUID() {
// TODO: maybe get from delegate, not needed for first pass
- return false;
+ return UUID();
}
uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) {
@@ -195,9 +194,7 @@ ArchSpec ObjectFileJIT::GetArchitecture() {
return ArchSpec();
}
-//------------------------------------------------------------------
// PluginInterface protocol
-//------------------------------------------------------------------
lldb_private::ConstString ObjectFileJIT::GetPluginName() {
return GetPluginNameStatic();
}
@@ -249,14 +246,12 @@ size_t ObjectFileJIT::ReadSectionData(
if (section->GetFileSize()) {
const void *src = (void *)(uintptr_t)section->GetFileOffset();
- DataBufferSP data_sp(
- new lldb_private::DataBufferHeap(src, section->GetFileSize()));
- if (data_sp) {
- section_data.SetData(data_sp, 0, data_sp->GetByteSize());
- section_data.SetByteOrder(GetByteOrder());
- section_data.SetAddressByteSize(GetAddressByteSize());
- return section_data.GetByteSize();
- }
+ DataBufferSP data_sp =
+ std::make_shared<DataBufferHeap>(src, section->GetFileSize());
+ section_data.SetData(data_sp, 0, data_sp->GetByteSize());
+ section_data.SetByteOrder(GetByteOrder());
+ section_data.SetAddressByteSize(GetAddressByteSize());
+ return section_data.GetByteSize();
}
section_data.Clear();
return 0;
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index 3d9e4748d3df3..99241126cd1a6 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -1,9 +1,8 @@
//===-- ObjectFileJIT.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
//
//===----------------------------------------------------------------------===//
@@ -13,10 +12,8 @@
#include "lldb/Core/Address.h"
#include "lldb/Symbol/ObjectFile.h"
-//----------------------------------------------------------------------
// This class needs to be hidden as eventually belongs in a plugin that
// will export the ObjectFile protocol
-//----------------------------------------------------------------------
class ObjectFileJIT : public lldb_private::ObjectFile {
public:
ObjectFileJIT(const lldb::ModuleSP &module_sp,
@@ -24,9 +21,7 @@ public:
~ObjectFileJIT() override;
- //------------------------------------------------------------------
// Static Functions
- //------------------------------------------------------------------
static void Initialize();
static void Terminate();
@@ -51,9 +46,7 @@ public:
lldb::offset_t length,
lldb_private::ModuleSpecList &specs);
- //------------------------------------------------------------------
// Member Functions
- //------------------------------------------------------------------
bool ParseHeader() override;
bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
@@ -75,7 +68,7 @@ public:
lldb_private::ArchSpec GetArchitecture() override;
- bool GetUUID(lldb_private::UUID *uuid) override;
+ lldb_private::UUID GetUUID() override;
uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
@@ -95,9 +88,7 @@ public:
ObjectFile::Strata CalculateStrata() override;
- //------------------------------------------------------------------
// PluginInterface protocol
- //------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;