summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-10 13:44:58 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-10 13:44:58 +0000
commitf1d04915a666728c241bedb36bd99aafee3ea444 (patch)
treed63378f567f214209764be264c47c8b0814e1665
parent60bb8ce74a67345b14fd540dd739254f562c605b (diff)
downloadsrc-test2-f1d04915a666728c241bedb36bd99aafee3ea444.tar.gz
src-test2-f1d04915a666728c241bedb36bd99aafee3ea444.zip
Notes
-rw-r--r--include/lldb/Core/Address.h10
-rw-r--r--include/lldb/Core/Section.h3
-rw-r--r--include/lldb/Core/dwarf.h2
-rw-r--r--include/lldb/Target/SectionLoadList.h3
-rw-r--r--include/lldb/Utility/SafeMachO.h2
-rw-r--r--include/lldb/Utility/TaskPool.h3
-rw-r--r--include/lldb/Utility/VMRange.h5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py53
-rw-r--r--packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s35
-rw-r--r--packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.corebin0 -> 40960 bytes
-rwxr-xr-xpackages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.outbin0 -> 520 bytes
-rw-r--r--source/Commands/CommandObjectRegister.cpp11
-rw-r--r--source/Core/Address.cpp12
-rw-r--r--source/Core/ArchSpec.cpp8
-rw-r--r--source/Core/CMakeLists.txt1
-rw-r--r--source/Core/Section.cpp22
-rw-r--r--source/DataFormatters/TypeCategory.cpp21
-rw-r--r--source/Host/common/Host.cpp8
-rw-r--r--source/Host/posix/ConnectionFileDescriptorPosix.cpp7
-rw-r--r--source/Host/posix/ProcessLauncherPosixFork.cpp5
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.cpp2
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp1
-rw-r--r--source/Plugins/ObjectFile/ELF/CMakeLists.txt1
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.h2
-rw-r--r--source/Plugins/ObjectFile/PECOFF/CMakeLists.txt1
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp2
-rw-r--r--source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp38
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp7
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.cpp10
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp12
-rw-r--r--source/Plugins/Process/elf-core/CMakeLists.txt1
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp5
-rw-r--r--source/Target/SectionLoadList.cpp15
-rw-r--r--source/Target/StackFrame.cpp3
-rw-r--r--source/Utility/CMakeLists.txt1
-rw-r--r--source/Utility/Status.cpp18
-rw-r--r--source/Utility/TaskPool.cpp2
-rw-r--r--source/Utility/VMRange.cpp46
-rw-r--r--tools/lldb-server/lldb-gdbserver.cpp11
-rw-r--r--unittests/CMakeLists.txt3
-rw-r--r--unittests/Core/ArchSpecTest.cpp2
-rw-r--r--unittests/Core/StructuredDataTest.cpp2
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp21
-rw-r--r--unittests/tools/CMakeLists.txt3
-rw-r--r--unittests/tools/lldb-server/CMakeLists.txt13
-rw-r--r--unittests/tools/lldb-server/inferior/thread_inferior.cpp41
-rw-r--r--unittests/tools/lldb-server/tests/CMakeLists.txt15
-rw-r--r--unittests/tools/lldb-server/tests/MessageObjects.cpp207
-rw-r--r--unittests/tools/lldb-server/tests/MessageObjects.h102
-rw-r--r--unittests/tools/lldb-server/tests/TestClient.cpp287
-rw-r--r--unittests/tools/lldb-server/tests/TestClient.h61
-rw-r--r--unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp58
56 files changed, 1022 insertions, 194 deletions
diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h
index a800570ec8b1..4c77458061d0 100644
--- a/include/lldb/Core/Address.h
+++ b/include/lldb/Core/Address.h
@@ -422,6 +422,10 @@ public:
/// a section + offset. The Target's SectionLoadList object
/// is used to resolve the address.
///
+ /// @param[in] allow_section_end
+ /// If true, treat an address pointing to the end of the module as
+ /// belonging to that module.
+ ///
/// @return
/// Returns \b true if the load address was resolved to be
/// section/offset, \b false otherwise. It is often ok for an
@@ -429,11 +433,13 @@ public:
/// happens for JIT'ed code, or any load addresses on the stack
/// or heap.
//------------------------------------------------------------------
- bool SetLoadAddress(lldb::addr_t load_addr, Target *target);
+ bool SetLoadAddress(lldb::addr_t load_addr, Target *target,
+ bool allow_section_end = false);
bool SetOpcodeLoadAddress(
lldb::addr_t load_addr, Target *target,
- lldb::AddressClass addr_class = lldb::eAddressClassInvalid);
+ lldb::AddressClass addr_class = lldb::eAddressClassInvalid,
+ bool allow_section_end = false);
bool SetCallableLoadAddress(lldb::addr_t load_addr, Target *target);
diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h
index a133298edaf3..0466693edbc4 100644
--- a/include/lldb/Core/Section.h
+++ b/include/lldb/Core/Section.h
@@ -143,7 +143,8 @@ public:
lldb::addr_t GetLoadBaseAddress(Target *target) const;
- bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr) const;
+ bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr,
+ bool allow_section_end = false) const;
lldb::offset_t GetFileOffset() const { return m_file_offset; }
diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h
index 4a935d5151e9..651a2bc29475 100644
--- a/include/lldb/Core/dwarf.h
+++ b/include/lldb/Core/dwarf.h
@@ -13,7 +13,7 @@
#include <stdint.h>
// Get the DWARF constant definitions from llvm
-#include "llvm/Support/Dwarf.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "lldb/Core/RangeMap.h"
diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h
index c232dd91a8b3..beb345b71290 100644
--- a/include/lldb/Target/SectionLoadList.h
+++ b/include/lldb/Target/SectionLoadList.h
@@ -47,7 +47,8 @@ public:
lldb::addr_t GetSectionLoadAddress(const lldb::SectionSP &section_sp) const;
- bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr) const;
+ bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr,
+ bool allow_section_end = false) const;
bool SetSectionLoadAddress(const lldb::SectionSP &section_sp,
lldb::addr_t load_addr,
diff --git a/include/lldb/Utility/SafeMachO.h b/include/lldb/Utility/SafeMachO.h
index 5da03c15da94..791410a38b34 100644
--- a/include/lldb/Utility/SafeMachO.h
+++ b/include/lldb/Utility/SafeMachO.h
@@ -114,6 +114,6 @@
#undef CPU_SUBTYPE_MC980000_ALL
#undef CPU_SUBTYPE_MC98601
-#include "llvm/Support/MachO.h"
+#include "llvm/BinaryFormat/MachO.h"
#endif // liblldb_SafeMachO_h_
diff --git a/include/lldb/Utility/TaskPool.h b/include/lldb/Utility/TaskPool.h
index 87b8824f9226..f2deaee506b8 100644
--- a/include/lldb/Utility/TaskPool.h
+++ b/include/lldb/Utility/TaskPool.h
@@ -10,6 +10,7 @@
#ifndef utility_TaskPool_h_
#define utility_TaskPool_h_
+#include "llvm/ADT/STLExtras.h"
#include <functional> // for bind, function
#include <future>
#include <list>
@@ -86,6 +87,6 @@ template <> struct TaskPool::RunTaskImpl<> {
// 'batch_size' numbers at a time to work on, so for very fast functions, batch
// should be large enough to avoid too much cache line contention.
void TaskMapOverInt(size_t begin, size_t end,
- std::function<void(size_t)> const &func);
+ const llvm::function_ref<void(size_t)> &func);
#endif // #ifndef utility_TaskPool_h_
diff --git a/include/lldb/Utility/VMRange.h b/include/lldb/Utility/VMRange.h
index 98362f4d7608..f03a1b0c1f97 100644
--- a/include/lldb/Utility/VMRange.h
+++ b/include/lldb/Utility/VMRange.h
@@ -111,11 +111,6 @@ public:
static bool ContainsRange(const VMRange::collection &coll,
const VMRange &range);
- // Returns a valid index into coll when a match is found, else UINT32_MAX
- // is returned
- static size_t FindRangeIndexThatContainsValue(const VMRange::collection &coll,
- lldb::addr_t value);
-
protected:
lldb::addr_t m_base_addr;
lldb::addr_t m_byte_size;
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
index eafe62a0e08f..d54e62887ce1 100644
--- a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
@@ -17,8 +17,8 @@ class NoreturnUnwind(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIfWindows # clang-cl does not support gcc style attributes.
- @expectedFailureAndroid(bugnumber="llvm.org/pr31192")
- @expectedFailureAll(bugnumber="llvm.org/pr31192", oslist=['linux'], compiler="gcc", archs=['arm'])
+ # clang does not preserve LR in noreturn functions, making unwinding impossible
+ @skipIf(compiler="clang", archs=['arm'], oslist=['linux'])
def test(self):
"""Test that we can backtrace correctly with 'noreturn' functions on the stack"""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
index 7190e38f5d8c..4f6525fbf52f 100644
--- a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
@@ -29,8 +29,6 @@ func_a (void)
int
main (int argc, char *argv[])
{
- sleep (2);
-
func_a ();
return 0;
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
new file mode 100644
index 000000000000..3aa6a230e8b6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
@@ -0,0 +1,53 @@
+"""
+Test that we properly display the backtrace when a noreturn function happens to
+be at the end of the stack.
+"""
+
+from __future__ import print_function
+
+import shutil
+import struct
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestNoreturnModuleEnd(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ super(TestNoreturnModuleEnd, self).setUp()
+ self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ def tearDown(self):
+ lldb.DBG.SetSelectedPlatform(self._initial_platform)
+ super(TestNoreturnModuleEnd, self).tearDown()
+
+ def test(self):
+ target = self.dbg.CreateTarget("test.out")
+ process = target.LoadCore("test.core")
+ self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 1)
+
+ thread = process.GetSelectedThread()
+ self.assertTrue(thread.IsValid())
+
+ backtrace = [
+ ["func2", 3],
+ ["func1", 8],
+ ["_start", 8],
+ ]
+ self.assertEqual(thread.GetNumFrames(), len(backtrace))
+ for i in range(len(backtrace)):
+ frame = thread.GetFrameAtIndex(i)
+ self.assertTrue(frame.IsValid())
+ symbol = frame.GetSymbol()
+ self.assertTrue(symbol.IsValid())
+ self.assertEqual(symbol.GetName(), backtrace[i][0])
+ function_start = symbol.GetStartAddress().GetLoadAddress(target)
+ self.assertEquals(function_start + backtrace[i][1], frame.GetPC())
+
+ self.dbg.DeleteTarget(target)
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
new file mode 100644
index 000000000000..119465c132a9
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
@@ -0,0 +1,35 @@
+# compile this with:
+# as a.s -o a.o --32 && ld a.o -m elf_i386
+# generate core file with:
+# ulimit -s 12 && ./a.out
+
+.text
+
+.globl func2
+.type func2, @function
+func2:
+ pushl %ebp
+ movl %esp, %ebp
+ movl 0, %eax
+ popl %ebp
+ ret
+.size func2, .-func2
+
+.globl _start
+.type _start, @function
+_start:
+ pushl %ebp
+ movl %esp, %ebp
+ call func1
+ popl %ebp
+ ret
+.size _start, .-_start
+
+.globl func1
+.type func1, @function
+func1:
+ pushl %ebp
+ movl %esp, %ebp
+ call func2
+.size func1, .-func1
+
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core
new file mode 100644
index 000000000000..6717d4ff6471
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out
new file mode 100755
index 000000000000..141c61ecbea3
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out
Binary files differ
diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp
index 6de8c667e7a7..d535742016ac 100644
--- a/source/Commands/CommandObjectRegister.cpp
+++ b/source/Commands/CommandObjectRegister.cpp
@@ -7,12 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ADT/STLExtras.h"
-
-// Project includes
#include "CommandObjectRegister.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/RegisterValue.h"
@@ -32,6 +26,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
+#include "llvm/Support/Errno.h"
using namespace lldb;
using namespace lldb_private;
@@ -178,8 +173,8 @@ protected:
if (set_idx < reg_ctx->GetRegisterSetCount()) {
if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) {
if (errno)
- result.AppendErrorWithFormat("register read failed: %s\n",
- strerror(errno));
+ result.AppendErrorWithFormatv("register read failed: {0}\n",
+ llvm::sys::StrError());
else
result.AppendError("unknown error while reading registers.\n");
result.SetStatus(eReturnStatusFailed);
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
index 6328e433852a..0c929c22f75f 100644
--- a/source/Core/Address.cpp
+++ b/source/Core/Address.cpp
@@ -361,8 +361,9 @@ addr_t Address::GetOpcodeLoadAddress(Target *target,
}
bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
- AddressClass addr_class) {
- if (SetLoadAddress(load_addr, target)) {
+ AddressClass addr_class,
+ bool allow_section_end) {
+ if (SetLoadAddress(load_addr, target, allow_section_end)) {
if (target) {
if (addr_class == eAddressClassInvalid)
addr_class = GetAddressClass();
@@ -1001,9 +1002,10 @@ AddressClass Address::GetAddressClass() const {
return eAddressClassUnknown;
}
-bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target) {
- if (target &&
- target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this))
+bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,
+ bool allow_section_end) {
+ if (target && target->GetSectionLoadList().ResolveLoadAddress(
+ load_addr, *this, allow_section_end))
return true;
m_section_wp.reset();
m_offset = load_addr;
diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp
index 91b73847ac1f..bfe9750f70f0 100644
--- a/source/Core/ArchSpec.cpp
+++ b/source/Core/ArchSpec.cpp
@@ -24,11 +24,11 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h" // for Twine
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
-#include "llvm/Support/ELF.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/MachO.h" // for CPUType::CPU_T...
+#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h" // for CPUType::CPU_T...
#include <memory> // for shared_ptr
#include <string>
diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt
index 7dcec050d866..806227793f24 100644
--- a/source/Core/CMakeLists.txt
+++ b/source/Core/CMakeLists.txt
@@ -67,6 +67,7 @@ add_lldb_library(lldbCore
lldbPluginObjectFileJIT
LINK_COMPONENTS
+ BinaryFormat
Support
Demangle
)
diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp
index f6428ced0164..3b76dd361ff3 100644
--- a/source/Core/Section.cpp
+++ b/source/Core/Section.cpp
@@ -220,18 +220,18 @@ addr_t Section::GetLoadBaseAddress(Target *target) const {
return load_base_addr;
}
-bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr) const {
+bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr,
+ bool allow_section_end) const {
const size_t num_children = m_children.GetSize();
- if (num_children > 0) {
- for (size_t i = 0; i < num_children; i++) {
- Section *child_section = m_children.GetSectionAtIndex(i).get();
-
- addr_t child_offset = child_section->GetOffset();
- if (child_offset <= offset &&
- offset - child_offset < child_section->GetByteSize())
- return child_section->ResolveContainedAddress(offset - child_offset,
- so_addr);
- }
+ for (size_t i = 0; i < num_children; i++) {
+ Section *child_section = m_children.GetSectionAtIndex(i).get();
+
+ addr_t child_offset = child_section->GetOffset();
+ if (child_offset <= offset &&
+ offset - child_offset <
+ child_section->GetByteSize() + (allow_section_end ? 1 : 0))
+ return child_section->ResolveContainedAddress(offset - child_offset,
+ so_addr, allow_section_end);
}
so_addr.SetOffset(offset);
so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp
index db3372c52925..184a8c98de62 100644
--- a/source/DataFormatters/TypeCategory.cpp
+++ b/source/DataFormatters/TypeCategory.cpp
@@ -36,23 +36,8 @@ TypeCategoryImpl::TypeCategoryImpl(
static bool IsApplicable(lldb::LanguageType category_lang,
lldb::LanguageType valobj_lang) {
switch (category_lang) {
- // these are not languages that LLDB would ordinarily deal with
- // only allow an exact equality here, since we really don't know
- // any better
- case eLanguageTypeAda83:
- case eLanguageTypeCobol74:
- case eLanguageTypeCobol85:
- case eLanguageTypeFortran77:
- case eLanguageTypeFortran90:
- case eLanguageTypePascal83:
- case eLanguageTypeModula2:
- case eLanguageTypeJava:
- case eLanguageTypeAda95:
- case eLanguageTypeFortran95:
- case eLanguageTypePLI:
- case eLanguageTypeUPC:
- case eLanguageTypeD:
- case eLanguageTypePython:
+ // Unless we know better, allow only exact equality.
+ default:
return category_lang == valobj_lang;
// the C family, we consider it as one
@@ -80,7 +65,7 @@ static bool IsApplicable(lldb::LanguageType category_lang,
valobj_lang == eLanguageTypeC_plus_plus ||
valobj_lang == eLanguageTypeObjC;
- default:
+ // Categories with unspecified language match everything.
case eLanguageTypeUnknown:
return true;
}
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index da35022c813c..d78961e5bffc 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -68,6 +68,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-forward.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#if defined(_WIN32)
@@ -217,10 +218,9 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) {
if (errno == EINTR)
continue;
else {
- if (log)
- log->Printf(
- "%s (arg = %p) thread exiting because waitpid failed (%s)...",
- __FUNCTION__, arg, strerror(errno));
+ LLDB_LOG(log,
+ "arg = {0}, thread exiting because waitpid failed ({1})...",
+ arg, llvm::sys::StrError());
break;
}
} else if (wait_pid > 0) {
diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 7a0c92b44918..c3b237a87302 100644
--- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -36,6 +36,7 @@
#include <sstream>
// Other libraries and framework includes
+#include "llvm/Support/Errno.h"
#include "llvm/Support/ErrorHandling.h"
#if defined(__APPLE__)
#include "llvm/ADT/SmallVector.h"
@@ -461,10 +462,8 @@ size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len,
return 0;
default:
- if (log)
- log->Printf(
- "%p ConnectionFileDescriptor::Read (), unexpected error: %s",
- static_cast<void *>(this), strerror(error_value));
+ LLDB_LOG(log, "this = {0}, unexpected error: {1}", this,
+ llvm::sys::StrError(error_value));
status = eConnectionStatusError;
break; // Break to close....
}
diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp
index 378670cd2a9a..1eace5cd24cd 100644
--- a/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -14,6 +14,7 @@
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "llvm/Support/Errno.h"
#include <limits.h>
#include <sys/ptrace.h>
@@ -204,8 +205,8 @@ ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info,
::pid_t pid = ::fork();
if (pid == -1) {
// Fork failed
- error.SetErrorStringWithFormat("Fork failed with error message: %s",
- strerror(errno));
+ error.SetErrorStringWithFormatv("Fork failed with error message: {0}",
+ llvm::sys::StrError());
return HostProcess(LLDB_INVALID_PROCESS_ID);
}
if (pid == 0) {
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 193c5864d01f..4d9227598cef 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -95,7 +95,7 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
// or '-' can be omitted
bool valid_prefix = false;
- if (name[0] == '+' || name[0] == '-') {
+ if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
valid_prefix = name[1] == '[';
if (name[0] == '+')
m_type = eTypeClassMethod;
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 566fefaf7984..9cac499c0ff0 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -171,6 +171,7 @@ UtilityFunction *AppleObjCRuntimeV1::CreateObjectChecker(const char *name) {
" \n",
name);
assert(strformatsize < (int)sizeof(buf->contents));
+ (void)strformatsize;
Status error;
return GetTargetRef().GetUtilityFunctionForLanguage(
diff --git a/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/source/Plugins/ObjectFile/ELF/CMakeLists.txt
index a941b8d55848..e0680b07efc5 100644
--- a/source/Plugins/ObjectFile/ELF/CMakeLists.txt
+++ b/source/Plugins/ObjectFile/ELF/CMakeLists.txt
@@ -8,5 +8,6 @@ add_lldb_library(lldbPluginObjectFileELF PLUGIN
lldbSymbol
lldbTarget
LINK_COMPONENTS
+ BinaryFormat
Support
)
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h
index e6738a1ecb2b..4e2d3155ebb9 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -21,7 +21,7 @@
#ifndef liblldb_ELFHeader_h_
#define liblldb_ELFHeader_h_
-#include "llvm/Support/ELF.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-types.h"
diff --git a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt b/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
index 1e8fb85c72c9..04321f276551 100644
--- a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
+++ b/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
@@ -8,5 +8,6 @@ add_lldb_library(lldbPluginObjectFilePECOFF PLUGIN
lldbSymbol
lldbTarget
LINK_COMPONENTS
+ BinaryFormat
Support
)
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index dcb9527f24c8..4739a4934aa6 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -10,7 +10,7 @@
#include "ObjectFilePECOFF.h"
#include "WindowsMiniDump.h"
-#include "llvm/Support/COFF.h"
+#include "llvm/BinaryFormat/COFF.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/FileSpecList.h"
diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
index 6845a36730c9..c6daf6ccea6e 100644
--- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
+++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
@@ -35,6 +35,7 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
+#include "llvm/Support/Errno.h"
#include "CFBundle.h"
#include "CFString.h"
@@ -319,13 +320,12 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
::posix_spawnattr_setsigdefault(&attr, &all_signals);
if ((error_code = ::posix_spawnattr_setflags(&attr, flags)) != 0) {
- if (log)
- log->Printf("::posix_spawnattr_setflags(&attr, "
- "POSIX_SPAWN_START_SUSPENDED%s) failed: %s",
- flags & _POSIX_SPAWN_DISABLE_ASLR
- ? " | _POSIX_SPAWN_DISABLE_ASLR"
- : "",
- strerror(error_code));
+ LLDB_LOG(log,
+ "::posix_spawnattr_setflags(&attr, "
+ "POSIX_SPAWN_START_SUSPENDED{0}) failed: {1}",
+ flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR"
+ : "",
+ llvm::sys::StrError(error_code));
error.SetError(error_code, eErrorTypePOSIX);
return error;
}
@@ -341,10 +341,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
error_code =
::posix_spawnattr_setbinpref_np(&attr, 1, &desired_cpu_type, &ocount);
if (error_code != 0) {
- if (log)
- log->Printf("::posix_spawnattr_setbinpref_np(&attr, 1, "
- "cpu_type = 0x%8.8x, count => %llu): %s",
- desired_cpu_type, (uint64_t)ocount, strerror(error_code));
+ LLDB_LOG(log,
+ "::posix_spawnattr_setbinpref_np(&attr, 1, "
+ "cpu_type = {0:x8}, count => {1}): {2}",
+ desired_cpu_type, ocount, llvm::sys::StrError(error_code));
error.SetError(error_code, eErrorTypePOSIX);
return error;
}
@@ -361,10 +361,8 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
posix_spawn_file_actions_t file_actions;
if ((error_code = ::posix_spawn_file_actions_init(&file_actions)) != 0) {
- if (log)
- log->Printf("::posix_spawn_file_actions_init(&file_actions) "
- "failed: %s",
- strerror(error_code));
+ LLDB_LOG(log, "::posix_spawn_file_actions_init(&file_actions) failed: {0}",
+ llvm::sys::StrError(error_code));
error.SetError(error_code, eErrorTypePOSIX);
return error;
}
@@ -409,11 +407,11 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
error_code = ::posix_spawnp(pid, path, &file_actions, &attr,
(char *const *)argv, (char *const *)envp);
if (error_code != 0) {
- if (log)
- log->Printf("::posix_spawnp(pid => %p, path = '%s', file_actions "
- "= %p, attr = %p, argv = %p, envp = %p) failed: %s",
- pid, path, &file_actions, &attr, argv, envp,
- strerror(error_code));
+ LLDB_LOG(log,
+ "::posix_spawnp(pid => {0}, path = '{1}', file_actions "
+ "= {2}, attr = {3}, argv = {4}, envp = {5}) failed: {6}",
+ pid, path, &file_actions, &attr, argv, envp,
+ llvm::sys::StrError(error_code));
error.SetError(error_code, eErrorTypePOSIX);
return error;
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 34d99cd39de2..10dd14753914 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -30,6 +30,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Status.h"
+#include "llvm/Support/Errno.h"
#include "FreeBSDThread.h"
#include "Plugins/Process/POSIX/CrashReason.h"
@@ -529,10 +530,8 @@ void ResumeOperation::Execute(ProcessMonitor *monitor) {
if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- if (log)
- log->Printf("ResumeOperation (%" PRIu64 ") failed: %s", pid,
- strerror(errno));
+ LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid,
+ llvm::sys::StrError(errno));
m_result = false;
} else
m_result = true;
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 15e7c9b5f698..a130472c72d0 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -43,14 +43,14 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
#include "NativeThreadLinux.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Procfs.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Threading.h"
-
#include <linux/unistd.h>
#include <sys/socket.h>
#include <sys/syscall.h>
@@ -97,7 +97,7 @@ static bool ProcessVmReadvSupported() {
LLDB_LOG(log,
"syscall process_vm_readv failed (error: {0}). Fast memory "
"reads disabled.",
- strerror(errno));
+ llvm::sys::StrError());
});
return is_supported;
@@ -1988,7 +1988,7 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
LLDB_LOG(log,
"using process_vm_readv to read {0} bytes from inferior "
"address {1:x}: {2}",
- size, addr, success ? "Success" : strerror(errno));
+ size, addr, success ? "Success" : llvm::sys::StrError(errno));
if (success)
return Status();
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 312c1887b581..bce77d7e0a32 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -329,7 +329,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
if (abi)
pc = abi->FixCodeAddress(pc);
- m_current_pc.SetLoadAddress(pc, &process->GetTarget());
+ const bool allow_section_end = true;
+ m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);
// If we don't have a Module for some reason, we're not going to find
// symbol/function information - just
@@ -477,11 +478,12 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
// Or if we're in the middle of the stack (and not "above" an asynchronous
// event like sigtramp),
// and our "current" pc is the start of a function...
- if (m_sym_ctx_valid && GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
+ if (GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
GetNextFrame()->m_frame_type != eDebuggerFrame &&
- addr_range.GetBaseAddress().IsValid() &&
- addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() &&
- addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) {
+ (!m_sym_ctx_valid ||
+ (addr_range.GetBaseAddress().IsValid() &&
+ addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() &&
+ addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()))) {
decr_pc_and_recompute_addr_range = true;
}
diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt
index b358697d25af..c7ffae695320 100644
--- a/source/Plugins/Process/elf-core/CMakeLists.txt
+++ b/source/Plugins/Process/elf-core/CMakeLists.txt
@@ -17,5 +17,6 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN
lldbPluginObjectFileELF
lldbPluginProcessUtility
LINK_COMPONENTS
+ BinaryFormat
Support
)
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 5a459e80348b..71eb6437ceed 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -27,7 +27,7 @@
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
-#include "llvm/Support/ELF.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Threading.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index cb00e840673f..f5418763d67b 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -3732,8 +3732,8 @@ static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {
}
}
}
- assert(!"Shouldn't call GetContainingFunctionWithAbstractOrigin on something "
- "not in a function");
+ assert(0 && "Shouldn't call GetContainingFunctionWithAbstractOrigin on "
+ "something not in a function");
return DWARFDIE();
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 279efe320a46..252a9807a3b5 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1958,7 +1958,7 @@ void SymbolFileDWARF::Index() {
&function_fullname_index, &function_method_index,
&function_selector_index, &objc_class_selectors_index,
&global_index, &type_index,
- &namespace_index](uint32_t cu_idx) {
+ &namespace_index](size_t cu_idx) {
DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu) {
dwarf_cu->Index(
@@ -1967,10 +1967,9 @@ void SymbolFileDWARF::Index() {
objc_class_selectors_index[cu_idx], global_index[cu_idx],
type_index[cu_idx], namespace_index[cu_idx]);
}
- return cu_idx;
};
- auto extract_fn = [debug_info, &clear_cu_dies](uint32_t cu_idx) {
+ auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) {
DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu) {
// dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the
diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp
index 7f12c262f47e..31ccf17369db 100644
--- a/source/Target/SectionLoadList.cpp
+++ b/source/Target/SectionLoadList.cpp
@@ -207,8 +207,8 @@ bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp,
return erased;
}
-bool SectionLoadList::ResolveLoadAddress(addr_t load_addr,
- Address &so_addr) const {
+bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
+ bool allow_section_end) const {
// First find the top level section that this load address exists in
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_addr_to_sect.empty()) {
@@ -220,10 +220,11 @@ bool SectionLoadList::ResolveLoadAddress(addr_t load_addr,
const addr_t pos_load_addr = pos->first;
if (load_addr >= pos_load_addr) {
addr_t offset = load_addr - pos_load_addr;
- if (offset < pos->second->GetByteSize()) {
+ if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
// We have found the top level section, now we need to find the
// deepest child section.
- return pos->second->ResolveContainedAddress(offset, so_addr);
+ return pos->second->ResolveContainedAddress(offset, so_addr,
+ allow_section_end);
}
}
} else {
@@ -233,10 +234,12 @@ bool SectionLoadList::ResolveLoadAddress(addr_t load_addr,
m_addr_to_sect.rbegin();
if (load_addr >= rpos->first) {
addr_t offset = load_addr - rpos->first;
- if (offset < rpos->second->GetByteSize()) {
+ if (offset <
+ rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
// We have found the top level section, now we need to find the
// deepest child section.
- return rpos->second->ResolveContainedAddress(offset, so_addr);
+ return rpos->second->ResolveContainedAddress(offset, so_addr,
+ allow_section_end);
}
}
}
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 9deebcaf9250..4ef4a399290a 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -191,9 +191,10 @@ const Address &StackFrame::GetFrameCodeAddress() {
if (thread_sp) {
TargetSP target_sp(thread_sp->CalculateTarget());
if (target_sp) {
+ const bool allow_section_end = true;
if (m_frame_code_addr.SetOpcodeLoadAddress(
m_frame_code_addr.GetOffset(), target_sp.get(),
- eAddressClassCode)) {
+ eAddressClassCode, allow_section_end)) {
ModuleSP module_sp(m_frame_code_addr.GetModule());
if (module_sp) {
m_sc.module_sp = module_sp;
diff --git a/source/Utility/CMakeLists.txt b/source/Utility/CMakeLists.txt
index a1675670f0b4..31b14acda962 100644
--- a/source/Utility/CMakeLists.txt
+++ b/source/Utility/CMakeLists.txt
@@ -38,5 +38,6 @@ add_lldb_library(lldbUtility
# lldbUtility cannot have any dependencies
LINK_COMPONENTS
+ BinaryFormat
Support
)
diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp
index ba87d3e5144f..6ecc7717620b 100644
--- a/source/Utility/Status.cpp
+++ b/source/Utility/Status.cpp
@@ -11,10 +11,11 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/VASPrintf.h"
-#include "lldb/lldb-defines.h" // for LLDB_GENERIC_ERROR
-#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType::eErr...
-#include "llvm/ADT/SmallString.h" // for SmallString
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-defines.h" // for LLDB_GENERIC_ERROR
+#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType::eErr...
+#include "llvm/ADT/SmallString.h" // for SmallString
+#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/Support/Errno.h"
#include "llvm/Support/FormatProviders.h" // for format_provider
#include <cerrno>
@@ -27,7 +28,6 @@
#endif
#include <stdint.h> // for uint32_t
-#include <string.h> // for strerror
namespace llvm {
class raw_ostream;
@@ -121,23 +121,21 @@ const char *Status::AsCString(const char *default_error_str) const {
return nullptr;
if (m_string.empty()) {
- const char *s = nullptr;
switch (m_type) {
case eErrorTypeMachKernel:
#if defined(__APPLE__)
- s = ::mach_error_string(m_code);
+ if (const char *s = ::mach_error_string(m_code))
+ m_string.assign(s);
#endif
break;
case eErrorTypePOSIX:
- s = ::strerror(m_code);
+ m_string = llvm::sys::StrError(m_code);
break;
default:
break;
}
- if (s != nullptr)
- m_string.assign(s);
}
if (m_string.empty()) {
if (default_error_str)
diff --git a/source/Utility/TaskPool.cpp b/source/Utility/TaskPool.cpp
index d8306dc7dc8f..d33f23cd861c 100644
--- a/source/Utility/TaskPool.cpp
+++ b/source/Utility/TaskPool.cpp
@@ -75,7 +75,7 @@ void TaskPoolImpl::Worker(TaskPoolImpl *pool) {
}
void TaskMapOverInt(size_t begin, size_t end,
- std::function<void(size_t)> const &func) {
+ const llvm::function_ref<void(size_t)> &func) {
std::atomic<size_t> idx{begin};
size_t num_workers =
std::min<size_t>(end, std::thread::hardware_concurrency());
diff --git a/source/Utility/VMRange.cpp b/source/Utility/VMRange.cpp
index 5eccd292a851..105b1a58c48c 100644
--- a/source/Utility/VMRange.cpp
+++ b/source/Utility/VMRange.cpp
@@ -25,34 +25,13 @@ using namespace lldb_private;
bool VMRange::ContainsValue(const VMRange::collection &coll,
lldb::addr_t value) {
ValueInRangeUnaryPredicate in_range_predicate(value);
- VMRange::const_iterator pos;
- VMRange::const_iterator end = coll.end();
- pos = std::find_if(coll.begin(), end, in_range_predicate);
- if (pos != end)
- return true;
- return false;
+ return llvm::find_if(coll, in_range_predicate) != coll.end();
}
bool VMRange::ContainsRange(const VMRange::collection &coll,
const VMRange &range) {
RangeInRangeUnaryPredicate in_range_predicate(range);
- VMRange::const_iterator pos;
- VMRange::const_iterator end = coll.end();
- pos = std::find_if(coll.begin(), end, in_range_predicate);
- if (pos != end)
- return true;
- return false;
-}
-
-size_t VMRange::FindRangeIndexThatContainsValue(const VMRange::collection &coll,
- lldb::addr_t value) {
- ValueInRangeUnaryPredicate in_range_predicate(value);
- VMRange::const_iterator begin = coll.begin();
- VMRange::const_iterator end = coll.end();
- VMRange::const_iterator pos = std::find_if(begin, end, in_range_predicate);
- if (pos != end)
- return std::distance(begin, pos);
- return UINT32_MAX;
+ return llvm::find_if(coll, in_range_predicate) != coll.end();
}
void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const {
@@ -66,8 +45,7 @@ bool lldb_private::operator==(const VMRange &lhs, const VMRange &rhs) {
}
bool lldb_private::operator!=(const VMRange &lhs, const VMRange &rhs) {
- return lhs.GetBaseAddress() != rhs.GetBaseAddress() ||
- lhs.GetEndAddress() != rhs.GetEndAddress();
+ return !(lhs == rhs);
}
bool lldb_private::operator<(const VMRange &lhs, const VMRange &rhs) {
@@ -79,25 +57,13 @@ bool lldb_private::operator<(const VMRange &lhs, const VMRange &rhs) {
}
bool lldb_private::operator<=(const VMRange &lhs, const VMRange &rhs) {
- if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
- return true;
- else if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
- return false;
- return lhs.GetEndAddress() <= rhs.GetEndAddress();
+ return !(lhs > rhs);
}
bool lldb_private::operator>(const VMRange &lhs, const VMRange &rhs) {
- if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
- return true;
- else if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
- return false;
- return lhs.GetEndAddress() > rhs.GetEndAddress();
+ return rhs < lhs;
}
bool lldb_private::operator>=(const VMRange &lhs, const VMRange &rhs) {
- if (lhs.GetBaseAddress() > rhs.GetBaseAddress())
- return true;
- else if (lhs.GetBaseAddress() < rhs.GetBaseAddress())
- return false;
- return lhs.GetEndAddress() >= rhs.GetEndAddress();
+ return !(lhs < rhs);
}
diff --git a/tools/lldb-server/lldb-gdbserver.cpp b/tools/lldb-server/lldb-gdbserver.cpp
index 6139bfabee3d..412d775e8394 100644
--- a/tools/lldb-server/lldb-gdbserver.cpp
+++ b/tools/lldb-server/lldb-gdbserver.cpp
@@ -21,8 +21,6 @@
// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
#include "Acceptor.h"
#include "LLDBServerUtilities.h"
@@ -36,6 +34,8 @@
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Status.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errno.h"
#ifndef LLGS_PROGRAM_NAME
#define LLGS_PROGRAM_NAME "lldb-server"
@@ -398,10 +398,9 @@ int main_gdbserver(int argc, char *argv[]) {
{
const ::pid_t new_sid = setsid();
if (new_sid == -1) {
- const char *errno_str = strerror(errno);
- fprintf(stderr, "failed to set new session id for %s (%s)\n",
- LLGS_PROGRAM_NAME,
- errno_str ? errno_str : "<no error string>");
+ llvm::errs() << llvm::formatv(
+ "failed to set new session id for {0} ({1})\n", LLGS_PROGRAM_NAME,
+ llvm::sys::StrError());
}
}
break;
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index f78879db09b4..c7c3140b121a 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -68,9 +68,10 @@ add_subdirectory(Signals)
add_subdirectory(Symbol)
add_subdirectory(SymbolFile)
add_subdirectory(Target)
+add_subdirectory(tools)
add_subdirectory(UnwindAssembly)
add_subdirectory(Utility)
if(LLDB_CAN_USE_DEBUGSERVER)
add_subdirectory(debugserver)
-endif() \ No newline at end of file
+endif()
diff --git a/unittests/Core/ArchSpecTest.cpp b/unittests/Core/ArchSpecTest.cpp
index 8fed7adba07c..98b77e1826b1 100644
--- a/unittests/Core/ArchSpecTest.cpp
+++ b/unittests/Core/ArchSpecTest.cpp
@@ -11,7 +11,7 @@
#include "lldb/Core/ArchSpec.h"
-#include "llvm/Support/MachO.h"
+#include "llvm/BinaryFormat/MachO.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/unittests/Core/StructuredDataTest.cpp b/unittests/Core/StructuredDataTest.cpp
index cac330304179..cdcf3236cd77 100644
--- a/unittests/Core/StructuredDataTest.cpp
+++ b/unittests/Core/StructuredDataTest.cpp
@@ -12,7 +12,7 @@
#include "lldb/Core/StructuredData.h"
#include "lldb/Utility/StreamString.h"
-#include "llvm/Support/MachO.h"
+#include "llvm/BinaryFormat/MachO.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index c9ab0b6050a0..8f6f9f0684a3 100644
--- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -318,8 +318,6 @@ TEST_F(GDBRemoteCommunicationClientTest, SendSignalsToIgnore) {
if (HasFailure())
return;
- const lldb::tid_t tid = 0x47;
- const uint32_t reg_num = 4;
std::future<Status> result = std::async(std::launch::async, [&] {
return client.SendSignalsToIgnore({2, 3, 5, 7, 0xB, 0xD, 0x11});
});
@@ -406,7 +404,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) {
R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
HandlePacket(server, (expected_packet1 + expected_packet2), "1");
ASSERT_TRUE(error.Success());
- ASSERT_EQ(result.get(), 1);
+ ASSERT_EQ(result.get(), 1u);
error.Clear();
result = std::async(std::launch::async, [&] {
@@ -468,7 +466,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) {
std::string expected_packet2 = R"("traceid" : 3})";
HandlePacket(server, expected_packet1+expected_packet2, "123456");
ASSERT_TRUE(result.get().Success());
- ASSERT_EQ(buffer.size(), 3);
+ ASSERT_EQ(buffer.size(), 3u);
ASSERT_EQ(buf[0], 0x12);
ASSERT_EQ(buf[1], 0x34);
ASSERT_EQ(buf[2], 0x56);
@@ -480,7 +478,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) {
HandlePacket(server, expected_packet1+expected_packet2, "E23");
ASSERT_FALSE(result.get().Success());
- ASSERT_EQ(buffer2.size(), 0);
+ ASSERT_EQ(buffer2.size(), 0u);
}
TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
@@ -506,7 +504,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
std::string expected_packet2 = R"("traceid" : 3})";
HandlePacket(server, expected_packet1+expected_packet2, "123456");
ASSERT_TRUE(result.get().Success());
- ASSERT_EQ(buffer.size(), 3);
+ ASSERT_EQ(buffer.size(), 3u);
ASSERT_EQ(buf[0], 0x12);
ASSERT_EQ(buf[1], 0x34);
ASSERT_EQ(buf[2], 0x56);
@@ -518,7 +516,7 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
HandlePacket(server, expected_packet1+expected_packet2, "E23");
ASSERT_FALSE(result.get().Success());
- ASSERT_EQ(buffer2.size(), 0);
+ ASSERT_EQ(buffer2.size(), 0u);
}
TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
@@ -545,8 +543,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
HandlePacket(server, expected_packet, response1+response2);
ASSERT_TRUE(result.get().Success());
- ASSERT_EQ(options.getTraceBufferSize(), 8192);
- ASSERT_EQ(options.getMetaDataBufferSize(), 8192);
+ ASSERT_EQ(options.getTraceBufferSize(), 8192u);
+ ASSERT_EQ(options.getMetaDataBufferSize(), 8192u);
ASSERT_EQ(options.getType(), 1);
auto custom_params = options.getTraceParams();
@@ -556,9 +554,8 @@ TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
ASSERT_TRUE(custom_params);
ASSERT_EQ(custom_params->GetType(), eStructuredDataTypeDictionary);
- ASSERT_TRUE(
- custom_params->GetValueForKeyAsInteger<uint64_t>("psb", psb_value));
- ASSERT_EQ(psb_value, 1);
+ ASSERT_TRUE(custom_params->GetValueForKeyAsInteger("psb", psb_value));
+ ASSERT_EQ(psb_value, 1u);
ASSERT_TRUE(
custom_params->GetValueForKeyAsString("tracetech", trace_tech_value));
ASSERT_STREQ(trace_tech_value.data(), "intel-pt");
diff --git a/unittests/tools/CMakeLists.txt b/unittests/tools/CMakeLists.txt
new file mode 100644
index 000000000000..2d41864d98f4
--- /dev/null
+++ b/unittests/tools/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(CMAKE_SYSTEM_NAME MATCHES "Android|Linux|NetBSD")
+ add_subdirectory(lldb-server)
+endif()
diff --git a/unittests/tools/lldb-server/CMakeLists.txt b/unittests/tools/lldb-server/CMakeLists.txt
new file mode 100644
index 000000000000..b7113c3d260c
--- /dev/null
+++ b/unittests/tools/lldb-server/CMakeLists.txt
@@ -0,0 +1,13 @@
+function(add_lldb_test_executable test_name)
+ set(EXCLUDE_FROM_ALL ON)
+ add_llvm_executable(${test_name} NO_INSTALL_RPATH ${ARGN})
+ set(outdir ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR})
+ set_output_directory(${test_name} BINARY_DIR ${outdir} LIBRARY_DIR ${outdir})
+endfunction()
+
+add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp)
+
+add_definitions(-DLLDB_SERVER="$<TARGET_FILE:lldb-server>")
+add_definitions(-DTHREAD_INFERIOR="${CMAKE_CURRENT_BINARY_DIR}/thread_inferior")
+add_subdirectory(tests)
+add_dependencies(LLDBServerTests thread_inferior)
diff --git a/unittests/tools/lldb-server/inferior/thread_inferior.cpp b/unittests/tools/lldb-server/inferior/thread_inferior.cpp
new file mode 100644
index 000000000000..d968e9ef71ea
--- /dev/null
+++ b/unittests/tools/lldb-server/inferior/thread_inferior.cpp
@@ -0,0 +1,41 @@
+//===-- thread_inferior.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <atomic>
+#include <chrono>
+#include <string>
+#include <thread>
+#include <vector>
+
+int main(int argc, char* argv[]) {
+ int thread_count = 2;
+ if (argc > 1) {
+ thread_count = std::stoi(argv[1], nullptr, 10);
+ }
+
+ std::atomic<bool> delay(true);
+ std::vector<std::thread> threads;
+ for (int i = 0; i < thread_count; i++) {
+ threads.push_back(std::thread([&delay] {
+ while (delay.load())
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }));
+ }
+
+ // Cause a break.
+ volatile char *p = NULL;
+ *p = 'a';
+
+ delay.store(false);
+ for (std::thread& t : threads) {
+ t.join();
+ }
+
+ return 0;
+}
diff --git a/unittests/tools/lldb-server/tests/CMakeLists.txt b/unittests/tools/lldb-server/tests/CMakeLists.txt
new file mode 100644
index 000000000000..4ef4165b27fe
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_lldb_unittest(LLDBServerTests
+ TestClient.cpp
+ MessageObjects.cpp
+ ThreadIdsInJstopinfoTest.cpp
+
+ LINK_LIBS
+ lldbHost
+ lldbCore
+ lldbInterpreter
+ lldbTarget
+ lldbPluginPlatformLinux
+ lldbPluginProcessGDBRemote
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/unittests/tools/lldb-server/tests/MessageObjects.cpp b/unittests/tools/lldb-server/tests/MessageObjects.cpp
new file mode 100644
index 000000000000..fd44bf6b23a9
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/MessageObjects.cpp
@@ -0,0 +1,207 @@
+//===-- MessageObjects.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MessageObjects.h"
+#include "lldb/Core/StructuredData.h"
+#include "llvm/ADT/StringExtras.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+using namespace llvm;
+using namespace llvm::support;
+namespace llgs_tests {
+
+Expected<ProcessInfo> ProcessInfo::Create(StringRef response) {
+ ProcessInfo process_info;
+ auto elements_or_error = SplitPairList("ProcessInfo", response);
+ if (!elements_or_error)
+ return elements_or_error.takeError();
+
+ auto &elements = *elements_or_error;
+ if (elements["pid"].getAsInteger(16, process_info.m_pid))
+ return make_parsing_error("ProcessInfo: pid");
+ if (elements["parent-pid"].getAsInteger(16, process_info.m_parent_pid))
+ return make_parsing_error("ProcessInfo: parent-pid");
+ if (elements["real-uid"].getAsInteger(16, process_info.m_real_uid))
+ return make_parsing_error("ProcessInfo: real-uid");
+ if (elements["real-gid"].getAsInteger(16, process_info.m_real_gid))
+ return make_parsing_error("ProcessInfo: real-uid");
+ if (elements["effective-uid"].getAsInteger(16, process_info.m_effective_uid))
+ return make_parsing_error("ProcessInfo: effective-uid");
+ if (elements["effective-gid"].getAsInteger(16, process_info.m_effective_gid))
+ return make_parsing_error("ProcessInfo: effective-gid");
+ if (elements["ptrsize"].getAsInteger(10, process_info.m_ptrsize))
+ return make_parsing_error("ProcessInfo: ptrsize");
+
+ process_info.m_triple = fromHex(elements["triple"]);
+ StringRef endian_str = elements["endian"];
+ if (endian_str == "little")
+ process_info.m_endian = support::little;
+ else if (endian_str == "big")
+ process_info.m_endian = support::big;
+ else
+ return make_parsing_error("ProcessInfo: endian");
+
+ return process_info;
+}
+
+lldb::pid_t ProcessInfo::GetPid() const { return m_pid; }
+
+endianness ProcessInfo::GetEndian() const { return m_endian; }
+
+//====== ThreadInfo ============================================================
+ThreadInfo::ThreadInfo(StringRef name, StringRef reason,
+ const RegisterMap &registers, unsigned int signal)
+ : m_name(name.str()), m_reason(reason.str()), m_registers(registers),
+ m_signal(signal) {}
+
+StringRef ThreadInfo::ReadRegister(unsigned int register_id) const {
+ return m_registers.lookup(register_id);
+}
+
+bool ThreadInfo::ReadRegisterAsUint64(unsigned int register_id,
+ uint64_t &value) const {
+ StringRef value_str(m_registers.lookup(register_id));
+ if (value_str.getAsInteger(16, value)) {
+ GTEST_LOG_(ERROR)
+ << formatv("ThreadInfo: Unable to parse register value at {0}.",
+ register_id)
+ .str();
+ return false;
+ }
+
+ sys::swapByteOrder(value);
+ return true;
+}
+
+//====== JThreadsInfo ==========================================================
+Expected<JThreadsInfo> JThreadsInfo::Create(StringRef response,
+ endianness endian) {
+ JThreadsInfo jthreads_info;
+
+ StructuredData::ObjectSP json = StructuredData::ParseJSON(response);
+ StructuredData::Array *array = json->GetAsArray();
+ if (!array)
+ return make_parsing_error("JThreadsInfo: JSON array");
+
+ for (size_t i = 0; i < array->GetSize(); i++) {
+ StructuredData::Dictionary *thread_info;
+ array->GetItemAtIndexAsDictionary(i, thread_info);
+ if (!thread_info)
+ return make_parsing_error("JThreadsInfo: JSON obj at {0}", i);
+
+ StringRef name, reason;
+ thread_info->GetValueForKeyAsString("name", name);
+ thread_info->GetValueForKeyAsString("reason", reason);
+ uint64_t signal;
+ thread_info->GetValueForKeyAsInteger("signal", signal);
+ uint64_t tid;
+ thread_info->GetValueForKeyAsInteger("tid", tid);
+
+ StructuredData::Dictionary *register_dict;
+ thread_info->GetValueForKeyAsDictionary("registers", register_dict);
+ if (!register_dict)
+ return make_parsing_error("JThreadsInfo: registers JSON obj");
+
+ RegisterMap registers;
+
+ auto keys_obj = register_dict->GetKeys();
+ auto keys = keys_obj->GetAsArray();
+ for (size_t i = 0; i < keys->GetSize(); i++) {
+ StringRef key_str, value_str;
+ keys->GetItemAtIndexAsString(i, key_str);
+ register_dict->GetValueForKeyAsString(key_str, value_str);
+ unsigned int register_id;
+ if (key_str.getAsInteger(10, register_id))
+ return make_parsing_error("JThreadsInfo: register key[{0}]", i);
+
+ registers[register_id] = value_str.str();
+ }
+
+ jthreads_info.m_thread_infos[tid] =
+ ThreadInfo(name, reason, registers, signal);
+ }
+
+ return jthreads_info;
+}
+
+const ThreadInfoMap &JThreadsInfo::GetThreadInfos() const {
+ return m_thread_infos;
+}
+
+//====== StopReply =============================================================
+const U64Map &StopReply::GetThreadPcs() const { return m_thread_pcs; }
+
+Expected<StopReply> StopReply::Create(StringRef response,
+ llvm::support::endianness endian) {
+ StopReply stop_reply;
+
+ auto elements_or_error = SplitPairList("StopReply", response);
+ if (auto split_error = elements_or_error.takeError()) {
+ return std::move(split_error);
+ }
+
+ auto elements = *elements_or_error;
+ stop_reply.m_name = elements["name"];
+ stop_reply.m_reason = elements["reason"];
+
+ SmallVector<StringRef, 20> threads;
+ SmallVector<StringRef, 20> pcs;
+ elements["threads"].split(threads, ',');
+ elements["thread-pcs"].split(pcs, ',');
+ if (threads.size() != pcs.size())
+ return make_parsing_error("StopReply: thread/PC count mismatch");
+
+ for (size_t i = 0; i < threads.size(); i++) {
+ lldb::tid_t thread_id;
+ uint64_t pc;
+ if (threads[i].getAsInteger(16, thread_id))
+ return make_parsing_error("StopReply: thread ID at [{0}].", i);
+ if (pcs[i].getAsInteger(16, pc))
+ return make_parsing_error("StopReply: thread PC at [{0}].", i);
+
+ stop_reply.m_thread_pcs[thread_id] = pc;
+ }
+
+ for (auto i = elements.begin(); i != elements.end(); i++) {
+ StringRef key = i->getKey();
+ StringRef val = i->getValue();
+ if (key.size() >= 9 && key[0] == 'T' && key.substr(3, 6) == "thread") {
+ if (val.getAsInteger(16, stop_reply.m_thread))
+ return make_parsing_error("StopReply: thread id");
+ if (key.substr(1, 2).getAsInteger(16, stop_reply.m_signal))
+ return make_parsing_error("StopReply: stop signal");
+ } else if (key.size() == 2) {
+ unsigned int reg;
+ if (!key.getAsInteger(16, reg)) {
+ stop_reply.m_registers[reg] = val.str();
+ }
+ }
+ }
+
+ return stop_reply;
+}
+
+//====== Globals ===============================================================
+Expected<StringMap<StringRef>> SplitPairList(StringRef caller, StringRef str) {
+ SmallVector<StringRef, 20> elements;
+ str.split(elements, ';');
+
+ StringMap<StringRef> pairs;
+ for (StringRef s : elements) {
+ std::pair<StringRef, StringRef> pair = s.split(':');
+ if (pairs.count(pair.first))
+ return make_parsing_error("{0}: Duplicate Key: {1}", caller, pair.first);
+
+ pairs.insert(s.split(':'));
+ }
+
+ return pairs;
+}
+} // namespace llgs_tests
diff --git a/unittests/tools/lldb-server/tests/MessageObjects.h b/unittests/tools/lldb-server/tests/MessageObjects.h
new file mode 100644
index 000000000000..82551e2bb549
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/MessageObjects.h
@@ -0,0 +1,102 @@
+//===-- MessageObjects.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <string>
+
+namespace llgs_tests {
+class ThreadInfo;
+typedef llvm::DenseMap<uint64_t, ThreadInfo> ThreadInfoMap;
+typedef llvm::DenseMap<uint64_t, uint64_t> U64Map;
+typedef llvm::DenseMap<unsigned int, std::string> RegisterMap;
+
+class ProcessInfo {
+public:
+ static llvm::Expected<ProcessInfo> Create(llvm::StringRef response);
+ lldb::pid_t GetPid() const;
+ llvm::support::endianness GetEndian() const;
+
+private:
+ ProcessInfo() = default;
+ lldb::pid_t m_pid;
+ lldb::pid_t m_parent_pid;
+ uint32_t m_real_uid;
+ uint32_t m_real_gid;
+ uint32_t m_effective_uid;
+ uint32_t m_effective_gid;
+ std::string m_triple;
+ llvm::SmallString<16> m_ostype;
+ llvm::support::endianness m_endian;
+ unsigned int m_ptrsize;
+};
+
+class ThreadInfo {
+public:
+ ThreadInfo() = default;
+ ThreadInfo(llvm::StringRef name, llvm::StringRef reason,
+ const RegisterMap &registers, unsigned int signal);
+
+ llvm::StringRef ReadRegister(unsigned int register_id) const;
+ bool ReadRegisterAsUint64(unsigned int register_id, uint64_t &value) const;
+
+private:
+ std::string m_name;
+ std::string m_reason;
+ RegisterMap m_registers;
+ unsigned int m_signal;
+};
+
+class JThreadsInfo {
+public:
+ static llvm::Expected<JThreadsInfo> Create(llvm::StringRef response,
+ llvm::support::endianness endian);
+
+ const ThreadInfoMap &GetThreadInfos() const;
+
+private:
+ JThreadsInfo() = default;
+ ThreadInfoMap m_thread_infos;
+};
+
+class StopReply {
+public:
+ static llvm::Expected<StopReply> Create(llvm::StringRef response,
+ llvm::support::endianness endian);
+ const U64Map &GetThreadPcs() const;
+
+private:
+ StopReply() = default;
+ void ParseResponse(llvm::StringRef response,
+ llvm::support::endianness endian);
+ unsigned int m_signal;
+ lldb::tid_t m_thread;
+ std::string m_name;
+ U64Map m_thread_pcs;
+ RegisterMap m_registers;
+ std::string m_reason;
+};
+
+// Common functions for parsing packet data.
+llvm::Expected<llvm::StringMap<llvm::StringRef>>
+SplitPairList(llvm::StringRef caller, llvm::StringRef s);
+
+template <typename... Args>
+llvm::Error make_parsing_error(llvm::StringRef format, Args &&... args) {
+ std::string error =
+ "Unable to parse " +
+ llvm::formatv(format.data(), std::forward<Args>(args)...).str();
+ return llvm::make_error<llvm::StringError>(error,
+ llvm::inconvertibleErrorCode());
+}
+} // namespace llgs_tests
diff --git a/unittests/tools/lldb-server/tests/TestClient.cpp b/unittests/tools/lldb-server/tests/TestClient.cpp
new file mode 100644
index 000000000000..540d7979055c
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/TestClient.cpp
@@ -0,0 +1,287 @@
+//===-- TestClient.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestClient.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/common/TCPSocket.h"
+#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
+#include "lldb/Host/posix/ProcessLauncherPosix.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+#include "llvm/ADT/StringExtras.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+#include <future>
+#include <sstream>
+#include <string>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+namespace llgs_tests {
+void TestClient::Initialize() { HostInfo::Initialize(); }
+
+TestClient::TestClient(const std::string &test_name,
+ const std::string &test_case_name)
+ : m_test_name(test_name), m_test_case_name(test_case_name),
+ m_pc_register(UINT_MAX) {}
+
+TestClient::~TestClient() {}
+
+bool TestClient::StartDebugger() {
+ const ArchSpec &arch_spec = HostInfo::GetArchitecture();
+ Args args;
+ args.AppendArgument(LLDB_SERVER);
+ args.AppendArgument("gdbserver");
+ args.AppendArgument("--log-channels=gdb-remote packets");
+ args.AppendArgument("--reverse-connect");
+ std::string log_file_name = GenerateLogFileName(arch_spec);
+ if (log_file_name.size()) {
+ args.AppendArgument("--log-file=" + log_file_name);
+ }
+
+ Status error;
+ TCPSocket listen_socket(true, false);
+ error = listen_socket.Listen("127.0.0.1:0", 5);
+ if (error.Fail()) {
+ GTEST_LOG_(ERROR) << "Unable to open listen socket.";
+ return false;
+ }
+
+ char connect_remote_address[64];
+ snprintf(connect_remote_address, sizeof(connect_remote_address),
+ "localhost:%u", listen_socket.GetLocalPortNumber());
+
+ args.AppendArgument(connect_remote_address);
+
+ m_server_process_info.SetArchitecture(arch_spec);
+ m_server_process_info.SetArguments(args, true);
+ Status status = Host::LaunchProcess(m_server_process_info);
+ if (status.Fail()) {
+ GTEST_LOG_(ERROR)
+ << formatv("Failure to launch lldb server: {0}.", status).str();
+ return false;
+ }
+
+ char connect_remote_uri[64];
+ snprintf(connect_remote_uri, sizeof(connect_remote_uri), "connect://%s",
+ connect_remote_address);
+ Socket *accept_socket;
+ listen_socket.Accept(accept_socket);
+ SetConnection(new ConnectionFileDescriptor(accept_socket));
+
+ SendAck(); // Send this as a handshake.
+ return true;
+}
+
+bool TestClient::StopDebugger() {
+ std::string response;
+ return SendMessage("k", response, PacketResult::ErrorDisconnected);
+}
+
+bool TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) {
+ std::stringstream command;
+ command << "A";
+ for (size_t i = 0; i < inferior_args.size(); i++) {
+ if (i > 0)
+ command << ',';
+ std::string hex_encoded = toHex(inferior_args[i]);
+ command << hex_encoded.size() << ',' << i << ',' << hex_encoded;
+ }
+
+ if (!SendMessage(command.str()))
+ return false;
+ if (!SendMessage("qLaunchSuccess"))
+ return false;
+ std::string response;
+ if (!SendMessage("qProcessInfo", response))
+ return false;
+ auto create_or_error = ProcessInfo::Create(response);
+ if (auto create_error = create_or_error.takeError()) {
+ GTEST_LOG_(ERROR) << toString(std::move(create_error));
+ return false;
+ }
+
+ m_process_info = *create_or_error;
+ return true;
+}
+
+bool TestClient::ListThreadsInStopReply() {
+ return SendMessage("QListThreadsInStopReply");
+}
+
+bool TestClient::SetBreakpoint(unsigned long address) {
+ std::stringstream command;
+ command << "Z0," << std::hex << address << ",1";
+ return SendMessage(command.str());
+}
+
+bool TestClient::ContinueAll() { return Continue("vCont;c"); }
+
+bool TestClient::ContinueThread(unsigned long thread_id) {
+ return Continue(formatv("vCont;c:{0:x-}", thread_id).str());
+}
+
+const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; }
+
+Optional<JThreadsInfo> TestClient::GetJThreadsInfo() {
+ std::string response;
+ if (!SendMessage("jThreadsInfo", response))
+ return llvm::None;
+ auto creation = JThreadsInfo::Create(response, m_process_info->GetEndian());
+ if (auto create_error = creation.takeError()) {
+ GTEST_LOG_(ERROR) << toString(std::move(create_error));
+ return llvm::None;
+ }
+
+ return std::move(*creation);
+}
+
+const StopReply &TestClient::GetLatestStopReply() {
+ return m_stop_reply.getValue();
+}
+
+bool TestClient::SendMessage(StringRef message) {
+ std::string dummy_string;
+ return SendMessage(message, dummy_string);
+}
+
+bool TestClient::SendMessage(StringRef message, std::string &response_string) {
+ if (!SendMessage(message, response_string, PacketResult::Success))
+ return false;
+ else if (response_string[0] == 'E') {
+ GTEST_LOG_(ERROR) << "Error " << response_string
+ << " while sending message: " << message.str();
+ return false;
+ }
+
+ return true;
+}
+
+bool TestClient::SendMessage(StringRef message, std::string &response_string,
+ PacketResult expected_result) {
+ StringExtractorGDBRemote response;
+ GTEST_LOG_(INFO) << "Send Packet: " << message.str();
+ PacketResult result = SendPacketAndWaitForResponse(message, response, false);
+ response.GetEscapedBinaryData(response_string);
+ GTEST_LOG_(INFO) << "Read Packet: " << response_string;
+ if (result != expected_result) {
+ GTEST_LOG_(ERROR) << FormatFailedResult(message, result);
+ return false;
+ }
+
+ return true;
+}
+
+unsigned int TestClient::GetPcRegisterId() {
+ if (m_pc_register != UINT_MAX)
+ return m_pc_register;
+
+ for (unsigned int register_id = 0;; register_id++) {
+ std::string message = formatv("qRegisterInfo{0:x-}", register_id).str();
+ std::string response;
+ if (!SendMessage(message, response)) {
+ GTEST_LOG_(ERROR) << "Unable to query register ID for PC register.";
+ return UINT_MAX;
+ }
+
+ auto elements_or_error = SplitPairList("GetPcRegisterId", response);
+ if (auto split_error = elements_or_error.takeError()) {
+ GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: "
+ << response;
+ return UINT_MAX;
+ }
+
+ auto elements = *elements_or_error;
+ if (elements["alt-name"] == "pc" || elements["generic"] == "pc") {
+ m_pc_register = register_id;
+ break;
+ }
+ }
+
+ return m_pc_register;
+}
+
+bool TestClient::Continue(StringRef message) {
+ if (!m_process_info.hasValue()) {
+ GTEST_LOG_(ERROR) << "Continue() called before m_process_info initialized.";
+ return false;
+ }
+
+ std::string response;
+ if (!SendMessage(message, response))
+ return false;
+ auto creation = StopReply::Create(response, m_process_info->GetEndian());
+ if (auto create_error = creation.takeError()) {
+ GTEST_LOG_(ERROR) << toString(std::move(create_error));
+ return false;
+ }
+
+ m_stop_reply = std::move(*creation);
+ return true;
+}
+
+std::string TestClient::GenerateLogFileName(const ArchSpec &arch) const {
+ char *log_directory = getenv("LOG_FILE_DIRECTORY");
+ if (!log_directory)
+ return "";
+
+ if (!llvm::sys::fs::is_directory(log_directory)) {
+ GTEST_LOG_(WARNING) << "Cannot access log directory: " << log_directory;
+ return "";
+ }
+
+ std::string log_file_name;
+ raw_string_ostream log_file(log_file_name);
+ log_file << log_directory << "/lldb-" << m_test_case_name << '-'
+ << m_test_name << '-' << arch.GetArchitectureName() << ".log";
+ return log_file.str();
+}
+
+std::string TestClient::FormatFailedResult(const std::string &message,
+ PacketResult result) {
+ std::string formatted_error;
+ raw_string_ostream error_stream(formatted_error);
+ error_stream << "Failure sending message: " << message << " Result: ";
+
+ switch (result) {
+ case PacketResult::ErrorSendFailed:
+ error_stream << "ErrorSendFailed";
+ break;
+ case PacketResult::ErrorSendAck:
+ error_stream << "ErrorSendAck";
+ break;
+ case PacketResult::ErrorReplyFailed:
+ error_stream << "ErrorReplyFailed";
+ break;
+ case PacketResult::ErrorReplyTimeout:
+ error_stream << "ErrorReplyTimeout";
+ break;
+ case PacketResult::ErrorReplyInvalid:
+ error_stream << "ErrorReplyInvalid";
+ break;
+ case PacketResult::ErrorReplyAck:
+ error_stream << "ErrorReplyAck";
+ break;
+ case PacketResult::ErrorDisconnected:
+ error_stream << "ErrorDisconnected";
+ break;
+ case PacketResult::ErrorNoSequenceLock:
+ error_stream << "ErrorNoSequenceLock";
+ break;
+ default:
+ error_stream << "Unknown Error";
+ }
+
+ error_stream.str();
+ return formatted_error;
+}
+} // namespace llgs_tests
diff --git a/unittests/tools/lldb-server/tests/TestClient.h b/unittests/tools/lldb-server/tests/TestClient.h
new file mode 100644
index 000000000000..ae620cc97207
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/TestClient.h
@@ -0,0 +1,61 @@
+//===-- TestClient.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MessageObjects.h"
+#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+#include "llvm/ADT/Optional.h"
+#include <memory>
+#include <string>
+
+namespace llgs_tests {
+// TODO: Make the test client an abstract base class, with different children
+// for different types of connections: llgs v. debugserver
+class TestClient
+ : public lldb_private::process_gdb_remote::GDBRemoteCommunicationClient {
+public:
+ static void Initialize();
+ TestClient(const std::string &test_name, const std::string &test_case_name);
+ virtual ~TestClient();
+ LLVM_NODISCARD bool StartDebugger();
+ LLVM_NODISCARD bool StopDebugger();
+ LLVM_NODISCARD bool SetInferior(llvm::ArrayRef<std::string> inferior_args);
+ LLVM_NODISCARD bool ListThreadsInStopReply();
+ LLVM_NODISCARD bool SetBreakpoint(unsigned long address);
+ LLVM_NODISCARD bool ContinueAll();
+ LLVM_NODISCARD bool ContinueThread(unsigned long thread_id);
+ const ProcessInfo &GetProcessInfo();
+ llvm::Optional<JThreadsInfo> GetJThreadsInfo();
+ const StopReply &GetLatestStopReply();
+ LLVM_NODISCARD bool SendMessage(llvm::StringRef message);
+ LLVM_NODISCARD bool SendMessage(llvm::StringRef message,
+ std::string &response_string);
+ LLVM_NODISCARD bool SendMessage(llvm::StringRef message,
+ std::string &response_string,
+ PacketResult expected_result);
+ unsigned int GetPcRegisterId();
+
+private:
+ LLVM_NODISCARD bool Continue(llvm::StringRef message);
+ LLVM_NODISCARD bool GenerateConnectionAddress(std::string &address);
+ std::string GenerateLogFileName(const lldb_private::ArchSpec &arch) const;
+ std::string FormatFailedResult(
+ const std::string &message,
+ lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult
+ result);
+
+ llvm::Optional<ProcessInfo> m_process_info;
+ llvm::Optional<StopReply> m_stop_reply;
+ lldb_private::ProcessLaunchInfo m_server_process_info;
+ std::string m_test_name;
+ std::string m_test_case_name;
+ unsigned int m_pc_register;
+};
+} // namespace llgs_tests
diff --git a/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
new file mode 100644
index 000000000000..961b0a3b3167
--- /dev/null
+++ b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
@@ -0,0 +1,58 @@
+//===-- ThreadsInJstopinfoTest.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestClient.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llgs_tests;
+
+class ThreadsInJstopinfoTest : public ::testing::Test {
+protected:
+ virtual void SetUp() { TestClient::Initialize(); }
+};
+
+TEST_F(ThreadsInJstopinfoTest, TestStopReplyContainsThreadPcsLlgs) {
+ std::vector<std::string> inferior_args;
+ // This inferior spawns N threads, then forces a break.
+ inferior_args.push_back(THREAD_INFERIOR);
+ inferior_args.push_back("4");
+
+ auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+
+ TestClient client(test_info->name(), test_info->test_case_name());
+ ASSERT_TRUE(client.StartDebugger());
+ ASSERT_TRUE(client.SetInferior(inferior_args));
+ ASSERT_TRUE(client.ListThreadsInStopReply());
+ ASSERT_TRUE(client.ContinueAll());
+ unsigned int pc_reg = client.GetPcRegisterId();
+ ASSERT_NE(pc_reg, UINT_MAX);
+
+ auto jthreads_info = client.GetJThreadsInfo();
+ ASSERT_TRUE(jthreads_info);
+
+ auto stop_reply = client.GetLatestStopReply();
+ auto stop_reply_pcs = stop_reply.GetThreadPcs();
+ auto thread_infos = jthreads_info->GetThreadInfos();
+ ASSERT_EQ(stop_reply_pcs.size(), thread_infos.size())
+ << "Thread count mismatch.";
+
+ for (auto stop_reply_pc : stop_reply_pcs) {
+ unsigned long tid = stop_reply_pc.first;
+ ASSERT_TRUE(thread_infos.find(tid) != thread_infos.end())
+ << "Thread ID: " << tid << " not in JThreadsInfo.";
+ uint64_t pc_value;
+ ASSERT_TRUE(thread_infos[tid].ReadRegisterAsUint64(pc_reg, pc_value))
+ << "Failure reading ThreadInfo register " << pc_reg;
+ ASSERT_EQ(stop_reply_pcs[tid], pc_value)
+ << "Mismatched PC for thread: " << tid;
+ }
+
+ ASSERT_TRUE(client.StopDebugger());
+}