summaryrefslogtreecommitdiffstats
path: root/source/Plugins/Process/Utility
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2013-11-06 16:48:53 +0000
committeremaste <emaste@FreeBSD.org>2013-11-06 16:48:53 +0000
commitc727fe695d28799acb499e9961f11ec07d4f9fe2 (patch)
tree56d79f94966870db1cecd65a7264510a25fd1cba /source/Plugins/Process/Utility
parent2e8c9206a971efee1b77ad2ae852265d6f4ecaa0 (diff)
downloadFreeBSD-src-c727fe695d28799acb499e9961f11ec07d4f9fe2.zip
FreeBSD-src-c727fe695d28799acb499e9961f11ec07d4f9fe2.tar.gz
Import lldb as of SVN r194122
Sponsored by: DARPA, AFRL
Diffstat (limited to 'source/Plugins/Process/Utility')
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp456
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h17
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp11
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp69
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp4
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp16
6 files changed, 509 insertions, 64 deletions
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 0c95d66..dc90b7a 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -16,6 +16,9 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/DataFormatters/FormatManager.h"
#ifndef LLDB_DISABLE_PYTHON
#include "lldb/Interpreter/PythonDataObjects.h"
@@ -29,18 +32,24 @@ DynamicRegisterInfo::DynamicRegisterInfo () :
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
}
-DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict, ByteOrder byte_order) :
m_regs (),
m_sets (),
m_set_reg_nums (),
m_set_names (),
- m_reg_data_byte_size (0)
+ m_value_regs_map (),
+ m_invalidate_regs_map (),
+ m_reg_data_byte_size (0),
+ m_finalized (false)
{
- SetRegisterInfo (dict);
+ SetRegisterInfo (dict, byte_order);
}
DynamicRegisterInfo::~DynamicRegisterInfo ()
@@ -49,8 +58,10 @@ DynamicRegisterInfo::~DynamicRegisterInfo ()
size_t
-DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ ByteOrder byte_order)
{
+ assert(!m_finalized);
#ifndef LLDB_DISABLE_PYTHON
PythonList sets (dict.GetItemForKey("sets"));
if (sets)
@@ -89,6 +100,12 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
PythonString gcc_pystr("gcc");
PythonString dwarf_pystr("dwarf");
PythonString generic_pystr("generic");
+ PythonString slice_pystr("slice");
+ PythonString composite_pystr("composite");
+ PythonString invalidate_regs_pystr("invalidate-regs");
+
+// typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap;
+// InvalidateNameMap invalidate_map;
for (uint32_t i=0; i<num_regs; ++i)
{
PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
@@ -96,6 +113,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
{
// { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
bzero (&reg_info, sizeof(reg_info));
reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
@@ -111,16 +130,177 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
if (reg_info.byte_offset == UINT32_MAX)
{
- Clear();
- return 0;
+ // No offset for this register, see if the register has a value expression
+ // which indicates this register is part of another register. Value expressions
+ // are things like "rax[31:0]" which state that the current register's value
+ // is in a concrete register "rax" in bits 31:0. If there is a value expression
+ // we can calculate the offset
+ bool success = false;
+ const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr);
+ if (slice_cstr)
+ {
+ // Slices use the following format:
+ // REGNAME[MSBIT:LSBIT]
+ // REGNAME - name of the register to grab a slice of
+ // MSBIT - the most significant bit at which the current register value starts at
+ // LSBIT - the least significant bit at which the current register value ends at
+ static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]");
+ RegularExpression::Match regex_match(3);
+ if (g_bitfield_regex.Execute(slice_cstr, &regex_match))
+ {
+ llvm::StringRef reg_name_str;
+ std::string msbit_str;
+ std::string lsbit_str;
+ if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) &&
+ regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str))
+ {
+ const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX);
+ const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX);
+ if (msbit != UINT32_MAX && lsbit != UINT32_MAX)
+ {
+ if (msbit > lsbit)
+ {
+ const uint32_t msbyte = msbit / 8;
+ const uint32_t lsbyte = lsbit / 8;
+
+ ConstString containing_reg_name(reg_name_str);
+
+ RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name);
+ if (containing_reg_info)
+ {
+ const uint32_t max_bit = containing_reg_info->byte_size * 8;
+ if (msbit < max_bit && lsbit < max_bit)
+ {
+ m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]);
+
+ if (byte_order == eByteOrderLittle)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte;
+ }
+ else if (byte_order == eByteOrderBig)
+ {
+ success = true;
+ reg_info.byte_offset = containing_reg_info->byte_offset + msbyte;
+ }
+ else
+ {
+ assert(!"Invalid byte order");
+ }
+ }
+ else
+ {
+ if (msbit > max_bit)
+ printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit);
+ else
+ printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit);
+ }
+ }
+ else
+ {
+ printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit);
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to extract regex matches for parsing the register bitfield regex\n");
+
+ }
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to match against register bitfield regex\n");
+ }
+ }
+ else
+ {
+ PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr));
+ if (composite_reg_list)
+ {
+ const size_t num_composite_regs = composite_reg_list.GetSize();
+ if (num_composite_regs > 0)
+ {
+ uint32_t composite_offset = UINT32_MAX;
+ for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx)
+ {
+ PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx));
+ if (composite_reg_name_pystr)
+ {
+ ConstString composite_reg_name(composite_reg_name_pystr.GetString());
+ if (composite_reg_name)
+ {
+ RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name);
+ if (composite_reg_info)
+ {
+ if (composite_offset > composite_reg_info->byte_offset)
+ composite_offset = composite_reg_info->byte_offset;
+ m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i);
+ m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString());
+ }
+ }
+ else
+ {
+ printf("error: 'composite' key contained an empty string\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list value wasn't a python string\n");
+ }
+ }
+ if (composite_offset != UINT32_MAX)
+ {
+ reg_info.byte_offset = composite_offset;
+ success = m_value_regs_map.find(i) != m_value_regs_map.end();
+ }
+ else
+ {
+ printf("error: 'composite' registers must specify at least one real register\n");
+ }
+ }
+ else
+ {
+ printf("error: 'composite' list was empty\n");
+ }
+ }
+ }
+
+
+ if (!success)
+ {
+ Clear();
+ return 0;
+ }
}
- reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
-
- if (reg_info.byte_size == 0)
+ const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0);
+ if (bitsize == 0)
{
Clear();
return 0;
}
+
+ reg_info.byte_size = bitsize / 8;
const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
if (format_cstr)
@@ -132,13 +312,15 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
}
}
else
- reg_info.format = eFormatHex;
-
+ {
+ reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex);
+ }
+
const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
if (encoding_cstr)
reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
else
- reg_info.encoding = eEncodingUint;
+ reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint);
const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
if (set >= m_sets.size())
@@ -147,11 +329,75 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
return 0;
}
+ // Fill in the register numbers
reg_info.kinds[lldb::eRegisterKindLLDB] = i;
reg_info.kinds[lldb::eRegisterKindGDB] = i;
reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
- reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
+ const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr);
+ if (generic_cstr)
+ reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr);
+ else
+ reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM);
+
+ // Check if this register invalidates any other register values when it is modified
+ PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr));
+ if (invalidate_reg_list)
+ {
+ const size_t num_regs = invalidate_reg_list.GetSize();
+ if (num_regs > 0)
+ {
+ for (uint32_t idx=0; idx<num_regs; ++idx)
+ {
+ PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx));
+ PythonString invalidate_reg_name_pystr(invalidate_reg_object);
+ if (invalidate_reg_name_pystr)
+ {
+ ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString());
+ if (invalidate_reg_name)
+ {
+ RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name);
+ if (invalidate_reg_info)
+ {
+ m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]);
+ }
+ else
+ {
+ // TODO: print error invalid slice string that doesn't follow the format
+ printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name);
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value was an empty string\n");
+ }
+ }
+ else
+ {
+ PythonInteger invalidate_reg_num(invalidate_reg_object);
+
+ if (invalidate_reg_num)
+ {
+ const int64_t r = invalidate_reg_num.GetInteger();
+ if (r != UINT64_MAX)
+ m_invalidate_regs_map[i].push_back(r);
+ else
+ printf("error: 'invalidate-regs' list value wasn't a valid integer\n");
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' list value wasn't a python string or integer\n");
+ }
+ }
+ }
+ }
+ else
+ {
+ printf("error: 'invalidate-regs' contained an empty list\n");
+ }
+ }
+
+ // Calculate the register offset
const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
if (m_reg_data_byte_size < end_reg_offset)
m_reg_data_byte_size = end_reg_offset;
@@ -169,7 +415,7 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict
Finalize ();
}
#endif
- return 0;
+ return m_regs.size();
}
@@ -179,10 +425,22 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
ConstString &reg_alt_name,
ConstString &set_name)
{
+ assert(!m_finalized);
const uint32_t reg_num = m_regs.size();
reg_info.name = reg_name.AsCString();
assert (reg_info.name);
reg_info.alt_name = reg_alt_name.AsCString(NULL);
+ uint32_t i;
+ if (reg_info.value_regs)
+ {
+ for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
+ }
+ if (reg_info.invalidate_regs)
+ {
+ for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
+ m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
+ }
m_regs.push_back (reg_info);
uint32_t set = GetRegisterSetIndexByName (set_name, true);
assert (set < m_sets.size());
@@ -197,12 +455,99 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
void
DynamicRegisterInfo::Finalize ()
{
- for (uint32_t set = 0; set < m_sets.size(); ++set)
+ if (m_finalized)
+ return;
+
+ m_finalized = true;
+ const size_t num_sets = m_sets.size();
+ for (size_t set = 0; set < num_sets; ++set)
{
assert (m_sets.size() == m_set_reg_nums.size());
m_sets[set].num_registers = m_set_reg_nums[set].size();
m_sets[set].registers = &m_set_reg_nums[set][0];
}
+
+ // sort and unique all value registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+
+ for (reg_to_regs_map::iterator pos = m_value_regs_map.begin(), end = m_value_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all value_regs with each register info as needed
+ const size_t num_regs = m_regs.size();
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_value_regs_map.find(i) != m_value_regs_map.end())
+ m_regs[i].value_regs = m_value_regs_map[i].data();
+ else
+ m_regs[i].value_regs = NULL;
+ }
+
+ // Expand all invalidation dependencies
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ const uint32_t reg_num = pos->first;
+
+ if (m_regs[reg_num].value_regs)
+ {
+ reg_num_collection extra_invalid_regs;
+ for (const uint32_t invalidate_reg_num : pos->second)
+ {
+ reg_to_regs_map::iterator invalidate_pos = m_invalidate_regs_map.find(invalidate_reg_num);
+ if (invalidate_pos != m_invalidate_regs_map.end())
+ {
+ for (const uint32_t concrete_invalidate_reg_num : invalidate_pos->second)
+ {
+ if (concrete_invalidate_reg_num != reg_num)
+ extra_invalid_regs.push_back(concrete_invalidate_reg_num);
+ }
+ }
+ }
+ pos->second.insert(pos->second.end(), extra_invalid_regs.begin(), extra_invalid_regs.end());
+ }
+ }
+
+ // sort and unique all invalidate registers and make sure each is terminated with
+ // LLDB_INVALID_REGNUM
+ for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(), end = m_invalidate_regs_map.end();
+ pos != end;
+ ++pos)
+ {
+ if (pos->second.size() > 1)
+ {
+ std::sort (pos->second.begin(), pos->second.end());
+ reg_num_collection::iterator unique_end = std::unique (pos->second.begin(), pos->second.end());
+ if (unique_end != pos->second.end())
+ pos->second.erase(unique_end, pos->second.end());
+ }
+ assert (!pos->second.empty());
+ if (pos->second.back() != LLDB_INVALID_REGNUM)
+ pos->second.push_back(LLDB_INVALID_REGNUM);
+ }
+
+ // Now update all invalidate_regs with each register info as needed
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end())
+ m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data();
+ else
+ m_regs[i].invalidate_regs = NULL;
+ }
}
size_t
@@ -276,4 +621,83 @@ DynamicRegisterInfo::Clear()
m_sets.clear();
m_set_reg_nums.clear();
m_set_names.clear();
+ m_value_regs_map.clear();
+ m_invalidate_regs_map.clear();
+ m_reg_data_byte_size = 0;
+ m_finalized = false;
+}
+
+void
+DynamicRegisterInfo::Dump () const
+{
+ StreamFile s(stdout, false);
+ const size_t num_regs = m_regs.size();
+ s.Printf("%p: DynamicRegisterInfo contains %zu registers:\n", this, num_regs);
+ for (size_t i=0; i<num_regs; ++i)
+ {
+ s.Printf("[%3zu] name = %-10s", i, m_regs[i].name);
+ s.Printf(", size = %2u, offset = %4u, encoding = %u, format = %-10s",
+ m_regs[i].byte_size,
+ m_regs[i].byte_offset,
+ m_regs[i].encoding,
+ FormatManager::GetFormatAsCString (m_regs[i].format));
+ if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM)
+ s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]);
+ if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
+ if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM)
+ s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]);
+ if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
+ s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
+ if (m_regs[i].alt_name)
+ s.Printf(", alt-name = %s", m_regs[i].alt_name);
+ if (m_regs[i].value_regs)
+ {
+ s.Printf(", value_regs = [ ");
+ for (size_t j=0; m_regs[i].value_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].value_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ if (m_regs[i].invalidate_regs)
+ {
+ s.Printf(", invalidate_regs = [ ");
+ for (size_t j=0; m_regs[i].invalidate_regs[j] != LLDB_INVALID_REGNUM; ++j)
+ {
+ s.Printf("%s ", m_regs[m_regs[i].invalidate_regs[j]].name);
+ }
+ s.Printf("]");
+ }
+ s.EOL();
+ }
+
+ const size_t num_sets = m_sets.size();
+ s.Printf("%p: DynamicRegisterInfo contains %zu register sets:\n", this, num_sets);
+ for (size_t i=0; i<num_sets; ++i)
+ {
+ s.Printf("set[%zu] name = %s, regs = [", i, m_sets[i].name);
+ for (size_t idx=0; idx<m_sets[i].num_registers; ++idx)
+ {
+ s.Printf("%s ", m_regs[m_sets[i].registers[idx]].name);
+ }
+ s.Printf("]\n");
+ }
+}
+
+
+
+lldb_private::RegisterInfo *
+DynamicRegisterInfo::GetRegisterInfo (const lldb_private::ConstString &reg_name)
+{
+ for (auto &reg_info : m_regs)
+ {
+ // We can use pointer comparison since we used a ConstString to set
+ // the "name" member in AddRegister()
+ if (reg_info.name == reg_name.GetCString())
+ {
+ return &reg_info;
+ }
+ }
+ return NULL;
}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index a11cd33..a41c77e 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <vector>
+#include <map>
// Other libraries and framework includes
// Project includes
@@ -24,13 +25,15 @@ class DynamicRegisterInfo
public:
DynamicRegisterInfo ();
- DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+ DynamicRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
virtual
~DynamicRegisterInfo ();
size_t
- SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+ SetRegisterInfo (const lldb_private::PythonDictionary &dict,
+ lldb::ByteOrder byte_order);
void
AddRegister (lldb_private::RegisterInfo &reg_info,
@@ -63,6 +66,9 @@ public:
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
void
+ Dump () const;
+
+ void
Clear();
protected:
@@ -74,12 +80,19 @@ protected:
typedef std::vector <uint32_t> reg_num_collection;
typedef std::vector <reg_num_collection> set_reg_num_collection;
typedef std::vector <lldb_private::ConstString> name_collection;
+ typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
+
+ lldb_private::RegisterInfo *
+ GetRegisterInfo (const lldb_private::ConstString &reg_name);
reg_collection m_regs;
set_collection m_sets;
set_reg_num_collection m_set_reg_nums;
name_collection m_set_names;
+ reg_to_regs_map m_value_regs_map;
+ reg_to_regs_map m_invalidate_regs_map;
size_t m_reg_data_byte_size; // The number of bytes required to store all registers
+ bool m_finalized;
};
#endif // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 499d6d7..8b22d64 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -17,8 +17,19 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Host/Config.h"
+#ifndef LLDB_DISABLE_POSIX
#include <sys/mman.h>
+#else
+// define them
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+#define MAP_PRIVATE 2
+#define MAP_ANON 0x1000
+#endif
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 1ffc30d..c19aec3 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -369,8 +369,13 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
+ bool resolve_tail_call_address = true; // m_current_pc can be one past the address range of the function...
+ uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
+ eSymbolContextFunction | eSymbolContextSymbol,
+ m_sym_ctx, resolve_tail_call_address);
+
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
- if ((pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if ((resolved_scope & eSymbolContextSymbol) == eSymbolContextSymbol)
{
m_sym_ctx_valid = true;
}
@@ -387,35 +392,18 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (m_sym_ctx_valid == false)
decr_pc_and_recompute_addr_range = true;
- // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
- // and our "current" pc is the start of a function...
+ // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), and
+ // our "current" pc is the start of a function or our "current" pc is one past the end of a function...
if (m_sym_ctx_valid
&& GetNextFrame()->m_frame_type != eSigtrampFrame
&& GetNextFrame()->m_frame_type != eDebuggerFrame
&& addr_range.GetBaseAddress().IsValid()
- && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
- && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
+ && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection())
{
- decr_pc_and_recompute_addr_range = true;
- }
-
- // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
- // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
- // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
- // to the ABI plugin and consult that.
- if (decr_pc_and_recompute_addr_range)
- {
- Address temporary_pc(m_current_pc);
- temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
- m_sym_ctx.Clear(false);
- m_sym_ctx_valid = false;
- if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ if (addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset() ||
+ addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize() == m_current_pc.GetOffset())
{
- m_sym_ctx_valid = true;
- }
- if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
- {
- m_sym_ctx_valid = false;
+ decr_pc_and_recompute_addr_range = true;
}
}
@@ -632,6 +620,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
}
+ else
+ {
+ UnwindLogMsg ("unable to get architectural default UnwindPlan from ABI plugin");
+ }
bool behaves_like_zeroth_frame = false;
if (IsFrameZero ()
@@ -648,9 +640,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
// Also, if this Process can report on memory region attributes, any non-executable region means
// we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
+ // Note, if we have a symbol context & a symbol, we don't want to follow this code path. This is
+ // for jumping to memory regions without any information available.
- if ((!m_sym_ctx_valid || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
+ if ((!m_sym_ctx_valid || m_sym_ctx.symbol == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
{
uint32_t permissions;
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
@@ -757,8 +750,24 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
return unwind_plan_sp;
}
+ // If we're on the first instruction of a function, and we have an architectural default UnwindPlan
+ // for the initial instruction of a function, use that.
+ if (m_current_offset_backed_up_one == 0)
+ {
+ unwind_plan_sp = func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry (m_thread);
+ if (unwind_plan_sp)
+ {
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+ return unwind_plan_sp;
+ }
+ }
+
// If nothing else, use the architectural default UnwindPlan and hope that does the job.
- UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ if (arch_default_unwind_plan_sp)
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ else
+ UnwindLogMsg ("Unable to find any UnwindPlan for full unwind of this frame.");
+
return arch_default_unwind_plan_sp;
}
@@ -1101,7 +1110,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+ UnwindLogMsg ("did not supply reg location for %d (%s) because it is volatile",
+ lldb_regnum, reg_info->name ? reg_info->name : "??");
return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
}
}
@@ -1186,7 +1196,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
- DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ ModuleSP opcode_ctx;
+ DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 2c3eee4..5b6d9fe 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -147,9 +147,9 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
}
break;
- // TOOD: need a better way to detect when "long double" types are
+ // TOOD: need a better way to detect when "long double" types are
// the same bytes size as "double"
-#if !defined(__arm__)
+#if !defined(__arm__) && !defined(_MSC_VER) && !defined(__mips__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 0eea003..552ae50 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -185,21 +185,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
goto unwind_done;
}
- if (!m_frames.empty())
- {
- if (m_frames.back()->start_pc == cursor_sp->start_pc)
- {
- if (m_frames.back()->cfa == cursor_sp->cfa)
- goto unwind_done; // Infinite loop where the current cursor is the same as the previous one...
- else if (abi && abi->StackUsesFrames())
- {
- // We might have a CFA that is not using the frame pointer and
- // we want to validate that the frame pointer is valid.
- if (reg_ctx_sp->GetFP() == 0)
- goto unwind_done;
- }
- }
- }
+
cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (cursor_sp);
return true;
OpenPOWER on IntegriCloud