aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Target
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /lldb/source/Target
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'lldb/source/Target')
-rw-r--r--lldb/source/Target/DynamicRegisterInfo.cpp36
-rw-r--r--lldb/source/Target/ExecutionContext.cpp6
-rw-r--r--lldb/source/Target/Language.cpp39
-rw-r--r--lldb/source/Target/Memory.cpp188
-rw-r--r--lldb/source/Target/PathMappingList.cpp18
-rw-r--r--lldb/source/Target/Platform.cpp54
-rw-r--r--lldb/source/Target/Process.cpp395
-rw-r--r--lldb/source/Target/RegisterContext.cpp17
-rw-r--r--lldb/source/Target/RegisterContextUnwind.cpp112
-rw-r--r--lldb/source/Target/RegisterFlags.cpp177
-rw-r--r--lldb/source/Target/StackFrame.cpp54
-rw-r--r--lldb/source/Target/StackFrameList.cpp122
-rw-r--r--lldb/source/Target/StopInfo.cpp110
-rw-r--r--lldb/source/Target/StructuredDataPlugin.cpp2
-rw-r--r--lldb/source/Target/Target.cpp706
-rw-r--r--lldb/source/Target/TargetList.cpp38
-rw-r--r--lldb/source/Target/TargetProperties.td14
-rw-r--r--lldb/source/Target/Thread.cpp112
-rw-r--r--lldb/source/Target/ThreadPlan.cpp3
-rw-r--r--lldb/source/Target/ThreadPlanCallFunction.cpp2
-rw-r--r--lldb/source/Target/ThreadPlanPython.cpp34
-rw-r--r--lldb/source/Target/ThreadPlanTracer.cpp9
-rw-r--r--lldb/source/Target/UnixSignals.cpp84
23 files changed, 1531 insertions, 801 deletions
diff --git a/lldb/source/Target/DynamicRegisterInfo.cpp b/lldb/source/Target/DynamicRegisterInfo.cpp
index 14c3faae38df..d577e20b3740 100644
--- a/lldb/source/Target/DynamicRegisterInfo.cpp
+++ b/lldb/source/Target/DynamicRegisterInfo.cpp
@@ -20,10 +20,17 @@
using namespace lldb;
using namespace lldb_private;
-DynamicRegisterInfo::DynamicRegisterInfo(
- const lldb_private::StructuredData::Dictionary &dict,
- const lldb_private::ArchSpec &arch) {
- SetRegisterInfo(dict, arch);
+std::unique_ptr<DynamicRegisterInfo>
+DynamicRegisterInfo::Create(const StructuredData::Dictionary &dict,
+ const ArchSpec &arch) {
+ auto dyn_reg_info = std::make_unique<DynamicRegisterInfo>();
+ if (!dyn_reg_info)
+ return nullptr;
+
+ if (dyn_reg_info->SetRegisterInfo(dict, arch) == 0)
+ return nullptr;
+
+ return dyn_reg_info;
}
DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) {
@@ -238,17 +245,20 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
std::vector<uint32_t> invalidate_regs;
memset(&reg_info, 0, sizeof(reg_info));
- ConstString name_val;
- ConstString alt_name_val;
- if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) {
+ llvm::StringRef name_val;
+ if (!reg_info_dict->GetValueForKeyAsString("name", name_val)) {
Clear();
printf("error: registers must have valid names and offsets\n");
reg_info_dict->DumpToStdout();
return 0;
}
- reg_info.name = name_val.GetCString();
- reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr);
- reg_info.alt_name = alt_name_val.GetCString();
+ reg_info.name = ConstString(name_val).GetCString();
+
+ llvm::StringRef alt_name_val;
+ if (reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val))
+ reg_info.alt_name = ConstString(alt_name_val).GetCString();
+ else
+ reg_info.alt_name = nullptr;
llvm::Expected<uint32_t> byte_offset =
ByteOffsetFromRegInfoDict(i, *reg_info_dict, byte_order);
@@ -262,7 +272,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
return 0;
}
- int64_t bitsize = 0;
+ uint64_t bitsize = 0;
if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) {
Clear();
printf("error: invalid or missing 'bitsize' key/value pair in register "
@@ -296,7 +306,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
eEncodingUint);
size_t set = 0;
- if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) ||
+ if (!reg_info_dict->GetValueForKeyAsInteger("set", set) ||
set >= m_sets.size()) {
Clear();
printf("error: invalid 'set' value in register dictionary, valid values "
@@ -407,7 +417,7 @@ size_t DynamicRegisterInfo::SetRegisterInfo(
{reg.regnum_ehframe, reg.regnum_dwarf, reg.regnum_generic,
reg.regnum_remote, local_regnum},
// value_regs and invalidate_regs are filled by Finalize()
- nullptr, nullptr
+ nullptr, nullptr, reg.flags_type
};
m_regs.push_back(reg_info);
diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp
index a5288b81cd17..b1563d9ceb71 100644
--- a/lldb/source/Target/ExecutionContext.cpp
+++ b/lldb/source/Target/ExecutionContext.cpp
@@ -85,7 +85,8 @@ ExecutionContext::ExecutionContext(Target *t,
if (m_process_sp) {
m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
if (m_thread_sp)
- m_frame_sp = m_thread_sp->GetSelectedFrame();
+ m_frame_sp =
+ m_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
}
}
}
@@ -517,7 +518,8 @@ void ExecutionContextRef::SetTargetPtr(Target *target, bool adopt_selected) {
if (thread_sp) {
SetThreadSP(thread_sp);
- lldb::StackFrameSP frame_sp(thread_sp->GetSelectedFrame());
+ lldb::StackFrameSP frame_sp(
+ thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame));
if (!frame_sp)
frame_sp = thread_sp->GetStackFrameAtIndex(0);
if (frame_sp)
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 892d2a86437e..78785352676d 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -194,9 +194,27 @@ struct language_name_pair language_names[] = {
{"c++14", eLanguageTypeC_plus_plus_14},
{"fortran03", eLanguageTypeFortran03},
{"fortran08", eLanguageTypeFortran08},
+ {"renderscript", eLanguageTypeRenderScript},
+ {"bliss", eLanguageTypeBLISS},
+ {"kotlin", eLanguageTypeKotlin},
+ {"zig", eLanguageTypeZig},
+ {"crystal", eLanguageTypeCrystal},
+ {"<invalid language>",
+ static_cast<LanguageType>(
+ 0x0029)}, // Not yet taken by any language in the DWARF spec
+ // and thus has no entry in LanguageType
+ {"c++17", eLanguageTypeC_plus_plus_17},
+ {"c++20", eLanguageTypeC_plus_plus_20},
+ {"c17", eLanguageTypeC17},
+ {"fortran18", eLanguageTypeFortran18},
+ {"ada2005", eLanguageTypeAda2005},
+ {"ada2012", eLanguageTypeAda2012},
+ {"HIP", eLanguageTypeHIP},
+ {"assembly", eLanguageTypeAssembly},
+ {"c-sharp", eLanguageTypeC_sharp},
+ {"mojo", eLanguageTypeMojo},
// Vendor Extensions
{"assembler", eLanguageTypeMipsAssembler},
- {"renderscript", eLanguageTypeExtRenderScript},
// Now synonyms, in arbitrary order
{"objc", eLanguageTypeObjC},
{"objc++", eLanguageTypeObjC_plus_plus},
@@ -253,6 +271,8 @@ bool Language::LanguageIsCPlusPlus(LanguageType language) {
case eLanguageTypeC_plus_plus_03:
case eLanguageTypeC_plus_plus_11:
case eLanguageTypeC_plus_plus_14:
+ case eLanguageTypeC_plus_plus_17:
+ case eLanguageTypeC_plus_plus_20:
case eLanguageTypeObjC_plus_plus:
return true;
default:
@@ -292,6 +312,8 @@ bool Language::LanguageIsCFamily(LanguageType language) {
case eLanguageTypeC_plus_plus_03:
case eLanguageTypeC_plus_plus_11:
case eLanguageTypeC_plus_plus_14:
+ case eLanguageTypeC_plus_plus_17:
+ case eLanguageTypeC_plus_plus_20:
case eLanguageTypeObjC_plus_plus:
case eLanguageTypeObjC:
return true;
@@ -315,6 +337,8 @@ LanguageType Language::GetPrimaryLanguage(LanguageType language) {
case eLanguageTypeC_plus_plus_03:
case eLanguageTypeC_plus_plus_11:
case eLanguageTypeC_plus_plus_14:
+ case eLanguageTypeC_plus_plus_17:
+ case eLanguageTypeC_plus_plus_20:
return eLanguageTypeC_plus_plus;
case eLanguageTypeC:
case eLanguageTypeC89:
@@ -350,7 +374,6 @@ LanguageType Language::GetPrimaryLanguage(LanguageType language) {
case eLanguageTypeJulia:
case eLanguageTypeDylan:
case eLanguageTypeMipsAssembler:
- case eLanguageTypeExtRenderScript:
case eLanguageTypeUnknown:
default:
return language;
@@ -432,19 +455,17 @@ bool Language::ImageListTypeScavenger::Find_Impl(
return result;
}
-bool Language::GetFormatterPrefixSuffix(ValueObject &valobj,
- ConstString type_hint,
- std::string &prefix,
- std::string &suffix) {
- return false;
+std::pair<llvm::StringRef, llvm::StringRef>
+Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {
+ return std::pair<llvm::StringRef, llvm::StringRef>();
}
-bool Language::DemangledNameContainsPath(llvm::StringRef path,
+bool Language::DemangledNameContainsPath(llvm::StringRef path,
ConstString demangled) const {
// The base implementation does a simple contains comparision:
if (path.empty())
return false;
- return demangled.GetStringRef().contains(path);
+ return demangled.GetStringRef().contains(path);
}
DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {
diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp
index d4dedeea7c2c..45786415d23b 100644
--- a/lldb/source/Target/Memory.cpp
+++ b/lldb/source/Target/Memory.cpp
@@ -123,18 +123,55 @@ bool MemoryCache::RemoveInvalidRange(lldb::addr_t base_addr,
return false;
}
+lldb::DataBufferSP MemoryCache::GetL2CacheLine(lldb::addr_t line_base_addr,
+ Status &error) {
+ // This function assumes that the address given is aligned correctly.
+ assert((line_base_addr % m_L2_cache_line_byte_size) == 0);
+
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ auto pos = m_L2_cache.find(line_base_addr);
+ if (pos != m_L2_cache.end())
+ return pos->second;
+
+ auto data_buffer_heap_sp =
+ std::make_shared<DataBufferHeap>(m_L2_cache_line_byte_size, 0);
+ size_t process_bytes_read = m_process.ReadMemoryFromInferior(
+ line_base_addr, data_buffer_heap_sp->GetBytes(),
+ data_buffer_heap_sp->GetByteSize(), error);
+
+ // If we failed a read, not much we can do.
+ if (process_bytes_read == 0)
+ return lldb::DataBufferSP();
+
+ // If we didn't get a complete read, we can still cache what we did get.
+ if (process_bytes_read < m_L2_cache_line_byte_size)
+ data_buffer_heap_sp->SetByteSize(process_bytes_read);
+
+ m_L2_cache[line_base_addr] = data_buffer_heap_sp;
+ return data_buffer_heap_sp;
+}
+
size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
Status &error) {
- size_t bytes_left = dst_len;
-
- // Check the L1 cache for a range that contain the entire memory read. If we
- // find a range in the L1 cache that does, we use it. Else we fall back to
- // reading memory in m_L2_cache_line_byte_size byte sized chunks. The L1
- // cache contains chunks of memory that are not required to be
- // m_L2_cache_line_byte_size bytes in size, so we don't try anything tricky
- // when reading from them (no partial reads from the L1 cache).
+ if (!dst || dst_len == 0)
+ return 0;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ // FIXME: We should do a more thorough check to make sure that we're not
+ // overlapping with any invalid ranges (e.g. Read 0x100 - 0x200 but there's an
+ // invalid range 0x180 - 0x280). `FindEntryThatContains` has an implementation
+ // that takes a range, but it only checks to see if the argument is contained
+ // by an existing invalid range. It cannot check if the argument contains
+ // invalid ranges and cannot check for overlaps.
+ if (m_invalid_ranges.FindEntryThatContains(addr)) {
+ error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
+ return 0;
+ }
+
+ // Check the L1 cache for a range that contains the entire memory read.
+ // L1 cache contains chunks of memory that are not required to be the size of
+ // an L2 cache line. We avoid trying to do partial reads from the L1 cache to
+ // simplify the implementation.
if (!m_L1_cache.empty()) {
AddrRange read_range(addr, dst_len);
BlockMap::iterator pos = m_L1_cache.upper_bound(addr);
@@ -149,105 +186,82 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
}
}
- // If this memory read request is larger than the cache line size, then we
- // (1) try to read as much of it at once as possible, and (2) don't add the
- // data to the memory cache. We don't want to split a big read up into more
- // separate reads than necessary, and with a large memory read request, it is
- // unlikely that the caller function will ask for the next
- // 4 bytes after the large memory read - so there's little benefit to saving
- // it in the cache.
- if (dst && dst_len > m_L2_cache_line_byte_size) {
+ // If the size of the read is greater than the size of an L2 cache line, we'll
+ // just read from the inferior. If that read is successful, we'll cache what
+ // we read in the L1 cache for future use.
+ if (dst_len > m_L2_cache_line_byte_size) {
size_t bytes_read =
m_process.ReadMemoryFromInferior(addr, dst, dst_len, error);
- // Add this non block sized range to the L1 cache if we actually read
- // anything
if (bytes_read > 0)
AddL1CacheData(addr, dst, bytes_read);
return bytes_read;
}
- if (dst && bytes_left > 0) {
- const uint32_t cache_line_byte_size = m_L2_cache_line_byte_size;
- uint8_t *dst_buf = (uint8_t *)dst;
- addr_t curr_addr = addr - (addr % cache_line_byte_size);
- addr_t cache_offset = addr - curr_addr;
-
- while (bytes_left > 0) {
- if (m_invalid_ranges.FindEntryThatContains(curr_addr)) {
- error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64,
- curr_addr);
- return dst_len - bytes_left;
- }
-
- BlockMap::const_iterator pos = m_L2_cache.find(curr_addr);
- BlockMap::const_iterator end = m_L2_cache.end();
-
- if (pos != end) {
- size_t curr_read_size = cache_line_byte_size - cache_offset;
- if (curr_read_size > bytes_left)
- curr_read_size = bytes_left;
+ // If the size of the read fits inside one L2 cache line, we'll try reading
+ // from the L2 cache. Note that if the range of memory we're reading sits
+ // between two contiguous cache lines, we'll touch two cache lines instead of
+ // just one.
- memcpy(dst_buf + dst_len - bytes_left,
- pos->second->GetBytes() + cache_offset, curr_read_size);
+ // We're going to have all of our loads and reads be cache line aligned.
+ addr_t cache_line_offset = addr % m_L2_cache_line_byte_size;
+ addr_t cache_line_base_addr = addr - cache_line_offset;
+ DataBufferSP first_cache_line = GetL2CacheLine(cache_line_base_addr, error);
+ // If we get nothing, then the read to the inferior likely failed. Nothing to
+ // do here.
+ if (!first_cache_line)
+ return 0;
- bytes_left -= curr_read_size;
- curr_addr += curr_read_size + cache_offset;
- cache_offset = 0;
+ // If the cache line was not filled out completely and the offset is greater
+ // than what we have available, we can't do anything further here.
+ if (cache_line_offset >= first_cache_line->GetByteSize())
+ return 0;
- if (bytes_left > 0) {
- // Get sequential cache page hits
- for (++pos; (pos != end) && (bytes_left > 0); ++pos) {
- assert((curr_addr % cache_line_byte_size) == 0);
+ uint8_t *dst_buf = (uint8_t *)dst;
+ size_t bytes_left = dst_len;
+ size_t read_size = first_cache_line->GetByteSize() - cache_line_offset;
+ if (read_size > bytes_left)
+ read_size = bytes_left;
- if (pos->first != curr_addr)
- break;
+ memcpy(dst_buf + dst_len - bytes_left,
+ first_cache_line->GetBytes() + cache_line_offset, read_size);
+ bytes_left -= read_size;
- curr_read_size = pos->second->GetByteSize();
- if (curr_read_size > bytes_left)
- curr_read_size = bytes_left;
+ // If the cache line was not filled out completely and we still have data to
+ // read, we can't do anything further.
+ if (first_cache_line->GetByteSize() < m_L2_cache_line_byte_size &&
+ bytes_left > 0)
+ return dst_len - bytes_left;
- memcpy(dst_buf + dst_len - bytes_left, pos->second->GetBytes(),
- curr_read_size);
+ // We'll hit this scenario if our read straddles two cache lines.
+ if (bytes_left > 0) {
+ cache_line_base_addr += m_L2_cache_line_byte_size;
- bytes_left -= curr_read_size;
- curr_addr += curr_read_size;
+ // FIXME: Until we are able to more thoroughly check for invalid ranges, we
+ // will have to check the second line to see if it is in an invalid range as
+ // well. See the check near the beginning of the function for more details.
+ if (m_invalid_ranges.FindEntryThatContains(cache_line_base_addr)) {
+ error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64,
+ cache_line_base_addr);
+ return dst_len - bytes_left;
+ }
- // We have a cache page that succeeded to read some bytes but not
- // an entire page. If this happens, we must cap off how much data
- // we are able to read...
- if (pos->second->GetByteSize() != cache_line_byte_size)
- return dst_len - bytes_left;
- }
- }
- }
+ DataBufferSP second_cache_line =
+ GetL2CacheLine(cache_line_base_addr, error);
+ if (!second_cache_line)
+ return dst_len - bytes_left;
- // We need to read from the process
+ read_size = bytes_left;
+ if (read_size > second_cache_line->GetByteSize())
+ read_size = second_cache_line->GetByteSize();
- if (bytes_left > 0) {
- assert((curr_addr % cache_line_byte_size) == 0);
- std::unique_ptr<DataBufferHeap> data_buffer_heap_up(
- new DataBufferHeap(cache_line_byte_size, 0));
- size_t process_bytes_read = m_process.ReadMemoryFromInferior(
- curr_addr, data_buffer_heap_up->GetBytes(),
- data_buffer_heap_up->GetByteSize(), error);
- if (process_bytes_read == 0)
- return dst_len - bytes_left;
+ memcpy(dst_buf + dst_len - bytes_left, second_cache_line->GetBytes(),
+ read_size);
+ bytes_left -= read_size;
- if (process_bytes_read != cache_line_byte_size) {
- if (process_bytes_read < data_buffer_heap_up->GetByteSize()) {
- dst_len -= data_buffer_heap_up->GetByteSize() - process_bytes_read;
- bytes_left = process_bytes_read;
- }
- data_buffer_heap_up->SetByteSize(process_bytes_read);
- }
- m_L2_cache[curr_addr] = DataBufferSP(data_buffer_heap_up.release());
- // We have read data and put it into the cache, continue through the
- // loop again to get the data out of the cache...
- }
- }
+ return dst_len - bytes_left;
}
- return dst_len - bytes_left;
+ return dst_len;
}
AllocatedBlock::AllocatedBlock(lldb::addr_t addr, uint32_t byte_size,
diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp
index 13bb50b362c6..c369018122a5 100644
--- a/lldb/source/Target/PathMappingList.cpp
+++ b/lldb/source/Target/PathMappingList.cpp
@@ -48,6 +48,7 @@ PathMappingList::PathMappingList(const PathMappingList &rhs)
const PathMappingList &PathMappingList::operator=(const PathMappingList &rhs) {
if (this != &rhs) {
+ std::scoped_lock<std::recursive_mutex, std::recursive_mutex> locks(m_mutex, rhs.m_mutex);
m_pairs = rhs.m_pairs;
m_callback = nullptr;
m_callback_baton = nullptr;
@@ -60,6 +61,7 @@ PathMappingList::~PathMappingList() = default;
void PathMappingList::Append(llvm::StringRef path, llvm::StringRef replacement,
bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
++m_mod_id;
m_pairs.emplace_back(pair(NormalizePath(path), NormalizePath(replacement)));
if (notify && m_callback)
@@ -67,6 +69,7 @@ void PathMappingList::Append(llvm::StringRef path, llvm::StringRef replacement,
}
void PathMappingList::Append(const PathMappingList &rhs, bool notify) {
+ std::scoped_lock<std::recursive_mutex, std::recursive_mutex> locks(m_mutex, rhs.m_mutex);
++m_mod_id;
if (!rhs.m_pairs.empty()) {
const_iterator pos, end = rhs.m_pairs.end();
@@ -81,6 +84,7 @@ bool PathMappingList::AppendUnique(llvm::StringRef path,
llvm::StringRef replacement, bool notify) {
auto normalized_path = NormalizePath(path);
auto normalized_replacement = NormalizePath(replacement);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
for (const auto &pair : m_pairs) {
if (pair.first.GetStringRef().equals(normalized_path) &&
pair.second.GetStringRef().equals(normalized_replacement))
@@ -92,6 +96,7 @@ bool PathMappingList::AppendUnique(llvm::StringRef path,
void PathMappingList::Insert(llvm::StringRef path, llvm::StringRef replacement,
uint32_t index, bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
++m_mod_id;
iterator insert_iter;
if (index >= m_pairs.size())
@@ -106,6 +111,7 @@ void PathMappingList::Insert(llvm::StringRef path, llvm::StringRef replacement,
bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef replacement,
uint32_t index, bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (index >= m_pairs.size())
return false;
++m_mod_id;
@@ -116,6 +122,7 @@ bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef replacement,
}
bool PathMappingList::Remove(size_t index, bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (index >= m_pairs.size())
return false;
@@ -130,6 +137,7 @@ bool PathMappingList::Remove(size_t index, bool notify) {
// For clients which do not need the pair index dumped, pass a pair_index >= 0
// to only dump the indicated pair.
void PathMappingList::Dump(Stream *s, int pair_index) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
unsigned int numPairs = m_pairs.size();
if (pair_index < 0) {
@@ -147,6 +155,7 @@ void PathMappingList::Dump(Stream *s, int pair_index) {
llvm::json::Value PathMappingList::ToJSON() {
llvm::json::Array entries;
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
for (const auto &pair : m_pairs) {
llvm::json::Array entry{pair.first.GetStringRef().str(),
pair.second.GetStringRef().str()};
@@ -156,6 +165,7 @@ llvm::json::Value PathMappingList::ToJSON() {
}
void PathMappingList::Clear(bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (!m_pairs.empty())
++m_mod_id;
m_pairs.clear();
@@ -186,6 +196,7 @@ static void AppendPathComponents(FileSpec &path, llvm::StringRef components,
std::optional<FileSpec> PathMappingList::RemapPath(llvm::StringRef mapping_path,
bool only_if_exists) const {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (m_pairs.empty() || mapping_path.empty())
return {};
LazyBool path_is_relative = eLazyBoolCalculate;
@@ -224,6 +235,7 @@ std::optional<llvm::StringRef>
PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const {
std::string path = file.GetPath();
llvm::StringRef path_ref(path);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
for (const auto &it : m_pairs) {
llvm::StringRef removed_prefix = it.second.GetStringRef();
if (!path_ref.consume_front(it.second.GetStringRef()))
@@ -252,6 +264,7 @@ PathMappingList::FindFile(const FileSpec &orig_spec) const {
bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef new_path,
bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
uint32_t idx = FindIndexForPath(path);
if (idx < m_pairs.size()) {
++m_mod_id;
@@ -264,6 +277,7 @@ bool PathMappingList::Replace(llvm::StringRef path, llvm::StringRef new_path,
}
bool PathMappingList::Remove(ConstString path, bool notify) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
iterator pos = FindIteratorForPath(path);
if (pos != m_pairs.end()) {
++m_mod_id;
@@ -277,6 +291,7 @@ bool PathMappingList::Remove(ConstString path, bool notify) {
PathMappingList::const_iterator
PathMappingList::FindIteratorForPath(ConstString path) const {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
const_iterator pos;
const_iterator begin = m_pairs.begin();
const_iterator end = m_pairs.end();
@@ -290,6 +305,7 @@ PathMappingList::FindIteratorForPath(ConstString path) const {
PathMappingList::iterator
PathMappingList::FindIteratorForPath(ConstString path) {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
iterator pos;
iterator begin = m_pairs.begin();
iterator end = m_pairs.end();
@@ -303,6 +319,7 @@ PathMappingList::FindIteratorForPath(ConstString path) {
bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path,
ConstString &new_path) const {
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (idx < m_pairs.size()) {
path = m_pairs[idx].first;
new_path = m_pairs[idx].second;
@@ -313,6 +330,7 @@ bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path,
uint32_t PathMappingList::FindIndexForPath(llvm::StringRef orig_path) const {
const ConstString path = ConstString(NormalizePath(orig_path));
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
const_iterator pos;
const_iterator begin = m_pairs.begin();
const_iterator end = m_pairs.end();
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 1ddd7596280e..11a123fb6d58 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -99,29 +99,27 @@ PlatformProperties::PlatformProperties() {
bool PlatformProperties::GetUseModuleCache() const {
const auto idx = ePropertyUseModuleCache;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_platform_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_platform_properties[idx].default_uint_value != 0);
}
bool PlatformProperties::SetUseModuleCache(bool use_module_cache) {
- return m_collection_sp->SetPropertyAtIndexAsBoolean(
- nullptr, ePropertyUseModuleCache, use_module_cache);
+ return SetPropertyAtIndex(ePropertyUseModuleCache, use_module_cache);
}
FileSpec PlatformProperties::GetModuleCacheDirectory() const {
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(
- nullptr, ePropertyModuleCacheDirectory);
+ return GetPropertyAtIndexAs<FileSpec>(ePropertyModuleCacheDirectory, {});
}
bool PlatformProperties::SetModuleCacheDirectory(const FileSpec &dir_spec) {
- return m_collection_sp->SetPropertyAtIndexAsFileSpec(
- nullptr, ePropertyModuleCacheDirectory, dir_spec);
+ return m_collection_sp->SetPropertyAtIndex(ePropertyModuleCacheDirectory,
+ dir_spec);
}
void PlatformProperties::SetDefaultModuleCacheDirectory(
const FileSpec &dir_spec) {
auto f_spec_opt = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(
- nullptr, false, ePropertyModuleCacheDirectory);
+ ePropertyModuleCacheDirectory);
assert(f_spec_opt);
f_spec_opt->SetDefaultValue(dir_spec);
}
@@ -160,7 +158,7 @@ Status Platform::GetFileWithUUID(const FileSpec &platform_file,
FileSpecList
Platform::LocateExecutableScriptingResources(Target *target, Module &module,
- Stream *feedback_stream) {
+ Stream &feedback_stream) {
return FileSpecList();
}
@@ -212,11 +210,10 @@ Status Platform::GetSharedModule(
Status error(eErrorTypeGeneric);
ModuleSpec resolved_spec;
// Check if we have sysroot set.
- if (m_sdk_sysroot) {
+ if (!m_sdk_sysroot.empty()) {
// Prepend sysroot to module spec.
resolved_spec = spec;
- resolved_spec.GetFileSpec().PrependPathComponent(
- m_sdk_sysroot.GetStringRef());
+ resolved_spec.GetFileSpec().PrependPathComponent(m_sdk_sysroot);
// Try to get shared module with resolved spec.
error = ModuleList::GetSharedModule(resolved_spec, module_sp,
module_search_paths_ptr, old_modules,
@@ -314,9 +311,9 @@ void Platform::GetStatus(Stream &strm) {
strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
}
- if (GetSDKRootDirectory()) {
- strm.Format(" Sysroot: {0}\n", GetSDKRootDirectory());
- }
+ if (const std::string &sdk_root = GetSDKRootDirectory(); !sdk_root.empty())
+ strm.Format(" Sysroot: {0}\n", sdk_root);
+
if (GetWorkingDirectory()) {
strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str());
}
@@ -435,7 +432,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
// make the new directory and get in there
FileSpec dst_dir = rc_baton->dst;
if (!dst_dir.GetFilename())
- dst_dir.SetFilename(src.GetLastPathComponent());
+ dst_dir.SetFilename(src.GetFilename());
Status error = rc_baton->platform_ptr->MakeDirectory(
dst_dir, lldb::eFilePermissionsDirectoryDefault);
if (error.Fail()) {
@@ -1063,7 +1060,7 @@ lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
Debugger &debugger, Target &target,
Status &error) {
Log *log = GetLog(LLDBLog::Platform);
- LLDB_LOG(log, "target = {0})", &target);
+ LLDB_LOG(log, "target = {0}", &target);
ProcessSP process_sp;
// Make sure we stop at the entry point
@@ -1633,7 +1630,7 @@ Status Platform::DownloadModuleSlice(const FileSpec &src_file_spec,
return error;
}
- std::vector<char> buffer(1024);
+ std::vector<char> buffer(512 * 1024);
auto offset = src_offset;
uint64_t total_bytes_read = 0;
while (total_bytes_read < src_size) {
@@ -1815,8 +1812,9 @@ lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,
nullptr);
process_sp->RestoreProcessEvents();
bool pop_process_io_handler = false;
- Process::HandleProcessStateChangedEvent(event_sp, stream,
- pop_process_io_handler);
+ // This is a user-level stop, so we allow recognizers to select frames.
+ Process::HandleProcessStateChangedEvent(
+ event_sp, stream, SelectMostRelevantFrame, pop_process_io_handler);
}
return process_sp;
@@ -1895,6 +1893,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
trap_opcode_size = sizeof(g_hex_opcode);
} break;
+ case llvm::Triple::msp430: {
+ static const uint8_t g_msp430_opcode[] = {0x43, 0x43};
+ trap_opcode = g_msp430_opcode;
+ trap_opcode_size = sizeof(g_msp430_opcode);
+ } break;
+
case llvm::Triple::systemz: {
static const uint8_t g_hex_opcode[] = {0x00, 0x01};
trap_opcode = g_hex_opcode;
@@ -1967,6 +1971,14 @@ Args Platform::GetExtraStartupCommands() {
return {};
}
+void Platform::SetLocateModuleCallback(LocateModuleCallback callback) {
+ m_locate_module_callback = callback;
+}
+
+Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {
+ return m_locate_module_callback;
+}
+
PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
for (const PlatformSP &platform_sp : m_platforms) {
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e0cca0595ee3..05ddbbd146a2 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -92,9 +92,9 @@ class ProcessOptionValueProperties
public:
ProcessOptionValueProperties(ConstString name) : Cloneable(name) {}
- const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
- bool will_modify,
- uint32_t idx) const override {
+ const Property *
+ GetPropertyAtIndex(size_t idx,
+ const ExecutionContext *exe_ctx) const override {
// When getting the value for a key from the process options, we will
// always try and grab the setting from the current process if there is
// one. Else we just use the one from this instance.
@@ -167,8 +167,8 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
std::make_shared<ProcessOptionValueProperties>(ConstString("process"));
m_collection_sp->Initialize(g_process_properties);
m_collection_sp->AppendProperty(
- ConstString("thread"), ConstString("Settings specific to threads."),
- true, Thread::GetGlobalProperties().GetValueProperties());
+ "thread", "Settings specific to threads.", true,
+ Thread::GetGlobalProperties().GetValueProperties());
} else {
m_collection_sp =
OptionValueProperties::CreateLocalCopy(Process::GetGlobalProperties());
@@ -180,9 +180,9 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
m_experimental_properties_up =
std::make_unique<ProcessExperimentalProperties>();
m_collection_sp->AppendProperty(
- ConstString(Properties::GetExperimentalSettingsName()),
- ConstString("Experimental settings - setting these won't produce "
- "errors if the setting is not present."),
+ Properties::GetExperimentalSettingsName(),
+ "Experimental settings - setting these won't produce "
+ "errors if the setting is not present.",
true, m_experimental_properties_up->GetValueProperties());
}
@@ -190,169 +190,183 @@ ProcessProperties::~ProcessProperties() = default;
bool ProcessProperties::GetDisableMemoryCache() const {
const uint32_t idx = ePropertyDisableMemCache;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
uint64_t ProcessProperties::GetMemoryCacheLineSize() const {
const uint32_t idx = ePropertyMemCacheLineSize;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_process_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_process_properties[idx].default_uint_value);
}
Args ProcessProperties::GetExtraStartupCommands() const {
Args args;
const uint32_t idx = ePropertyExtraStartCommand;
- m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args);
+ m_collection_sp->GetPropertyAtIndexAsArgs(idx, args);
return args;
}
void ProcessProperties::SetExtraStartupCommands(const Args &args) {
const uint32_t idx = ePropertyExtraStartCommand;
- m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args);
+ m_collection_sp->SetPropertyAtIndexFromArgs(idx, args);
}
FileSpec ProcessProperties::GetPythonOSPluginPath() const {
const uint32_t idx = ePropertyPythonOSPluginPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
}
uint32_t ProcessProperties::GetVirtualAddressableBits() const {
const uint32_t idx = ePropertyVirtualAddressableBits;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_process_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_process_properties[idx].default_uint_value);
}
void ProcessProperties::SetVirtualAddressableBits(uint32_t bits) {
const uint32_t idx = ePropertyVirtualAddressableBits;
- m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, bits);
+ SetPropertyAtIndex(idx, static_cast<uint64_t>(bits));
}
+
+uint32_t ProcessProperties::GetHighmemVirtualAddressableBits() const {
+ const uint32_t idx = ePropertyHighmemVirtualAddressableBits;
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_process_properties[idx].default_uint_value);
+}
+
+void ProcessProperties::SetHighmemVirtualAddressableBits(uint32_t bits) {
+ const uint32_t idx = ePropertyHighmemVirtualAddressableBits;
+ SetPropertyAtIndex(idx, static_cast<uint64_t>(bits));
+}
+
void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) {
const uint32_t idx = ePropertyPythonOSPluginPath;
- m_collection_sp->SetPropertyAtIndexAsFileSpec(nullptr, idx, file);
+ SetPropertyAtIndex(idx, file);
}
bool ProcessProperties::GetIgnoreBreakpointsInExpressions() const {
const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
void ProcessProperties::SetIgnoreBreakpointsInExpressions(bool ignore) {
const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, ignore);
+ SetPropertyAtIndex(idx, ignore);
}
bool ProcessProperties::GetUnwindOnErrorInExpressions() const {
const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
void ProcessProperties::SetUnwindOnErrorInExpressions(bool ignore) {
const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, ignore);
+ SetPropertyAtIndex(idx, ignore);
}
bool ProcessProperties::GetStopOnSharedLibraryEvents() const {
const uint32_t idx = ePropertyStopOnSharedLibraryEvents;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
void ProcessProperties::SetStopOnSharedLibraryEvents(bool stop) {
const uint32_t idx = ePropertyStopOnSharedLibraryEvents;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop);
+ SetPropertyAtIndex(idx, stop);
}
bool ProcessProperties::GetDisableLangRuntimeUnwindPlans() const {
const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
void ProcessProperties::SetDisableLangRuntimeUnwindPlans(bool disable) {
const uint32_t idx = ePropertyDisableLangRuntimeUnwindPlans;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, disable);
+ SetPropertyAtIndex(idx, disable);
m_process->Flush();
}
bool ProcessProperties::GetDetachKeepsStopped() const {
const uint32_t idx = ePropertyDetachKeepsStopped;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
void ProcessProperties::SetDetachKeepsStopped(bool stop) {
const uint32_t idx = ePropertyDetachKeepsStopped;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, stop);
+ SetPropertyAtIndex(idx, stop);
}
bool ProcessProperties::GetWarningsOptimization() const {
const uint32_t idx = ePropertyWarningOptimization;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
bool ProcessProperties::GetWarningsUnsupportedLanguage() const {
const uint32_t idx = ePropertyWarningUnsupportedLanguage;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
bool ProcessProperties::GetStopOnExec() const {
const uint32_t idx = ePropertyStopOnExec;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
const uint32_t idx = ePropertyUtilityExpressionTimeout;
- uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_process_properties[idx].default_uint_value);
+ uint64_t value = GetPropertyAtIndexAs<uint64_t>(
+ idx, g_process_properties[idx].default_uint_value);
return std::chrono::seconds(value);
}
std::chrono::seconds ProcessProperties::GetInterruptTimeout() const {
const uint32_t idx = ePropertyInterruptTimeout;
- uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_process_properties[idx].default_uint_value);
+ uint64_t value = GetPropertyAtIndexAs<uint64_t>(
+ idx, g_process_properties[idx].default_uint_value);
return std::chrono::seconds(value);
}
bool ProcessProperties::GetSteppingRunsAllThreads() const {
const uint32_t idx = ePropertySteppingRunsAllThreads;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_process_properties[idx].default_uint_value != 0);
}
bool ProcessProperties::GetOSPluginReportsAllThreads() const {
const bool fail_value = true;
const Property *exp_property =
- m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyExperimental);
+ m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (!exp_values)
return fail_value;
- return exp_values->GetPropertyAtIndexAsBoolean(
- nullptr, ePropertyOSPluginReportsAllThreads, fail_value);
+ return exp_values
+ ->GetPropertyAtIndexAs<bool>(ePropertyOSPluginReportsAllThreads)
+ .value_or(fail_value);
}
void ProcessProperties::SetOSPluginReportsAllThreads(bool does_report) {
const Property *exp_property =
- m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyExperimental);
+ m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (exp_values)
- exp_values->SetPropertyAtIndexAsBoolean(
- nullptr, ePropertyOSPluginReportsAllThreads, does_report);
+ exp_values->SetPropertyAtIndex(ePropertyOSPluginReportsAllThreads,
+ does_report);
}
FollowForkMode ProcessProperties::GetFollowForkMode() const {
const uint32_t idx = ePropertyFollowForkMode;
- return (FollowForkMode)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_process_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<FollowForkMode>(
+ idx, static_cast<FollowForkMode>(
+ g_process_properties[idx].default_uint_value));
}
ProcessSP Process::FindPlugin(lldb::TargetSP target_sp,
@@ -402,8 +416,7 @@ ConstString &Process::GetStaticBroadcasterClass() {
}
Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp)
- : Process(target_sp, listener_sp,
- UnixSignals::Create(HostInfo::GetArchitecture())) {
+ : Process(target_sp, listener_sp, UnixSignals::CreateForHost()) {
// This constructor just delegates to the full Process constructor,
// defaulting to using the Host's UnixSignals.
}
@@ -480,13 +493,12 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
// Allow the platform to override the default cache line size
OptionValueSP value_sp =
- m_collection_sp
- ->GetPropertyAtIndex(nullptr, true, ePropertyMemCacheLineSize)
+ m_collection_sp->GetPropertyAtIndex(ePropertyMemCacheLineSize)
->GetValue();
- uint32_t platform_cache_line_size =
+ uint64_t platform_cache_line_size =
target_sp->GetPlatform()->GetDefaultMemoryCacheLineSize();
if (!value_sp->OptionWasSet() && platform_cache_line_size != 0)
- value_sp->SetUInt64Value(platform_cache_line_size);
+ value_sp->SetValueAs(platform_cache_line_size);
RegisterAssertFrameRecognizer(this);
}
@@ -645,10 +657,10 @@ void Process::SyncIOHandler(uint32_t iohandler_id,
}
}
-StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout,
- EventSP *event_sp_ptr, bool wait_always,
- ListenerSP hijack_listener_sp,
- Stream *stream, bool use_run_lock) {
+StateType Process::WaitForProcessToStop(
+ const Timeout<std::micro> &timeout, EventSP *event_sp_ptr, bool wait_always,
+ ListenerSP hijack_listener_sp, Stream *stream, bool use_run_lock,
+ SelectMostRelevant select_most_relevant) {
// We can't just wait for a "stopped" event, because the stopped event may
// have restarted the target. We have to actually check each event, and in
// the case of a stopped event check the restarted flag on the event.
@@ -683,8 +695,8 @@ StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout,
*event_sp_ptr = event_sp;
bool pop_process_io_handler = (hijack_listener_sp.get() != nullptr);
- Process::HandleProcessStateChangedEvent(event_sp, stream,
- pop_process_io_handler);
+ Process::HandleProcessStateChangedEvent(
+ event_sp, stream, select_most_relevant, pop_process_io_handler);
switch (state) {
case eStateCrashed:
@@ -713,9 +725,10 @@ StateType Process::WaitForProcessToStop(const Timeout<std::micro> &timeout,
return state;
}
-bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
- Stream *stream,
- bool &pop_process_io_handler) {
+bool Process::HandleProcessStateChangedEvent(
+ const EventSP &event_sp, Stream *stream,
+ SelectMostRelevant select_most_relevant,
+ bool &pop_process_io_handler) {
const bool handle_pop = pop_process_io_handler;
pop_process_io_handler = false;
@@ -897,7 +910,8 @@ bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp,
return false;
const bool only_threads_with_stop_reason = true;
- const uint32_t start_frame = thread_sp->GetSelectedFrameIndex();
+ const uint32_t start_frame =
+ thread_sp->GetSelectedFrameIndex(select_most_relevant);
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
const bool stop_format = true;
@@ -1054,14 +1068,16 @@ bool Process::SetExitStatus(int status, const char *cstr) {
std::lock_guard<std::mutex> guard(m_exit_status_mutex);
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
- LLDB_LOGF(
- log, "Process::SetExitStatus (status=%i (0x%8.8x), description=%s%s%s)",
- status, status, cstr ? "\"" : "", cstr ? cstr : "NULL", cstr ? "\"" : "");
+ LLDB_LOGF(log, "(plugin = %s status=%i (0x%8.8x), description=%s%s%s)",
+ GetPluginName().data(), status, status, cstr ? "\"" : "",
+ cstr ? cstr : "NULL", cstr ? "\"" : "");
// We were already in the exited state
if (m_private_state.GetValue() == eStateExited) {
- LLDB_LOGF(log, "Process::SetExitStatus () ignoring exit status because "
- "state was already set to eStateExited");
+ LLDB_LOGF(log,
+ "(plugin = %s) ignoring exit status because state was already set "
+ "to eStateExited",
+ GetPluginName().data());
return false;
}
@@ -1313,8 +1329,8 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
}
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
- LLDB_LOGF(log, "Process::SetPublicState (state = %s, restarted = %i)",
- StateAsCString(new_state), restarted);
+ LLDB_LOGF(log, "(plugin = %s, state = %s, restarted = %i)",
+ GetPluginName().data(), StateAsCString(new_state), restarted);
const StateType old_state = m_public_state.GetValue();
m_public_state.SetValue(new_state);
@@ -1324,15 +1340,15 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
if (!StateChangedIsExternallyHijacked()) {
if (new_state == eStateDetached) {
LLDB_LOGF(log,
- "Process::SetPublicState (%s) -- unlocking run lock for detach",
- StateAsCString(new_state));
+ "(plugin = %s, state = %s) -- unlocking run lock for detach",
+ GetPluginName().data(), StateAsCString(new_state));
m_public_run_lock.SetStopped();
} else {
const bool old_state_is_stopped = StateIsStoppedState(old_state, false);
if ((old_state_is_stopped != new_state_is_stopped)) {
if (new_state_is_stopped && !restarted) {
- LLDB_LOGF(log, "Process::SetPublicState (%s) -- unlocking run lock",
- StateAsCString(new_state));
+ LLDB_LOGF(log, "(plugin = %s, state = %s) -- unlocking run lock",
+ GetPluginName().data(), StateAsCString(new_state));
m_public_run_lock.SetStopped();
}
}
@@ -1342,10 +1358,11 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
Status Process::Resume() {
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
- LLDB_LOGF(log, "Process::Resume -- locking run lock");
+ LLDB_LOGF(log, "(plugin = %s) -- locking run lock", GetPluginName().data());
if (!m_public_run_lock.TrySetRunning()) {
Status error("Resume request failed - process still running.");
- LLDB_LOGF(log, "Process::Resume: -- TrySetRunning failed, not resuming.");
+ LLDB_LOGF(log, "(plugin = %s) -- TrySetRunning failed, not resuming.",
+ GetPluginName().data());
return error;
}
Status error = PrivateResume();
@@ -1356,8 +1373,6 @@ Status Process::Resume() {
return error;
}
-static const char *g_resume_sync_name = "lldb.Process.ResumeSynchronous.hijack";
-
Status Process::ResumeSynchronous(Stream *stream) {
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
LLDB_LOGF(log, "Process::ResumeSynchronous -- locking run lock");
@@ -1368,13 +1383,14 @@ Status Process::ResumeSynchronous(Stream *stream) {
}
ListenerSP listener_sp(
- Listener::MakeListener(g_resume_sync_name));
+ Listener::MakeListener(ResumeSynchronousHijackListenerName.data()));
HijackProcessEvents(listener_sp);
Status error = PrivateResume();
if (error.Success()) {
StateType state =
- WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream);
+ WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream,
+ true /* use_run_lock */, SelectMostRelevantFrame);
const bool must_be_alive =
false; // eStateExited is ok, so this must be false
if (!StateIsStoppedState(state, must_be_alive))
@@ -1394,9 +1410,8 @@ Status Process::ResumeSynchronous(Stream *stream) {
bool Process::StateChangedIsExternallyHijacked() {
if (IsHijackedForEvent(eBroadcastBitStateChanged)) {
- const char *hijacking_name = GetHijackingListenerName();
- if (hijacking_name &&
- strcmp(hijacking_name, g_resume_sync_name))
+ llvm::StringRef hijacking_name = GetHijackingListenerName();
+ if (!hijacking_name.starts_with("lldb.internal"))
return true;
}
return false;
@@ -1404,9 +1419,8 @@ bool Process::StateChangedIsExternallyHijacked() {
bool Process::StateChangedIsHijackedForSynchronousResume() {
if (IsHijackedForEvent(eBroadcastBitStateChanged)) {
- const char *hijacking_name = GetHijackingListenerName();
- if (hijacking_name &&
- strcmp(hijacking_name, g_resume_sync_name) == 0)
+ llvm::StringRef hijacking_name = GetHijackingListenerName();
+ if (hijacking_name == ResumeSynchronousHijackListenerName)
return true;
}
return false;
@@ -1421,7 +1435,8 @@ void Process::SetPrivateState(StateType new_state) {
Log *log(GetLog(LLDBLog::State | LLDBLog::Process | LLDBLog::Unwind));
bool state_changed = false;
- LLDB_LOGF(log, "Process::SetPrivateState (%s)", StateAsCString(new_state));
+ LLDB_LOGF(log, "(plugin = %s, state = %s)", GetPluginName().data(),
+ StateAsCString(new_state));
std::lock_guard<std::recursive_mutex> thread_guard(m_thread_list.GetMutex());
std::lock_guard<std::recursive_mutex> guard(m_private_state.GetMutex());
@@ -1462,15 +1477,15 @@ void Process::SetPrivateState(StateType new_state) {
if (!m_mod_id.IsLastResumeForUserExpression())
m_mod_id.SetStopEventForLastNaturalStopID(event_sp);
m_memory_cache.Clear();
- LLDB_LOGF(log, "Process::SetPrivateState (%s) stop_id = %u",
- StateAsCString(new_state), m_mod_id.GetStopID());
+ LLDB_LOGF(log, "(plugin = %s, state = %s, stop_id = %u",
+ GetPluginName().data(), StateAsCString(new_state),
+ m_mod_id.GetStopID());
}
m_private_state_broadcaster.BroadcastEvent(event_sp);
} else {
- LLDB_LOGF(log,
- "Process::SetPrivateState (%s) state didn't change. Ignoring...",
- StateAsCString(new_state));
+ LLDB_LOGF(log, "(plugin = %s, state = %s) state didn't change. Ignoring...",
+ GetPluginName().data(), StateAsCString(new_state));
}
}
@@ -2355,6 +2370,23 @@ Status Process::DeallocateMemory(addr_t ptr) {
return error;
}
+bool Process::GetWatchpointReportedAfter() {
+ if (std::optional<bool> subclass_override = DoGetWatchpointReportedAfter())
+ return *subclass_override;
+
+ bool reported_after = true;
+ const ArchSpec &arch = GetTarget().GetArchitecture();
+ if (!arch.IsValid())
+ return reported_after;
+ llvm::Triple triple = arch.GetTriple();
+
+ if (triple.isMIPS() || triple.isPPC64() || triple.isRISCV() ||
+ triple.isAArch64() || triple.isArmMClass() || triple.isARM())
+ reported_after = false;
+
+ return reported_after;
+}
+
ModuleSP Process::ReadModuleFromMemory(const FileSpec &file_spec,
lldb::addr_t header_addr,
size_t size_to_read) {
@@ -2435,6 +2467,7 @@ Process::WaitForProcessStopPrivate(EventSP &event_sp,
}
void Process::LoadOperatingSystemPlugin(bool flush) {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_mutex);
if (flush)
m_thread_list.Clear();
m_os_up.reset(OperatingSystem::FindPlugin(this, nullptr));
@@ -2495,7 +2528,7 @@ Status Process::LaunchPrivate(ProcessLaunchInfo &launch_info, StateType &state,
FileSpec exe_spec_to_use;
if (!exe_module) {
- if (!launch_info.GetExecutableFile()) {
+ if (!launch_info.GetExecutableFile() && !launch_info.IsScriptedProcess()) {
error.SetErrorString("executable module does not exist");
return error;
}
@@ -2637,7 +2670,8 @@ Status Process::LoadCore() {
// Wait for a stopped event since we just posted one above...
lldb::EventSP event_sp;
StateType state =
- WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp);
+ WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp,
+ nullptr, true, SelectMostRelevantFrame);
if (!StateIsStoppedState(state, false)) {
Log *log = GetLog(LLDBLog::Process);
@@ -3142,9 +3176,13 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) {
}
// Wait for the process halt timeout seconds for the process to stop.
- StateType state =
- WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true,
- halt_listener_sp, nullptr, use_run_lock);
+ // If we are going to use the run lock, that means we're stopping out to the
+ // user, so we should also select the most relevant frame.
+ SelectMostRelevant select_most_relevant =
+ use_run_lock ? SelectMostRelevantFrame : DoNoSelectMostRelevantFrame;
+ StateType state = WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true,
+ halt_listener_sp, nullptr,
+ use_run_lock, select_most_relevant);
RestoreProcessEvents();
if (state == eStateInvalid || !event_sp) {
@@ -3352,7 +3390,7 @@ Status Process::Signal(int signal) {
void Process::SetUnixSignals(UnixSignalsSP &&signals_sp) {
assert(signals_sp && "null signals_sp");
- m_unix_signals_sp = signals_sp;
+ m_unix_signals_sp = std::move(signals_sp);
}
const lldb::UnixSignalsSP &Process::GetUnixSignals() {
@@ -3562,8 +3600,8 @@ bool Process::StartPrivateStateThread(bool is_secondary_thread) {
},
8 * 1024 * 1024);
if (!private_state_thread) {
- LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
- llvm::toString(private_state_thread.takeError()));
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Host), private_state_thread.takeError(),
+ "failed to launch host thread: {0}");
return false;
}
@@ -3913,12 +3951,11 @@ Process::ProcessEventData::ProcessEventData(const ProcessSP &process_sp,
Process::ProcessEventData::~ProcessEventData() = default;
-ConstString Process::ProcessEventData::GetFlavorString() {
- static ConstString g_flavor("Process::ProcessEventData");
- return g_flavor;
+llvm::StringRef Process::ProcessEventData::GetFlavorString() {
+ return "Process::ProcessEventData";
}
-ConstString Process::ProcessEventData::GetFlavor() const {
+llvm::StringRef Process::ProcessEventData::GetFlavor() const {
return ProcessEventData::GetFlavorString();
}
@@ -4265,7 +4302,7 @@ void Process::BroadcastStructuredData(const StructuredData::ObjectSP &object_sp,
}
StructuredDataPluginSP
-Process::GetStructuredDataPlugin(ConstString type_name) const {
+Process::GetStructuredDataPlugin(llvm::StringRef type_name) const {
auto find_it = m_structured_data_plugin_map.find(type_name);
if (find_it != m_structured_data_plugin_map.end())
return find_it->second;
@@ -4745,10 +4782,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
// Save the thread & frame from the exe_ctx for restoration after we run
const uint32_t thread_idx_id = thread->GetIndexID();
- StackFrameSP selected_frame_sp = thread->GetSelectedFrame();
+ StackFrameSP selected_frame_sp =
+ thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
if (!selected_frame_sp) {
thread->SetSelectedFrame(nullptr);
- selected_frame_sp = thread->GetSelectedFrame();
+ selected_frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
if (!selected_frame_sp) {
diagnostic_manager.Printf(
eDiagnosticSeverityError,
@@ -4780,7 +4818,9 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
StackID selected_stack_id;
if (selected_thread_sp) {
selected_tid = selected_thread_sp->GetIndexID();
- selected_stack_id = selected_thread_sp->GetSelectedFrame()->GetStackID();
+ selected_stack_id =
+ selected_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame)
+ ->GetStackID();
} else {
selected_tid = LLDB_INVALID_THREAD_ID;
}
@@ -5624,25 +5664,75 @@ void Process::Flush() {
}
lldb::addr_t Process::GetCodeAddressMask() {
- if (m_code_address_mask == 0) {
- if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
- lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
- SetCodeAddressMask(address_mask);
- }
- }
+ if (uint32_t num_bits_setting = GetVirtualAddressableBits())
+ return ~((1ULL << num_bits_setting) - 1);
+
return m_code_address_mask;
}
lldb::addr_t Process::GetDataAddressMask() {
- if (m_data_address_mask == 0) {
- if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
- lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
- SetDataAddressMask(address_mask);
- }
- }
+ if (uint32_t num_bits_setting = GetVirtualAddressableBits())
+ return ~((1ULL << num_bits_setting) - 1);
+
return m_data_address_mask;
}
+lldb::addr_t Process::GetHighmemCodeAddressMask() {
+ if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
+ return ~((1ULL << num_bits_setting) - 1);
+ return GetCodeAddressMask();
+}
+
+lldb::addr_t Process::GetHighmemDataAddressMask() {
+ if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
+ return ~((1ULL << num_bits_setting) - 1);
+ return GetDataAddressMask();
+}
+
+void Process::SetCodeAddressMask(lldb::addr_t code_address_mask) {
+ LLDB_LOG(GetLog(LLDBLog::Process),
+ "Setting Process code address mask to {0:x}", code_address_mask);
+ m_code_address_mask = code_address_mask;
+}
+
+void Process::SetDataAddressMask(lldb::addr_t data_address_mask) {
+ LLDB_LOG(GetLog(LLDBLog::Process),
+ "Setting Process data address mask to {0:x}", data_address_mask);
+ m_data_address_mask = data_address_mask;
+}
+
+void Process::SetHighmemCodeAddressMask(lldb::addr_t code_address_mask) {
+ LLDB_LOG(GetLog(LLDBLog::Process),
+ "Setting Process highmem code address mask to {0:x}",
+ code_address_mask);
+ m_highmem_code_address_mask = code_address_mask;
+}
+
+void Process::SetHighmemDataAddressMask(lldb::addr_t data_address_mask) {
+ LLDB_LOG(GetLog(LLDBLog::Process),
+ "Setting Process highmem data address mask to {0:x}",
+ data_address_mask);
+ m_highmem_data_address_mask = data_address_mask;
+}
+
+addr_t Process::FixCodeAddress(addr_t addr) {
+ if (ABISP abi_sp = GetABI())
+ addr = abi_sp->FixCodeAddress(addr);
+ return addr;
+}
+
+addr_t Process::FixDataAddress(addr_t addr) {
+ if (ABISP abi_sp = GetABI())
+ addr = abi_sp->FixDataAddress(addr);
+ return addr;
+}
+
+addr_t Process::FixAnyAddress(addr_t addr) {
+ if (ABISP abi_sp = GetABI())
+ addr = abi_sp->FixAnyAddress(addr);
+ return addr;
+}
+
void Process::DidExec() {
Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "Process::%s()", __FUNCTION__);
@@ -5737,7 +5827,7 @@ void Process::ModulesDidLoad(ModuleList &module_list) {
LoadOperatingSystemPlugin(false);
// Inform the structured-data plugins of the modified modules.
- for (auto pair : m_structured_data_plugin_map) {
+ for (auto &pair : m_structured_data_plugin_map) {
if (pair.second)
pair.second->ModulesDidLoad(*this, module_list);
}
@@ -5918,7 +6008,7 @@ Status Process::GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) {
}
Status
-Process::ConfigureStructuredData(ConstString type_name,
+Process::ConfigureStructuredData(llvm::StringRef type_name,
const StructuredData::ObjectSP &config_sp) {
// If you get this, the Process-derived class needs to implement a method to
// enable an already-reported asynchronous structured data feature. See
@@ -5932,34 +6022,29 @@ void Process::MapSupportedStructuredDataPlugins(
// Bail out early if there are no type names to map.
if (supported_type_names.GetSize() == 0) {
- LLDB_LOGF(log, "Process::%s(): no structured data types supported",
- __FUNCTION__);
+ LLDB_LOG(log, "no structured data types supported");
return;
}
- // Convert StructuredData type names to ConstString instances.
- std::set<ConstString> const_type_names;
+ // These StringRefs are backed by the input parameter.
+ std::set<llvm::StringRef> type_names;
- LLDB_LOGF(log,
- "Process::%s(): the process supports the following async "
- "structured data types:",
- __FUNCTION__);
+ LLDB_LOG(log,
+ "the process supports the following async structured data types:");
supported_type_names.ForEach(
- [&const_type_names, &log](StructuredData::Object *object) {
- if (!object) {
- // Invalid - shouldn't be null objects in the array.
+ [&type_names, &log](StructuredData::Object *object) {
+ // There shouldn't be null objects in the array.
+ if (!object)
return false;
- }
- auto type_name = object->GetAsString();
- if (!type_name) {
- // Invalid format - all type names should be strings.
+ // All type names should be strings.
+ const llvm::StringRef type_name = object->GetStringValue();
+ if (type_name.empty())
return false;
- }
- const_type_names.insert(ConstString(type_name->GetValue()));
- LLDB_LOG(log, "- {0}", type_name->GetValue());
+ type_names.insert(type_name);
+ LLDB_LOG(log, "- {0}", type_name);
return true;
});
@@ -5968,10 +6053,10 @@ void Process::MapSupportedStructuredDataPlugins(
// we've consumed all the type names.
// FIXME: should we return an error if there are type names nobody
// supports?
- for (uint32_t plugin_index = 0; !const_type_names.empty(); plugin_index++) {
+ for (uint32_t plugin_index = 0; !type_names.empty(); plugin_index++) {
auto create_instance =
- PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(
- plugin_index);
+ PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(
+ plugin_index);
if (!create_instance)
break;
@@ -5984,8 +6069,8 @@ void Process::MapSupportedStructuredDataPlugins(
}
// For any of the remaining type names, map any that this plugin supports.
- std::vector<ConstString> names_to_remove;
- for (auto &type_name : const_type_names) {
+ std::vector<llvm::StringRef> names_to_remove;
+ for (llvm::StringRef type_name : type_names) {
if (plugin_sp->SupportsStructuredDataType(type_name)) {
m_structured_data_plugin_map.insert(
std::make_pair(type_name, plugin_sp));
@@ -5996,8 +6081,8 @@ void Process::MapSupportedStructuredDataPlugins(
}
// Remove the type names that were consumed by this plugin.
- for (auto &type_name : names_to_remove)
- const_type_names.erase(type_name);
+ for (llvm::StringRef type_name : names_to_remove)
+ type_names.erase(type_name);
}
}
@@ -6014,7 +6099,7 @@ bool Process::RouteAsyncStructuredData(
return false;
// Grab the async structured type name (i.e. the feature/plugin name).
- ConstString type_name;
+ llvm::StringRef type_name;
if (!dictionary->GetValueForKeyAsString("type", type_name))
return false;
diff --git a/lldb/source/Target/RegisterContext.cpp b/lldb/source/Target/RegisterContext.cpp
index ee344b01c6b8..7236a45bff3b 100644
--- a/lldb/source/Target/RegisterContext.cpp
+++ b/lldb/source/Target/RegisterContext.cpp
@@ -320,11 +320,6 @@ Status RegisterContext::ReadRegisterValueFromMemory(
// |AABB| Address contents
// |AABB0000| Register contents [on little-endian hardware]
// |0000AABB| Register contents [on big-endian hardware]
- if (src_len > RegisterValue::kMaxRegisterByteSize) {
- error.SetErrorString("register too small to receive memory data");
- return error;
- }
-
const uint32_t dst_len = reg_info->byte_size;
if (src_len > dst_len) {
@@ -336,11 +331,11 @@ Status RegisterContext::ReadRegisterValueFromMemory(
ProcessSP process_sp(m_thread.GetProcess());
if (process_sp) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
+ RegisterValue::BytesContainer src(src_len);
// Read the memory
const uint32_t bytes_read =
- process_sp->ReadMemory(src_addr, src, src_len, error);
+ process_sp->ReadMemory(src_addr, src.data(), src_len, error);
// Make sure the memory read succeeded...
if (bytes_read != src_len) {
@@ -357,7 +352,7 @@ Status RegisterContext::ReadRegisterValueFromMemory(
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
// assuming they are the same.
- reg_value.SetFromMemoryData(*reg_info, src, src_len,
+ reg_value.SetFromMemoryData(*reg_info, src.data(), src_len,
process_sp->GetByteOrder(), error);
} else
error.SetErrorString("invalid process");
@@ -384,16 +379,16 @@ Status RegisterContext::WriteRegisterValueToMemory(
// TODO: we might need to add a parameter to this function in case the byte
// order of the memory data doesn't match the process. For now we are
// assuming they are the same.
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+ RegisterValue::BytesContainer dst(dst_len);
const uint32_t bytes_copied = reg_value.GetAsMemoryData(
- *reg_info, dst, dst_len, process_sp->GetByteOrder(), error);
+ *reg_info, dst.data(), dst_len, process_sp->GetByteOrder(), error);
if (error.Success()) {
if (bytes_copied == 0) {
error.SetErrorString("byte copy failed.");
} else {
const uint32_t bytes_written =
- process_sp->WriteMemory(dst_addr, dst, bytes_copied, error);
+ process_sp->WriteMemory(dst_addr, dst.data(), bytes_copied, error);
if (bytes_written != bytes_copied) {
if (error.Success()) {
// This might happen if we read _some_ bytes but not all
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 2da40ba2bf61..242c7d3f6b94 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -37,6 +37,8 @@
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/VASPrintf.h"
#include "lldb/lldb-private.h"
+
+#include <cassert>
#include <memory>
using namespace lldb;
@@ -135,9 +137,8 @@ void RegisterContextUnwind::InitializeZerothFrame() {
// (which would be a no-op in frame 0 where we get it from the register set,
// but still a good idea to make the call here for other ABIs that may
// exist.)
- ABI *abi = process->GetABI().get();
- if (abi)
- current_pc = abi->FixCodeAddress(current_pc);
+ if (ABISP abi_sp = process->GetABI())
+ current_pc = abi_sp->FixCodeAddress(current_pc);
UnwindPlanSP lang_runtime_plan_sp = LanguageRuntime::GetRuntimeUnwindPlan(
m_thread, this, m_behaves_like_zeroth_frame);
@@ -289,6 +290,13 @@ void RegisterContextUnwind::InitializeZerothFrame() {
} else
ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
+ if (m_cfa == LLDB_INVALID_ADDRESS && m_afa == LLDB_INVALID_ADDRESS) {
+ UnwindLogMsg(
+ "could not read CFA or AFA values for first frame, not valid.");
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
+
UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
" afa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
@@ -346,17 +354,23 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
// this will strip bit zero in case we read a PC from memory or from the LR.
- ABI *abi = process->GetABI().get();
- if (abi)
- pc = abi->FixCodeAddress(pc);
+ ABISP abi_sp = process->GetABI();
+ if (abi_sp)
+ pc = abi_sp->FixCodeAddress(pc);
if (log) {
UnwindLogMsg("pc = 0x%" PRIx64, pc);
addr_t reg_val;
- if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
+ if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) {
+ if (abi_sp)
+ reg_val = abi_sp->FixDataAddress(reg_val);
UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
- if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
+ }
+ if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) {
+ if (abi_sp)
+ reg_val = abi_sp->FixDataAddress(reg_val);
UnwindLogMsg("sp = 0x%" PRIx64, reg_val);
+ }
}
// A pc of 0x0 means it's the end of the stack crawl unless we're above a trap
@@ -415,11 +429,11 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
}
}
- if (abi) {
+ if (abi_sp) {
m_fast_unwind_plan_sp.reset();
m_full_unwind_plan_sp =
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
- abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
+ abi_sp->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
m_frame_type = eNormalFrame;
@@ -1742,8 +1756,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
old_caller_pc_value = reg_value.GetAsUInt64();
if (ProcessSP process_sp = m_thread.GetProcess()) {
- if (ABISP abi = process_sp->GetABI())
- old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value);
+ if (ABISP abi_sp = process_sp->GetABI())
+ old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
}
}
}
@@ -1802,8 +1816,8 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
reg_value)) {
new_caller_pc_value = reg_value.GetAsUInt64();
if (ProcessSP process_sp = m_thread.GetProcess()) {
- if (ABISP abi = process_sp->GetABI())
- new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value);
+ if (ABISP abi_sp = process_sp->GetABI())
+ new_caller_pc_value = abi_sp->FixCodeAddress(new_caller_pc_value);
}
}
}
@@ -1944,6 +1958,7 @@ bool RegisterContextUnwind::ReadFrameAddress(
address = LLDB_INVALID_ADDRESS;
addr_t cfa_reg_contents;
+ ABISP abi_sp = m_thread.GetProcess()->GetABI();
switch (fa.GetValueType()) {
case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
@@ -1954,11 +1969,13 @@ bool RegisterContextUnwind::ReadFrameAddress(
GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
RegisterValue reg_value;
if (reg_info) {
+ if (abi_sp)
+ cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
Status error = ReadRegisterValueFromMemory(
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
if (error.Success()) {
address = reg_value.GetAsUInt64();
- if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ if (abi_sp)
address = abi_sp->FixCodeAddress(address);
UnwindLogMsg(
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
@@ -1980,6 +1997,8 @@ bool RegisterContextUnwind::ReadFrameAddress(
RegisterNumber cfa_reg(m_thread, row_register_kind,
fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
+ if (abi_sp)
+ cfa_reg_contents = abi_sp->FixDataAddress(cfa_reg_contents);
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
cfa_reg_contents == 1) {
UnwindLogMsg(
@@ -2067,6 +2086,8 @@ lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
return LLDB_INVALID_ADDRESS;
if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
return LLDB_INVALID_ADDRESS;
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ hint = abi_sp->FixCodeAddress(hint);
hint += plan_offset;
@@ -2116,28 +2137,46 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
}
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
+ assert(reg_info);
+ if (!reg_info) {
+ UnwindLogMsg(
+ "Could not find RegisterInfo definition for lldb register number %d",
+ lldb_regnum);
+ return false;
+ }
+
+ uint32_t generic_regnum = LLDB_INVALID_REGNUM;
+ if (register_kind == eRegisterKindGeneric)
+ generic_regnum = regnum;
+ else
+ m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
+ register_kind, regnum, eRegisterKindGeneric, generic_regnum);
+ ABISP abi_sp = m_thread.GetProcess()->GetABI();
+
RegisterValue reg_value;
// if this is frame 0 (currently executing frame), get the requested reg
// contents from the actual thread registers
if (IsFrameZero()) {
if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
value = reg_value.GetAsUInt64();
+ if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
+ if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+ generic_regnum == LLDB_REGNUM_GENERIC_RA)
+ value = abi_sp->FixCodeAddress(value);
+ if (generic_regnum == LLDB_REGNUM_GENERIC_SP ||
+ generic_regnum == LLDB_REGNUM_GENERIC_FP)
+ value = abi_sp->FixDataAddress(value);
+ }
return true;
}
return false;
}
bool pc_register = false;
- uint32_t generic_regnum;
- if (register_kind == eRegisterKindGeneric &&
- (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) {
+ if (generic_regnum != LLDB_INVALID_REGNUM &&
+ (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+ generic_regnum == LLDB_REGNUM_GENERIC_RA))
pc_register = true;
- } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
- register_kind, regnum, eRegisterKindGeneric, generic_regnum) &&
- (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
- generic_regnum == LLDB_REGNUM_GENERIC_RA)) {
- pc_register = true;
- }
lldb_private::UnwindLLDB::RegisterLocation regloc;
if (!m_parent_unwind.SearchForSavedLocationForRegister(
@@ -2147,9 +2186,8 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
value = reg_value.GetAsUInt64();
if (pc_register) {
- if (ProcessSP process_sp = m_thread.GetProcess()) {
- if (ABISP abi = process_sp->GetABI())
- value = abi->FixCodeAddress(value);
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
+ value = abi_sp->FixCodeAddress(value);
}
}
return true;
@@ -2198,10 +2236,8 @@ bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
if (reg_value != LLDB_INVALID_ADDRESS) {
- if(ProcessSP process_sp = m_thread.GetProcess()) {
- if (ABISP abi = process_sp->GetABI())
- value = abi->FixCodeAddress(reg_value);
- }
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ value = abi_sp->FixCodeAddress(reg_value);
}
}
}
@@ -2283,9 +2319,8 @@ bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
ProcessSP process_sp (m_thread.GetProcess());
if (process_sp)
{
- ABI *abi = process_sp->GetABI().get();
- if (abi)
- start_pc = abi->FixCodeAddress(start_pc);
+ if (ABISP abi_sp = process_sp->GetABI())
+ start_pc = abi_sp->FixCodeAddress(start_pc);
}
}
return read_successfully;
@@ -2313,13 +2348,8 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) {
// through a NULL pointer -- we want to be able to unwind past that frame
// to help find the bug.
- ProcessSP process_sp (m_thread.GetProcess());
- if (process_sp)
- {
- ABI *abi = process_sp->GetABI().get();
- if (abi)
- pc = abi->FixCodeAddress(pc);
- }
+ if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
+ pc = abi_sp->FixCodeAddress(pc);
return !(m_all_registers_available == false &&
above_trap_handler == false && (pc == 0 || pc == 1));
diff --git a/lldb/source/Target/RegisterFlags.cpp b/lldb/source/Target/RegisterFlags.cpp
new file mode 100644
index 000000000000..06fb45d777ec
--- /dev/null
+++ b/lldb/source/Target/RegisterFlags.cpp
@@ -0,0 +1,177 @@
+//===-- RegisterFlags.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/RegisterFlags.h"
+#include "lldb/Utility/StreamString.h"
+
+#include <numeric>
+#include <optional>
+
+using namespace lldb_private;
+
+void RegisterFlags::Field::log(Log *log) const {
+ LLDB_LOG(log, " Name: \"{0}\" Start: {1} End: {2}", m_name.c_str(), m_start,
+ m_end);
+}
+
+bool RegisterFlags::Field::Overlaps(const Field &other) const {
+ unsigned overlap_start = std::max(GetStart(), other.GetStart());
+ unsigned overlap_end = std::min(GetEnd(), other.GetEnd());
+ return overlap_start <= overlap_end;
+}
+
+unsigned RegisterFlags::Field::PaddingDistance(const Field &other) const {
+ assert(!Overlaps(other) &&
+ "Cannot get padding distance for overlapping fields.");
+ assert((other < (*this)) && "Expected fields in MSB to LSB order.");
+
+ // If they don't overlap they are either next to each other or separated
+ // by some number of bits.
+
+ // Where left will be the MSB and right will be the LSB.
+ unsigned lhs_start = GetStart();
+ unsigned rhs_end = other.GetStart() + other.GetSizeInBits() - 1;
+
+ if (*this < other) {
+ lhs_start = other.GetStart();
+ rhs_end = GetStart() + GetSizeInBits() - 1;
+ }
+
+ return lhs_start - rhs_end - 1;
+}
+
+RegisterFlags::RegisterFlags(std::string id, unsigned size,
+ const std::vector<Field> &fields)
+ : m_id(std::move(id)), m_size(size) {
+ // We expect that the XML processor will discard anything describing flags but
+ // with no fields.
+ assert(fields.size() && "Some fields must be provided.");
+
+ // We expect that these are unsorted but do not overlap.
+ // They could fill the register but may have gaps.
+ std::vector<Field> provided_fields = fields;
+ m_fields.reserve(provided_fields.size());
+
+ // ProcessGDBRemote should have sorted these in descending order already.
+ assert(std::is_sorted(provided_fields.rbegin(), provided_fields.rend()));
+
+ // Build a new list of fields that includes anonymous (empty name) fields
+ // wherever there is a gap. This will simplify processing later.
+ std::optional<Field> previous_field;
+ unsigned register_msb = (size * 8) - 1;
+ for (auto field : provided_fields) {
+ if (previous_field) {
+ unsigned padding = previous_field->PaddingDistance(field);
+ if (padding) {
+ // -1 to end just before the previous field.
+ unsigned end = previous_field->GetStart() - 1;
+ // +1 because if you want to pad 1 bit you want to start and end
+ // on the same bit.
+ m_fields.push_back(Field("", field.GetEnd() + 1, end));
+ }
+ } else {
+ // This is the first field. Check that it starts at the register's MSB.
+ if (field.GetEnd() != register_msb)
+ m_fields.push_back(Field("", field.GetEnd() + 1, register_msb));
+ }
+ m_fields.push_back(field);
+ previous_field = field;
+ }
+
+ // The last field may not extend all the way to bit 0.
+ if (previous_field && previous_field->GetStart() != 0)
+ m_fields.push_back(Field("", 0, previous_field->GetStart() - 1));
+}
+
+void RegisterFlags::log(Log *log) const {
+ LLDB_LOG(log, "ID: \"{0}\" Size: {1}", m_id.c_str(), m_size);
+ for (const Field &field : m_fields)
+ field.log(log);
+}
+
+static StreamString FormatCell(const StreamString &content,
+ unsigned column_width) {
+ unsigned pad = column_width - content.GetString().size();
+ std::string pad_l;
+ std::string pad_r;
+ if (pad) {
+ pad_l = std::string(pad / 2, ' ');
+ pad_r = std::string((pad / 2) + (pad % 2), ' ');
+ }
+
+ StreamString aligned;
+ aligned.Printf("|%s%s%s", pad_l.c_str(), content.GetString().data(),
+ pad_r.c_str());
+ return aligned;
+}
+
+static void EmitTable(std::string &out, std::array<std::string, 3> &table) {
+ // Close the table.
+ for (std::string &line : table)
+ line += '|';
+
+ out += std::accumulate(table.begin() + 1, table.end(), table.front(),
+ [](std::string lhs, const auto &rhs) {
+ return std::move(lhs) + "\n" + rhs;
+ });
+}
+
+std::string RegisterFlags::AsTable(uint32_t max_width) const {
+ std::string table;
+ // position / gridline / name
+ std::array<std::string, 3> lines;
+ uint32_t current_width = 0;
+
+ for (const RegisterFlags::Field &field : m_fields) {
+ StreamString position;
+ if (field.GetEnd() == field.GetStart())
+ position.Printf(" %d ", field.GetEnd());
+ else
+ position.Printf(" %d-%d ", field.GetEnd(), field.GetStart());
+
+ StreamString name;
+ name.Printf(" %s ", field.GetName().c_str());
+
+ unsigned column_width = position.GetString().size();
+ unsigned name_width = name.GetString().size();
+ if (name_width > column_width)
+ column_width = name_width;
+
+ // If the next column would overflow and we have already formatted at least
+ // one column, put out what we have and move to a new table on the next line
+ // (+1 here because we need to cap the ends with '|'). If this is the first
+ // column, just let it overflow and we'll wrap next time around. There's not
+ // much we can do with a very small terminal.
+ if (current_width && ((current_width + column_width + 1) >= max_width)) {
+ EmitTable(table, lines);
+ // Blank line between each.
+ table += "\n\n";
+
+ for (std::string &line : lines)
+ line.clear();
+ current_width = 0;
+ }
+
+ StreamString aligned_position = FormatCell(position, column_width);
+ lines[0] += aligned_position.GetString();
+ StreamString grid;
+ grid << '|' << std::string(column_width, '-');
+ lines[1] += grid.GetString();
+ StreamString aligned_name = FormatCell(name, column_width);
+ lines[2] += aligned_name.GetString();
+
+ // +1 for the left side '|'.
+ current_width += column_width + 1;
+ }
+
+ // If we didn't overflow and still have table to print out.
+ if (lines[0].size())
+ EmitTable(table, lines);
+
+ return table;
+}
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index c04b58e80523..11ada92348ec 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -567,26 +567,21 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
// Check for direct ivars access which helps us with implicit access to
// ivars using "this" or "self".
GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);
- lldb::LanguageType method_language = eLanguageTypeUnknown;
- bool is_instance_method = false;
- ConstString method_object_name;
- if (m_sc.GetFunctionMethodInfo(method_language, is_instance_method,
- method_object_name)) {
- if (is_instance_method && method_object_name) {
- var_sp = variable_list->FindVariable(method_object_name);
- if (var_sp) {
- separator_idx = 0;
- if (Type *var_type = var_sp->GetType())
- if (auto compiler_type = var_type->GetForwardCompilerType())
- if (!compiler_type.IsPointerType())
- var_expr_storage = ".";
+ llvm::StringRef instance_var_name = m_sc.GetInstanceVariableName();
+ if (!instance_var_name.empty()) {
+ var_sp = variable_list->FindVariable(ConstString(instance_var_name));
+ if (var_sp) {
+ separator_idx = 0;
+ if (Type *var_type = var_sp->GetType())
+ if (auto compiler_type = var_type->GetForwardCompilerType())
+ if (!compiler_type.IsPointerType())
+ var_expr_storage = ".";
- if (var_expr_storage.empty())
- var_expr_storage = "->";
- var_expr_storage += var_expr;
- var_expr = var_expr_storage;
- synthetically_added_instance_object = true;
- }
+ if (var_expr_storage.empty())
+ var_expr_storage = "->";
+ var_expr_storage += var_expr;
+ var_expr = var_expr_storage;
+ synthetically_added_instance_object = true;
}
}
}
@@ -609,7 +604,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);
if (!valobj_sp)
return valobj_sp;
- valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true);
+ valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);
if (valobj_sp)
break;
}
@@ -710,13 +705,13 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
return ValueObjectSP();
}
}
- child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name, true);
+ child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name);
if (!child_valobj_sp) {
if (!no_synth_child) {
child_valobj_sp = valobj_sp->GetSyntheticValue();
if (child_valobj_sp)
child_valobj_sp =
- child_valobj_sp->GetChildMemberWithName(child_name, true);
+ child_valobj_sp->GetChildMemberWithName(child_name);
}
if (no_synth_child || !child_valobj_sp) {
@@ -819,7 +814,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
// extract bit low out of it. reading array item low would be done by
// saying arr[low], without a deref * sign
Status error;
- ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
if (error.Fail()) {
valobj_sp->GetExpressionPath(var_expr_path_strm);
error.SetErrorStringWithFormat(
@@ -873,7 +868,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
valobj_sp->GetTypeName().AsCString("<invalid type>"),
var_expr_path_strm.GetData());
} else {
- child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index);
if (!child_valobj_sp) {
valobj_sp->GetExpressionPath(var_expr_path_strm);
error.SetErrorStringWithFormat(
@@ -899,7 +894,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
nullptr, nullptr, &is_incomplete_array)) {
// Pass false to dynamic_value here so we can tell the difference
// between no dynamic value and no member of this type...
- child_valobj_sp = valobj_sp->GetChildAtIndex(child_index, true);
+ child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);
if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
child_valobj_sp =
valobj_sp->GetSyntheticArrayMember(child_index, true);
@@ -945,7 +940,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
valobj_sp->GetTypeName().AsCString("<invalid type>"),
var_expr_path_strm.GetData());
} else {
- child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index);
if (!child_valobj_sp) {
valobj_sp->GetExpressionPath(var_expr_path_strm);
error.SetErrorStringWithFormat(
@@ -1017,7 +1012,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
// extract bits low thru high out of it. reading array items low thru
// high would be done by saying arr[low-high], without a deref * sign
Status error;
- ValueObjectSP temp(valobj_sp->GetChildAtIndex(0, true));
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));
if (error.Fail()) {
valobj_sp->GetExpressionPath(var_expr_path_strm);
error.SetErrorStringWithFormat(
@@ -1365,7 +1360,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
if (auto err = c_type_system_or_err.takeError()) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),
- "Unable to guess value for given address");
+ "Unable to guess value for given address: {0}");
return ValueObjectSP();
} else {
auto ts = *c_type_system_or_err;
@@ -1405,8 +1400,7 @@ ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,
}
for (int ci = 0, ce = parent->GetNumChildren(); ci != ce; ++ci) {
- const bool can_create = true;
- ValueObjectSP child_sp = parent->GetChildAtIndex(ci, can_create);
+ ValueObjectSP child_sp = parent->GetChildAtIndex(ci);
if (!child_sp) {
return ValueObjectSP();
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index c782b506a9cb..2841f512439a 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -9,6 +9,7 @@
#include "lldb/Target/StackFrameList.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/Block.h"
@@ -17,6 +18,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -37,7 +39,7 @@ StackFrameList::StackFrameList(Thread &thread,
const lldb::StackFrameListSP &prev_frames_sp,
bool show_inline_frames)
: m_thread(thread), m_prev_frames_sp(prev_frames_sp), m_mutex(), m_frames(),
- m_selected_frame_idx(0), m_concrete_frames_fetched(0),
+ m_selected_frame_idx(), m_concrete_frames_fetched(0),
m_current_inlined_depth(UINT32_MAX),
m_current_inlined_pc(LLDB_INVALID_ADDRESS),
m_show_inlined_frames(show_inline_frames) {
@@ -83,8 +85,8 @@ void StackFrameList::ResetCurrentInlinedDepth() {
return;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- GetFramesUpTo(0);
+
+ GetFramesUpTo(0, DoNotAllowInterruption);
if (m_frames.empty())
return;
if (!m_frames[0]->IsInlined()) {
@@ -251,7 +253,7 @@ struct CallDescriptor {
using CallSequence = std::vector<CallDescriptor>;
/// Find the unique path through the call graph from \p begin (with return PC
-/// \p return_pc) to \p end. On success this path is stored into \p path, and
+/// \p return_pc) to \p end. On success this path is stored into \p path, and
/// on failure \p path is unchanged.
static void FindInterveningFrames(Function &begin, Function &end,
ExecutionContext &exe_ctx, Target &target,
@@ -434,21 +436,23 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
next_frame.SetFrameIndex(m_frames.size());
}
-void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
+bool StackFrameList::GetFramesUpTo(uint32_t end_idx,
+ InterruptionControl allow_interrupt) {
// Do not fetch frames for an invalid thread.
+ bool was_interrupted = false;
if (!m_thread.IsValid())
- return;
+ return false;
// We've already gotten more frames than asked for, or we've already finished
// unwinding, return.
if (m_frames.size() > end_idx || GetAllFramesFetched())
- return;
+ return false;
Unwind &unwinder = m_thread.GetUnwinder();
if (!m_show_inlined_frames) {
GetOnlyConcreteFramesUpTo(end_idx, unwinder);
- return;
+ return false;
}
#if defined(DEBUG_STACK_FRAMES)
@@ -470,6 +474,7 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
}
StackFrameSP unwind_frame_sp;
+ Debugger &dbg = m_thread.GetProcess()->GetTarget().GetDebugger();
do {
uint32_t idx = m_concrete_frames_fetched++;
lldb::addr_t pc = LLDB_INVALID_ADDRESS;
@@ -502,6 +507,15 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
}
} else {
+ // Check for interruption when building the frames.
+ // Do the check in idx > 0 so that we'll always create a 0th frame.
+ if (allow_interrupt
+ && INTERRUPT_REQUESTED(dbg, "Interrupted having fetched {0} frames",
+ m_frames.size())) {
+ was_interrupted = true;
+ break;
+ }
+
const bool success =
unwinder.GetFrameInfoAtIndex(idx, cfa, pc, behaves_like_zeroth_frame);
if (!success) {
@@ -614,14 +628,19 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
Dump(&s);
s.EOL();
#endif
+ // Don't report interrupted if we happen to have gotten all the frames:
+ if (!GetAllFramesFetched())
+ return was_interrupted;
+ return false;
}
uint32_t StackFrameList::GetNumFrames(bool can_create) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (can_create)
- GetFramesUpTo(UINT32_MAX);
-
+ if (can_create) {
+ // Don't allow interrupt or we might not return the correct count
+ GetFramesUpTo(UINT32_MAX, DoNotAllowInterruption);
+ }
return GetVisibleStackFrameIndex(m_frames.size());
}
@@ -662,7 +681,13 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
// GetFramesUpTo will fill m_frames with as many frames as you asked for, if
// there are that many. If there weren't then you asked for too many frames.
- GetFramesUpTo(idx);
+ // GetFramesUpTo returns true if interrupted:
+ if (GetFramesUpTo(idx)) {
+ Log *log = GetLog(LLDBLog::Thread);
+ LLDB_LOG(log, "GetFrameAtIndex was interrupted");
+ return {};
+ }
+
if (idx < m_frames.size()) {
if (m_show_inlined_frames) {
// When inline frames are enabled we actually create all the frames in
@@ -772,9 +797,52 @@ bool StackFrameList::SetFrameAtIndex(uint32_t idx, StackFrameSP &frame_sp) {
return false; // resize failed, out of memory?
}
-uint32_t StackFrameList::GetSelectedFrameIndex() const {
+void StackFrameList::SelectMostRelevantFrame() {
+ // Don't call into the frame recognizers on the private state thread as
+ // they can cause code to run in the target, and that can cause deadlocks
+ // when fetching stop events for the expression.
+ if (m_thread.GetProcess()->CurrentThreadIsPrivateStateThread())
+ return;
+
+ Log *log = GetLog(LLDBLog::Thread);
+
+ // Only the top frame should be recognized.
+ StackFrameSP frame_sp = GetFrameAtIndex(0);
+ if (!frame_sp) {
+ LLDB_LOG(log, "Failed to construct Frame #0");
+ return;
+ }
+
+ RecognizedStackFrameSP recognized_frame_sp = frame_sp->GetRecognizedFrame();
+
+ if (!recognized_frame_sp) {
+ LLDB_LOG(log, "Frame #0 not recognized");
+ return;
+ }
+
+ if (StackFrameSP most_relevant_frame_sp =
+ recognized_frame_sp->GetMostRelevantFrame()) {
+ LLDB_LOG(log, "Found most relevant frame at index {0}",
+ most_relevant_frame_sp->GetFrameIndex());
+ SetSelectedFrame(most_relevant_frame_sp.get());
+ } else {
+ LLDB_LOG(log, "No relevant frame!");
+ }
+}
+
+uint32_t StackFrameList::GetSelectedFrameIndex(
+ SelectMostRelevant select_most_relevant) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- return m_selected_frame_idx;
+ if (!m_selected_frame_idx && select_most_relevant)
+ SelectMostRelevantFrame();
+ if (!m_selected_frame_idx) {
+ // If we aren't selecting the most relevant frame, and the selected frame
+ // isn't set, then don't force a selection here, just return 0.
+ if (!select_most_relevant)
+ return 0;
+ m_selected_frame_idx = 0;
+ }
+ return *m_selected_frame_idx;
}
uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
@@ -783,17 +851,19 @@ uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
const_iterator begin = m_frames.begin();
const_iterator end = m_frames.end();
m_selected_frame_idx = 0;
+
for (pos = begin; pos != end; ++pos) {
if (pos->get() == frame) {
m_selected_frame_idx = std::distance(begin, pos);
uint32_t inlined_depth = GetCurrentInlinedDepth();
if (inlined_depth != UINT32_MAX)
- m_selected_frame_idx -= inlined_depth;
+ m_selected_frame_idx = *m_selected_frame_idx - inlined_depth;
break;
}
}
+
SetDefaultFileAndLineToSelectedFrame();
- return m_selected_frame_idx;
+ return *m_selected_frame_idx;
}
bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
@@ -809,7 +879,8 @@ bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
if (m_thread.GetID() ==
m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) {
- StackFrameSP frame_sp(GetFrameAtIndex(GetSelectedFrameIndex()));
+ StackFrameSP frame_sp(
+ GetFrameAtIndex(GetSelectedFrameIndex(DoNoSelectMostRelevantFrame)));
if (frame_sp) {
SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry);
if (sc.line_entry.file)
@@ -821,10 +892,16 @@ void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
// The thread has been run, reset the number stack frames to zero so we can
// determine how many frames we have lazily.
+// Note, we don't actually re-use StackFrameLists, we always make a new
+// StackFrameList every time we stop, and then copy frame information frame
+// by frame from the old to the new StackFrameList. So the comment above,
+// does not describe how StackFrameLists are currently used.
+// Clear is currently only used to clear the list in the destructor.
void StackFrameList::Clear() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
m_frames.clear();
m_concrete_frames_fetched = 0;
+ m_selected_frame_idx.reset();
}
lldb::StackFrameSP
@@ -863,7 +940,8 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
else
last_frame = first_frame + num_frames;
- StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame();
+ StackFrameSP selected_frame_sp =
+ m_thread.GetSelectedFrame(DoNoSelectMostRelevantFrame);
const char *unselected_marker = nullptr;
std::string buffer;
if (selected_frame_marker) {
@@ -884,6 +962,14 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
else
marker = unselected_marker;
}
+ // Check for interruption here. If we're fetching arguments, this loop
+ // can go slowly:
+ Debugger &dbg = m_thread.GetProcess()->GetTarget().GetDebugger();
+ if (INTERRUPT_REQUESTED(dbg,
+ "Interrupted dumping stack for thread {0:hex} with {1} shown.",
+ m_thread.GetID(), num_frames_displayed))
+ break;
+
if (!frame_sp->GetStatus(strm, show_frame_info,
num_frames_with_source > (first_frame - frame_idx),
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 225234c0ffba..efc8fd269ac2 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -256,7 +256,7 @@ protected:
if (!m_should_perform_action)
return;
m_should_perform_action = false;
- bool internal_breakpoint = true;
+ bool all_stopping_locs_internal = true;
ThreadSP thread_sp(m_thread_wp.lock());
@@ -332,7 +332,7 @@ protected:
ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
Process *process = exe_ctx.GetProcessPtr();
- if (process->GetModIDRef().IsLastResumeForUserExpression()) {
+ if (process->GetModIDRef().IsRunningExpression()) {
// If we are in the middle of evaluating an expression, don't run
// asynchronous breakpoint commands or expressions. That could
// lead to infinite recursion if the command or condition re-calls
@@ -421,8 +421,6 @@ protected:
continue;
}
- internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
-
// First run the precondition, but since the precondition is per
// breakpoint, only run it once per breakpoint.
std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
@@ -509,7 +507,7 @@ protected:
loc_desc.GetData());
// We want this stop reported, so you will know we auto-continued
// but only for external breakpoints:
- if (!internal_breakpoint)
+ if (!bp_loc_sp->GetBreakpoint().IsInternal())
thread_sp->SetShouldReportStop(eVoteYes);
auto_continue_says_stop = false;
}
@@ -539,6 +537,9 @@ protected:
actually_said_continue = true;
}
+ if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
+ all_stopping_locs_internal = false;
+
// If we are going to stop for this breakpoint, then remove the
// breakpoint.
if (callback_says_stop && bp_loc_sp &&
@@ -576,7 +577,7 @@ protected:
__FUNCTION__, m_value);
}
- if ((!m_should_stop || internal_breakpoint) &&
+ if ((!m_should_stop || all_stopping_locs_internal) &&
thread_sp->CompletedPlanOverridesBreakpoint()) {
// Override should_stop decision when we have completed step plan
@@ -665,9 +666,8 @@ public:
WatchpointSP watchpoint_sp;
};
- StopInfoWatchpoint(Thread &thread, break_id_t watch_id,
- lldb::addr_t watch_hit_addr)
- : StopInfo(thread, watch_id), m_watch_hit_addr(watch_hit_addr) {}
+ StopInfoWatchpoint(Thread &thread, break_id_t watch_id, bool silently_skip_wp)
+ : StopInfo(thread, watch_id), m_silently_skip_wp(silently_skip_wp) {}
~StopInfoWatchpoint() override = default;
@@ -822,22 +822,19 @@ protected:
// stop
ProcessSP process_sp = exe_ctx.GetProcessSP();
- uint32_t num;
- bool wp_triggers_after;
+ bool wp_triggers_after = process_sp->GetWatchpointReportedAfter();
- if (!process_sp->GetWatchpointSupportInfo(num, wp_triggers_after)
- .Success()) {
- m_should_stop_is_valid = true;
- m_should_stop = true;
- return m_should_stop;
- }
-
if (!wp_triggers_after) {
// We have to step over the watchpoint before we know what to do:
StopInfoWatchpointSP me_as_siwp_sp
= std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this());
ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint(
*(thread_sp.get()), me_as_siwp_sp, wp_sp));
+ // When this plan is done we want to stop, so set this as a Controlling
+ // plan.
+ step_over_wp_sp->SetIsControllingPlan(true);
+ step_over_wp_sp->SetOkayToDiscard(false);
+
Status error;
error = thread_sp->QueueThreadPlan(step_over_wp_sp, false);
// If we couldn't push the thread plan, just stop here:
@@ -895,27 +892,9 @@ protected:
WatchpointSentry sentry(process_sp, wp_sp);
- /*
- * MIPS: Last 3bits of the watchpoint address are masked by the kernel.
- * For example:
- * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is
- * set at 'm', then
- * watch exception is generated even when 'n' is read/written. To handle
- * this case,
- * server emulates the instruction at PC and finds the base address of
- * the load/store
- * instruction and appends it in the description of the stop-info
- * packet. If watchpoint
- * is not set on this address by user then this do not stop.
- */
- if (m_watch_hit_addr != LLDB_INVALID_ADDRESS) {
- WatchpointSP wp_hit_sp =
- thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(
- m_watch_hit_addr);
- if (!wp_hit_sp) {
- m_should_stop = false;
- wp_sp->IncrementFalseAlarmsAndReviseHitCount();
- }
+ if (m_silently_skip_wp) {
+ m_should_stop = false;
+ wp_sp->UndoHitCount();
}
if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {
@@ -1037,7 +1016,17 @@ private:
bool m_should_stop = false;
bool m_should_stop_is_valid = false;
- lldb::addr_t m_watch_hit_addr;
+ // A false watchpoint hit has happened -
+ // the thread stopped with a watchpoint
+ // hit notification, but the watched region
+ // was not actually accessed (as determined
+ // by the gdb stub we're talking to).
+ // Continue past this watchpoint without
+ // notifying the user; on some targets this
+ // may mean disable wp, instruction step,
+ // re-enable wp, continue.
+ // On others, just continue.
+ bool m_silently_skip_wp = false;
bool m_step_over_plan_complete = false;
bool m_using_step_over_plan = false;
};
@@ -1046,8 +1035,9 @@ private:
class StopInfoUnixSignal : public StopInfo {
public:
- StopInfoUnixSignal(Thread &thread, int signo, const char *description)
- : StopInfo(thread, signo) {
+ StopInfoUnixSignal(Thread &thread, int signo, const char *description,
+ std::optional<int> code)
+ : StopInfo(thread, signo), m_code(code) {
SetDescription(description);
}
@@ -1102,19 +1092,26 @@ public:
if (m_description.empty()) {
ThreadSP thread_sp(m_thread_wp.lock());
if (thread_sp) {
+ UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();
StreamString strm;
- const char *signal_name =
- thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
- m_value);
- if (signal_name)
- strm.Printf("signal %s", signal_name);
+ strm << "signal ";
+
+ std::string signal_name =
+ unix_signals->GetSignalDescription(m_value, m_code);
+ if (signal_name.size())
+ strm << signal_name;
else
- strm.Printf("signal %" PRIi64, m_value);
+ strm.Printf("%" PRIi64, m_value);
+
m_description = std::string(strm.GetString());
}
}
return m_description.c_str();
}
+
+private:
+ // In siginfo_t terms, if m_value is si_signo, m_code is si_code.
+ std::optional<int> m_code;
};
// StopInfoTrace
@@ -1366,16 +1363,18 @@ StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
}
-StopInfoSP
-StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id,
- lldb::addr_t watch_hit_addr) {
- return StopInfoSP(new StopInfoWatchpoint(thread, watch_id, watch_hit_addr));
+StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread,
+ break_id_t watch_id,
+ bool silently_continue) {
+ return StopInfoSP(
+ new StopInfoWatchpoint(thread, watch_id, silently_continue));
}
StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
- const char *description) {
+ const char *description,
+ std::optional<int> code) {
thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
- return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));
+ return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code));
}
StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {
@@ -1457,7 +1456,8 @@ StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
return ValueObjectSP();
}
- StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ StackFrameSP frame_sp =
+ thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
if (!frame_sp) {
return ValueObjectSP();
diff --git a/lldb/source/Target/StructuredDataPlugin.cpp b/lldb/source/Target/StructuredDataPlugin.cpp
index 20ed26a1a99a..1b5894b5df4b 100644
--- a/lldb/source/Target/StructuredDataPlugin.cpp
+++ b/lldb/source/Target/StructuredDataPlugin.cpp
@@ -32,7 +32,7 @@ StructuredDataPlugin::StructuredDataPlugin(const ProcessWP &process_wp)
StructuredDataPlugin::~StructuredDataPlugin() = default;
-bool StructuredDataPlugin::GetEnabled(ConstString type_name) const {
+bool StructuredDataPlugin::GetEnabled(llvm::StringRef type_name) const {
// By default, plugins are always enabled. Plugin authors should override
// this if there is an enabled/disabled state for their plugin.
return true;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index fd0cf0a5361d..f0c57ef83c4a 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -46,6 +46,7 @@
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterTypeBuilder.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
@@ -68,6 +69,7 @@
#include <memory>
#include <mutex>
#include <optional>
+#include <sstream>
using namespace lldb;
using namespace lldb_private;
@@ -292,6 +294,7 @@ void Target::Destroy() {
m_stop_hooks.clear();
m_stop_hook_next_id = 0;
m_suppress_stop_hooks = false;
+ m_repl_map.clear();
Args signal_args;
ClearDummySignals(signal_args);
}
@@ -790,19 +793,18 @@ bool Target::ProcessIsValid() {
}
static bool CheckIfWatchpointsSupported(Target *target, Status &error) {
- uint32_t num_supported_hardware_watchpoints;
- Status rc = target->GetProcessSP()->GetWatchpointSupportInfo(
- num_supported_hardware_watchpoints);
+ std::optional<uint32_t> num_supported_hardware_watchpoints =
+ target->GetProcessSP()->GetWatchpointSlotCount();
// If unable to determine the # of watchpoints available,
// assume they are supported.
- if (rc.Fail())
+ if (!num_supported_hardware_watchpoints)
return true;
if (num_supported_hardware_watchpoints == 0) {
error.SetErrorStringWithFormat(
"Target supports (%u) hardware watchpoint slots.\n",
- num_supported_hardware_watchpoints);
+ *num_supported_hardware_watchpoints);
return false;
}
return true;
@@ -1391,8 +1393,8 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
Target *target) {
Status error;
StreamString feedback_stream;
- if (module_sp && !module_sp->LoadScriptingResourceInTarget(
- target, error, &feedback_stream)) {
+ if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error,
+ feedback_stream)) {
if (error.AsCString())
target->GetDebugger().GetErrorStream().Printf(
"unable to load scripting data for module %s - error reported was "
@@ -2127,19 +2129,46 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
// of the library
bool did_create_module = false;
FileSpecList search_paths = GetExecutableSearchPaths();
- // If there are image search path entries, try to use them first to acquire
- // a suitable image.
- if (m_image_search_paths.GetSize()) {
- ModuleSpec transformed_spec(module_spec);
- ConstString transformed_dir;
- if (m_image_search_paths.RemapPath(
- module_spec.GetFileSpec().GetDirectory(), transformed_dir)) {
- transformed_spec.GetFileSpec().SetDirectory(transformed_dir);
- transformed_spec.GetFileSpec().SetFilename(
- module_spec.GetFileSpec().GetFilename());
- error = ModuleList::GetSharedModule(transformed_spec, module_sp,
- &search_paths, &old_modules,
- &did_create_module);
+ FileSpec symbol_file_spec;
+
+ // Call locate module callback if set. This allows users to implement their
+ // own module cache system. For example, to leverage build system artifacts,
+ // to bypass pulling files from remote platform, or to search symbol files
+ // from symbol servers.
+ CallLocateModuleCallbackIfSet(module_spec, module_sp, symbol_file_spec,
+ did_create_module);
+
+ // The result of this CallLocateModuleCallbackIfSet is one of the following.
+ // 1. module_sp:loaded, symbol_file_spec:set
+ // The callback found a module file and a symbol file for the
+ // module_spec. We will call module_sp->SetSymbolFileFileSpec with
+ // the symbol_file_spec later.
+ // 2. module_sp:loaded, symbol_file_spec:empty
+ // The callback only found a module file for the module_spec.
+ // 3. module_sp:empty, symbol_file_spec:set
+ // The callback only found a symbol file for the module. We continue
+ // to find a module file for this module_spec and we will call
+ // module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.
+ // 4. module_sp:empty, symbol_file_spec:empty
+ // The callback is not set. Or the callback did not find any module
+ // files nor any symbol files. Or the callback failed, or something
+ // went wrong. We continue to find a module file for this module_spec.
+
+ if (!module_sp) {
+ // If there are image search path entries, try to use them to acquire a
+ // suitable image.
+ if (m_image_search_paths.GetSize()) {
+ ModuleSpec transformed_spec(module_spec);
+ ConstString transformed_dir;
+ if (m_image_search_paths.RemapPath(
+ module_spec.GetFileSpec().GetDirectory(), transformed_dir)) {
+ transformed_spec.GetFileSpec().SetDirectory(transformed_dir);
+ transformed_spec.GetFileSpec().SetFilename(
+ module_spec.GetFileSpec().GetFilename());
+ error = ModuleList::GetSharedModule(transformed_spec, module_sp,
+ &search_paths, &old_modules,
+ &did_create_module);
+ }
}
}
@@ -2230,11 +2259,15 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
});
}
+ // If the locate module callback had found a symbol file, set it to the
+ // module_sp before preloading symbols.
+ if (symbol_file_spec)
+ module_sp->SetSymbolFileFileSpec(symbol_file_spec);
+
// Preload symbols outside of any lock, so hopefully we can do this for
// each library in parallel.
if (GetPreloadSymbols())
module_sp->PreloadSymbols();
-
llvm::SmallVector<ModuleSP, 1> replaced_modules;
for (ModuleSP &old_module_sp : old_modules) {
if (m_images.GetIndexForModule(old_module_sp.get()) !=
@@ -2269,7 +2302,7 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
message << " (uuid ";
if (dump_uuid.IsValid())
- dump_uuid.Dump(&message);
+ dump_uuid.Dump(message);
else
message << "not specified";
@@ -2305,6 +2338,113 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
return module_sp;
}
+void Target::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ FileSpec &symbol_file_spec,
+ bool &did_create_module) {
+ if (!m_platform_sp)
+ return;
+
+ Platform::LocateModuleCallback locate_module_callback =
+ m_platform_sp->GetLocateModuleCallback();
+ if (!locate_module_callback)
+ return;
+
+ FileSpec module_file_spec;
+ Status error =
+ locate_module_callback(module_spec, module_file_spec, symbol_file_spec);
+
+ // Locate module callback is set and called. Check the error.
+ Log *log = GetLog(LLDBLog::Target);
+ if (error.Fail()) {
+ LLDB_LOGF(log, "%s: locate module callback failed: %s",
+ LLVM_PRETTY_FUNCTION, error.AsCString());
+ return;
+ }
+
+ // The locate module callback was succeeded. It should returned
+ // 1. a combination of a module file and a symbol file.
+ // 2. or only a module file.
+ // 3. or only a symbol file. For example, a breakpad symbol text file.
+ //
+ // Check the module_file_spec and symbol_file_spec values.
+ // 1. module:empty symbol:empty -> Invalid
+ // 2. module:exists symbol:exists -> Success
+ // 3. module:exists symbol:empty -> Success
+ // 4. module:empty symbol:exists -> Success
+ if (!module_file_spec && !symbol_file_spec) {
+ // This is '1. module:empty symbol:empty -> Invalid'.
+ LLDB_LOGF(log,
+ "%s: locate module callback did not set both "
+ "module_file_spec and symbol_file_spec",
+ LLVM_PRETTY_FUNCTION);
+ return;
+ }
+
+ // The module file should exist.
+ if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) {
+ LLDB_LOGF(log,
+ "%s: locate module callback set a non-existent file to "
+ "module_file_spec: %s",
+ LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str());
+ // Clear symbol_file_spec for the error.
+ symbol_file_spec.Clear();
+ return;
+ }
+
+ // The symbol file should exist.
+ if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) {
+ LLDB_LOGF(log,
+ "%s: locate module callback set a non-existent file to "
+ "symbol_file_spec: %s",
+ LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());
+ // Clear symbol_file_spec for the error.
+ symbol_file_spec.Clear();
+ return;
+ }
+
+ if (!module_file_spec && symbol_file_spec) {
+ // This is '4. module:empty symbol:exists -> Success'.
+ // The locate module callback returned only a symbol file. For example,
+ // a breakpad symbol text file. GetOrCreateModule will use this returned
+ // symbol_file_spec.
+ LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s",
+ LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());
+ return;
+ }
+
+ // The locate module callback returned
+ // - '2. module:exists symbol:exists -> Success'
+ // - a combination of a module file and a symbol file.
+ // - Or '3. module:exists symbol:empty -> Success'
+ // - only a module file.
+ // Load the module file.
+ auto cached_module_spec(module_spec);
+ cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5
+ // content hash instead of real UUID.
+ cached_module_spec.GetFileSpec() = module_file_spec;
+ cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();
+ cached_module_spec.SetObjectOffset(0);
+
+ error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr,
+ nullptr, &did_create_module, false);
+ if (error.Success() && module_sp) {
+ // Succeeded to load the module file.
+ LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s",
+ LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),
+ symbol_file_spec.GetPath().c_str());
+ } else {
+ LLDB_LOGF(log,
+ "%s: locate module callback succeeded but failed to load: "
+ "module=%s symbol=%s",
+ LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),
+ symbol_file_spec.GetPath().c_str());
+ // Clear module_sp and symbol_file_spec for the error.
+ module_sp.reset();
+ symbol_file_spec.Clear();
+ }
+}
+
TargetSP Target::CalculateTarget() { return shared_from_this(); }
ProcessSP Target::CalculateProcess() { return m_process_sp; }
@@ -2359,6 +2499,14 @@ Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language,
create_on_demand);
}
+CompilerType Target::GetRegisterType(const std::string &name,
+ const lldb_private::RegisterFlags &flags,
+ uint32_t byte_size) {
+ RegisterTypeBuilderSP provider = PluginManager::GetRegisterTypeBuilder(*this);
+ assert(provider);
+ return provider->GetRegisterType(name, flags, byte_size);
+}
+
std::vector<lldb::TypeSystemSP>
Target::GetScratchTypeSystems(bool create_on_demand) {
if (!m_valid)
@@ -2377,18 +2525,17 @@ Target::GetScratchTypeSystems(bool create_on_demand) {
auto type_system_or_err =
GetScratchTypeSystemForLanguage(language, create_on_demand);
if (!type_system_or_err)
- LLDB_LOG_ERROR(GetLog(LLDBLog::Target), type_system_or_err.takeError(),
- "Language '{}' has expression support but no scratch type "
- "system available",
- Language::GetNameForLanguageType(language));
+ LLDB_LOG_ERROR(
+ GetLog(LLDBLog::Target), type_system_or_err.takeError(),
+ "Language '{1}' has expression support but no scratch type "
+ "system available: {0}",
+ Language::GetNameForLanguageType(language));
else
if (auto ts = *type_system_or_err)
scratch_type_systems.push_back(ts);
}
- std::sort(scratch_type_systems.begin(), scratch_type_systems.end(),
- [](lldb::TypeSystemSP a, lldb::TypeSystemSP b) {
- return a.get() <= b.get();
- });
+
+ std::sort(scratch_type_systems.begin(), scratch_type_systems.end());
scratch_type_systems.erase(
std::unique(scratch_type_systems.begin(), scratch_type_systems.end()),
scratch_type_systems.end());
@@ -2400,9 +2547,10 @@ Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) {
auto type_system_or_err = GetScratchTypeSystemForLanguage(language, true);
if (auto err = type_system_or_err.takeError()) {
- LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err),
- "Unable to get persistent expression state for language {}",
- Language::GetNameForLanguageType(language));
+ LLDB_LOG_ERROR(
+ GetLog(LLDBLog::Target), std::move(err),
+ "Unable to get persistent expression state for language {1}: {0}",
+ Language::GetNameForLanguageType(language));
return nullptr;
}
@@ -2410,7 +2558,7 @@ Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) {
return ts->GetPersistentExpressionState();
LLDB_LOG(GetLog(LLDBLog::Target),
- "Unable to get persistent expression state for language {}",
+ "Unable to get persistent expression state for language {1}: {0}",
Language::GetNameForLanguageType(language));
return nullptr;
}
@@ -2529,6 +2677,27 @@ void Target::SetDefaultArchitecture(const ArchSpec &arch) {
Target::GetGlobalProperties().SetDefaultArchitecture(arch);
}
+llvm::Error Target::SetLabel(llvm::StringRef label) {
+ size_t n = LLDB_INVALID_INDEX32;
+ if (llvm::to_integer(label, n))
+ return llvm::make_error<llvm::StringError>(
+ "Cannot use integer as target label.", llvm::inconvertibleErrorCode());
+ TargetList &targets = GetDebugger().GetTargetList();
+ for (size_t i = 0; i < targets.GetNumTargets(); i++) {
+ TargetSP target_sp = targets.GetTargetAtIndex(i);
+ if (target_sp && target_sp->GetLabel() == label) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv(
+ "Cannot use label '{0}' since it's set in target #{1}.", label,
+ i),
+ llvm::inconvertibleErrorCode());
+ }
+ }
+
+ m_label = label.str();
+ return llvm::Error::success();
+}
+
Target *Target::GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
const SymbolContext *sc_ptr) {
// The target can either exist in the "process" of ExecutionContext, or in
@@ -2588,7 +2757,7 @@ ExpressionResults Target::EvaluateExpression(
auto ts = *type_system_or_err;
if (!ts)
LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err),
- "Scratch type system is no longer live");
+ "Scratch type system is no longer live: {0}");
else
persistent_var_sp =
ts->GetPersistentExpressionState()->GetVariable(expr);
@@ -2863,7 +3032,7 @@ bool Target::RunStopHooks() {
if (print_hook_header && !any_thread_matched) {
StreamString s;
- cur_hook_sp->GetDescription(&s, eDescriptionLevelBrief);
+ cur_hook_sp->GetDescription(s, eDescriptionLevelBrief);
if (s.GetSize() != 0)
output_sp->Printf("\n- Hook %" PRIu64 " (%s)\n", cur_hook_sp->GetID(),
s.GetData());
@@ -3082,6 +3251,17 @@ bool Target::SetSectionUnloaded(const lldb::SectionSP &section_sp,
void Target::ClearAllLoadedSections() { m_section_load_history.Clear(); }
+void Target::SaveScriptedLaunchInfo(lldb_private::ProcessInfo &process_info) {
+ if (process_info.IsScriptedProcess()) {
+ // Only copy scripted process launch options.
+ ProcessLaunchInfo &default_launch_info = const_cast<ProcessLaunchInfo &>(
+ GetGlobalProperties().GetProcessLaunchInfo());
+ default_launch_info.SetProcessPluginName("ScriptedProcess");
+ default_launch_info.SetScriptedMetadata(process_info.GetScriptedMetadata());
+ SetProcessLaunchInfo(default_launch_info);
+ }
+}
+
Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
m_stats.SetLaunchOrAttachTime();
Status error;
@@ -3111,19 +3291,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
launch_info.GetFlags().Set(eLaunchFlagDebug);
- if (launch_info.IsScriptedProcess()) {
- // Only copy scripted process launch options.
- ProcessLaunchInfo &default_launch_info = const_cast<ProcessLaunchInfo &>(
- GetGlobalProperties().GetProcessLaunchInfo());
-
- default_launch_info.SetProcessPluginName("ScriptedProcess");
- default_launch_info.SetScriptedProcessClassName(
- launch_info.GetScriptedProcessClassName());
- default_launch_info.SetScriptedProcessDictionarySP(
- launch_info.GetScriptedProcessDictionarySP());
-
- SetProcessLaunchInfo(launch_info);
- }
+ SaveScriptedLaunchInfo(launch_info);
// Get the value of synchronous execution here. If you wait till after you
// have started to run, then you could have hit a breakpoint, whose command
@@ -3152,8 +3320,8 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
// its own hijacking listener or if the process is created by the target
// manually, without the platform).
if (!launch_info.GetHijackListener())
- launch_info.SetHijackListener(
- Listener::MakeListener("lldb.Target.Launch.hijack"));
+ launch_info.SetHijackListener(Listener::MakeListener(
+ Process::LaunchSynchronousHijackListenerName.data()));
// If we're not already connected to the process, and if we have a platform
// that can launch a process for debugging, go ahead and do that here.
@@ -3181,13 +3349,14 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
assert(m_process_sp);
} else {
// Use a Process plugin to construct the process.
- const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess(launch_info.GetListener(), plugin_name, nullptr, false);
+ CreateProcess(launch_info.GetListener(),
+ launch_info.GetProcessPluginName(), nullptr, false);
}
// Since we didn't have a platform launch the process, launch it here.
if (m_process_sp) {
m_process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+ m_process_sp->SetShadowListener(launch_info.GetShadowListener());
error = m_process_sp->Launch(launch_info);
}
}
@@ -3226,7 +3395,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
// SyncResume hijacker.
m_process_sp->ResumeSynchronous(stream);
else
- error = m_process_sp->PrivateResume();
+ error = m_process_sp->Resume();
if (!error.Success()) {
Status error2;
error2.SetErrorStringWithFormat(
@@ -3329,26 +3498,27 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
ListenerSP hijack_listener_sp;
const bool async = attach_info.GetAsync();
if (!async) {
- hijack_listener_sp =
- Listener::MakeListener("lldb.Target.Attach.attach.hijack");
+ hijack_listener_sp = Listener::MakeListener(
+ Process::AttachSynchronousHijackListenerName.data());
attach_info.SetHijackListener(hijack_listener_sp);
}
Status error;
if (state != eStateConnected && platform_sp != nullptr &&
- platform_sp->CanDebugProcess()) {
+ platform_sp->CanDebugProcess() && !attach_info.IsScriptedProcess()) {
SetPlatform(platform_sp);
process_sp = platform_sp->Attach(attach_info, GetDebugger(), this, error);
} else {
if (state != eStateConnected) {
- const char *plugin_name = attach_info.GetProcessPluginName();
+ SaveScriptedLaunchInfo(attach_info);
+ llvm::StringRef plugin_name = attach_info.GetProcessPluginName();
process_sp =
CreateProcess(attach_info.GetListenerForProcess(GetDebugger()),
plugin_name, nullptr, false);
- if (process_sp == nullptr) {
- error.SetErrorStringWithFormat(
- "failed to create process using plugin %s",
- (plugin_name) ? plugin_name : "null");
+ if (!process_sp) {
+ error.SetErrorStringWithFormatv(
+ "failed to create process using plugin '{0}'",
+ plugin_name.empty() ? "<empty>" : plugin_name);
return error;
}
}
@@ -3361,9 +3531,10 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
if (async) {
process_sp->RestoreProcessEvents();
} else {
- state = process_sp->WaitForProcessToStop(std::nullopt, nullptr, false,
- attach_info.GetHijackListener(),
- stream);
+ // We are stopping all the way out to the user, so update selected frames.
+ state = process_sp->WaitForProcessToStop(
+ std::nullopt, nullptr, false, attach_info.GetHijackListener(), stream,
+ true, SelectMostRelevantFrame);
process_sp->RestoreProcessEvents();
if (state != eStateStopped) {
@@ -3620,7 +3791,7 @@ bool Target::StopHook::ExecutionContextPasses(const ExecutionContext &exc_ctx) {
return will_run;
}
-void Target::StopHook::GetDescription(Stream *s,
+void Target::StopHook::GetDescription(Stream &s,
lldb::DescriptionLevel level) const {
// For brief descriptions, only print the subclass description:
@@ -3629,55 +3800,55 @@ void Target::StopHook::GetDescription(Stream *s,
return;
}
- unsigned indent_level = s->GetIndentLevel();
+ unsigned indent_level = s.GetIndentLevel();
- s->SetIndentLevel(indent_level + 2);
+ s.SetIndentLevel(indent_level + 2);
- s->Printf("Hook: %" PRIu64 "\n", GetID());
+ s.Printf("Hook: %" PRIu64 "\n", GetID());
if (m_active)
- s->Indent("State: enabled\n");
+ s.Indent("State: enabled\n");
else
- s->Indent("State: disabled\n");
+ s.Indent("State: disabled\n");
if (m_auto_continue)
- s->Indent("AutoContinue on\n");
+ s.Indent("AutoContinue on\n");
if (m_specifier_sp) {
- s->Indent();
- s->PutCString("Specifier:\n");
- s->SetIndentLevel(indent_level + 4);
- m_specifier_sp->GetDescription(s, level);
- s->SetIndentLevel(indent_level + 2);
+ s.Indent();
+ s.PutCString("Specifier:\n");
+ s.SetIndentLevel(indent_level + 4);
+ m_specifier_sp->GetDescription(&s, level);
+ s.SetIndentLevel(indent_level + 2);
}
if (m_thread_spec_up) {
StreamString tmp;
- s->Indent("Thread:\n");
+ s.Indent("Thread:\n");
m_thread_spec_up->GetDescription(&tmp, level);
- s->SetIndentLevel(indent_level + 4);
- s->Indent(tmp.GetString());
- s->PutCString("\n");
- s->SetIndentLevel(indent_level + 2);
+ s.SetIndentLevel(indent_level + 4);
+ s.Indent(tmp.GetString());
+ s.PutCString("\n");
+ s.SetIndentLevel(indent_level + 2);
}
GetSubclassDescription(s, level);
}
void Target::StopHookCommandLine::GetSubclassDescription(
- Stream *s, lldb::DescriptionLevel level) const {
+ Stream &s, lldb::DescriptionLevel level) const {
// The brief description just prints the first command.
if (level == eDescriptionLevelBrief) {
if (m_commands.GetSize() == 1)
- s->PutCString(m_commands.GetStringAtIndex(0));
+ s.PutCString(m_commands.GetStringAtIndex(0));
return;
}
- s->Indent("Commands: \n");
- s->SetIndentLevel(s->GetIndentLevel() + 4);
+ s.Indent("Commands: \n");
+ s.SetIndentLevel(s.GetIndentLevel() + 4);
uint32_t num_commands = m_commands.GetSize();
for (uint32_t i = 0; i < num_commands; i++) {
- s->Indent(m_commands.GetStringAtIndex(i));
- s->PutCString("\n");
+ s.Indent(m_commands.GetStringAtIndex(i));
+ s.PutCString("\n");
}
- s->SetIndentLevel(s->GetIndentLevel() - 4);
+ s.SetIndentLevel(s.GetIndentLevel() - 4);
}
// Target::StopHookCommandLine
@@ -3765,13 +3936,13 @@ Target::StopHookScripted::HandleStop(ExecutionContext &exc_ctx,
}
void Target::StopHookScripted::GetSubclassDescription(
- Stream *s, lldb::DescriptionLevel level) const {
+ Stream &s, lldb::DescriptionLevel level) const {
if (level == eDescriptionLevelBrief) {
- s->PutCString(m_class_name);
+ s.PutCString(m_class_name);
return;
}
- s->Indent("Class:");
- s->Printf("%s\n", m_class_name.c_str());
+ s.Indent("Class:");
+ s.Printf("%s\n", m_class_name.c_str());
// Now print the extra args:
// FIXME: We should use StructuredData.GetDescription on the m_extra_args
@@ -3790,20 +3961,20 @@ void Target::StopHookScripted::GetSubclassDescription(
if (num_keys == 0)
return;
- s->Indent("Args:\n");
- s->SetIndentLevel(s->GetIndentLevel() + 4);
+ s.Indent("Args:\n");
+ s.SetIndentLevel(s.GetIndentLevel() + 4);
auto print_one_element = [&s](ConstString key,
StructuredData::Object *object) {
- s->Indent();
- s->Printf("%s : %s\n", key.GetCString(),
+ s.Indent();
+ s.Printf("%s : %s\n", key.GetCString(),
object->GetStringValue().str().c_str());
return true;
};
as_dict->ForEach(print_one_element);
- s->SetIndentLevel(s->GetIndentLevel() - 4);
+ s.SetIndentLevel(s.GetIndentLevel() - 4);
}
static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
@@ -3998,9 +4169,9 @@ class TargetOptionValueProperties
public:
TargetOptionValueProperties(ConstString name) : Cloneable(name) {}
- const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
- bool will_modify,
- uint32_t idx) const override {
+ const Property *
+ GetPropertyAtIndex(size_t idx,
+ const ExecutionContext *exe_ctx = nullptr) const override {
// When getting the value for a key from the target options, we will always
// try and grab the setting from the current target if there is one. Else
// we just use the one from this instance.
@@ -4081,9 +4252,9 @@ TargetProperties::TargetProperties(Target *target)
m_experimental_properties_up =
std::make_unique<TargetExperimentalProperties>();
m_collection_sp->AppendProperty(
- ConstString(Properties::GetExperimentalSettingsName()),
- ConstString("Experimental settings - setting these won't produce "
- "errors if the setting is not present."),
+ Properties::GetExperimentalSettingsName(),
+ "Experimental settings - setting these won't produce "
+ "errors if the setting is not present.",
true, m_experimental_properties_up->GetValueProperties());
} else {
m_collection_sp =
@@ -4092,13 +4263,13 @@ TargetProperties::TargetProperties(Target *target)
m_experimental_properties_up =
std::make_unique<TargetExperimentalProperties>();
m_collection_sp->AppendProperty(
- ConstString(Properties::GetExperimentalSettingsName()),
- ConstString("Experimental settings - setting these won't produce "
- "errors if the setting is not present."),
+ Properties::GetExperimentalSettingsName(),
+ "Experimental settings - setting these won't produce "
+ "errors if the setting is not present.",
true, m_experimental_properties_up->GetValueProperties());
m_collection_sp->AppendProperty(
- ConstString("process"), ConstString("Settings specific to processes."),
- true, Process::GetGlobalProperties().GetValueProperties());
+ "process", "Settings specific to processes.", true,
+ Process::GetGlobalProperties().GetValueProperties());
m_collection_sp->SetValueChangedCallback(
ePropertySaveObjectsDir, [this] { CheckJITObjectsDir(); });
}
@@ -4121,13 +4292,14 @@ void TargetProperties::UpdateLaunchInfoFromProperties() {
bool TargetProperties::GetInjectLocalVariables(
ExecutionContext *exe_ctx) const {
- const Property *exp_property = m_collection_sp->GetPropertyAtIndex(
- exe_ctx, false, ePropertyExperimental);
+ const Property *exp_property =
+ m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (exp_values)
- return exp_values->GetPropertyAtIndexAsBoolean(
- exe_ctx, ePropertyInjectLocalVars, true);
+ return exp_values
+ ->GetPropertyAtIndexAs<bool>(ePropertyInjectLocalVars, exe_ctx)
+ .value_or(true);
else
return true;
}
@@ -4135,100 +4307,98 @@ bool TargetProperties::GetInjectLocalVariables(
void TargetProperties::SetInjectLocalVariables(ExecutionContext *exe_ctx,
bool b) {
const Property *exp_property =
- m_collection_sp->GetPropertyAtIndex(exe_ctx, true, ePropertyExperimental);
+ m_collection_sp->GetPropertyAtIndex(ePropertyExperimental, exe_ctx);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (exp_values)
- exp_values->SetPropertyAtIndexAsBoolean(exe_ctx, ePropertyInjectLocalVars,
- true);
+ exp_values->SetPropertyAtIndex(ePropertyInjectLocalVars, true, exe_ctx);
}
ArchSpec TargetProperties::GetDefaultArchitecture() const {
- OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(
- nullptr, ePropertyDefaultArch);
- if (value)
- return value->GetCurrentValue();
- return ArchSpec();
+ const uint32_t idx = ePropertyDefaultArch;
+ return GetPropertyAtIndexAs<ArchSpec>(idx, {});
}
void TargetProperties::SetDefaultArchitecture(const ArchSpec &arch) {
- OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(
- nullptr, ePropertyDefaultArch);
- if (value)
- return value->SetCurrentValue(arch, true);
+ const uint32_t idx = ePropertyDefaultArch;
+ SetPropertyAtIndex(idx, arch);
}
bool TargetProperties::GetMoveToNearestCode() const {
const uint32_t idx = ePropertyMoveToNearestCode;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
lldb::DynamicValueType TargetProperties::GetPreferDynamicValue() const {
const uint32_t idx = ePropertyPreferDynamic;
- return (lldb::DynamicValueType)
- m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<lldb::DynamicValueType>(
+ idx, static_cast<lldb::DynamicValueType>(
+ g_target_properties[idx].default_uint_value));
}
bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) {
const uint32_t idx = ePropertyPreferDynamic;
- return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d);
+ return SetPropertyAtIndex(idx, d);
}
bool TargetProperties::GetPreloadSymbols() const {
+ if (INTERRUPT_REQUESTED(m_target->GetDebugger(),
+ "Interrupted checking preload symbols")) {
+ return false;
+ }
const uint32_t idx = ePropertyPreloadSymbols;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetPreloadSymbols(bool b) {
const uint32_t idx = ePropertyPreloadSymbols;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetDisableASLR() const {
const uint32_t idx = ePropertyDisableASLR;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDisableASLR(bool b) {
const uint32_t idx = ePropertyDisableASLR;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetInheritTCC() const {
const uint32_t idx = ePropertyInheritTCC;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetInheritTCC(bool b) {
const uint32_t idx = ePropertyInheritTCC;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetDetachOnError() const {
const uint32_t idx = ePropertyDetachOnError;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDetachOnError(bool b) {
const uint32_t idx = ePropertyDetachOnError;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetDisableSTDIO() const {
const uint32_t idx = ePropertyDisableSTDIO;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDisableSTDIO(bool b) {
const uint32_t idx = ePropertyDisableSTDIO;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
const char *TargetProperties::GetDisassemblyFlavor() const {
@@ -4236,38 +4406,41 @@ const char *TargetProperties::GetDisassemblyFlavor() const {
const char *return_value;
x86DisassemblyFlavor flavor_value =
- (x86DisassemblyFlavor)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ GetPropertyAtIndexAs<x86DisassemblyFlavor>(
+ idx, static_cast<x86DisassemblyFlavor>(
+ g_target_properties[idx].default_uint_value));
+
return_value = g_x86_dis_flavor_value_types[flavor_value].string_value;
return return_value;
}
InlineStrategy TargetProperties::GetInlineStrategy() const {
const uint32_t idx = ePropertyInlineStrategy;
- return (InlineStrategy)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<InlineStrategy>(
+ idx,
+ static_cast<InlineStrategy>(g_target_properties[idx].default_uint_value));
}
llvm::StringRef TargetProperties::GetArg0() const {
const uint32_t idx = ePropertyArg0;
- return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx,
- llvm::StringRef());
+ return GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_target_properties[idx].default_cstr_value);
}
void TargetProperties::SetArg0(llvm::StringRef arg) {
const uint32_t idx = ePropertyArg0;
- m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, arg);
+ SetPropertyAtIndex(idx, arg);
m_launch_info.SetArg0(arg);
}
bool TargetProperties::GetRunArguments(Args &args) const {
const uint32_t idx = ePropertyRunArgs;
- return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args);
+ return m_collection_sp->GetPropertyAtIndexAsArgs(idx, args);
}
void TargetProperties::SetRunArguments(const Args &args) {
const uint32_t idx = ePropertyRunArgs;
- m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args);
+ m_collection_sp->SetPropertyAtIndexFromArgs(idx, args);
m_launch_info.GetArguments() = args;
}
@@ -4275,8 +4448,8 @@ Environment TargetProperties::ComputeEnvironment() const {
Environment env;
if (m_target &&
- m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, ePropertyInheritEnv,
+ GetPropertyAtIndexAs<bool>(
+ ePropertyInheritEnv,
g_target_properties[ePropertyInheritEnv].default_uint_value != 0)) {
if (auto platform_sp = m_target->GetPlatform()) {
Environment platform_env = platform_sp->GetEnvironment();
@@ -4286,14 +4459,13 @@ Environment TargetProperties::ComputeEnvironment() const {
}
Args property_unset_env;
- m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyUnsetEnvVars,
+ m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyUnsetEnvVars,
property_unset_env);
for (const auto &var : property_unset_env)
env.erase(var.ref());
Args property_env;
- m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEnvVars,
- property_env);
+ m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyEnvVars, property_env);
for (const auto &KV : Environment(property_env))
env[KV.first()] = KV.second;
@@ -4310,8 +4482,8 @@ Environment TargetProperties::GetInheritedEnvironment() const {
if (m_target == nullptr)
return environment;
- if (!m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, ePropertyInheritEnv,
+ if (!GetPropertyAtIndexAs<bool>(
+ ePropertyInheritEnv,
g_target_properties[ePropertyInheritEnv].default_uint_value != 0))
return environment;
@@ -4324,7 +4496,7 @@ Environment TargetProperties::GetInheritedEnvironment() const {
environment[KV.first()] = KV.second;
Args property_unset_environment;
- m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyUnsetEnvVars,
+ m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyUnsetEnvVars,
property_unset_environment);
for (const auto &var : property_unset_environment)
environment.erase(var.ref());
@@ -4334,7 +4506,7 @@ Environment TargetProperties::GetInheritedEnvironment() const {
Environment TargetProperties::GetTargetEnvironment() const {
Args property_environment;
- m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEnvVars,
+ m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyEnvVars,
property_environment);
Environment environment;
for (const auto &KV : Environment(property_environment))
@@ -4346,106 +4518,93 @@ Environment TargetProperties::GetTargetEnvironment() const {
void TargetProperties::SetEnvironment(Environment env) {
// TODO: Get rid of the Args intermediate step
const uint32_t idx = ePropertyEnvVars;
- m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, Args(env));
+ m_collection_sp->SetPropertyAtIndexFromArgs(idx, Args(env));
}
bool TargetProperties::GetSkipPrologue() const {
const uint32_t idx = ePropertySkipPrologue;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
PathMappingList &TargetProperties::GetSourcePathMap() const {
const uint32_t idx = ePropertySourceMap;
OptionValuePathMappings *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(nullptr,
- false, idx);
+ m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(idx);
assert(option_value);
return option_value->GetCurrentValue();
}
bool TargetProperties::GetAutoSourceMapRelative() const {
const uint32_t idx = ePropertyAutoSourceMapRelative;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::AppendExecutableSearchPaths(const FileSpec &dir) {
const uint32_t idx = ePropertyExecutableSearchPaths;
OptionValueFileSpecList *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
- false, idx);
+ m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(idx);
assert(option_value);
option_value->AppendCurrentValue(dir);
}
FileSpecList TargetProperties::GetExecutableSearchPaths() {
const uint32_t idx = ePropertyExecutableSearchPaths;
- const OptionValueFileSpecList *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
- false, idx);
- assert(option_value);
- return option_value->GetCurrentValue();
+ return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}
FileSpecList TargetProperties::GetDebugFileSearchPaths() {
const uint32_t idx = ePropertyDebugFileSearchPaths;
- const OptionValueFileSpecList *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
- false, idx);
- assert(option_value);
- return option_value->GetCurrentValue();
+ return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}
FileSpecList TargetProperties::GetClangModuleSearchPaths() {
const uint32_t idx = ePropertyClangModuleSearchPaths;
- const OptionValueFileSpecList *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
- false, idx);
- assert(option_value);
- return option_value->GetCurrentValue();
+ return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}
bool TargetProperties::GetEnableAutoImportClangModules() const {
const uint32_t idx = ePropertyAutoImportClangModules;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
ImportStdModule TargetProperties::GetImportStdModule() const {
const uint32_t idx = ePropertyImportStdModule;
- return (ImportStdModule)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<ImportStdModule>(
+ idx, static_cast<ImportStdModule>(
+ g_target_properties[idx].default_uint_value));
}
DynamicClassInfoHelper TargetProperties::GetDynamicClassInfoHelper() const {
const uint32_t idx = ePropertyDynamicClassInfoHelper;
- return (DynamicClassInfoHelper)
- m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<DynamicClassInfoHelper>(
+ idx, static_cast<DynamicClassInfoHelper>(
+ g_target_properties[idx].default_uint_value));
}
bool TargetProperties::GetEnableAutoApplyFixIts() const {
const uint32_t idx = ePropertyAutoApplyFixIts;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
uint64_t TargetProperties::GetNumberOfRetriesWithFixits() const {
const uint32_t idx = ePropertyRetriesWithFixIts;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
bool TargetProperties::GetEnableNotifyAboutFixIts() const {
const uint32_t idx = ePropertyNotifyAboutFixIts;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
FileSpec TargetProperties::GetSaveJITObjectsDir() const {
const uint32_t idx = ePropertySaveObjectsDir;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
}
void TargetProperties::CheckJITObjectsDir() {
@@ -4461,7 +4620,7 @@ void TargetProperties::CheckJITObjectsDir() {
if (exists && is_directory && writable)
return;
- m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertySaveObjectsDir)
+ m_collection_sp->GetPropertyAtIndex(ePropertySaveObjectsDir)
->GetValue()
->Clear();
@@ -4483,87 +4642,82 @@ void TargetProperties::CheckJITObjectsDir() {
bool TargetProperties::GetEnableSyntheticValue() const {
const uint32_t idx = ePropertyEnableSynthetic;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
uint32_t TargetProperties::GetMaxZeroPaddingInFloatFormat() const {
const uint32_t idx = ePropertyMaxZeroPaddingInFloatFormat;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
uint32_t TargetProperties::GetMaximumNumberOfChildrenToDisplay() const {
const uint32_t idx = ePropertyMaxChildrenCount;
- return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<int64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
std::pair<uint32_t, bool>
TargetProperties::GetMaximumDepthOfChildrenToDisplay() const {
const uint32_t idx = ePropertyMaxChildrenDepth;
auto *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(nullptr, idx);
+ m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(idx);
bool is_default = !option_value->OptionWasSet();
return {option_value->GetCurrentValue(), is_default};
}
uint32_t TargetProperties::GetMaximumSizeOfStringSummary() const {
const uint32_t idx = ePropertyMaxSummaryLength;
- return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
uint32_t TargetProperties::GetMaximumMemReadSize() const {
const uint32_t idx = ePropertyMaxMemReadSize;
- return m_collection_sp->GetPropertyAtIndexAsSInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
FileSpec TargetProperties::GetStandardInputPath() const {
const uint32_t idx = ePropertyInputPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
}
void TargetProperties::SetStandardInputPath(llvm::StringRef path) {
const uint32_t idx = ePropertyInputPath;
- m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, path);
+ SetPropertyAtIndex(idx, path);
}
FileSpec TargetProperties::GetStandardOutputPath() const {
const uint32_t idx = ePropertyOutputPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
}
void TargetProperties::SetStandardOutputPath(llvm::StringRef path) {
const uint32_t idx = ePropertyOutputPath;
- m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, path);
+ SetPropertyAtIndex(idx, path);
}
FileSpec TargetProperties::GetStandardErrorPath() const {
const uint32_t idx = ePropertyErrorPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
}
void TargetProperties::SetStandardErrorPath(llvm::StringRef path) {
const uint32_t idx = ePropertyErrorPath;
- m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, path);
+ SetPropertyAtIndex(idx, path);
}
LanguageType TargetProperties::GetLanguage() const {
- OptionValueLanguage *value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(
- nullptr, ePropertyLanguage);
- if (value)
- return value->GetCurrentValue();
- return LanguageType();
+ const uint32_t idx = ePropertyLanguage;
+ return GetPropertyAtIndexAs<LanguageType>(idx, {});
}
llvm::StringRef TargetProperties::GetExpressionPrefixContents() {
const uint32_t idx = ePropertyExprPrefix;
OptionValueFileSpec *file =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false,
- idx);
+ m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(idx);
if (file) {
DataBufferSP data_sp(file->GetFileContents());
if (data_sp)
@@ -4576,89 +4730,110 @@ llvm::StringRef TargetProperties::GetExpressionPrefixContents() {
uint64_t TargetProperties::GetExprErrorLimit() const {
const uint32_t idx = ePropertyExprErrorLimit;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
+}
+
+uint64_t TargetProperties::GetExprAllocAddress() const {
+ const uint32_t idx = ePropertyExprAllocAddress;
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
+}
+
+uint64_t TargetProperties::GetExprAllocSize() const {
+ const uint32_t idx = ePropertyExprAllocSize;
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
+}
+
+uint64_t TargetProperties::GetExprAllocAlign() const {
+ const uint32_t idx = ePropertyExprAllocAlign;
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_target_properties[idx].default_uint_value);
}
bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() {
const uint32_t idx = ePropertyBreakpointUseAvoidList;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
bool TargetProperties::GetUseHexImmediates() const {
const uint32_t idx = ePropertyUseHexImmediates;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
bool TargetProperties::GetUseFastStepping() const {
const uint32_t idx = ePropertyUseFastStepping;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
bool TargetProperties::GetDisplayExpressionsInCrashlogs() const {
const uint32_t idx = ePropertyDisplayExpressionsInCrashlogs;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
LoadScriptFromSymFile TargetProperties::GetLoadScriptFromSymbolFile() const {
const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
- return (LoadScriptFromSymFile)
- m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<LoadScriptFromSymFile>(
+ idx, static_cast<LoadScriptFromSymFile>(
+ g_target_properties[idx].default_uint_value));
}
LoadCWDlldbinitFile TargetProperties::GetLoadCWDlldbinitFile() const {
const uint32_t idx = ePropertyLoadCWDlldbinitFile;
- return (LoadCWDlldbinitFile)m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<LoadCWDlldbinitFile>(
+ idx, static_cast<LoadCWDlldbinitFile>(
+ g_target_properties[idx].default_uint_value));
}
Disassembler::HexImmediateStyle TargetProperties::GetHexImmediateStyle() const {
const uint32_t idx = ePropertyHexImmediateStyle;
- return (Disassembler::HexImmediateStyle)
- m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<Disassembler::HexImmediateStyle>(
+ idx, static_cast<Disassembler::HexImmediateStyle>(
+ g_target_properties[idx].default_uint_value));
}
MemoryModuleLoadLevel TargetProperties::GetMemoryModuleLoadLevel() const {
const uint32_t idx = ePropertyMemoryModuleLoadLevel;
- return (MemoryModuleLoadLevel)
- m_collection_sp->GetPropertyAtIndexAsEnumeration(
- nullptr, idx, g_target_properties[idx].default_uint_value);
+ return GetPropertyAtIndexAs<MemoryModuleLoadLevel>(
+ idx, static_cast<MemoryModuleLoadLevel>(
+ g_target_properties[idx].default_uint_value));
}
bool TargetProperties::GetUserSpecifiedTrapHandlerNames(Args &args) const {
const uint32_t idx = ePropertyTrapHandlerNames;
- return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args);
+ return m_collection_sp->GetPropertyAtIndexAsArgs(idx, args);
}
void TargetProperties::SetUserSpecifiedTrapHandlerNames(const Args &args) {
const uint32_t idx = ePropertyTrapHandlerNames;
- m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args);
+ m_collection_sp->SetPropertyAtIndexFromArgs(idx, args);
}
bool TargetProperties::GetDisplayRuntimeSupportValues() const {
const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDisplayRuntimeSupportValues(bool b) {
const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetDisplayRecognizedArguments() const {
const uint32_t idx = ePropertyDisplayRecognizedArguments;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDisplayRecognizedArguments(bool b) {
const uint32_t idx = ePropertyDisplayRecognizedArguments;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ SetPropertyAtIndex(idx, b);
}
const ProcessLaunchInfo &TargetProperties::GetProcessLaunchInfo() const {
@@ -4695,19 +4870,19 @@ void TargetProperties::SetProcessLaunchInfo(
bool TargetProperties::GetRequireHardwareBreakpoints() const {
const uint32_t idx = ePropertyRequireHardwareBreakpoints;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
const uint32_t idx = ePropertyRequireHardwareBreakpoints;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+ m_collection_sp->SetPropertyAtIndex(idx, b);
}
bool TargetProperties::GetAutoInstallMainExecutable() const {
const uint32_t idx = ePropertyAutoInstallMainExecutable;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::Arg0ValueChangedCallback() {
@@ -4769,13 +4944,13 @@ void TargetProperties::DisableSTDIOValueChangedCallback() {
bool TargetProperties::GetDebugUtilityExpression() const {
const uint32_t idx = ePropertyDebugUtilityExpression;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_target_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_target_properties[idx].default_uint_value != 0);
}
void TargetProperties::SetDebugUtilityExpression(bool debug) {
const uint32_t idx = ePropertyDebugUtilityExpression;
- m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, debug);
+ SetPropertyAtIndex(idx, debug);
}
// Target::TargetEventData
@@ -4789,9 +4964,8 @@ Target::TargetEventData::TargetEventData(const lldb::TargetSP &target_sp,
Target::TargetEventData::~TargetEventData() = default;
-ConstString Target::TargetEventData::GetFlavorString() {
- static ConstString g_flavor("Target::TargetEventData");
- return g_flavor;
+llvm::StringRef Target::TargetEventData::GetFlavorString() {
+ return "Target::TargetEventData";
}
void Target::TargetEventData::Dump(Stream *s) const {
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 8ce2ae8c2898..cb198e388011 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -325,6 +325,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
return error;
}
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
+ debugger.GetTargetList().RegisterInProcessTarget(target_sp);
target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
if (user_exe_path_is_bundle)
exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
@@ -336,6 +337,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
// No file was specified, just create an empty target with any arch if a
// valid arch was specified
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
+ debugger.GetTargetList().RegisterInProcessTarget(target_sp);
}
if (!target_sp)
@@ -489,7 +491,7 @@ uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
return num_signals_sent;
}
-int TargetList::GetNumTargets() const {
+size_t TargetList::GetNumTargets() const {
std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
return m_target_list.size();
}
@@ -513,6 +515,7 @@ uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
lldbassert(!llvm::is_contained(m_target_list, target_sp) &&
"target already exists it the list");
+ UnregisterInProcessTarget(target_sp);
m_target_list.push_back(std::move(target_sp));
if (do_select)
SetSelectedTargetInternal(m_target_list.size() - 1);
@@ -540,3 +543,36 @@ lldb::TargetSP TargetList::GetSelectedTarget() {
m_selected_target_idx = 0;
return GetTargetAtIndex(m_selected_target_idx);
}
+
+bool TargetList::AnyTargetContainsModule(Module &module) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ for (const auto &target_sp : m_target_list) {
+ if (target_sp->GetImages().FindModule(&module))
+ return true;
+ }
+ for (const auto &target_sp: m_in_process_target_list) {
+ if (target_sp->GetImages().FindModule(&module))
+ return true;
+ }
+ return false;
+}
+
+ void TargetList::RegisterInProcessTarget(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ [[maybe_unused]] bool was_added;
+ std::tie(std::ignore, was_added) =
+ m_in_process_target_list.insert(target_sp);
+ assert(was_added && "Target pointer was left in the in-process map");
+ }
+
+ void TargetList::UnregisterInProcessTarget(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ [[maybe_unused]] bool was_present =
+ m_in_process_target_list.erase(target_sp);
+ assert(was_present && "Target pointer being removed was not registered");
+ }
+
+ bool TargetList::IsTargetInProcess(TargetSP target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ return m_in_process_target_list.count(target_sp) == 1;
+ }
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 202304174bc1..19ea505af656 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -24,6 +24,15 @@ let Definition = "target" in {
DefaultUnsignedValue<5>,
Desc<"The maximum amount of errors to emit while parsing an expression. "
"A value of 0 means to always continue parsing if possible.">;
+ def ExprAllocAddress: Property<"expr-alloc-address", "UInt64">,
+ DefaultUnsignedValue<0>,
+ Desc<"Start address within the process address space of memory allocation for expression evaluation.">;
+ def ExprAllocSize: Property<"expr-alloc-size", "UInt64">,
+ DefaultUnsignedValue<0>,
+ Desc<"Amount of memory in bytes to allocate for expression evaluation.">;
+ def ExprAllocAlign: Property<"expr-alloc-align", "UInt64">,
+ DefaultUnsignedValue<0>,
+ Desc<"Alignment for each memory allocation for expression evaluation.">;
def PreferDynamic: Property<"prefer-dynamic-value", "Enum">,
DefaultEnumValue<"eDynamicDontRunTarget">,
EnumValues<"OptionEnumValues(g_dynamic_value_types)">,
@@ -216,7 +225,7 @@ let Definition = "process" in {
def DisableLangRuntimeUnwindPlans: Property<"disable-language-runtime-unwindplans", "Boolean">,
Global,
DefaultFalse,
- Desc<"If true, LanguageRuntime plugins' UnwindPlans will not be used when backtracing.">;
+ Desc<"If true, language runtime augmented/overidden backtraces will not be used when printing a stack trace.">;
def DetachKeepsStopped: Property<"detach-keeps-stopped", "Boolean">,
Global,
DefaultFalse,
@@ -246,6 +255,9 @@ let Definition = "process" in {
def VirtualAddressableBits: Property<"virtual-addressable-bits", "UInt64">,
DefaultUnsignedValue<0>,
Desc<"The number of bits used for addressing. If the value is 39, then bits 0..38 are used for addressing. The default value of 0 means unspecified.">;
+ def HighmemVirtualAddressableBits: Property<"highmem-virtual-addressable-bits", "UInt64">,
+ DefaultUnsignedValue<0>,
+ Desc<"The number of bits used for addressing high memory, when it differs from low memory in the same Process. When this is non-zero, target.process.virtual-addressable-bits will be the value for low memory (0x000... addresses) and this setting will be the value for high memory (0xfff... addresses). When this is zero, target.process.virtual-addressable-bits applies to all addresses. It is very uncommon to use this setting.">;
def FollowForkMode: Property<"follow-fork-mode", "Enum">,
DefaultEnumValue<"eFollowParent">,
EnumValues<"OptionEnumValues(g_follow_fork_mode_values)">,
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index d620f746339e..ec4ffcbd9205 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -78,9 +78,9 @@ class ThreadOptionValueProperties
public:
ThreadOptionValueProperties(ConstString name) : Cloneable(name) {}
- const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
- bool will_modify,
- uint32_t idx) const override {
+ const Property *
+ GetPropertyAtIndex(size_t idx,
+ const ExecutionContext *exe_ctx) const override {
// When getting the value for a key from the thread options, we will always
// try and grab the setting from the current thread if there is one. Else
// we just use the one from this instance.
@@ -112,47 +112,42 @@ ThreadProperties::~ThreadProperties() = default;
const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() {
const uint32_t idx = ePropertyStepAvoidRegex;
- return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex(nullptr, idx);
+ return GetPropertyAtIndexAs<const RegularExpression *>(idx);
}
FileSpecList ThreadProperties::GetLibrariesToAvoid() const {
const uint32_t idx = ePropertyStepAvoidLibraries;
- const OptionValueFileSpecList *option_value =
- m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
- false, idx);
- assert(option_value);
- return option_value->GetCurrentValue();
+ return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}
bool ThreadProperties::GetTraceEnabledState() const {
const uint32_t idx = ePropertyEnableThreadTrace;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_thread_properties[idx].default_uint_value != 0);
}
bool ThreadProperties::GetStepInAvoidsNoDebug() const {
const uint32_t idx = ePropertyStepInAvoidsNoDebug;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_thread_properties[idx].default_uint_value != 0);
}
bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_thread_properties[idx].default_uint_value != 0);
}
uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
const uint32_t idx = ePropertyMaxBacktraceDepth;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(
- nullptr, idx, g_thread_properties[idx].default_uint_value != 0);
+ return GetPropertyAtIndexAs<uint64_t>(
+ idx, g_thread_properties[idx].default_uint_value);
}
// Thread Event Data
-ConstString Thread::ThreadEventData::GetFlavorString() {
- static ConstString g_flavor("Thread::ThreadEventData");
- return g_flavor;
+llvm::StringRef Thread::ThreadEventData::GetFlavorString() {
+ return "Thread::ThreadEventData";
}
Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp)
@@ -264,10 +259,11 @@ void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) {
new ThreadEventData(this->shared_from_this(), new_frame_id));
}
-lldb::StackFrameSP Thread::GetSelectedFrame() {
+lldb::StackFrameSP
+Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) {
StackFrameListSP stack_frame_list_sp(GetStackFrameList());
StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex(
- stack_frame_list_sp->GetSelectedFrameIndex());
+ stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant));
FrameSelectedCallback(frame_sp.get());
return frame_sp;
}
@@ -298,15 +294,22 @@ bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
const bool broadcast = true;
bool success = SetSelectedFrameByIndex(frame_idx, broadcast);
if (success) {
- StackFrameSP frame_sp = GetSelectedFrame();
+ StackFrameSP frame_sp = GetSelectedFrame(DoNoSelectMostRelevantFrame);
if (frame_sp) {
bool already_shown = false;
SymbolContext frame_sc(
frame_sp->GetSymbolContext(eSymbolContextLineEntry));
- if (GetProcess()->GetTarget().GetDebugger().GetUseExternalEditor() &&
- frame_sc.line_entry.file && frame_sc.line_entry.line != 0) {
- already_shown = Host::OpenFileInExternalEditor(
- frame_sc.line_entry.file, frame_sc.line_entry.line);
+ const Debugger &debugger = GetProcess()->GetTarget().GetDebugger();
+ if (debugger.GetUseExternalEditor() && frame_sc.line_entry.file &&
+ frame_sc.line_entry.line != 0) {
+ if (llvm::Error e = Host::OpenFileInExternalEditor(
+ debugger.GetExternalEditor(), frame_sc.line_entry.file,
+ frame_sc.line_entry.line)) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
+ "OpenFileInExternalEditor failed: {0}");
+ } else {
+ already_shown = true;
+ }
}
bool show_frame_info = true;
@@ -588,36 +591,9 @@ std::string Thread::GetStopDescriptionRaw() {
return raw_stop_description;
}
-void Thread::SelectMostRelevantFrame() {
- Log *log = GetLog(LLDBLog::Thread);
-
- auto frames_list_sp = GetStackFrameList();
-
- // Only the top frame should be recognized.
- auto frame_sp = frames_list_sp->GetFrameAtIndex(0);
-
- auto recognized_frame_sp = frame_sp->GetRecognizedFrame();
-
- if (!recognized_frame_sp) {
- LLDB_LOG(log, "Frame #0 not recognized");
- return;
- }
-
- if (StackFrameSP most_relevant_frame_sp =
- recognized_frame_sp->GetMostRelevantFrame()) {
- LLDB_LOG(log, "Found most relevant frame at index {0}",
- most_relevant_frame_sp->GetFrameIndex());
- SetSelectedFrame(most_relevant_frame_sp.get());
- } else {
- LLDB_LOG(log, "No relevant frame!");
- }
-}
-
void Thread::WillStop() {
ThreadPlan *current_plan = GetCurrentPlan();
- SelectMostRelevantFrame();
-
// FIXME: I may decide to disallow threads with no plans. In which
// case this should go to an assert.
@@ -734,7 +710,7 @@ bool Thread::ShouldResume(StateType resume_state) {
return need_to_resume;
}
-void Thread::DidResume() {
+void Thread::DidResume() {
SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER);
// This will get recomputed each time when we stop.
SetShouldRunBeforePublicStop(false);
@@ -778,7 +754,7 @@ bool Thread::ShouldStop(Event *event_ptr) {
: LLDB_INVALID_ADDRESS);
return false;
}
-
+
// Clear the "must run me before stop" if it was set:
SetShouldRunBeforePublicStop(false);
@@ -1008,7 +984,7 @@ Vote Thread::ShouldReportStop(Event *event_ptr) {
}
if (GetPlans().AnyCompletedPlans()) {
- // Pass skip_private = false to GetCompletedPlan, since we want to ask
+ // Pass skip_private = false to GetCompletedPlan, since we want to ask
// the last plan, regardless of whether it is private or not.
LLDB_LOGF(log,
"Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
@@ -1046,7 +1022,7 @@ Vote Thread::ShouldReportRun(Event *event_ptr) {
Log *log = GetLog(LLDBLog::Step);
if (GetPlans().AnyCompletedPlans()) {
- // Pass skip_private = false to GetCompletedPlan, since we want to ask
+ // Pass skip_private = false to GetCompletedPlan, since we want to ask
// the last plan, regardless of whether it is private or not.
LLDB_LOGF(log,
"Current Plan for thread %d(%p) (0x%4.4" PRIx64
@@ -1099,7 +1075,7 @@ void Thread::PushPlan(ThreadPlanSP thread_plan_sp) {
static_cast<void *>(this), s.GetData(),
thread_plan_sp->GetThread().GetID());
}
-
+
GetPlans().PushPlan(std::move(thread_plan_sp));
}
@@ -1117,7 +1093,7 @@ void Thread::DiscardPlan() {
ThreadPlanSP discarded_plan_sp = GetPlans().DiscardPlan();
LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
- discarded_plan_sp->GetName(),
+ discarded_plan_sp->GetName(),
discarded_plan_sp->GetThread().GetID());
}
@@ -1246,7 +1222,7 @@ Status Thread::UnwindInnermostExpression() {
if (!innermost_expr_plan) {
error.SetErrorString("No expressions currently active on this thread");
return error;
- }
+ }
DiscardThreadPlansUpToPlan(innermost_expr_plan);
return error;
}
@@ -1390,8 +1366,8 @@ ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
}
lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
- bool abort_other_plans, const char *class_name,
- StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
+ bool abort_other_plans, const char *class_name,
+ StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(
@@ -1752,8 +1728,12 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
SymbolContext frame_sc(
frame_sp->GetSymbolContext(eSymbolContextLineEntry));
if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) {
- Host::OpenFileInExternalEditor(frame_sc.line_entry.file,
- frame_sc.line_entry.line);
+ if (llvm::Error e = Host::OpenFileInExternalEditor(
+ target->GetDebugger().GetExternalEditor(),
+ frame_sc.line_entry.file, frame_sc.line_entry.line)) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
+ "OpenFileInExternalEditor failed: {0}");
+ }
}
}
}
@@ -1826,7 +1806,7 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
id->GetType() == eStructuredDataTypeInteger) {
strm.Format(" Activity '{0}', {1:x}\n",
name->GetAsString()->GetValue(),
- id->GetAsInteger()->GetValue());
+ id->GetUnsignedIntegerValue());
}
printed_activity = true;
}
diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp
index 9913ecb591fa..7927fc314014 100644
--- a/lldb/source/Target/ThreadPlan.cpp
+++ b/lldb/source/Target/ThreadPlan.cpp
@@ -171,6 +171,9 @@ bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
case eStopReasonExec:
case eStopReasonThreadExiting:
case eStopReasonInstrumentation:
+ case eStopReasonFork:
+ case eStopReasonVFork:
+ case eStopReasonVForkDone:
return true;
default:
return false;
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
index 7e9bb963bb5d..31027cd9e011 100644
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -163,7 +163,7 @@ void ThreadPlanCallFunction::ReportRegisterState(const char *message) {
reg_idx < num_registers; ++reg_idx) {
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx);
if (reg_ctx->ReadRegister(reg_info, reg_value)) {
- DumpRegisterValue(reg_value, &strm, reg_info, true, false,
+ DumpRegisterValue(reg_value, strm, *reg_info, true, false,
eFormatDefault);
strm.EOL();
}
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
index bc2a7a02e99c..d6de6b3c3cf0 100644
--- a/lldb/source/Target/ThreadPlanPython.cpp
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -136,8 +136,11 @@ bool ThreadPlanPython::MischiefManaged() {
// I don't really need mischief_managed, since it's simpler to just call
// SetPlanComplete in should_stop.
mischief_managed = IsPlanComplete();
- if (mischief_managed)
+ if (mischief_managed) {
+ // We need to cache the stop reason here we'll need it in GetDescription.
+ GetDescription(&m_stop_description, eDescriptionLevelBrief);
m_implementation_sp.reset();
+ }
}
return mischief_managed;
}
@@ -158,15 +161,40 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
return run_state;
}
-// The ones below are not currently exported to Python.
void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
- s->Printf("Python thread plan implemented by class %s.",
+ Log *log = GetLog(LLDBLog::Thread);
+ LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
+ m_class_name.c_str());
+ if (m_implementation_sp) {
+ ScriptInterpreter *script_interp = GetScriptInterpreter();
+ if (script_interp) {
+ bool script_error;
+ bool added_desc = script_interp->ScriptedThreadPlanGetStopDescription(
+ m_implementation_sp, s, script_error);
+ if (script_error || !added_desc)
+ s->Printf("Python thread plan implemented by class %s.",
m_class_name.c_str());
+ }
+ return;
+ }
+ // It's an error not to have a description, so if we get here, we should
+ // add something.
+ if (m_stop_description.Empty())
+ s->Printf("Python thread plan implemented by class %s.",
+ m_class_name.c_str());
+ s->PutCString(m_stop_description.GetData());
}
+// The ones below are not currently exported to Python.
bool ThreadPlanPython::WillStop() {
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
m_class_name.c_str());
return true;
}
+
+bool ThreadPlanPython::DoWillResume(lldb::StateType resume_state,
+ bool current_plan) {
+ m_stop_description.Clear();
+ return true;
+}
diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp
index 82927ef64877..f4d80ba89071 100644
--- a/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/lldb/source/Target/ThreadPlanTracer.cpp
@@ -56,7 +56,7 @@ Stream *ThreadPlanTracer::GetLogStream() {
Thread &ThreadPlanTracer::GetThread() {
if (m_thread)
return *m_thread;
-
+
ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(m_tid);
m_thread = thread_sp.get();
return *m_thread;
@@ -107,8 +107,9 @@ TypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() {
auto type_system_or_err =
target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
if (auto err = type_system_or_err.takeError()) {
- LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
- "Unable to get integer pointer type from TypeSystem");
+ LLDB_LOG_ERROR(
+ GetLog(LLDBLog::Types), std::move(err),
+ "Unable to get integer pointer type from TypeSystem: {0}");
} else {
if (auto ts = *type_system_or_err)
m_intptr_type = TypeFromUser(ts->GetBuiltinTypeForEncodingAndBitSize(
@@ -223,7 +224,7 @@ void ThreadPlanAssemblyTracer::Log() {
reg_value != m_register_values[reg_num]) {
if (reg_value.GetType() != RegisterValue::eTypeInvalid) {
stream->PutCString("\n\t");
- DumpRegisterValue(reg_value, stream, reg_info, true, false,
+ DumpRegisterValue(reg_value, *stream, *reg_info, true, false,
eFormatDefault);
}
}
diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp
index 858b1691f318..0e738241b1c5 100644
--- a/lldb/source/Target/UnixSignals.cpp
+++ b/lldb/source/Target/UnixSignals.cpp
@@ -9,11 +9,11 @@
#include "lldb/Target/UnixSignals.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
-#include "Plugins/Process/Utility/MipsLinuxSignals.h"
#include "Plugins/Process/Utility/NetBSDSignals.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include <optional>
+#include <sstream>
using namespace lldb_private;
using namespace llvm;
@@ -33,17 +33,8 @@ UnixSignals::Signal::Signal(const char *name, bool default_suppress,
lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) {
const auto &triple = arch.GetTriple();
switch (triple.getOS()) {
- case llvm::Triple::Linux: {
- switch (triple.getArch()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return std::make_shared<MipsLinuxSignals>();
- default:
- return std::make_shared<LinuxSignals>();
- }
- }
+ case llvm::Triple::Linux:
+ return std::make_shared<LinuxSignals>();
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
return std::make_shared<FreeBSDSignals>();
@@ -122,6 +113,17 @@ void UnixSignals::AddSignal(int signo, const char *name, bool default_suppress,
++m_version;
}
+void UnixSignals::AddSignalCode(int signo, int code,
+ const llvm::StringLiteral description,
+ SignalCodePrintOption print_option) {
+ collection::iterator signal = m_signals.find(signo);
+ assert(signal != m_signals.end() &&
+ "Tried to add code to signal that does not exist.");
+ signal->second.m_codes.insert(
+ std::pair{code, SignalCode{description, print_option}});
+ ++m_version;
+}
+
void UnixSignals::RemoveSignal(int signo) {
collection::iterator pos = m_signals.find(signo);
if (pos != m_signals.end())
@@ -137,14 +139,64 @@ const char *UnixSignals::GetSignalAsCString(int signo) const {
return pos->second.m_name.GetCString();
}
+std::string
+UnixSignals::GetSignalDescription(int32_t signo, std::optional<int32_t> code,
+ std::optional<lldb::addr_t> addr,
+ std::optional<lldb::addr_t> lower,
+ std::optional<lldb::addr_t> upper) const {
+ std::string str;
+
+ collection::const_iterator pos = m_signals.find(signo);
+ if (pos != m_signals.end()) {
+ str = pos->second.m_name.GetCString();
+
+ if (code) {
+ std::map<int32_t, SignalCode>::const_iterator cpos =
+ pos->second.m_codes.find(*code);
+ if (cpos != pos->second.m_codes.end()) {
+ const SignalCode &sc = cpos->second;
+ str += ": ";
+ if (sc.m_print_option != SignalCodePrintOption::Bounds)
+ str += sc.m_description.str();
+
+ std::stringstream strm;
+ switch (sc.m_print_option) {
+ case SignalCodePrintOption::None:
+ break;
+ case SignalCodePrintOption::Address:
+ if (addr)
+ strm << " (fault address: 0x" << std::hex << *addr << ")";
+ break;
+ case SignalCodePrintOption::Bounds:
+ if (lower && upper && addr) {
+ if ((unsigned long)(*addr) < *lower)
+ strm << "lower bound violation ";
+ else
+ strm << "upper bound violation ";
+
+ strm << "(fault address: 0x" << std::hex << *addr;
+ strm << ", lower bound: 0x" << std::hex << *lower;
+ strm << ", upper bound: 0x" << std::hex << *upper;
+ strm << ")";
+ } else
+ strm << sc.m_description.str();
+
+ break;
+ }
+ str += strm.str();
+ }
+ }
+ }
+
+ return str;
+}
+
bool UnixSignals::SignalIsValid(int32_t signo) const {
return m_signals.find(signo) != m_signals.end();
}
-ConstString UnixSignals::GetShortName(ConstString name) const {
- if (name)
- return ConstString(name.GetStringRef().substr(3)); // Remove "SIG" from name
- return name;
+llvm::StringRef UnixSignals::GetShortName(llvm::StringRef name) const {
+ return name.substr(3); // Remove "SIG" from name
}
int32_t UnixSignals::GetSignalNumberFromName(const char *name) const {