summaryrefslogtreecommitdiff
path: root/source/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'source/Utility')
-rw-r--r--source/Utility/ConvertEnum.cpp2
-rw-r--r--source/Utility/JSON.cpp1
-rw-r--r--source/Utility/Makefile15
-rw-r--r--source/Utility/ModuleCache.cpp24
-rw-r--r--source/Utility/SharingPtr.cpp8
-rw-r--r--source/Utility/StringExtractor.cpp3
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp133
-rw-r--r--source/Utility/StringExtractorGDBRemote.h32
-rw-r--r--source/Utility/TaskPool.cpp5
9 files changed, 192 insertions, 31 deletions
diff --git a/source/Utility/ConvertEnum.cpp b/source/Utility/ConvertEnum.cpp
index 3231397a05e3b..99515631db250 100644
--- a/source/Utility/ConvertEnum.cpp
+++ b/source/Utility/ConvertEnum.cpp
@@ -115,6 +115,8 @@ lldb_private::GetSectionTypeAsCString(lldb::SectionType sect_type)
return "compact-unwind";
case eSectionTypeGoSymtab:
return "go-symtab";
+ case eSectionTypeAbsoluteAddress:
+ return "absolute";
case eSectionTypeOther:
return "regular";
}
diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp
index 8b96a06e08e82..7ad3232c564d8 100644
--- a/source/Utility/JSON.cpp
+++ b/source/Utility/JSON.cpp
@@ -445,6 +445,7 @@ JSONParser::GetToken (std::string &value)
value = std::move(error.GetString());
return Token::Error;
}
+ break;
default:
done = true;
diff --git a/source/Utility/Makefile b/source/Utility/Makefile
deleted file mode 100644
index 13bcd8376c2df..0000000000000
--- a/source/Utility/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- source/Utility/Makefile -----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLDB_LEVEL := ../..
-LIBRARYNAME := lldbUtility
-BUILD_ARCHIVE = 1
-NO_PEDANTIC = 1
-
-include $(LLDB_LEVEL)/Makefile
diff --git a/source/Utility/ModuleCache.cpp b/source/Utility/ModuleCache.cpp
index 7c57d0baeccdc..92520f768b3f3 100644
--- a/source/Utility/ModuleCache.cpp
+++ b/source/Utility/ModuleCache.cpp
@@ -33,6 +33,21 @@ const char* kLockDirName = ".lock";
const char* kTempFileName = ".temp";
const char* kTempSymFileName = ".symtemp";
const char* kSymFileExtension = ".sym";
+const char* kFSIllegalChars = "\\/:*?\"<>|";
+
+std::string
+GetEscapedHostname(const char* hostname)
+{
+ std::string result(hostname);
+ size_t size = result.size();
+ for (size_t i = 0; i < size; ++i)
+ {
+ if ((result[i] >=1 && result[i] <= 31) ||
+ strchr(kFSIllegalChars, result[i]) != nullptr)
+ result[i] = '_';
+ }
+ return result;
+}
class ModuleLock
{
@@ -280,8 +295,9 @@ ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
if (error.Fail ())
return Error("Failed to lock module %s: %s", module_spec.GetUUID ().GetAsString().c_str(), error.AsCString ());
+ const auto escaped_hostname(GetEscapedHostname(hostname));
// Check local cache for a module.
- error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr);
+ error = Get (root_dir_spec, escaped_hostname.c_str(), module_spec, cached_module_sp, did_create_ptr);
if (error.Success ())
return error;
@@ -292,12 +308,12 @@ ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
return Error("Failed to download module: %s", error.AsCString ());
// Put downloaded file into local module cache.
- error = Put (root_dir_spec, hostname, module_spec, tmp_download_file_spec, module_spec.GetFileSpec ());
+ error = Put (root_dir_spec, escaped_hostname.c_str(), module_spec, tmp_download_file_spec, module_spec.GetFileSpec ());
if (error.Fail ())
return Error ("Failed to put module into cache: %s", error.AsCString ());
tmp_file_remover.releaseFile ();
- error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr);
+ error = Get (root_dir_spec, escaped_hostname.c_str(), module_spec, cached_module_sp, did_create_ptr);
if (error.Fail ())
return error;
@@ -310,7 +326,7 @@ ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
// contain the neccessary symbols and the debugging is also possible without a symfile.
return Error ();
- error = Put (root_dir_spec, hostname, module_spec, tmp_download_sym_file_spec, GetSymbolFileSpec(module_spec.GetFileSpec ()));
+ error = Put (root_dir_spec, escaped_hostname.c_str(), module_spec, tmp_download_sym_file_spec, GetSymbolFileSpec(module_spec.GetFileSpec ()));
if (error.Fail ())
return Error ("Failed to put symbol file into cache: %s", error.AsCString ());
diff --git a/source/Utility/SharingPtr.cpp b/source/Utility/SharingPtr.cpp
index 7f1278567ff11..7eedeb08afd1f 100644
--- a/source/Utility/SharingPtr.cpp
+++ b/source/Utility/SharingPtr.cpp
@@ -14,12 +14,12 @@
// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments
// and allow them to be queried using a pointer by a call to:
#include <execinfo.h>
-#include <map>
#include <assert.h>
-#include "lldb/Host/Mutex.h"
#include "llvm/ADT/STLExtras.h"
+#include <map>
+#include <mutex>
#include <vector>
class Backtrace
@@ -70,8 +70,8 @@ extern "C" void track_sp (void *sp_this, void *ptr, long use_count)
{
typedef std::pair<void *, Backtrace> PtrBacktracePair;
typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap;
- static lldb_private::Mutex g_mutex(lldb_private::Mutex::eMutexTypeNormal);
- lldb_private::Mutex::Locker locker (g_mutex);
+ static std::mutex g_mutex;
+ std::lock_guard<std::mutex> guard(g_mutex);
static PtrToBacktraceMap g_map;
if (sp_this)
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index ae92704668fc7..4c0029a0649b4 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -104,6 +104,7 @@ StringExtractor::GetChar (char fail_value)
int
StringExtractor::DecodeHexU8()
{
+ SkipSpaces();
if (GetBytesLeft() < 2)
{
return -1;
@@ -230,6 +231,7 @@ StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value)
uint32_t result = 0;
uint32_t nibble_count = 0;
+ SkipSpaces();
if (little_endian)
{
uint32_t shift_amount = 0;
@@ -292,6 +294,7 @@ StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value)
uint64_t result = 0;
uint32_t nibble_count = 0;
+ SkipSpaces();
if (little_endian)
{
uint32_t shift_amount = 0;
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 56df0be21edf3..d2619afd5bfa3 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -15,8 +15,6 @@
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
-
-
StringExtractorGDBRemote::ResponseType
StringExtractorGDBRemote::GetResponseType () const
{
@@ -227,7 +225,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'j':
if (PACKET_MATCHES("jSignalsInfo")) return eServerPacketType_jSignalsInfo;
if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo;
-
+ break;
case 'v':
if (PACKET_STARTS_WITH("vFile:"))
@@ -391,3 +389,132 @@ StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
return str.size();
}
+static bool
+OKErrorNotSupportedResponseValidator(void *, const StringExtractorGDBRemote &response)
+{
+ switch (response.GetResponseType())
+ {
+ case StringExtractorGDBRemote::eOK:
+ case StringExtractorGDBRemote::eError:
+ case StringExtractorGDBRemote::eUnsupported:
+ return true;
+
+ case StringExtractorGDBRemote::eAck:
+ case StringExtractorGDBRemote::eNack:
+ case StringExtractorGDBRemote::eResponse:
+ break;
+ }
+ return false;
+}
+
+static bool
+JSONResponseValidator(void *, const StringExtractorGDBRemote &response)
+{
+ switch (response.GetResponseType())
+ {
+ case StringExtractorGDBRemote::eUnsupported:
+ case StringExtractorGDBRemote::eError:
+ return true; // Accept unsupported or EXX as valid responses
+
+ case StringExtractorGDBRemote::eOK:
+ case StringExtractorGDBRemote::eAck:
+ case StringExtractorGDBRemote::eNack:
+ break;
+
+ case StringExtractorGDBRemote::eResponse:
+ // JSON that is returned in from JSON query packets is currently always
+ // either a dictionary which starts with a '{', or an array which
+ // starts with a '['. This is a quick validator to just make sure the
+ // response could be valid JSON without having to validate all of the
+ // JSON content.
+ switch (response.GetStringRef()[0])
+ {
+ case '{': return true;
+ case '[': return true;
+ default:
+ break;
+ }
+ break;
+ }
+ return false;
+}
+
+static bool
+ASCIIHexBytesResponseValidator(void *, const StringExtractorGDBRemote &response)
+{
+ switch (response.GetResponseType())
+ {
+ case StringExtractorGDBRemote::eUnsupported:
+ case StringExtractorGDBRemote::eError:
+ return true; // Accept unsupported or EXX as valid responses
+
+ case StringExtractorGDBRemote::eOK:
+ case StringExtractorGDBRemote::eAck:
+ case StringExtractorGDBRemote::eNack:
+ break;
+
+ case StringExtractorGDBRemote::eResponse:
+ {
+ uint32_t valid_count = 0;
+ for (const char ch : response.GetStringRef())
+ {
+ if (!isxdigit(ch))
+ {
+ return false;
+ }
+ if (++valid_count >= 16)
+ break; // Don't validate all the characters in case the packet is very large
+ }
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+void
+StringExtractorGDBRemote::CopyResponseValidator(const StringExtractorGDBRemote& rhs)
+{
+ m_validator = rhs.m_validator;
+ m_validator_baton = rhs.m_validator_baton;
+}
+
+void
+StringExtractorGDBRemote::SetResponseValidator(ResponseValidatorCallback callback, void *baton)
+{
+ m_validator = callback;
+ m_validator_baton = baton;
+}
+
+void
+StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported()
+{
+ m_validator = OKErrorNotSupportedResponseValidator;
+ m_validator_baton = nullptr;
+}
+
+void
+StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes()
+{
+ m_validator = ASCIIHexBytesResponseValidator;
+ m_validator_baton = nullptr;
+}
+
+void
+StringExtractorGDBRemote::SetResponseValidatorToJSON()
+{
+ m_validator = JSONResponseValidator;
+ m_validator_baton = nullptr;
+}
+
+bool
+StringExtractorGDBRemote::ValidateResponse() const
+{
+ // If we have a validator callback, try to validate the callback
+ if (m_validator)
+ return m_validator(m_validator_baton, *this);
+ else
+ return true; // No validator, so response is valid
+}
+
+
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index 7e2f1e7c69625..ade0edbbb7aed 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -20,18 +20,23 @@
class StringExtractorGDBRemote : public StringExtractor
{
public:
+ typedef bool (*ResponseValidatorCallback)(void * baton, const StringExtractorGDBRemote &response);
StringExtractorGDBRemote() :
- StringExtractor ()
+ StringExtractor(),
+ m_validator(nullptr)
{
}
StringExtractorGDBRemote(const char *cstr) :
- StringExtractor (cstr)
+ StringExtractor(cstr),
+ m_validator(nullptr)
{
}
+
StringExtractorGDBRemote(const StringExtractorGDBRemote& rhs) :
- StringExtractor (rhs)
+ StringExtractor(rhs),
+ m_validator(rhs.m_validator)
{
}
@@ -39,6 +44,24 @@ public:
{
}
+ bool
+ ValidateResponse() const;
+
+ void
+ CopyResponseValidator(const StringExtractorGDBRemote& rhs);
+
+ void
+ SetResponseValidator(ResponseValidatorCallback callback, void *baton);
+
+ void
+ SetResponseValidatorToOKErrorNotSupported();
+
+ void
+ SetResponseValidatorToASCIIHexBytes();
+
+ void
+ SetResponseValidatorToJSON();
+
enum ServerPacketType
{
eServerPacketType_nack = 0,
@@ -192,6 +215,9 @@ public:
size_t
GetEscapedBinaryData (std::string &str);
+protected:
+ ResponseValidatorCallback m_validator;
+ void *m_validator_baton;
};
#endif // utility_StringExtractorGDBRemote_h_
diff --git a/source/Utility/TaskPool.cpp b/source/Utility/TaskPool.cpp
index 75fe59d1e7110..c5c63a20cebca 100644
--- a/source/Utility/TaskPool.cpp
+++ b/source/Utility/TaskPool.cpp
@@ -61,8 +61,9 @@ TaskPoolImpl::AddTask(std::function<void()>&& task_fn)
if (m_thread_count < max_threads)
{
m_thread_count++;
- lock.unlock();
-
+ // Note that this detach call needs to happen with the m_tasks_mutex held. This prevents the thread
+ // from exiting prematurely and triggering a linux libc bug
+ // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951).
std::thread (Worker, this).detach();
}
}