[llvm-branch-commits] [lldb] r183468 - Update platform branch with top of tree.
Greg Clayton
gclayton at apple.com
Thu Jun 6 17:08:20 PDT 2013
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "AppleObjCTrampolineHandler.h"
// C Includes
@@ -18,15 +20,15 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
-
+#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -41,7 +43,8 @@ using namespace lldb;
using namespace lldb_private;
const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = " \n\
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = " \n\
extern \"C\" \n\
{ \n\
extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
@@ -150,6 +153,106 @@ extern \"C\" void * __lldb_objc_find_imp
return return_struct.impl_addr; \n\
} \n\
";
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = " \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
+ printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ if (class_ptr == object) \n\
+ { \n\
+ struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr; \n\
+ if (debug) \n\
+ printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\", \n\
+ class_ptr, class_as_class_struct->isa); \n\
+ return_struct.class_addr = class_as_class_struct->isa; \n\
+ } \n\
+ else \n\
+ { \n\
+ if (debug) \n\
+ printf (\"[object class] returned: 0x%p.\\n\", class_ptr); \n\
+ return_struct.class_addr = class_ptr; \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\", \n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
+";
AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
m_valid (true),
@@ -192,12 +295,12 @@ AppleObjCTrampolineHandler::AppleObjCVTa
return;
}
- uint32_t offset_ptr = 0;
- const uint16_t header_size = data.GetU16(&offset_ptr);
- const uint16_t descriptor_size = data.GetU16(&offset_ptr);
- const size_t num_descriptors = data.GetU32(&offset_ptr);
+ lldb::offset_t offset = 0;
+ const uint16_t header_size = data.GetU16(&offset);
+ const uint16_t descriptor_size = data.GetU16(&offset);
+ const size_t num_descriptors = data.GetU32(&offset);
- m_next_region = data.GetPointer(&offset_ptr);
+ m_next_region = data.GetPointer(&offset);
// If the header size is 0, that means we've come in too early before this data is set up.
// Set ourselves as not valid, and continue.
@@ -237,16 +340,16 @@ AppleObjCTrampolineHandler::AppleObjCVTa
// The actual code for the vtables will be laid out consecutively, so I also
// compute the start and end of the whole code block.
- offset_ptr = 0;
+ offset = 0;
m_code_start_addr = 0;
m_code_end_addr = 0;
for (int i = 0; i < num_descriptors; i++)
{
- lldb::addr_t start_offset = offset_ptr;
- uint32_t offset = desc_extractor.GetU32 (&offset_ptr);
- uint32_t flags = desc_extractor.GetU32 (&offset_ptr);
- lldb::addr_t code_addr = desc_ptr + start_offset + offset;
+ lldb::addr_t start_offset = offset;
+ uint32_t voffset = desc_extractor.GetU32 (&offset);
+ uint32_t flags = desc_extractor.GetU32 (&offset);
+ lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
m_descriptors.push_back (VTableDescriptor(flags, code_addr));
if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
@@ -254,7 +357,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
if (code_addr > m_code_end_addr)
m_code_end_addr = code_addr;
- offset_ptr = start_offset + descriptor_size;
+ offset = start_offset + descriptor_size;
}
// Finally, a little bird told me that all the vtable code blocks are the same size.
// Let's compute the blocks and if they are all the same add the size to the code end address:
@@ -301,13 +404,13 @@ AppleObjCTrampolineHandler::AppleObjCVTa
void
AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
{
- s.Printf ("Header addr: 0x%llx Code start: 0x%llx Code End: 0x%llx Next: 0x%llx\n",
+ s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
size_t num_elements = m_descriptors.size();
for (size_t i = 0; i < num_elements; i++)
{
s.Indent();
- s.Printf ("Code start: 0x%llx Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
+ s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
}
}
@@ -334,7 +437,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
return true;
Target &target = m_process_sp->GetTarget();
- ModuleList &target_modules = target.GetImages();
+ const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
size_t num_modules = target_modules.GetSize();
if (!m_objc_module_sp)
@@ -380,6 +483,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
{
m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
+ trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
return true;
}
}
@@ -425,8 +529,8 @@ AppleObjCTrampolineHandler::AppleObjCVTa
data,
0,
NULL);
- uint32_t offset_ptr = 0;
- lldb::addr_t region_addr = data.GetPointer(&offset_ptr);
+ lldb::offset_t offset = 0;
+ lldb::addr_t region_addr = data.GetPointer(&offset);
if (region_addr != 0)
vtable_handler->ReadRegions(region_addr);
@@ -456,7 +560,7 @@ AppleObjCTrampolineHandler::AppleObjCVTa
if (!m_process_sp)
return false;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
// We aren't starting at the trampoline symbol.
InitializeVTableSymbols ();
@@ -553,8 +657,29 @@ AppleObjCTrampolineHandler::AppleObjCTra
m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
// FIXME: Do some kind of logging here.
- if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+ if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
+ {
+ // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
+ // step through any method dispatches. Warn to that effect and get out of here.
+ if (process_sp->CanJIT())
+ {
+ process_sp->GetTarget().GetDebugger().GetErrorStream().Printf("Could not find implementation lookup function \"%s\""
+ " step in through ObjC method dispatch will not work.\n",
+ get_impl_name.AsCString());
+ }
return;
+ }
+ else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+ {
+ // It there is no stret return lookup function, assume that it is the same as the straight lookup:
+ m_impl_stret_fn_addr = m_impl_fn_addr;
+ // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
+ g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
+ }
+ else
+ {
+ g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
+ }
// Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol
// names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can
@@ -589,7 +714,7 @@ AppleObjCTrampolineHandler::SetupDispatc
ExecutionContext exe_ctx (thread.shared_from_this());
Address impl_code_address;
StreamString errors;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
// Scope for mutex locker:
@@ -616,7 +741,7 @@ AppleObjCTrampolineHandler::SetupDispatc
impl_code_address = sc.symbol->GetAddress();
//lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%llx.\n", addr);
+ //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
}
else
{
@@ -626,15 +751,26 @@ AppleObjCTrampolineHandler::SetupDispatc
}
else if (!m_impl_code.get())
{
- m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
- g_lookup_implementation_function_name));
- if (!m_impl_code->Install(errors, exe_ctx))
+ if (g_lookup_implementation_function_code != NULL)
+ {
+ m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
+ g_lookup_implementation_function_name));
+ if (!m_impl_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_impl_code.reset();
+ return args_addr;
+ }
+ }
+ else
{
if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
- m_impl_code.reset();
- return args_addr;
+ log->Printf("No method lookup implementation code.");
+ errors.Printf ("No method lookup implementation code found.");
+ return LLDB_INVALID_ADDRESS;
}
+
impl_code_address.Clear();
impl_code_address.SetOffset(m_impl_code->StartAddress());
}
@@ -732,7 +868,7 @@ AppleObjCTrampolineHandler::GetStepThrou
if (found_it)
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
// We are decoding a method dispatch.
// First job is to pull the arguments out:
@@ -882,7 +1018,7 @@ AppleObjCTrampolineHandler::GetStepThrou
{
if (log)
{
- log->Printf("Resolving call for class - 0x%llx and selector - 0x%llx",
+ log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
isa_addr, sel_addr);
}
ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
@@ -896,7 +1032,7 @@ AppleObjCTrampolineHandler::GetStepThrou
// Yup, it was in the cache, so we can run to that address directly.
if (log)
- log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);
+ log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
}
@@ -973,12 +1109,16 @@ AppleObjCTrampolineHandler::GetStepThrou
flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
dispatch_values.PushValue (flag_value);
+
+ // The step through code might have to fill in the cache, so it is not safe to run only one thread.
+ // So we override the stop_others value passed in to us here:
+ const bool trampoline_stop_others = false;
ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
this,
dispatch_values,
isa_addr,
sel_addr,
- stop_others));
+ trampoline_stop_others));
if (log)
{
StreamString s;
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h Thu Jun 6 19:06:43 2013
@@ -67,6 +67,8 @@ public:
private:
static const char *g_lookup_implementation_function_name;
static const char *g_lookup_implementation_function_code;
+ static const char *g_lookup_implementation_with_stret_function_code;
+ static const char *g_lookup_implementation_no_stret_function_code;
class AppleObjCVTables
{
@@ -195,14 +197,14 @@ private:
MsgsendMap m_msgSend_map;
lldb::ProcessSP m_process_sp;
lldb::ModuleSP m_objc_module_sp;
- std::auto_ptr<ClangFunction> m_impl_function;
- std::auto_ptr<ClangUtilityFunction> m_impl_code;
+ std::unique_ptr<ClangFunction> m_impl_function;
+ std::unique_ptr<ClangUtilityFunction> m_impl_code;
Mutex m_impl_function_mutex;
lldb::addr_t m_impl_fn_addr;
lldb::addr_t m_impl_stret_fn_addr;
lldb::addr_t m_msg_forward_addr;
lldb::addr_t m_msg_forward_stret_addr;
- std::auto_ptr<AppleObjCVTables> m_vtables_ap;
+ std::unique_ptr<AppleObjCVTables> m_vtables_ap;
};
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Thu Jun 6 19:06:43 2013
@@ -84,9 +84,15 @@ AppleThreadPlanStepThroughObjCTrampoline
}
m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction();
ExecutionContext exc_ctx;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
m_thread.CalculateExecutionContext(exc_ctx);
- m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx, m_args_addr, errors, m_stop_others));
- m_func_sp->SetPrivate(true);
+ m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+ m_args_addr,
+ errors,
+ m_stop_others,
+ unwind_on_error,
+ ignore_breakpoints));
m_func_sp->SetOkayToDiscard(true);
m_thread.QueueThreadPlan (m_func_sp, false);
}
@@ -108,8 +114,8 @@ AppleThreadPlanStepThroughObjCTrampoline
s->Printf("Step through ObjC trampoline");
else
{
- s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%llx, sel: 0x%llx",
- m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
+ s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%" PRIx64 ", sel: 0x%" PRIx64,
+ m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
}
}
@@ -120,7 +126,7 @@ AppleThreadPlanStepThroughObjCTrampoline
}
bool
-AppleThreadPlanStepThroughObjCTrampoline::PlanExplainsStop ()
+AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (Event *event_ptr)
{
// If we get asked to explain the stop it will be because something went
// wrong (like the implementation for selector function crashed... We're going
@@ -167,7 +173,7 @@ AppleThreadPlanStepThroughObjCTrampoline
lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
Address target_so_addr;
target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (target_addr == 0)
{
if (log)
@@ -178,7 +184,7 @@ AppleThreadPlanStepThroughObjCTrampoline
if (m_trampoline_handler->AddrIsMsgForward(target_addr))
{
if (log)
- log->Printf ("Implementation lookup returned msgForward function: 0x%llx, stopping.", target_addr);
+ log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
m_run_to_sp.reset(new ThreadPlanStepOut (m_thread,
@@ -194,13 +200,13 @@ AppleThreadPlanStepThroughObjCTrampoline
}
if (log)
- log->Printf("Running to ObjC method implementation: 0x%llx", target_addr);
+ log->Printf("Running to ObjC method implementation: 0x%" PRIx64, target_addr);
ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime();
assert (objc_runtime != NULL);
objc_runtime->AddToMethodCache (m_isa_addr, m_sel_addr, target_addr);
if (log)
- log->Printf("Adding {isa-addr=0x%llx, sel-addr=0x%llx} = addr=0x%llx to cache.", m_isa_addr, m_sel_addr, target_addr);
+ log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 "} = addr=0x%" PRIx64 " to cache.", m_isa_addr, m_sel_addr, target_addr);
// Extract the target address from the value:
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h Thu Jun 6 19:06:43 2013
@@ -45,15 +45,17 @@ public:
virtual bool
ValidatePlan (Stream *error);
- virtual bool
- PlanExplainsStop ();
-
-
virtual lldb::StateType
GetPlanRunState ();
virtual bool
ShouldStop (Event *event_ptr);
+
+ virtual bool
+ StopOthers()
+ {
+ return m_stop_others;
+ }
// The base class MischiefManaged does some cleanup - so you have to call it
// in your MischiefManaged derived class.
@@ -75,6 +77,8 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from AppleThreadPlanStepThroughObjCTrampoline can see and modify these
//------------------------------------------------------------------
+ virtual bool
+ DoPlanExplainsStop (Event *event_ptr);
private:
bool
Modified: lldb/branches/lldb-platform-work/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Makefile Thu Jun 6 19:06:43 2013
@@ -19,19 +19,20 @@ DIRS := ABI/MacOSX-arm ABI/MacOSX-i386 A
UnwindAssembly/InstEmulation UnwindAssembly/x86 \
LanguageRuntime/CPlusPlus/ItaniumABI \
LanguageRuntime/ObjC/AppleObjCRuntime \
- DynamicLoader/POSIX-DYLD
+ DynamicLoader/POSIX-DYLD \
+ OperatingSystem/Python
ifeq ($(HOST_OS),Darwin)
DIRS += Process/MacOSX-Kernel
DIRS += DynamicLoader/MacOSX-DYLD DynamicLoader/Darwin-Kernel
DIRS += ObjectContainer/Universal-Mach-O ObjectFile/Mach-O
DIRS += SymbolVendor/MacOSX
-DIRS += OperatingSystem/Darwin-Kernel
#DIRS += Process/MacOSX-User
DIRS += Process/mach-core
endif
ifeq ($(HOST_OS),Linux)
+DIRS += DynamicLoader/MacOSX-DYLD
DIRS += Process/Linux Process/POSIX
endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp Thu Jun 6 19:06:43 2013
@@ -15,7 +15,6 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -50,8 +49,8 @@ ObjectContainerBSDArchive::Object::Clear
ar_file_size = 0;
}
-uint32_t
-ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, uint32_t offset)
+lldb::offset_t
+ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::offset_t offset)
{
size_t ar_name_len = 0;
std::string str;
@@ -99,17 +98,19 @@ ObjectContainerBSDArchive::Object::Extra
ar_file_size = ar_size - ar_name_len;
return offset;
}
- return LLDB_INVALID_INDEX32;
+ return LLDB_INVALID_OFFSET;
}
ObjectContainerBSDArchive::Archive::Archive
(
const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &time
+ const lldb_private::TimeValue &time,
+ lldb_private::DataExtractor &data
) :
m_arch (arch),
m_time (time),
- m_objects()
+ m_objects(),
+ m_data (data)
{
}
@@ -118,10 +119,11 @@ ObjectContainerBSDArchive::Archive::~Arc
}
size_t
-ObjectContainerBSDArchive::Archive::ParseObjects (DataExtractor &data)
+ObjectContainerBSDArchive::Archive::ParseObjects ()
{
+ DataExtractor &data = m_data;
std::string str;
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
if (str == ARMAG)
{
@@ -129,9 +131,9 @@ ObjectContainerBSDArchive::Archive::Pars
do
{
offset = obj.Extract (data, offset);
- if (offset == LLDB_INVALID_INDEX32)
+ if (offset == LLDB_INVALID_OFFSET)
break;
- uint32_t obj_idx = m_objects.size();
+ size_t obj_idx = m_objects.size();
m_objects.push_back(obj);
// Insert all of the C strings out of order for now...
m_object_name_to_index_map.Append (obj.ar_name.GetCString(), obj_idx);
@@ -146,11 +148,29 @@ ObjectContainerBSDArchive::Archive::Pars
}
ObjectContainerBSDArchive::Object *
-ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name)
+ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name, const TimeValue &object_mod_time)
{
- const UniqueCStringMap<uint32_t>::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
+ const ObjectNameToIndexMap::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
if (match)
- return &m_objects[match->value];
+ {
+ if (object_mod_time.IsValid())
+ {
+ const uint64_t object_date = object_mod_time.GetAsSecondsSinceJan1_1970();
+ if (m_objects[match->value].ar_date == object_date)
+ return &m_objects[match->value];
+ const ObjectNameToIndexMap::Entry *next_match = m_object_name_to_index_map.FindNextValueForName (match);
+ while (next_match)
+ {
+ if (m_objects[next_match->value].ar_date == object_date)
+ return &m_objects[next_match->value];
+ next_match = m_object_name_to_index_map.FindNextValueForName (next_match);
+ }
+ }
+ else
+ {
+ return &m_objects[match->value];
+ }
+ }
return NULL;
}
@@ -166,7 +186,7 @@ ObjectContainerBSDArchive::Archive::Find
// delete an archive entry...
while (pos != archive_map.end() && pos->first == file)
{
- if (pos->second->GetArchitecture() == arch)
+ if (pos->second->GetArchitecture().IsCompatibleMatch(arch))
{
if (pos->second->GetModificationTime() == time)
{
@@ -201,10 +221,10 @@ ObjectContainerBSDArchive::Archive::Pars
DataExtractor &data
)
{
- shared_ptr archive_sp(new Archive (arch, time));
+ shared_ptr archive_sp(new Archive (arch, time, data));
if (archive_sp)
{
- if (archive_sp->ParseObjects (data) > 0)
+ if (archive_sp->ParseObjects () > 0)
{
Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
@@ -237,7 +257,8 @@ ObjectContainerBSDArchive::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ GetModuleSpecifications);
}
void
@@ -247,10 +268,11 @@ ObjectContainerBSDArchive::Terminate()
}
-const char *
+lldb_private::ConstString
ObjectContainerBSDArchive::GetPluginNameStatic()
{
- return "object-container.bsd-archive";
+ static ConstString g_name("bsd-archive");
+ return g_name;
}
const char *
@@ -265,34 +287,69 @@ ObjectContainerBSDArchive::CreateInstanc
(
const lldb::ModuleSP &module_sp,
DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const FileSpec *file,
- addr_t offset,
- addr_t length)
+ lldb::offset_t file_offset,
+ lldb::offset_t length)
{
- DataExtractor data;
- data.SetData (data_sp, offset, length);
- if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+ ConstString object_name (module_sp->GetObjectName());
+ if (object_name)
{
- Timer scoped_timer (__PRETTY_FUNCTION__,
- "ObjectContainerBSDArchive::CreateInstance (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
- module_sp->GetFileSpec().GetDirectory().AsCString(),
- module_sp->GetFileSpec().GetFilename().AsCString(),
- file, offset, length);
-
- Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
-
- std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, file, offset, length));
-
- if (container_ap.get())
+ if (data_sp)
+ {
+ // We have data, which means this is the first 512 bytes of the file
+ // Check to see if the magic bytes match and if they do, read the entire
+ // table of contents for the archive and cache it
+ DataExtractor data;
+ data.SetData (data_sp, data_offset, length);
+ if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+ {
+ Timer scoped_timer (__PRETTY_FUNCTION__,
+ "ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
+ module_sp->GetFileSpec().GetPath().c_str(),
+ file, (uint64_t) file_offset, (uint64_t) length);
+
+ // Map the entire .a file to be sure that we don't lose any data if the file
+ // gets updated by a new build while this .a file is being used for debugging
+ DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length));
+ lldb::offset_t archive_data_offset = 0;
+
+ Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
+ std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp,
+ archive_data_sp,
+ archive_data_offset,
+ file,
+ file_offset,
+ length));
+
+ if (container_ap.get())
+ {
+ if (archive_sp)
+ {
+ // We already have this archive in our cache, use it
+ container_ap->SetArchive (archive_sp);
+ return container_ap.release();
+ }
+ else if (container_ap->ParseHeader())
+ return container_ap.release();
+ }
+ }
+ }
+ else
{
+ // No data, just check for a cached archive
+ Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime()));
if (archive_sp)
{
- // We already have this archive in our cache, use it
- container_ap->SetArchive (archive_sp);
- return container_ap.release();
+ std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, data_offset, file, file_offset, length));
+
+ if (container_ap.get())
+ {
+ // We already have this archive in our cache, use it
+ container_ap->SetArchive (archive_sp);
+ return container_ap.release();
+ }
}
- else if (container_ap->ParseHeader())
- return container_ap.release();
}
}
return NULL;
@@ -317,19 +374,20 @@ ObjectContainerBSDArchive::MagicBytesMat
ObjectContainerBSDArchive::ObjectContainerBSDArchive
(
const lldb::ModuleSP &module_sp,
- DataBufferSP& dataSP,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec *file,
- lldb::addr_t offset,
- lldb::addr_t size
+ lldb::offset_t file_offset,
+ lldb::offset_t size
) :
- ObjectContainer (module_sp, file, offset, size, dataSP),
+ ObjectContainer (module_sp, file, file_offset, size, data_sp, data_offset),
m_archive_sp ()
{
}
void
ObjectContainerBSDArchive::SetArchive (Archive::shared_ptr &archive_sp)
{
- m_archive_sp = archive_sp;
+ m_archive_sp = archive_sp;
}
@@ -353,6 +411,9 @@ ObjectContainerBSDArchive::ParseHeader (
module_sp->GetModificationTime(),
m_data);
}
+ // Clear the m_data that contains the entire archive
+ // data and let our m_archive_sp hold onto the data.
+ m_data.Clear();
}
}
return m_archive_sp.get() != NULL;
@@ -392,13 +453,18 @@ ObjectContainerBSDArchive::GetObjectFile
{
if (module_sp->GetObjectName() && m_archive_sp)
{
- Object *object = m_archive_sp->FindObject (module_sp->GetObjectName());
+ Object *object = m_archive_sp->FindObject (module_sp->GetObjectName(),
+ module_sp->GetObjectModificationTime());
if (object)
- return ObjectFile::FindPlugin (module_sp,
+ {
+ lldb::offset_t data_offset = object->ar_file_offset;
+ return ObjectFile::FindPlugin (module_sp,
file,
- object->ar_file_offset,
- object->ar_file_size,
- m_data.GetSharedDataBuffer());
+ m_offset + object->ar_file_offset,
+ object->ar_file_size,
+ m_archive_sp->GetData().GetSharedDataBuffer(),
+ data_offset);
+ }
}
}
return ObjectFileSP();
@@ -408,15 +474,9 @@ ObjectContainerBSDArchive::GetObjectFile
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ObjectContainerBSDArchive::GetPluginName()
{
- return "object-container.bsd-archive";
-}
-
-const char *
-ObjectContainerBSDArchive::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -426,3 +486,14 @@ ObjectContainerBSDArchive::GetPluginVers
return 1;
}
+
+size_t
+ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ return 0;
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h Thu Jun 6 19:06:43 2013
@@ -32,7 +32,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -40,10 +40,19 @@ public:
static lldb_private::ObjectContainer *
CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec *file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
+
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
static bool
MagicBytesMatch (const lldb_private::DataExtractor &data);
@@ -52,10 +61,11 @@ public:
// Member Functions
//------------------------------------------------------------------
ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec *file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
virtual
~ObjectContainerBSDArchive();
@@ -79,12 +89,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -97,8 +104,8 @@ protected:
void
Clear();
- uint32_t
- Extract (const lldb_private::DataExtractor& data, uint32_t offset);
+ lldb::offset_t
+ Extract (const lldb_private::DataExtractor& data, lldb::offset_t offset);
lldb_private::ConstString ar_name; // name
uint32_t ar_date; // modification time
@@ -106,9 +113,8 @@ protected:
uint16_t ar_gid; // group id
uint16_t ar_mode; // octal file permissions
uint32_t ar_size; // size in bytes
- uint32_t ar_file_offset; // file offset in bytes from the beginning of the file of the object data
- uint32_t ar_file_size; // length of the object data
- lldb::ObjectFileSP object_file_sp;
+ lldb::offset_t ar_file_offset; // file offset in bytes from the beginning of the file of the object data
+ lldb::offset_t ar_file_size; // length of the object data
typedef std::vector<Object> collection;
typedef collection::iterator iterator;
@@ -118,7 +124,7 @@ protected:
class Archive
{
public:
- typedef STD_SHARED_PTR(Archive) shared_ptr;
+ typedef std::shared_ptr<Archive> shared_ptr;
typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
static Map &
@@ -139,7 +145,8 @@ protected:
lldb_private::DataExtractor &data);
Archive (const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time);
+ const lldb_private::TimeValue &mod_time,
+ lldb_private::DataExtractor &data);
~Archive ();
@@ -150,10 +157,11 @@ protected:
}
size_t
- ParseObjects (lldb_private::DataExtractor &data);
+ ParseObjects ();
Object *
- FindObject (const lldb_private::ConstString &object_name);
+ FindObject (const lldb_private::ConstString &object_name,
+ const lldb_private::TimeValue &object_mod_time);
const lldb_private::TimeValue &
GetModificationTime()
@@ -170,15 +178,22 @@ protected:
bool
HasNoExternalReferences() const;
- protected:
+ lldb_private::DataExtractor &
+ GetData ()
+ {
+ return m_data;
+ }
+ protected:
+ typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap;
//----------------------------------------------------------------------
// Member Variables
//----------------------------------------------------------------------
lldb_private::ArchSpec m_arch;
lldb_private::TimeValue m_time;
- Object::collection m_objects;
- lldb_private::UniqueCStringMap<uint32_t> m_object_name_to_index_map;
+ Object::collection m_objects;
+ ObjectNameToIndexMap m_object_name_to_index_map;
+ lldb_private::DataExtractor m_data; ///< The data for this object container so we don't lose data if the .a files gets modified
};
void
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp Thu Jun 6 19:06:43 2013
@@ -8,10 +8,12 @@
//===----------------------------------------------------------------------===//
#include "ObjectContainerUniversalMachO.h"
-#include "lldb/Core/Stream.h"
#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
@@ -24,7 +26,8 @@ ObjectContainerUniversalMachO::Initializ
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ GetModuleSpecifications);
}
void
@@ -34,10 +37,11 @@ ObjectContainerUniversalMachO::Terminate
}
-const char *
+lldb_private::ConstString
ObjectContainerUniversalMachO::GetPluginNameStatic()
{
- return "object-container.mach-o";
+ static ConstString g_name("mach-o");
+ return g_name;
}
const char *
@@ -52,30 +56,34 @@ ObjectContainerUniversalMachO::CreateIns
(
const lldb::ModuleSP &module_sp,
DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const FileSpec *file,
- addr_t offset,
- addr_t length
+ lldb::offset_t file_offset,
+ lldb::offset_t length
)
{
- DataExtractor data;
- data.SetData (data_sp, offset, length);
- if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
+ // We get data when we aren't trying to look for cached container information,
+ // so only try and look for an architecture slice if we get data
+ if (data_sp)
{
- std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, file, offset, length));
- if (container_ap->ParseHeader())
+ DataExtractor data;
+ data.SetData (data_sp, data_offset, length);
+ if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
{
- return container_ap.release();
+ std::unique_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, data_offset, file, file_offset, length));
+ if (container_ap->ParseHeader())
+ {
+ return container_ap.release();
+ }
}
}
return NULL;
}
-
-
bool
ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
uint32_t magic = data.GetU32(&offset);
return magic == UniversalMagic || magic == UniversalMagicSwapped;
}
@@ -83,12 +91,13 @@ ObjectContainerUniversalMachO::MagicByte
ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
(
const lldb::ModuleSP &module_sp,
- DataBufferSP& dataSP,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const FileSpec *file,
- addr_t offset,
- addr_t length
+ lldb::offset_t file_offset,
+ lldb::offset_t length
) :
- ObjectContainer (module_sp, file, offset, length, dataSP),
+ ObjectContainer (module_sp, file, file_offset, length, data_sp, data_offset),
m_header(),
m_fat_archs()
{
@@ -103,41 +112,53 @@ ObjectContainerUniversalMachO::~ObjectCo
bool
ObjectContainerUniversalMachO::ParseHeader ()
{
+ bool success = ParseHeader (m_data, m_header, m_fat_archs);
+ // We no longer need any data, we parsed all we needed to parse
+ // and cached it in m_header and m_fat_archs
+ m_data.Clear();
+ return success;
+}
+
+bool
+ObjectContainerUniversalMachO::ParseHeader (lldb_private::DataExtractor &data,
+ llvm::MachO::fat_header &header,
+ std::vector<llvm::MachO::fat_arch> &fat_archs)
+{
+ bool success = false;
// Store the file offset for this universal file as we could have a universal .o file
// in a BSD archive, or be contained in another kind of object.
- uint32_t offset = 0;
// Universal mach-o files always have their headers in big endian.
- m_data.SetByteOrder (eByteOrderBig);
- m_header.magic = m_data.GetU32(&offset);
+ lldb::offset_t offset = 0;
+ data.SetByteOrder (eByteOrderBig);
+ header.magic = data.GetU32(&offset);
+ fat_archs.clear();
- if (m_header.magic == UniversalMagic)
+ if (header.magic == UniversalMagic)
{
- m_data.SetAddressByteSize(4);
-
- m_header.nfat_arch = m_data.GetU32(&offset);
+ data.SetAddressByteSize(4);
+
+ header.nfat_arch = data.GetU32(&offset);
+
// Now we should have enough data for all of the fat headers, so lets index
// them so we know how many architectures that this universal binary contains.
uint32_t arch_idx = 0;
- for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
+ for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx)
{
- if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
+ if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
{
fat_arch arch;
- if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
- {
- m_fat_archs.push_back(arch);
- }
+ if (data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
+ fat_archs.push_back(arch);
}
}
- return true;
+ success = true;
}
else
{
- memset(&m_header, 0, sizeof(m_header));
+ memset(&header, 0, sizeof(header));
}
-
- return false;
+ return success;
}
void
@@ -203,20 +224,34 @@ ObjectContainerUniversalMachO::GetObject
arch = module_sp->GetArchitecture();
ArchSpec curr_arch;
+ // First, try to find an exact match for the Arch of the Target.
for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
{
- if (GetArchitectureAtIndex (arch_idx, curr_arch))
+ if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsExactMatch(curr_arch))
+ break;
+ }
+
+ // Failing an exact match, try to find a compatible Arch of the Target.
+ if (arch_idx >= m_header.nfat_arch)
+ {
+ for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
{
- if (arch == curr_arch)
- {
- return ObjectFile::FindPlugin (module_sp,
- file,
- m_offset + m_fat_archs[arch_idx].offset,
- m_fat_archs[arch_idx].size,
- m_data.GetSharedDataBuffer());
- }
+ if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch))
+ break;
}
}
+
+ if (arch_idx < m_header.nfat_arch)
+ {
+ DataBufferSP data_sp;
+ lldb::offset_t data_offset = 0;
+ return ObjectFile::FindPlugin (module_sp,
+ file,
+ m_offset + m_fat_archs[arch_idx].offset,
+ m_fat_archs[arch_idx].size,
+ data_sp,
+ data_offset);
+ }
}
return ObjectFileSP();
}
@@ -225,15 +260,9 @@ ObjectContainerUniversalMachO::GetObject
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ObjectContainerUniversalMachO::GetPluginName()
{
- return "ObjectContainerUniversalMachO";
-}
-
-const char *
-ObjectContainerUniversalMachO::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -244,3 +273,33 @@ ObjectContainerUniversalMachO::GetPlugin
}
+size_t
+ObjectContainerUniversalMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ const size_t initial_count = specs.GetSize();
+
+ DataExtractor data;
+ data.SetData (data_sp, data_offset, length);
+
+ if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
+ {
+ llvm::MachO::fat_header header;
+ std::vector<llvm::MachO::fat_arch> fat_archs;
+ if (ParseHeader (data, header, fat_archs))
+ {
+ for (const llvm::MachO::fat_arch &fat_arch : fat_archs)
+ {
+ ObjectFile::GetModuleSpecifications (file,
+ fat_arch.offset + file_offset,
+ specs);
+ }
+ }
+ }
+ return specs.GetSize() - initial_count;
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h Thu Jun 6 19:06:43 2013
@@ -28,7 +28,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -36,10 +36,19 @@ public:
static lldb_private::ObjectContainer *
CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec *file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
+
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
static bool
MagicBytesMatch (const lldb_private::DataExtractor &data);
@@ -48,10 +57,11 @@ public:
// Member Functions
//------------------------------------------------------------------
ObjectContainerUniversalMachO (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec *file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
virtual
~ObjectContainerUniversalMachO();
@@ -74,18 +84,21 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
protected:
llvm::MachO::fat_header m_header;
std::vector<llvm::MachO::fat_arch> m_fat_archs;
+
+ static bool
+ ParseHeader (lldb_private::DataExtractor &data,
+ llvm::MachO::fat_header &header,
+ std::vector<llvm::MachO::fat_arch> &fat_archs);
+
};
#endif // liblldb_ObjectContainerUniversalMachO_h_
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.cpp Thu Jun 6 19:06:43 2013
@@ -10,6 +10,8 @@
#include <cstring>
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
#include "ELFHeader.h"
@@ -23,20 +25,24 @@ using namespace llvm::ELF;
// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
// with error handling code and provide for parsing a sequence of values.
static bool
-GetMaxU64(const lldb_private::DataExtractor &data,
- uint32_t *offset, uint64_t *value, uint32_t byte_size)
+GetMaxU64(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset,
+ uint64_t *value,
+ uint32_t byte_size)
{
- const uint32_t saved_offset = *offset;
+ const lldb::offset_t saved_offset = *offset;
*value = data.GetMaxU64(offset, byte_size);
return *offset != saved_offset;
}
static bool
GetMaxU64(const lldb_private::DataExtractor &data,
- uint32_t *offset, uint64_t *value, uint32_t byte_size,
+ lldb::offset_t *offset,
+ uint64_t *value,
+ uint32_t byte_size,
uint32_t count)
{
- uint32_t saved_offset = *offset;
+ lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value)
{
@@ -51,19 +57,23 @@ GetMaxU64(const lldb_private::DataExtrac
static bool
GetMaxS64(const lldb_private::DataExtractor &data,
- uint32_t *offset, int64_t *value, uint32_t byte_size)
+ lldb::offset_t *offset,
+ int64_t *value,
+ uint32_t byte_size)
{
- const uint32_t saved_offset = *offset;
+ const lldb::offset_t saved_offset = *offset;
*value = data.GetMaxS64(offset, byte_size);
return *offset != saved_offset;
}
static bool
GetMaxS64(const lldb_private::DataExtractor &data,
- uint32_t *offset, int64_t *value, uint32_t byte_size,
+ lldb::offset_t *offset,
+ int64_t *value,
+ uint32_t byte_size,
uint32_t count)
{
- uint32_t saved_offset = *offset;
+ lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value)
{
@@ -95,7 +105,7 @@ ELFHeader::GetByteOrder() const
}
bool
-ELFHeader::Parse(lldb_private::DataExtractor &data, uint32_t *offset)
+ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
// Read e_ident. This provides byte order and address size info.
if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
@@ -190,7 +200,7 @@ ELFSectionHeader::ELFSectionHeader()
bool
ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
- uint32_t *offset)
+ lldb::offset_t *offset)
{
const unsigned byte_size = data.GetAddressByteSize();
@@ -225,8 +235,92 @@ ELFSymbol::ELFSymbol()
memset(this, 0, sizeof(ELFSymbol));
}
+#define ENUM_TO_CSTR(e) case e: return #e
+
+const char *
+ELFSymbol::bindingToCString(unsigned char binding)
+{
+ switch (binding)
+ {
+ ENUM_TO_CSTR(STB_LOCAL);
+ ENUM_TO_CSTR(STB_GLOBAL);
+ ENUM_TO_CSTR(STB_WEAK);
+ ENUM_TO_CSTR(STB_LOOS);
+ ENUM_TO_CSTR(STB_HIOS);
+ ENUM_TO_CSTR(STB_LOPROC);
+ ENUM_TO_CSTR(STB_HIPROC);
+ }
+ return "";
+}
+
+const char *
+ELFSymbol::typeToCString(unsigned char type)
+{
+ switch (type)
+ {
+ ENUM_TO_CSTR(STT_NOTYPE);
+ ENUM_TO_CSTR(STT_OBJECT);
+ ENUM_TO_CSTR(STT_FUNC);
+ ENUM_TO_CSTR(STT_SECTION);
+ ENUM_TO_CSTR(STT_FILE);
+ ENUM_TO_CSTR(STT_COMMON);
+ ENUM_TO_CSTR(STT_TLS);
+ ENUM_TO_CSTR(STT_LOOS);
+ ENUM_TO_CSTR(STT_HIOS);
+ ENUM_TO_CSTR(STT_GNU_IFUNC);
+ ENUM_TO_CSTR(STT_LOPROC);
+ ENUM_TO_CSTR(STT_HIPROC);
+ }
+ return "";
+}
+
+const char *
+ELFSymbol::sectionIndexToCString (elf_half shndx,
+ const lldb_private::SectionList *section_list)
+{
+ switch (shndx)
+ {
+ ENUM_TO_CSTR(SHN_UNDEF);
+ ENUM_TO_CSTR(SHN_LOPROC);
+ ENUM_TO_CSTR(SHN_HIPROC);
+ ENUM_TO_CSTR(SHN_LOOS);
+ ENUM_TO_CSTR(SHN_HIOS);
+ ENUM_TO_CSTR(SHN_ABS);
+ ENUM_TO_CSTR(SHN_COMMON);
+ ENUM_TO_CSTR(SHN_XINDEX);
+ default:
+ {
+ const lldb_private::Section *section = section_list->GetSectionAtIndex(shndx).get();
+ if (section)
+ return section->GetName().AsCString("");
+ }
+ break;
+ }
+ return "";
+}
+
+void
+ELFSymbol::Dump (lldb_private::Stream *s,
+ uint32_t idx,
+ const lldb_private::DataExtractor *strtab_data,
+ const lldb_private::SectionList *section_list)
+{
+ s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
+ idx,
+ st_value,
+ st_size,
+ st_name,
+ st_info,
+ bindingToCString (getBinding()),
+ typeToCString (getType()),
+ st_other,
+ st_shndx,
+ sectionIndexToCString (st_shndx, section_list),
+ strtab_data ? strtab_data->PeekCStr(st_name) : "");
+}
+
bool
-ELFSymbol::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
const unsigned byte_size = data.GetAddressByteSize();
const bool parsing_32 = byte_size == 4;
@@ -276,7 +370,7 @@ ELFProgramHeader::ELFProgramHeader()
bool
ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
- uint32_t *offset)
+ lldb::offset_t *offset)
{
const uint32_t byte_size = data.GetAddressByteSize();
const bool parsing_32 = byte_size == 4;
@@ -320,7 +414,7 @@ ELFDynamic::ELFDynamic()
}
bool
-ELFDynamic::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
const unsigned byte_size = data.GetAddressByteSize();
return GetMaxS64(data, offset, &d_tag, byte_size, 2);
@@ -335,7 +429,7 @@ ELFRel::ELFRel()
}
bool
-ELFRel::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
const unsigned byte_size = data.GetAddressByteSize();
@@ -355,7 +449,7 @@ ELFRela::ELFRela()
}
bool
-ELFRela::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
const unsigned byte_size = data.GetAddressByteSize();
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ELFHeader.h Thu Jun 6 19:06:43 2013
@@ -107,7 +107,7 @@ struct ELFHeader
GetRelocationJumpSlotType() const;
//--------------------------------------------------------------------------
- /// Parse an ELFSectionHeader entry starting at position \p offset and
+ /// Parse an ELFHeader entry starting at position \p offset and
/// update the data extractor with the address size and byte order
/// attributes as defined by the header.
///
@@ -120,10 +120,10 @@ struct ELFHeader
/// advanced by the number of bytes read.
///
/// @return
- /// True if the ELFSectionHeader was successfully read and false
+ /// True if the ELFHeader was successfully read and false
/// otherwise.
bool
- Parse(lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
//--------------------------------------------------------------------------
/// Examines at most EI_NIDENT bytes starting from the given pointer and
@@ -181,7 +181,7 @@ struct ELFSectionHeader
/// True if the ELFSectionHeader was successfully read and false
/// otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
@@ -216,7 +216,7 @@ struct ELFProgramHeader
/// True if the ELFProgramHeader was successfully read and false
/// otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
@@ -244,6 +244,16 @@ struct ELFSymbol
st_info = (binding << 4) + (type & 0x0F);
}
+ static const char *
+ bindingToCString(unsigned char binding);
+
+ static const char *
+ typeToCString(unsigned char type);
+
+ static const char *
+ sectionIndexToCString(elf_half shndx,
+ const lldb_private::SectionList *section_list);
+
/// Parse an ELFSymbol entry from the given DataExtractor starting at
/// position \p offset. The address size of the DataExtractor determines if
/// a 32 or 64 bit object is to be parsed.
@@ -259,7 +269,13 @@ struct ELFSymbol
/// @return
/// True if the ELFSymbol was successfully read and false otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ void
+ Dump (lldb_private::Stream *s,
+ uint32_t idx,
+ const lldb_private::DataExtractor *strtab_data,
+ const lldb_private::SectionList *section_list);
};
//------------------------------------------------------------------------------
@@ -292,7 +308,7 @@ struct ELFDynamic
/// True if the ELFDynamic entry was successfully read and false
/// otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
@@ -320,7 +336,7 @@ struct ELFRel
/// @return
/// True if the ELFRel entry was successfully read and false otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
/// Returns the type when the given entry represents a 32-bit relocation.
static unsigned
@@ -379,7 +395,7 @@ struct ELFRela
/// @return
/// True if the ELFRela entry was successfully read and false otherwise.
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
/// Returns the type when the given entry represents a 32-bit relocation.
static unsigned
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Thu Jun 6 19:06:43 2013
@@ -17,6 +17,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
@@ -53,7 +54,7 @@ public:
~ELFRelocation();
bool
- Parse(const lldb_private::DataExtractor &data, uint32_t *offset);
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
static unsigned
RelocType32(const ELFRelocation &rel);
@@ -94,7 +95,7 @@ ELFRelocation::~ELFRelocation()
}
bool
-ELFRelocation::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
+ELFRelocation::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
{
if (reloc.is<ELFRel*>())
return reloc.get<ELFRel*>()->Parse(data, offset);
@@ -149,7 +150,8 @@ ObjectFileELF::Initialize()
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance,
- CreateMemoryInstance);
+ CreateMemoryInstance,
+ GetModuleSpecifications);
}
void
@@ -158,10 +160,11 @@ ObjectFileELF::Terminate()
PluginManager::UnregisterPlugin(CreateInstance);
}
-const char *
+lldb_private::ConstString
ObjectFileELF::GetPluginNameStatic()
{
- return "object-file.elf";
+ static ConstString g_name("elf");
+ return g_name;
}
const char *
@@ -173,19 +176,32 @@ ObjectFileELF::GetPluginDescriptionStati
ObjectFile *
ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
- const FileSpec *file,
- addr_t offset,
- addr_t length)
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length)
{
- if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + offset))
+ if (!data_sp)
{
- const uint8_t *magic = data_sp->GetBytes() + offset;
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_offset = 0;
+ }
+
+ if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+ {
+ const uint8_t *magic = data_sp->GetBytes() + data_offset;
if (ELFHeader::MagicBytesMatch(magic))
{
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length) {
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_offset = 0;
+ magic = data_sp->GetBytes();
+ }
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8)
{
- std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, file, offset, length));
+ std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, data_offset, file, file_offset, length));
ArchSpec spec;
if (objfile_ap->GetArchitecture(spec) &&
objfile_ap->SetModulesArchitecture(spec))
@@ -206,19 +222,68 @@ ObjectFileELF::CreateMemoryInstance (con
return NULL;
}
+bool
+ObjectFileELF::MagicBytesMatch (DataBufferSP& data_sp,
+ lldb::addr_t data_offset,
+ lldb::addr_t data_length)
+{
+ if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+ {
+ const uint8_t *magic = data_sp->GetBytes() + data_offset;
+ return ELFHeader::MagicBytesMatch(magic);
+ }
+ return false;
+}
+
+size_t
+ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ const size_t initial_count = specs.GetSize();
+
+ if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+ {
+ DataExtractor data;
+ data.SetData(data_sp);
+ elf::ELFHeader header;
+ if (header.Parse(data, &data_offset))
+ {
+ if (data_sp)
+ {
+ ModuleSpec spec;
+ spec.GetFileSpec() = file;
+ spec.GetArchitecture().SetArchitecture(eArchTypeELF,
+ header.e_machine,
+ LLDB_INVALID_CPUTYPE);
+ if (spec.GetArchitecture().IsValid())
+ {
+ // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
+ // machine information. However, we'd have to read a good bit of the rest of the file,
+ // and this info isn't guaranteed to exist or be correct. More details here:
+ // http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
+ // Instead of passing potentially incorrect information down the pipeline, grab
+ // the host information and use it.
+ spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
+ spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
+ specs.Append(spec);
+ }
+ }
+ }
+ }
+
+ return specs.GetSize() - initial_count;
+}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ObjectFileELF::GetPluginName()
{
- return "ObjectFileELF";
-}
-
-const char *
-ObjectFileELF::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -232,16 +297,15 @@ ObjectFileELF::GetPluginVersion()
//------------------------------------------------------------------
ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
- DataBufferSP& dataSP,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const FileSpec* file,
- addr_t offset,
- addr_t length) :
- ObjectFile(module_sp, file, offset, length, dataSP),
+ lldb::offset_t file_offset,
+ lldb::offset_t length) :
+ ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_header(),
m_program_headers(),
m_section_headers(),
- m_sections_ap(),
- m_symtab_ap(),
m_filespec_ap(),
m_shstr_data()
{
@@ -270,35 +334,40 @@ ObjectFileELF::GetByteOrder() const
return eByteOrderInvalid;
}
-size_t
+uint32_t
ObjectFileELF::GetAddressByteSize() const
{
return m_data.GetAddressByteSize();
}
-unsigned
+size_t
ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
{
- return std::distance(m_section_headers.begin(), I) + 1;
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
-unsigned
+size_t
ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const
{
- return std::distance(m_section_headers.begin(), I) + 1;
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
bool
ObjectFileELF::ParseHeader()
{
- uint32_t offset = GetOffset();
+ lldb::offset_t offset = 0;
return m_header.Parse(m_data, &offset);
}
bool
ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
{
- // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
+ if (m_uuid.IsValid())
+ {
+ *uuid = m_uuid;
+ return true;
+ }
+ // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
return false;
}
@@ -445,8 +514,8 @@ ObjectFileELF::ParseDependentModules()
ReadSectionData(dynstr, dynstr_data))
{
ELFDynamic symbol;
- const unsigned section_size = dynsym_data.GetByteSize();
- unsigned offset = 0;
+ const lldb::offset_t section_size = dynsym_data.GetByteSize();
+ lldb::offset_t offset = 0;
// The only type of entries we are concerned with are tagged DT_NEEDED,
// yielding the name of a required library.
@@ -492,7 +561,7 @@ ObjectFileELF::ParseProgramHeaders()
return 0;
uint32_t idx;
- uint32_t offset;
+ lldb::offset_t offset;
for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
{
if (m_program_headers[idx].Parse(data, &offset) == false)
@@ -530,7 +599,7 @@ ObjectFileELF::ParseSectionHeaders()
return 0;
uint32_t idx;
- uint32_t offset;
+ lldb::offset_t offset;
for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx)
{
if (m_section_headers[idx].Parse(data, &offset) == false)
@@ -599,6 +668,51 @@ ObjectFileELF::GetSectionHeaderByIndex(l
return NULL;
}
+static bool
+ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
+{
+ // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
+ // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
+ struct
+ {
+ uint32_t name_len; // Length of note name
+ uint32_t desc_len; // Length of note descriptor
+ uint32_t type; // Type of note (1 is ABI_TAG, 3 is BUILD_ID)
+ } notehdr;
+ lldb::offset_t offset = 0;
+ static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
+
+ while (true)
+ {
+ if (data.GetU32 (&offset, ¬ehdr, 3) == NULL)
+ return false;
+
+ notehdr.name_len = llvm::RoundUpToAlignment (notehdr.name_len, 4);
+ notehdr.desc_len = llvm::RoundUpToAlignment (notehdr.desc_len, 4);
+
+ lldb::offset_t offset_next_note = offset + notehdr.name_len + notehdr.desc_len;
+
+ // 16 bytes is UUID|MD5, 20 bytes is SHA1
+ if ((notehdr.type == g_gnu_build_id) && (notehdr.name_len == 4) &&
+ (notehdr.desc_len == 16 || notehdr.desc_len == 20))
+ {
+ char name[4];
+ if (data.GetU8 (&offset, name, 4) == NULL)
+ return false;
+ if (!strcmp(name, "GNU"))
+ {
+ uint8_t uuidbuf[20];
+ if (data.GetU8 (&offset, &uuidbuf, notehdr.desc_len) == NULL)
+ return false;
+ uuid.SetBytes (uuidbuf, notehdr.desc_len);
+ return true;
+ }
+ }
+ offset = offset_next_note;
+ }
+ return false;
+}
+
SectionList *
ObjectFileELF::GetSectionList()
{
@@ -665,7 +779,17 @@ ObjectFileELF::GetSectionList()
else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
-
+ else if (header.sh_type == SHT_NOTE)
+ {
+ if (!m_uuid.IsValid())
+ {
+ DataExtractor data;
+ if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size))
+ {
+ ParseNoteGNUBuildID (data, m_uuid);
+ }
+ }
+ }
SectionSP section_sp(new Section(
GetModule(), // Module to which this section belongs.
@@ -698,9 +822,8 @@ ParseSymbols(Symtab *symtab,
const DataExtractor &strtab_data)
{
ELFSymbol symbol;
- uint32_t offset = 0;
- const unsigned num_symbols =
- symtab_data.GetByteSize() / symtab_shdr->sh_entsize;
+ lldb::offset_t offset = 0;
+ const size_t num_symbols = symtab_data.GetByteSize() / symtab_shdr->sh_entsize;
static ConstString text_section_name(".text");
static ConstString init_section_name(".init");
@@ -714,11 +837,20 @@ ParseSymbols(Symtab *symtab,
static ConstString data2_section_name(".data1");
static ConstString bss_section_name(".bss");
+ //StreamFile strm(stdout, false);
unsigned i;
for (i = 0; i < num_symbols; ++i)
{
if (symbol.Parse(symtab_data, &offset) == false)
break;
+
+ const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+
+ // No need to add symbols that have no names
+ if (symbol_name == NULL || symbol_name[0] == '\0')
+ continue;
+
+ //symbol.Dump (&strm, i, &strtab_data, section_list);
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
@@ -737,37 +869,47 @@ ParseSymbols(Symtab *symtab,
break;
}
- switch (symbol.getType())
+ // If a symbol is undefined do not process it further even if it has a STT type
+ if (symbol_type != eSymbolTypeUndefined)
{
- default:
- case STT_NOTYPE:
- // The symbol's type is not specified.
- break;
+ switch (symbol.getType())
+ {
+ default:
+ case STT_NOTYPE:
+ // The symbol's type is not specified.
+ break;
- case STT_OBJECT:
- // The symbol is associated with a data object, such as a variable,
- // an array, etc.
- symbol_type = eSymbolTypeData;
- break;
+ case STT_OBJECT:
+ // The symbol is associated with a data object, such as a variable,
+ // an array, etc.
+ symbol_type = eSymbolTypeData;
+ break;
- case STT_FUNC:
- // The symbol is associated with a function or other executable code.
- symbol_type = eSymbolTypeCode;
- break;
+ case STT_FUNC:
+ // The symbol is associated with a function or other executable code.
+ symbol_type = eSymbolTypeCode;
+ break;
- case STT_SECTION:
- // The symbol is associated with a section. Symbol table entries of
- // this type exist primarily for relocation and normally have
- // STB_LOCAL binding.
- break;
+ case STT_SECTION:
+ // The symbol is associated with a section. Symbol table entries of
+ // this type exist primarily for relocation and normally have
+ // STB_LOCAL binding.
+ break;
- case STT_FILE:
- // Conventionally, the symbol's name gives the name of the source
- // file associated with the object file. A file symbol has STB_LOCAL
- // binding, its section index is SHN_ABS, and it precedes the other
- // STB_LOCAL symbols for the file, if it is present.
- symbol_type = eSymbolTypeObjectFile;
- break;
+ case STT_FILE:
+ // Conventionally, the symbol's name gives the name of the source
+ // file associated with the object file. A file symbol has STB_LOCAL
+ // binding, its section index is SHN_ABS, and it precedes the other
+ // STB_LOCAL symbols for the file, if it is present.
+ symbol_type = eSymbolTypeSourceFile;
+ break;
+
+ case STT_GNU_IFUNC:
+ // The symbol is associated with an indirect function. The actual
+ // function will be resolved if it is referenced.
+ symbol_type = eSymbolTypeResolver;
+ break;
+ }
}
if (symbol_type == eSymbolTypeInvalid)
@@ -797,7 +939,6 @@ ParseSymbols(Symtab *symtab,
uint64_t symbol_value = symbol.st_value;
if (symbol_section_sp)
symbol_value -= symbol_section_sp->GetFileAddress();
- const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
bool is_global = symbol.getBinding() == STB_GLOBAL;
uint32_t flags = symbol.st_other << 8 | symbol.st_info;
bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
@@ -813,6 +954,7 @@ ParseSymbols(Symtab *symtab,
symbol_section_sp, // Section in which this symbol is defined or null.
symbol_value, // Offset in section or symbol value.
symbol.st_size, // Size in bytes of this symbol.
+ true, // Size is valid
flags); // Symbol flags.
symtab->AddSymbol(dc_symbol);
}
@@ -877,8 +1019,8 @@ ObjectFileELF::ParseDynamicSymbols()
DataExtractor dynsym_data;
if (ReadSectionData(dynsym, dynsym_data))
{
- const unsigned section_size = dynsym_data.GetByteSize();
- unsigned cursor = 0;
+ const lldb::offset_t section_size = dynsym_data.GetByteSize();
+ lldb::offset_t cursor = 0;
while (cursor < section_size)
{
@@ -956,15 +1098,15 @@ ParsePLTRelocations(Symtab *symbol_table
{
ELFRelocation rel(rel_type);
ELFSymbol symbol;
- uint32_t offset = 0;
- const unsigned plt_entsize = plt_hdr->sh_entsize;
- const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+ lldb::offset_t offset = 0;
+ const elf_xword plt_entsize = plt_hdr->sh_entsize;
+ const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
reloc_info_fn reloc_type;
reloc_info_fn reloc_symbol;
- if (hdr->Is32Bit() == 4)
+ if (hdr->Is32Bit())
{
reloc_type = ELFRelocation::RelocType32;
reloc_symbol = ELFRelocation::RelocSymbol32;
@@ -985,7 +1127,7 @@ ParsePLTRelocations(Symtab *symbol_table
if (reloc_type(rel) != slot_type)
continue;
- unsigned symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
+ lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
uint64_t plt_index = (i + 1) * plt_entsize;
if (!symbol.Parse(symtab_data, &symbol_offset))
@@ -1006,6 +1148,7 @@ ParsePLTRelocations(Symtab *symbol_table
plt_section_sp, // Section in which this symbol is defined or null.
plt_index, // Offset in section or symbol value.
plt_entsize, // Size in bytes of this symbol.
+ true, // Size is valid
0); // Symbol flags.
symbol_table->AddSymbol(jump_symbol);
@@ -1186,9 +1329,9 @@ ObjectFileELF::DumpELFHeader(Stream *s,
DumpELFHeader_e_type(s, header.e_type);
s->Printf("\ne_machine = 0x%4.4x\n", header.e_machine);
s->Printf("e_version = 0x%8.8x\n", header.e_version);
- s->Printf("e_entry = 0x%8.8llx\n", header.e_entry);
- s->Printf("e_phoff = 0x%8.8llx\n", header.e_phoff);
- s->Printf("e_shoff = 0x%8.8llx\n", header.e_shoff);
+ s->Printf("e_entry = 0x%8.8" PRIx64 "\n", header.e_entry);
+ s->Printf("e_phoff = 0x%8.8" PRIx64 "\n", header.e_phoff);
+ s->Printf("e_shoff = 0x%8.8" PRIx64 "\n", header.e_shoff);
s->Printf("e_flags = 0x%8.8x\n", header.e_flags);
s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize);
s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
@@ -1246,11 +1389,11 @@ void
ObjectFileELF::DumpELFProgramHeader(Stream *s, const ELFProgramHeader &ph)
{
DumpELFProgramHeader_p_type(s, ph.p_type);
- s->Printf(" %8.8llx %8.8llx %8.8llx", ph.p_offset, ph.p_vaddr, ph.p_paddr);
- s->Printf(" %8.8llx %8.8llx %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset, ph.p_vaddr, ph.p_paddr);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
DumpELFProgramHeader_p_flags(s, ph.p_flags);
- s->Printf(") %8.8llx", ph.p_align);
+ s->Printf(") %8.8" PRIx64, ph.p_align);
}
//----------------------------------------------------------------------
@@ -1262,16 +1405,18 @@ ObjectFileELF::DumpELFProgramHeader(Stre
void
ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
{
- const int kStrWidth = 10;
+ const int kStrWidth = 15;
switch (p_type)
{
- CASE_AND_STREAM(s, PT_NULL , kStrWidth);
- CASE_AND_STREAM(s, PT_LOAD , kStrWidth);
- CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth);
- CASE_AND_STREAM(s, PT_INTERP , kStrWidth);
- CASE_AND_STREAM(s, PT_NOTE , kStrWidth);
- CASE_AND_STREAM(s, PT_SHLIB , kStrWidth);
- CASE_AND_STREAM(s, PT_PHDR , kStrWidth);
+ CASE_AND_STREAM(s, PT_NULL , kStrWidth);
+ CASE_AND_STREAM(s, PT_LOAD , kStrWidth);
+ CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth);
+ CASE_AND_STREAM(s, PT_INTERP , kStrWidth);
+ CASE_AND_STREAM(s, PT_NOTE , kStrWidth);
+ CASE_AND_STREAM(s, PT_SHLIB , kStrWidth);
+ CASE_AND_STREAM(s, PT_PHDR , kStrWidth);
+ CASE_AND_STREAM(s, PT_TLS , kStrWidth);
+ CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
default:
s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
break;
@@ -1305,9 +1450,9 @@ ObjectFileELF::DumpELFProgramHeaders(Str
if (ParseProgramHeaders())
{
s->PutCString("Program Headers\n");
- s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
+ s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
"p_filesz p_memsz p_flags p_align\n");
- s->PutCString("==== ---------- -------- -------- -------- "
+ s->PutCString("==== --------------- -------- -------- -------- "
"-------- -------- ------------------------- --------\n");
uint32_t idx = 0;
@@ -1331,11 +1476,11 @@ ObjectFileELF::DumpELFSectionHeader(Stre
{
s->Printf("%8.8x ", sh.sh_name);
DumpELFSectionHeader_sh_type(s, sh.sh_type);
- s->Printf(" %8.8llx (", sh.sh_flags);
+ s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
- s->Printf(") %8.8llx %8.8llx %8.8llx", sh.sh_addr, sh.sh_offset, sh.sh_size);
+ s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr, sh.sh_offset, sh.sh_size);
s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
- s->Printf(" %8.8llx %8.8llx", sh.sh_addralign, sh.sh_entsize);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
}
//----------------------------------------------------------------------
@@ -1378,7 +1523,7 @@ ObjectFileELF::DumpELFSectionHeader_sh_t
// Dump an token value for the ELF section header member sh_flags
//----------------------------------------------------------------------
void
-ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_word sh_flags)
+ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags)
{
*s << ((sh_flags & SHF_WRITE) ? "WRITE" : " ")
<< (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Thu Jun 6 19:06:43 2013
@@ -16,6 +16,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/UUID.h"
#include "ELFHeader.h"
@@ -38,7 +39,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -46,10 +47,11 @@ public:
static lldb_private::ObjectFile *
CreateInstance(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t file_offset,
+ lldb::offset_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (const lldb::ModuleSP &module_sp,
@@ -57,15 +59,25 @@ public:
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ static bool
+ MagicBytesMatch (lldb::DataBufferSP& data_sp,
+ lldb::addr_t offset,
+ lldb::addr_t length);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -84,7 +96,7 @@ public:
virtual bool
IsExecutable () const;
- virtual size_t
+ virtual uint32_t
GetAddressByteSize() const;
virtual lldb_private::Symtab *
@@ -119,10 +131,11 @@ public:
private:
ObjectFileELF(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
@@ -142,6 +155,9 @@ private:
/// ELF file header.
elf::ELFHeader m_header;
+ /// ELF build ID
+ lldb_private::UUID m_uuid;
+
/// Collection of program headers.
ProgramHeaderColl m_program_headers;
@@ -151,15 +167,9 @@ private:
/// Collection of symbols from the dynamic table.
DynamicSymbolColl m_dynamic_symbols;
- /// List of sections present in this ELF object file.
- mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
-
- /// Table of all non-dynamic symbols present in this object file.
- mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
-
/// List of file specifications corresponding to the modules (shared
/// libraries) on which this object file depends.
- mutable std::auto_ptr<lldb_private::FileSpecList> m_filespec_ap;
+ mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
/// Data extractor holding the string table used to resolve section names.
lldb_private::DataExtractor m_shstr_data;
@@ -168,11 +178,11 @@ private:
lldb_private::Address m_entry_point_address;
/// Returns a 1 based index of the given section header.
- unsigned
+ size_t
SectionIndex(const SectionHeaderCollIter &I);
/// Returns a 1 based index of the given section header.
- unsigned
+ size_t
SectionIndex(const SectionHeaderCollConstIter &I) const;
/// Parses all section headers present in this object file and populates
@@ -282,7 +292,7 @@ private:
static void
DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,
- elf::elf_word sh_flags);
+ elf::elf_xword sh_flags);
//@}
/// ELF dependent module dump routine.
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Thu Jun 6 19:06:43 2013
@@ -12,10 +12,14 @@
#include "ObjectFileMachO.h"
+#include "lldb/lldb-private-log.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
@@ -26,6 +30,7 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -34,11 +39,20 @@
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
+#if defined (__APPLE__) && defined (__arm__)
+// GetLLDBSharedCacheUUID() needs to call dlsym()
+#include <dlfcn.h>
+#endif
+
+#ifndef __APPLE__
+#include "Utility/UuidCompatibility.h"
+#endif
+
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
-class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64
+class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64
{
public:
RegisterContextDarwin_x86_64_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
@@ -56,12 +70,12 @@ public:
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
bool done = false;
-
+
while (!done)
{
int flavor = data.GetU32 (&offset);
@@ -78,13 +92,13 @@ public:
(&gpr.rax)[i] = data.GetU64(&offset);
SetError (GPRRegSet, Read, 0);
done = true;
-
+
break;
case FPURegSet:
// TODO: fill in FPU regs....
//SetError (FPURegSet, Read, -1);
done = true;
-
+
break;
case EXCRegSet:
exc.trapno = data.GetU32(&offset);
@@ -99,7 +113,7 @@ public:
// fancy flavors that encapsulate of the the above
// falvors...
break;
-
+
default:
done = true;
break;
@@ -113,31 +127,31 @@ protected:
{
return 0;
}
-
+
virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return 0;
}
-
+
virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return 0;
}
-
+
virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return 0;
}
-
+
virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return 0;
}
-
+
virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
@@ -146,7 +160,7 @@ protected:
};
-class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386
+class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386
{
public:
RegisterContextDarwin_i386_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
@@ -154,22 +168,22 @@ public:
{
SetRegisterDataFrom_LC_THREAD (data);
}
-
+
virtual void
InvalidateAllRegisters ()
{
// Do nothing... registers are always valid...
}
-
+
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
bool done = false;
-
+
while (!done)
{
int flavor = data.GetU32 (&offset);
@@ -207,7 +221,7 @@ public:
// fancy flavors that encapsulate of the the above
// falvors...
break;
-
+
default:
done = true;
break;
@@ -221,31 +235,31 @@ protected:
{
return 0;
}
-
+
virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return 0;
}
-
+
virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return 0;
}
-
+
virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return 0;
}
-
+
virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return 0;
}
-
+
virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
@@ -253,87 +267,156 @@ protected:
}
};
-class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm
+class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm
{
public:
RegisterContextDarwin_arm_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
- RegisterContextDarwin_arm (thread, 0)
+ RegisterContextDarwin_arm (thread, 0)
{
SetRegisterDataFrom_LC_THREAD (data);
}
-
+
virtual void
InvalidateAllRegisters ()
{
// Do nothing... registers are always valid...
}
-
+
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
- int flavor = data.GetU32 (&offset);
- uint32_t count = data.GetU32 (&offset);
- switch (flavor)
- {
- case GPRRegSet:
- for (uint32_t i=0; i<count; ++i)
- gpr.r[i] = data.GetU32(&offset);
- SetError (GPRRegSet, Read, 0);
- break;
- case FPURegSet:
- // TODO: fill in FPU regs....
- //SetError (FPURegSet, Read, -1);
- break;
- case EXCRegSet:
- exc.exception = data.GetU32(&offset);
- exc.fsr = data.GetU32(&offset);
- exc.far = data.GetU32(&offset);
- SetError (EXCRegSet, Read, 0);
- break;
+ bool done = false;
+
+ while (!done)
+ {
+ int flavor = data.GetU32 (&offset);
+ uint32_t count = data.GetU32 (&offset);
+ lldb::offset_t next_thread_state = offset + (count * 4);
+ switch (flavor)
+ {
+ case GPRRegSet:
+ for (uint32_t i=0; i<count; ++i)
+ {
+ gpr.r[i] = data.GetU32(&offset);
+ }
+
+ // Note that gpr.cpsr is also copied by the above loop; this loop technically extends
+ // one element past the end of the gpr.r[] array.
+
+ SetError (GPRRegSet, Read, 0);
+ offset = next_thread_state;
+ break;
+
+ case FPURegSet:
+ {
+ uint8_t *fpu_reg_buf = (uint8_t*) &fpu.floats.s[0];
+ const int fpu_reg_buf_size = sizeof (fpu.floats);
+ if (data.ExtractBytes (offset, fpu_reg_buf_size, eByteOrderLittle, fpu_reg_buf) == fpu_reg_buf_size)
+ {
+ offset += fpu_reg_buf_size;
+ fpu.fpscr = data.GetU32(&offset);
+ SetError (FPURegSet, Read, 0);
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ offset = next_thread_state;
+ break;
+
+ case EXCRegSet:
+ if (count == 3)
+ {
+ exc.exception = data.GetU32(&offset);
+ exc.fsr = data.GetU32(&offset);
+ exc.far = data.GetU32(&offset);
+ SetError (EXCRegSet, Read, 0);
+ }
+ done = true;
+ offset = next_thread_state;
+ break;
+
+ // Unknown register set flavor, stop trying to parse.
+ default:
+ done = true;
+ }
}
}
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
- return 0;
+ return -1;
}
-
+
virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
- return 0;
+ return -1;
}
-
+
virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
- return 0;
+ return -1;
}
-
+
+ virtual int
+ DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
+ {
+ return -1;
+ }
+
virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return 0;
}
-
+
virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return 0;
}
-
+
virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return 0;
}
+
+ virtual int
+ DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
+ {
+ return -1;
+ }
};
+static uint32_t
+MachHeaderSizeFromMagic(uint32_t magic)
+{
+ switch (magic)
+ {
+ case HeaderMagic32:
+ case HeaderMagic32Swapped:
+ return sizeof(struct mach_header);
+
+ case HeaderMagic64:
+ case HeaderMagic64Swapped:
+ return sizeof(struct mach_header_64);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
#define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008
void
@@ -342,7 +425,8 @@ ObjectFileMachO::Initialize()
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance,
- CreateMemoryInstance);
+ CreateMemoryInstance,
+ GetModuleSpecifications);
}
void
@@ -352,10 +436,11 @@ ObjectFileMachO::Terminate()
}
-const char *
+lldb_private::ConstString
ObjectFileMachO::GetPluginNameStatic()
{
- return "object-file.mach-o";
+ static ConstString g_name("mach-o");
+ return g_name;
}
const char *
@@ -364,13 +449,29 @@ ObjectFileMachO::GetPluginDescriptionSta
return "Mach-o object file reader (32 and 64 bit)";
}
-
ObjectFile *
-ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFileMachO::CreateInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length)
{
- if (ObjectFileMachO::MagicBytesMatch(data_sp, offset, length))
+ if (!data_sp)
+ {
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_offset = 0;
+ }
+
+ if (ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length))
{
- std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, file, offset, length));
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length)
+ {
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_offset = 0;
+ }
+ std::unique_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, data_offset, file, file_offset, length));
if (objfile_ap.get() && objfile_ap->ParseHeader())
return objfile_ap.release();
}
@@ -378,21 +479,62 @@ ObjectFileMachO::CreateInstance (const l
}
ObjectFile *
-ObjectFileMachO::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- const ProcessSP &process_sp,
+ObjectFileMachO::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ const ProcessSP &process_sp,
lldb::addr_t header_addr)
{
if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
{
- std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, process_sp, header_addr));
+ std::unique_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, process_sp, header_addr));
if (objfile_ap.get() && objfile_ap->ParseHeader())
return objfile_ap.release();
}
- return NULL;
+ return NULL;
+}
+
+size_t
+ObjectFileMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ const size_t initial_count = specs.GetSize();
+
+ if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
+ {
+ DataExtractor data;
+ data.SetData(data_sp);
+ llvm::MachO::mach_header header;
+ if (ParseHeader (data, &data_offset, header))
+ {
+ if (header.sizeofcmds >= data_sp->GetByteSize())
+ {
+ data_sp = file.ReadFileContents(file_offset, header.sizeofcmds);
+ data_offset = MachHeaderSizeFromMagic(header.magic) + file_offset;
+ }
+ if (data_sp)
+ {
+ ModuleSpec spec;
+ spec.GetFileSpec() = file;
+ spec.GetArchitecture().SetArchitecture(eArchTypeMachO,
+ header.cputype,
+ header.cpusubtype);
+ if (spec.GetArchitecture().IsValid())
+ {
+ GetUUID (header, data, data_offset, spec.GetUUID());
+ specs.Append(spec);
+ }
+ }
+ }
+ }
+ return specs.GetSize() - initial_count;
}
+
const ConstString &
ObjectFileMachO::GetSegmentNameTEXT()
{
@@ -428,46 +570,26 @@ ObjectFileMachO::GetSectionNameEHFrame()
return g_section_name_eh_frame;
}
-
-
-static uint32_t
-MachHeaderSizeFromMagic(uint32_t magic)
-{
- switch (magic)
- {
- case HeaderMagic32:
- case HeaderMagic32Swapped:
- return sizeof(struct mach_header);
-
- case HeaderMagic64:
- case HeaderMagic64Swapped:
- return sizeof(struct mach_header_64);
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-
bool
-ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp,
- lldb::addr_t data_offset,
+ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp,
+ lldb::addr_t data_offset,
lldb::addr_t data_length)
{
DataExtractor data;
data.SetData (data_sp, data_offset, data_length);
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
uint32_t magic = data.GetU32(&offset);
return MachHeaderSizeFromMagic(magic) != 0;
}
-ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length) :
- ObjectFile(module_sp, file, offset, length, data_sp),
- m_sections_ap(),
- m_symtab_ap(),
+ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length) :
+ ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_mach_segments(),
m_mach_sections(),
m_entry_point_address(),
@@ -483,8 +605,6 @@ ObjectFileMachO::ObjectFileMachO (const
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr) :
ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
- m_sections_ap(),
- m_symtab_ap(),
m_mach_segments(),
m_mach_sections(),
m_entry_point_address(),
@@ -499,6 +619,61 @@ ObjectFileMachO::~ObjectFileMachO()
{
}
+bool
+ObjectFileMachO::ParseHeader (DataExtractor &data,
+ lldb::offset_t *data_offset_ptr,
+ llvm::MachO::mach_header &header)
+{
+ data.SetByteOrder (lldb::endian::InlHostByteOrder());
+ // Leave magic in the original byte order
+ header.magic = data.GetU32(data_offset_ptr);
+ bool can_parse = false;
+ bool is_64_bit = false;
+ switch (header.magic)
+ {
+ case HeaderMagic32:
+ data.SetByteOrder (lldb::endian::InlHostByteOrder());
+ data.SetAddressByteSize(4);
+ can_parse = true;
+ break;
+
+ case HeaderMagic64:
+ data.SetByteOrder (lldb::endian::InlHostByteOrder());
+ data.SetAddressByteSize(8);
+ can_parse = true;
+ is_64_bit = true;
+ break;
+
+ case HeaderMagic32Swapped:
+ data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+ data.SetAddressByteSize(4);
+ can_parse = true;
+ break;
+
+ case HeaderMagic64Swapped:
+ data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
+ data.SetAddressByteSize(8);
+ is_64_bit = true;
+ can_parse = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (can_parse)
+ {
+ data.GetU32(data_offset_ptr, &header.cputype, 6);
+ if (is_64_bit)
+ *data_offset_ptr += 4;
+ return true;
+ }
+ else
+ {
+ memset(&header, 0, sizeof(header));
+ }
+ return false;
+}
bool
ObjectFileMachO::ParseHeader ()
@@ -508,7 +683,7 @@ ObjectFileMachO::ParseHeader ()
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
bool can_parse = false;
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
m_data.SetByteOrder (lldb::endian::InlHostByteOrder());
// Leave magic in the original byte order
m_header.magic = m_data.GetU32(&offset);
@@ -547,7 +722,12 @@ ObjectFileMachO::ParseHeader ()
m_data.GetU32(&offset, &m_header.cputype, 6);
ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
-
+
+ // Check if the module has a required architecture
+ const ArchSpec &module_arch = module_sp->GetArchitecture();
+ if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
+ return false;
+
if (SetModulesArchitecture (mach_arch))
{
const size_t header_and_lc_size = m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic);
@@ -557,12 +737,12 @@ ObjectFileMachO::ParseHeader ()
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
- data_sp = ReadMemory (process_sp, m_offset, header_and_lc_size);
+ data_sp = ReadMemory (process_sp, m_memory_addr, header_and_lc_size);
}
else
{
// Read in all only the load command data from the file on disk
- data_sp = m_file.ReadFileContents(m_offset, header_and_lc_size);
+ data_sp = m_file.ReadFileContents(m_file_offset, header_and_lc_size);
if (data_sp->GetByteSize() != header_and_lc_size)
return false;
}
@@ -593,7 +773,7 @@ ObjectFileMachO::IsExecutable() const
return m_header.filetype == HeaderFileTypeExecutable;
}
-size_t
+uint32_t
ObjectFileMachO::GetAddressByteSize () const
{
return m_data.GetAddressByteSize ();
@@ -662,15 +842,16 @@ ObjectFileMachO::GetAddressClass (lldb::
}
}
}
-
+
const SymbolType symbol_type = symbol->GetType();
switch (symbol_type)
{
case eSymbolTypeAny: return eAddressClassUnknown;
case eSymbolTypeAbsolute: return eAddressClassUnknown;
-
+
case eSymbolTypeCode:
case eSymbolTypeTrampoline:
+ case eSymbolTypeResolver:
if (m_header.cputype == llvm::MachO::CPUTypeARM)
{
// For ARM we have a bit in the n_desc field of the symbol
@@ -750,7 +931,7 @@ ObjectFileMachO::ParseSections ()
{
lldb::user_id_t segID = 0;
lldb::user_id_t sectID = 0;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
const bool is_core = GetType() == eTypeCoreFile;
//bool dump_sections = false;
@@ -761,10 +942,10 @@ ObjectFileMachO::ParseSections ()
encryption_info_command encryption_cmd;
for (i=0; i<m_header.ncmds; ++i)
{
- const uint32_t load_cmd_offset = offset;
+ const lldb::offset_t load_cmd_offset = offset;
if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL)
break;
-
+
if (encryption_cmd.cmd == LoadCommandEncryptionInfo)
{
if (m_data.GetU32(&offset, &encryption_cmd.cryptoff, 3))
@@ -786,7 +967,7 @@ ObjectFileMachO::ParseSections ()
struct segment_command_64 load_cmd;
for (i=0; i<m_header.ncmds; ++i)
{
- const uint32_t load_cmd_offset = offset;
+ const lldb::offset_t load_cmd_offset = offset;
if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
@@ -798,16 +979,54 @@ ObjectFileMachO::ParseSections ()
load_cmd.vmsize = m_data.GetAddress(&offset);
load_cmd.fileoff = m_data.GetAddress(&offset);
load_cmd.filesize = m_data.GetAddress(&offset);
- if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+ if (m_length != 0 && load_cmd.filesize != 0)
{
+ if (load_cmd.fileoff > m_length)
+ {
+ // We have a load command that says it extends past the end of hte file. This is likely
+ // a corrupt file. We don't have any way to return an error condition here (this method
+ // was likely invokved from something like ObjectFile::GetSectionList()) -- all we can do
+ // is null out the SectionList vector and if a process has been set up, dump a message
+ // to stdout. The most common case here is core file debugging with a truncated file.
+ const char *lc_segment_name = load_cmd.cmd == LoadCommandSegment64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+ GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 ")",
+ i,
+ lc_segment_name,
+ load_cmd.fileoff,
+ m_length);
+
+ load_cmd.fileoff = 0;
+ load_cmd.filesize = 0;
+ }
+ if (load_cmd.fileoff + load_cmd.filesize > m_length)
+ {
+ // We have a load command that says it extends past the end of hte file. This is likely
+ // a corrupt file. We don't have any way to return an error condition here (this method
+ // was likely invokved from something like ObjectFile::GetSectionList()) -- all we can do
+ // is null out the SectionList vector and if a process has been set up, dump a message
+ // to stdout. The most common case here is core file debugging with a truncated file.
+ const char *lc_segment_name = load_cmd.cmd == LoadCommandSegment64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+ GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff + filesize (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 "), the segment will be truncated",
+ i,
+ lc_segment_name,
+ load_cmd.fileoff + load_cmd.filesize,
+ m_length);
+
+ // Tuncase the length
+ load_cmd.filesize = m_length - load_cmd.fileoff;
+ }
+ }
+ if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+ {
+
const bool segment_is_encrypted = (load_cmd.flags & SegmentCommandFlagBitProtectedVersion1) != 0;
// Keep a list of mach segments around in case we need to
// get at data that isn't stored in the abstracted Sections.
m_mach_segments.push_back (load_cmd);
- ConstString segment_name (load_cmd.segname, std::min<int>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
+ ConstString segment_name (load_cmd.segname, std::min<size_t>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
// Use a segment ID of the segment index shifted left by 8 so they
// never conflict with any of the sections.
SectionSP segment_sp;
@@ -830,7 +1049,7 @@ ObjectFileMachO::ParseSections ()
struct section_64 sect64;
::memset (§64, 0, sizeof(sect64));
// Push a section into our mach sections for the section at
- // index zero (NListSectionNoSection) if we don't have any
+ // index zero (NListSectionNoSection) if we don't have any
// mach sections yet...
if (m_mach_sections.empty())
m_mach_sections.push_back(sect64);
@@ -1011,11 +1230,11 @@ ObjectFileMachO::ParseSections ()
// TODO: categorize sections by other flags for regular sections
case SectionTypeRegular:
if (segment_sp->GetName() == g_sect_name_TEXT)
- sect_type = eSectionTypeCode;
+ sect_type = eSectionTypeCode;
else if (segment_sp->GetName() == g_sect_name_DATA)
- sect_type = eSectionTypeData;
+ sect_type = eSectionTypeData;
else
- sect_type = eSectionTypeOther;
+ sect_type = eSectionTypeOther;
break;
case SectionTypeZeroFill: sect_type = eSectionTypeZeroFill; break;
case SectionTypeCStringLiterals: sect_type = eSectionTypeDataCString; break; // section with only literal C strings
@@ -1048,7 +1267,7 @@ ObjectFileMachO::ParseSections ()
sect64.offset == 0 ? 0 : sect64.size,
sect64.flags));
// Set the section to be encrypted to match the segment
-
+
bool section_is_encrypted = false;
if (!segment_is_encrypted && load_cmd.filesize != 0)
section_is_encrypted = encrypted_file_ranges.FindEntryThatContains(sect64.offset) != NULL;
@@ -1190,14 +1409,14 @@ ObjectFileMachO::ParseSymtab (bool minim
struct linkedit_data_command function_starts_load_command = { 0, 0, 0, 0 };
typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;
FunctionStarts function_starts;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
for (i=0; i<m_header.ncmds; ++i)
{
- const uint32_t cmd_offset = offset;
+ const lldb::offset_t cmd_offset = offset;
// Read in the load command and load command size
struct load_command lc;
if (m_data.GetU32(&offset, &lc, 2) == NULL)
@@ -1214,28 +1433,28 @@ ObjectFileMachO::ParseSymtab (bool minim
if (symtab_load_command.symoff == 0)
{
if (log)
- module_sp->LogMessage(log.get(), "LC_SYMTAB.symoff == 0");
+ module_sp->LogMessage(log, "LC_SYMTAB.symoff == 0");
return 0;
}
if (symtab_load_command.stroff == 0)
{
if (log)
- module_sp->LogMessage(log.get(), "LC_SYMTAB.stroff == 0");
+ module_sp->LogMessage(log, "LC_SYMTAB.stroff == 0");
return 0;
}
-
+
if (symtab_load_command.nsyms == 0)
{
if (log)
- module_sp->LogMessage(log.get(), "LC_SYMTAB.nsyms == 0");
+ module_sp->LogMessage(log, "LC_SYMTAB.nsyms == 0");
return 0;
}
-
+
if (symtab_load_command.strsize == 0)
{
if (log)
- module_sp->LogMessage(log.get(), "LC_SYMTAB.strsize == 0");
+ module_sp->LogMessage(log, "LC_SYMTAB.strsize == 0");
return 0;
}
break;
@@ -1263,14 +1482,16 @@ ObjectFileMachO::ParseSymtab (bool minim
ProcessSP process_sp (m_process_wp.lock());
Process *process = process_sp.get();
- const size_t addr_byte_size = m_data.GetAddressByteSize();
+ const uint32_t addr_byte_size = m_data.GetAddressByteSize();
+ const ByteOrder byte_order = m_data.GetByteOrder();
bool bit_width_32 = addr_byte_size == 4;
const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
- DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
- DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
- DataExtractor function_starts_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
-
+ DataExtractor nlist_data (NULL, 0, byte_order, addr_byte_size);
+ DataExtractor strtab_data (NULL, 0, byte_order, addr_byte_size);
+ DataExtractor function_starts_data (NULL, 0, byte_order, addr_byte_size);
+ DataExtractor indirect_symbol_index_data (NULL, 0, byte_order, addr_byte_size);
+
const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size;
const addr_t strtab_data_byte_size = symtab_load_command.strsize;
addr_t strtab_addr = LLDB_INVALID_ADDRESS;
@@ -1306,8 +1527,21 @@ ObjectFileMachO::ParseSymtab (bool minim
// symbol and string table. Reading all of this symbol and string table
// data across can slow down debug launch times, so we optimize this by
// reading the memory for the __LINKEDIT section from this process.
+
+ UUID lldb_shared_cache(GetLLDBSharedCacheUUID());
+ UUID process_shared_cache(GetProcessSharedCacheUUID(process));
+ bool use_lldb_cache = true;
+ if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() && lldb_shared_cache != process_shared_cache)
+ {
+ use_lldb_cache = false;
+ ModuleSP module_sp (GetModule());
+ if (module_sp)
+ module_sp->ReportWarning ("shared cache in process does not match lldb's own shared cache, startup will be slow.");
+
+ }
+
PlatformSP platform_sp (target.GetPlatform());
- if (platform_sp && platform_sp->IsHost())
+ if (platform_sp && platform_sp->IsHost() && use_lldb_cache)
{
data_was_read = true;
nlist_data.SetData((void *)symoff_addr, nlist_data_byte_size, eByteOrderLittle);
@@ -1329,6 +1563,13 @@ ObjectFileMachO::ParseSymtab (bool minim
//DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr, strtab_data_byte_size));
//if (strtab_data_sp)
// strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+ if (m_dysymtab.nindirectsyms != 0)
+ {
+ const addr_t indirect_syms_addr = linkedit_load_addr + m_dysymtab.indirectsymoff - linkedit_file_offset;
+ DataBufferSP indirect_syms_data_sp (ReadMemory (process_sp, indirect_syms_addr, m_dysymtab.nindirectsyms * 4));
+ if (indirect_syms_data_sp)
+ indirect_symbol_index_data.SetData (indirect_syms_data_sp, 0, indirect_syms_data_sp->GetByteSize());
+ }
if (function_starts_load_command.cmd)
{
const addr_t func_start_addr = linkedit_load_addr + function_starts_load_command.dataoff - linkedit_file_offset;
@@ -1341,12 +1582,18 @@ ObjectFileMachO::ParseSymtab (bool minim
}
else
{
- nlist_data.SetData (m_data,
- symtab_load_command.symoff,
+ nlist_data.SetData (m_data,
+ symtab_load_command.symoff,
nlist_data_byte_size);
strtab_data.SetData (m_data,
- symtab_load_command.stroff,
+ symtab_load_command.stroff,
strtab_data_byte_size);
+ if (m_dysymtab.nindirectsyms != 0)
+ {
+ indirect_symbol_index_data.SetData (m_data,
+ m_dysymtab.indirectsymoff,
+ m_dysymtab.nindirectsyms * 4);
+ }
if (function_starts_load_command.cmd)
{
function_starts_data.SetData (m_data,
@@ -1358,7 +1605,7 @@ ObjectFileMachO::ParseSymtab (bool minim
if (nlist_data.GetByteSize() == 0)
{
if (log)
- module_sp->LogMessage(log.get(), "failed to read nlist data");
+ module_sp->LogMessage(log, "failed to read nlist data");
return 0;
}
@@ -1371,14 +1618,14 @@ ObjectFileMachO::ParseSymtab (bool minim
if (strtab_addr == LLDB_INVALID_ADDRESS)
{
if (log)
- module_sp->LogMessage(log.get(), "failed to locate the strtab in memory");
+ module_sp->LogMessage(log, "failed to locate the strtab in memory");
return 0;
}
}
else
{
if (log)
- module_sp->LogMessage(log.get(), "failed to read strtab data");
+ module_sp->LogMessage(log, "failed to read strtab data");
return 0;
}
}
@@ -1397,11 +1644,22 @@ ObjectFileMachO::ParseSymtab (bool minim
eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
const bool is_arm = (m_header.cputype == llvm::MachO::CPUTypeARM);
+
+ // lldb works best if it knows the start addresss of all functions in a module.
+ // Linker symbols or debug info are normally the best source of information for start addr / size but
+ // they may be stripped in a released binary.
+ // Two additional sources of information exist in Mach-O binaries:
+ // LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each function's start address in the
+ // binary, relative to the text section.
+ // eh_frame - the eh_frame FDEs have the start addr & size of each function
+ // LC_FUNCTION_STARTS is the fastest source to read in, and is present on all modern binaries.
+ // Binaries built to run on older releases may need to use eh_frame information.
+
if (text_section_sp && function_starts_data.GetByteSize())
{
FunctionStarts::Entry function_start_entry;
function_start_entry.data = false;
- uint32_t function_start_offset = 0;
+ lldb::offset_t function_start_offset = 0;
function_start_entry.addr = text_section_sp->GetFileAddress();
uint64_t delta;
while ((delta = function_starts_data.GetULEB128(&function_start_offset)) > 0)
@@ -1411,12 +1669,37 @@ ObjectFileMachO::ParseSymtab (bool minim
function_starts.Append(function_start_entry);
}
}
-
- const uint32_t function_starts_count = function_starts.GetSize();
+ else
+ {
+ // If m_type is eTypeDebugInfo, then this is a dSYM - it will have the load command claiming an eh_frame
+ // but it doesn't actually have the eh_frame content. And if we have a dSYM, we don't need to do any
+ // of this fill-in-the-missing-symbols works anyway - the debug info should give us all the functions in
+ // the module.
+ if (text_section_sp.get() && eh_frame_section_sp.get() && m_type != eTypeDebugInfo)
+ {
+ DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp, eRegisterKindGCC, true);
+ DWARFCallFrameInfo::FunctionAddressAndSizeVector functions;
+ eh_frame.GetFunctionAddressAndSizeVector (functions);
+ addr_t text_base_addr = text_section_sp->GetFileAddress();
+ size_t count = functions.GetSize();
+ for (size_t i = 0; i < count; ++i)
+ {
+ const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func = functions.GetEntryAtIndex (i);
+ if (func)
+ {
+ FunctionStarts::Entry function_start_entry;
+ function_start_entry.addr = func->base - text_base_addr;
+ function_starts.Append(function_start_entry);
+ }
+ }
+ }
+ }
- uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
+ const size_t function_starts_count = function_starts.GetSize();
- uint32_t nlist_data_offset = 0;
+ const user_id_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
+
+ lldb::offset_t nlist_data_offset = 0;
uint32_t N_SO_index = UINT32_MAX;
@@ -1428,8 +1711,10 @@ ObjectFileMachO::ParseSymtab (bool minim
std::vector<uint32_t> N_COMM_indexes;
typedef std::map <uint64_t, uint32_t> ValueToSymbolIndexMap;
typedef std::map <uint32_t, uint32_t> NListIndexToSymbolIndexMap;
+ typedef std::map <const char *, uint32_t> ConstNameToSymbolIndexMap;
ValueToSymbolIndexMap N_FUN_addr_to_sym_idx;
ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx;
+ ConstNameToSymbolIndexMap N_GSYM_name_to_sym_idx;
// Any symbols that get merged into another will get an entry
// in this map so we know
NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx;
@@ -1438,7 +1723,7 @@ ObjectFileMachO::ParseSymtab (bool minim
uint32_t sym_idx = 0;
Symbol *sym = NULL;
- uint32_t num_syms = 0;
+ size_t num_syms = 0;
std::string memory_symbol_name;
uint32_t unmapped_local_symbols_found = 0;
@@ -1456,59 +1741,75 @@ ObjectFileMachO::ParseSymtab (bool minim
// Before we can start mapping the DSC, we need to make certain the target process is actually
// using the cache we can find.
- /*
- * TODO (FIXME!)
- *
- * Consider the case of testing with a separate DSC file.
- * If we go through the normal code paths, we will give symbols for the wrong DSC, and
- * that is bad. We need to read the target process' all_image_infos struct, and look
- * at the values of the processDetachedFromSharedRegion field. If that is set, we should skip
- * this code section.
- */
-
// Next we need to determine the correct path for the dyld shared cache.
ArchSpec header_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
char dsc_path[PATH_MAX];
snprintf(dsc_path, sizeof(dsc_path), "%s%s%s",
- "/System/Library/Caches/com.apple.dyld/", /* IPHONE_DYLD_SHARED_CACHE_DIR */
- "dyld_shared_cache_", /* DYLD_SHARED_CACHE_BASE_NAME */
+ "/System/Library/Caches/com.apple.dyld/", /* IPHONE_DYLD_SHARED_CACHE_DIR */
+ "dyld_shared_cache_", /* DYLD_SHARED_CACHE_BASE_NAME */
header_arch.GetArchitectureName());
FileSpec dsc_filespec(dsc_path, false);
// We need definitions of two structures in the on-disk DSC, copy them here manually
-struct lldb_copy_dyld_cache_header
-{
- char magic[16];
- uint32_t mappingOffset;
- uint32_t mappingCount;
- uint32_t imagesOffset;
- uint32_t imagesCount;
- uint64_t dyldBaseAddress;
- uint64_t codeSignatureOffset;
- uint64_t codeSignatureSize;
- uint64_t slideInfoOffset;
- uint64_t slideInfoSize;
- uint64_t localSymbolsOffset;
- uint64_t localSymbolsSize;
-};
-struct lldb_copy_dyld_cache_local_symbols_info
-{
- uint32_t nlistOffset;
- uint32_t nlistCount;
- uint32_t stringsOffset;
- uint32_t stringsSize;
- uint32_t entriesOffset;
- uint32_t entriesCount;
-};
-struct lldb_copy_dyld_cache_local_symbols_entry
-{
- uint32_t dylibOffset;
- uint32_t nlistStartIndex;
- uint32_t nlistCount;
-};
+ struct lldb_copy_dyld_cache_header_v0
+ {
+ char magic[16]; // e.g. "dyld_v0 i386", "dyld_v1 armv7", etc.
+ uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info
+ uint32_t mappingCount; // number of dyld_cache_mapping_info entries
+ uint32_t imagesOffset;
+ uint32_t imagesCount;
+ uint64_t dyldBaseAddress;
+ uint64_t codeSignatureOffset;
+ uint64_t codeSignatureSize;
+ uint64_t slideInfoOffset;
+ uint64_t slideInfoSize;
+ uint64_t localSymbolsOffset; // file offset of where local symbols are stored
+ uint64_t localSymbolsSize; // size of local symbols information
+ };
+ struct lldb_copy_dyld_cache_header_v1
+ {
+ char magic[16]; // e.g. "dyld_v0 i386", "dyld_v1 armv7", etc.
+ uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info
+ uint32_t mappingCount; // number of dyld_cache_mapping_info entries
+ uint32_t imagesOffset;
+ uint32_t imagesCount;
+ uint64_t dyldBaseAddress;
+ uint64_t codeSignatureOffset;
+ uint64_t codeSignatureSize;
+ uint64_t slideInfoOffset;
+ uint64_t slideInfoSize;
+ uint64_t localSymbolsOffset;
+ uint64_t localSymbolsSize;
+ uint8_t uuid[16]; // v1 and above, also recorded in dyld_all_image_infos v13 and later
+ };
+
+ struct lldb_copy_dyld_cache_mapping_info
+ {
+ uint64_t address;
+ uint64_t size;
+ uint64_t fileOffset;
+ uint32_t maxProt;
+ uint32_t initProt;
+ };
+
+ struct lldb_copy_dyld_cache_local_symbols_info
+ {
+ uint32_t nlistOffset;
+ uint32_t nlistCount;
+ uint32_t stringsOffset;
+ uint32_t stringsSize;
+ uint32_t entriesOffset;
+ uint32_t entriesCount;
+ };
+ struct lldb_copy_dyld_cache_local_symbols_entry
+ {
+ uint32_t dylibOffset;
+ uint32_t nlistStartIndex;
+ uint32_t nlistCount;
+ };
/* The dyld_cache_header has a pointer to the dyld_cache_local_symbols_info structure (localSymbolsOffset).
The dyld_cache_local_symbols_info structure gives us three things:
@@ -1518,7 +1819,7 @@ struct lldb_copy_dyld_cache_local_symbol
There is one dyld_cache_local_symbols_entry per dylib/framework in the dyld shared cache.
The "dylibOffset" field is the Mach-O header of this dylib/framework in the dyld shared cache.
- The dyld_cache_local_symbols_entry also lists the start of this dylib/framework's nlist records
+ The dyld_cache_local_symbols_entry also lists the start of this dylib/framework's nlist records
and the count of how many nlist records there are for this dylib/framework.
*/
@@ -1526,28 +1827,81 @@ struct lldb_copy_dyld_cache_local_symbol
//
// Save some VM space, do not map the entire cache in one shot.
- if (DataBufferSP dsc_data_sp = dsc_filespec.MemoryMapFileContents(0, sizeof(struct lldb_copy_dyld_cache_header)))
+ DataBufferSP dsc_data_sp;
+ dsc_data_sp = dsc_filespec.MemoryMapFileContents(0, sizeof(struct lldb_copy_dyld_cache_header_v1));
+
+ if (dsc_data_sp)
{
- DataExtractor dsc_header_data(dsc_data_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+ DataExtractor dsc_header_data(dsc_data_sp, byte_order, addr_byte_size);
+
+ char version_str[17];
+ int version = -1;
+ lldb::offset_t offset = 0;
+ memcpy (version_str, dsc_header_data.GetData (&offset, 16), 16);
+ version_str[16] = '\0';
+ if (strncmp (version_str, "dyld_v", 6) == 0 && isdigit (version_str[6]))
+ {
+ int v;
+ if (::sscanf (version_str + 6, "%d", &v) == 1)
+ {
+ version = v;
+ }
+ }
+
+ UUID dsc_uuid;
+ if (version >= 1)
+ {
+ offset = offsetof (struct lldb_copy_dyld_cache_header_v1, uuid);
+ uint8_t uuid_bytes[sizeof (uuid_t)];
+ memcpy (uuid_bytes, dsc_header_data.GetData (&offset, sizeof (uuid_t)), sizeof (uuid_t));
+ dsc_uuid.SetBytes (uuid_bytes);
+ }
+
+ bool uuid_match = true;
+ if (dsc_uuid.IsValid() && process)
+ {
+ UUID shared_cache_uuid(GetProcessSharedCacheUUID(process));
+
+ if (shared_cache_uuid.IsValid() && dsc_uuid != shared_cache_uuid)
+ {
+ // The on-disk dyld_shared_cache file is not the same as the one in this
+ // process' memory, don't use it.
+ uuid_match = false;
+ ModuleSP module_sp (GetModule());
+ if (module_sp)
+ module_sp->ReportWarning ("process shared cache does not match on-disk dyld_shared_cache file, some symbol names will be missing.");
+ }
+ }
+
+ offset = offsetof (struct lldb_copy_dyld_cache_header_v1, mappingOffset);
- uint32_t offset = offsetof (struct lldb_copy_dyld_cache_header, mappingOffset);
uint32_t mappingOffset = dsc_header_data.GetU32(&offset);
// If the mappingOffset points to a location inside the header, we've
// opened an old dyld shared cache, and should not proceed further.
- if (mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header))
+ if (uuid_match && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0))
{
- offset = offsetof (struct lldb_copy_dyld_cache_header, localSymbolsOffset);
+ DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContents(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info));
+ DataExtractor dsc_mapping_info_data(dsc_mapping_info_data_sp, byte_order, addr_byte_size);
+ offset = 0;
+
+ // The File addresses (from the in-memory Mach-O load commands) for the shared libraries
+ // in the shared library cache need to be adjusted by an offset to match up with the
+ // dylibOffset identifying field in the dyld_cache_local_symbol_entry's. This offset is
+ // recorded in mapping_offset_value.
+ const uint64_t mapping_offset_value = dsc_mapping_info_data.GetU64(&offset);
+
+ offset = offsetof (struct lldb_copy_dyld_cache_header_v1, localSymbolsOffset);
uint64_t localSymbolsOffset = dsc_header_data.GetU64(&offset);
uint64_t localSymbolsSize = dsc_header_data.GetU64(&offset);
- if (localSymbolsOffset && localSymbolsSize)
+ if (localSymbolsOffset && localSymbolsSize)
{
// Map the local symbols
- if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContents(localSymbolsOffset, localSymbolsSize))
+ if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContents(localSymbolsOffset, localSymbolsSize))
{
- DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
+ DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, byte_order, addr_byte_size);
offset = 0;
@@ -1555,14 +1909,9 @@ struct lldb_copy_dyld_cache_local_symbol
struct lldb_copy_dyld_cache_local_symbols_info local_symbols_info;
dsc_local_symbols_data.GetU32(&offset, &local_symbols_info.nlistOffset, 6);
- // The local_symbols_infos offsets are offsets into local symbols memory, NOT file offsets!
- // We first need to identify the local "entry" that matches the current header.
- // The "entry" is stored as a file offset in the dyld_shared_cache, so we need to
- // adjust the raw m_header value by slide and 0x30000000.
-
SectionSP text_section_sp(section_list->FindSectionByName(GetSegmentNameTEXT()));
- uint32_t header_file_offset = (text_section_sp->GetFileAddress() - 0x30000000);
+ uint32_t header_file_offset = (text_section_sp->GetFileAddress() - mapping_offset_value);
offset = local_symbols_info.entriesOffset;
for (uint32_t entry_index = 0; entry_index < local_symbols_info.entriesCount; entry_index++)
@@ -1572,7 +1921,7 @@ struct lldb_copy_dyld_cache_local_symbol
local_symbols_entry.nlistStartIndex = dsc_local_symbols_data.GetU32(&offset);
local_symbols_entry.nlistCount = dsc_local_symbols_data.GetU32(&offset);
- if (header_file_offset == local_symbols_entry.dylibOffset)
+ if (header_file_offset == local_symbols_entry.dylibOffset)
{
unmapped_local_symbols_found = local_symbols_entry.nlistCount;
@@ -1583,7 +1932,7 @@ struct lldb_copy_dyld_cache_local_symbol
nlist_data_offset = local_symbols_info.nlistOffset + (nlist_byte_size * local_symbols_entry.nlistStartIndex);
uint32_t string_table_offset = local_symbols_info.stringsOffset;
- for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++)
+ for (uint32_t nlist_index = 0; nlist_index < local_symbols_entry.nlistCount; nlist_index++)
{
/////////////////////////////
{
@@ -1606,11 +1955,10 @@ struct lldb_copy_dyld_cache_local_symbol
// string values should have an offset zero which points
// to an empty C-string
Host::SystemLog (Host::eSystemLogError,
- "error: DSC unmapped local symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n",
+ "error: DSC unmapped local symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n",
entry_index,
nlist.n_strx,
- module_sp->GetFileSpec().GetDirectory().GetCString(),
- module_sp->GetFileSpec().GetFilename().GetCString());
+ module_sp->GetFileSpec().GetPath().c_str());
continue;
}
if (symbol_name[0] == '\0')
@@ -1622,6 +1970,8 @@ struct lldb_copy_dyld_cache_local_symbol
uint32_t symbol_byte_size = 0;
bool add_nlist = true;
bool is_debug = ((nlist.n_type & NlistMaskStab) != 0);
+ bool demangled_is_synthesized = false;
+ bool is_gsym = false;
assert (sym_idx < num_syms);
@@ -1649,6 +1999,7 @@ struct lldb_copy_dyld_cache_local_symbol
add_nlist = false;
else
{
+ is_gsym = true;
sym[sym_idx].SetExternal(true);
if (nlist.n_value != 0)
symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -1820,6 +2171,24 @@ struct lldb_copy_dyld_cache_local_symbol
if (so_path && so_path[0])
{
std::string full_so_path (so_path);
+ const size_t double_slash_pos = full_so_path.find("//");
+ if (double_slash_pos != std::string::npos)
+ {
+ // The linker has been generating bad N_SO entries with doubled up paths
+ // in the format "%s%s" where the first stirng in the DW_AT_comp_dir,
+ // and the second is the directory for the source file so you end up with
+ // a path that looks like "/tmp/src//tmp/src/"
+ FileSpec so_dir(so_path, false);
+ if (!so_dir.Exists())
+ {
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1], false);
+ if (so_dir.Exists())
+ {
+ // Trim off the incorrect path
+ full_so_path.erase(0, double_slash_pos + 1);
+ }
+ }
+ }
if (*full_so_path.rbegin() != '/')
full_so_path += '/';
full_so_path += symbol_name;
@@ -1828,8 +2197,12 @@ struct lldb_copy_dyld_cache_local_symbol
m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
}
}
+ else
+ {
+ // This could be a relative path to a N_SO
+ N_SO_index = sym_idx;
+ }
}
-
break;
case StabObjectFileName:
@@ -1994,68 +2367,67 @@ struct lldb_copy_dyld_cache_local_symbol
break;
case NListTypeSection: // N_SECT
- {
- symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
-
- if (symbol_section == NULL)
{
- // TODO: warn about this?
- add_nlist = false;
- break;
- }
+ symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
- if (TEXT_eh_frame_sectID == nlist.n_sect)
- {
- type = eSymbolTypeException;
- }
- else
- {
- uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType;
-
- switch (section_type)
+ if (symbol_section == NULL)
{
- case SectionTypeRegular: break; // regular section
- //case SectionTypeZeroFill: type = eSymbolTypeData; break; // zero fill on demand section
- case SectionTypeCStringLiterals: type = eSymbolTypeData; break; // section with only literal C strings
- case SectionType4ByteLiterals: type = eSymbolTypeData; break; // section with only 4 byte literals
- case SectionType8ByteLiterals: type = eSymbolTypeData; break; // section with only 8 byte literals
- case SectionTypeLiteralPointers: type = eSymbolTypeTrampoline; break; // section with only pointers to literals
- case SectionTypeNonLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
- case SectionTypeLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
- case SectionTypeSymbolStubs: type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
- case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for initialization
- case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for termination
- //case SectionTypeCoalesced: type = eSymbolType; break; // section contains symbols that are to be coalesced
- //case SectionTypeZeroFillLarge: type = eSymbolTypeData; break; // zero fill on demand section (that can be larger than 4 gigabytes)
- case SectionTypeInterposing: type = eSymbolTypeTrampoline; break; // section with only pairs of function pointers for interposing
- case SectionType16ByteLiterals: type = eSymbolTypeData; break; // section with only 16 byte literals
- case SectionTypeDTraceObjectFormat: type = eSymbolTypeInstrumentation; break;
- case SectionTypeLazyDylibSymbolPointers: type = eSymbolTypeTrampoline; break;
- default: break;
+ // TODO: warn about this?
+ add_nlist = false;
+ break;
}
-
- if (type == eSymbolTypeInvalid)
+
+ if (TEXT_eh_frame_sectID == nlist.n_sect)
{
- const char *symbol_sect_name = symbol_section->GetName().AsCString();
- if (symbol_section->IsDescendant (text_section_sp.get()))
+ type = eSymbolTypeException;
+ }
+ else
+ {
+ uint32_t section_type = symbol_section->Get() & SectionFlagMaskSectionType;
+
+ switch (section_type)
{
- if (symbol_section->IsClear(SectionAttrUserPureInstructions |
- SectionAttrUserSelfModifyingCode |
- SectionAttrSytemSomeInstructions))
- type = eSymbolTypeData;
- else
- type = eSymbolTypeCode;
+ case SectionTypeRegular: break; // regular section
+ //case SectionTypeZeroFill: type = eSymbolTypeData; break; // zero fill on demand section
+ case SectionTypeCStringLiterals: type = eSymbolTypeData; break; // section with only literal C strings
+ case SectionType4ByteLiterals: type = eSymbolTypeData; break; // section with only 4 byte literals
+ case SectionType8ByteLiterals: type = eSymbolTypeData; break; // section with only 8 byte literals
+ case SectionTypeLiteralPointers: type = eSymbolTypeTrampoline; break; // section with only pointers to literals
+ case SectionTypeNonLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
+ case SectionTypeLazySymbolPointers: type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
+ case SectionTypeSymbolStubs: type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
+ case SectionTypeModuleInitFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for initialization
+ case SectionTypeModuleTermFunctionPointers: type = eSymbolTypeCode; break; // section with only function pointers for termination
+ //case SectionTypeCoalesced: type = eSymbolType; break; // section contains symbols that are to be coalesced
+ //case SectionTypeZeroFillLarge: type = eSymbolTypeData; break; // zero fill on demand section (that can be larger than 4 gigabytes)
+ case SectionTypeInterposing: type = eSymbolTypeTrampoline; break; // section with only pairs of function pointers for interposing
+ case SectionType16ByteLiterals: type = eSymbolTypeData; break; // section with only 16 byte literals
+ case SectionTypeDTraceObjectFormat: type = eSymbolTypeInstrumentation; break;
+ case SectionTypeLazyDylibSymbolPointers: type = eSymbolTypeTrampoline; break;
+ default: break;
}
- else
- if (symbol_section->IsDescendant(data_section_sp.get()))
+
+ if (type == eSymbolTypeInvalid)
+ {
+ const char *symbol_sect_name = symbol_section->GetName().AsCString();
+ if (symbol_section->IsDescendant (text_section_sp.get()))
+ {
+ if (symbol_section->IsClear(SectionAttrUserPureInstructions |
+ SectionAttrUserSelfModifyingCode |
+ SectionAttrSytemSomeInstructions))
+ type = eSymbolTypeData;
+ else
+ type = eSymbolTypeCode;
+ }
+ else if (symbol_section->IsDescendant(data_section_sp.get()))
{
if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name)
{
type = eSymbolTypeRuntime;
-
- if (symbol_name &&
- symbol_name[0] == '_' &&
- symbol_name[1] == 'O' &&
+
+ if (symbol_name &&
+ symbol_name[0] == '_' &&
+ symbol_name[1] == 'O' &&
symbol_name[2] == 'B')
{
llvm::StringRef symbol_name_ref(symbol_name);
@@ -2067,64 +2439,65 @@ struct lldb_copy_dyld_cache_local_symbol
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_class.size();
type = eSymbolTypeObjCClass;
+ demangled_is_synthesized = true;
}
else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass))
{
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
type = eSymbolTypeObjCMetaClass;
+ demangled_is_synthesized = true;
}
else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar))
{
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
type = eSymbolTypeObjCIVar;
+ demangled_is_synthesized = true;
}
}
}
- else
- if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
- {
- type = eSymbolTypeException;
- }
- else
- {
- type = eSymbolTypeData;
- }
- }
- else
- if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
+ else if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
{
- type = eSymbolTypeTrampoline;
+ type = eSymbolTypeException;
}
else
- if (symbol_section->IsDescendant(objc_section_sp.get()))
+ {
+ type = eSymbolTypeData;
+ }
+ }
+ else if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
+ {
+ type = eSymbolTypeTrampoline;
+ }
+ else if (symbol_section->IsDescendant(objc_section_sp.get()))
+ {
+ type = eSymbolTypeRuntime;
+ if (symbol_name && symbol_name[0] == '.')
+ {
+ llvm::StringRef symbol_name_ref(symbol_name);
+ static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_");
+ if (symbol_name_ref.startswith(g_objc_v1_prefix_class))
{
- type = eSymbolTypeRuntime;
- if (symbol_name && symbol_name[0] == '.')
- {
- llvm::StringRef symbol_name_ref(symbol_name);
- static const llvm::StringRef g_objc_v1_prefix_class (".objc_class_name_");
- if (symbol_name_ref.startswith(g_objc_v1_prefix_class))
- {
- symbol_name_non_abi_mangled = symbol_name;
- symbol_name = symbol_name + g_objc_v1_prefix_class.size();
- type = eSymbolTypeObjCClass;
- }
- }
+ symbol_name_non_abi_mangled = symbol_name;
+ symbol_name = symbol_name + g_objc_v1_prefix_class.size();
+ type = eSymbolTypeObjCClass;
+ demangled_is_synthesized = true;
}
+ }
+ }
+ }
}
}
- }
break;
- }
+ }
}
if (add_nlist)
{
uint64_t symbol_value = nlist.n_value;
bool symbol_name_is_mangled = false;
-
+
if (symbol_name_non_abi_mangled)
{
sym[sym_idx].GetMangled().SetMangledName (ConstString(symbol_name_non_abi_mangled));
@@ -2137,56 +2510,13 @@ struct lldb_copy_dyld_cache_local_symbol
symbol_name_is_mangled = symbol_name[1] == '_';
symbol_name++; // Skip the leading underscore
}
-
+
if (symbol_name)
{
- sym[sym_idx].GetMangled().SetValue(ConstString(symbol_name), symbol_name_is_mangled);
- }
- }
-
- if (is_debug == false)
- {
- if (type == eSymbolTypeCode)
- {
- // See if we can find a N_FUN entry for any code symbols.
- // If we do find a match, and the name matches, then we
- // can merge the two into just the function symbol to avoid
- // duplicate entries in the symbol table
- ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value);
- if (pos != N_FUN_addr_to_sym_idx.end())
- {
- if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
- (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
- {
- m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
- // We just need the flags from the linker symbol, so put these flags
- // into the N_FUN flags to avoid duplicate symbols in the symbol table
- sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
- sym[sym_idx].Clear();
- continue;
- }
- }
- }
- else if (type == eSymbolTypeData)
- {
- // See if we can find a N_STSYM entry for any data symbols.
- // If we do find a match, and the name matches, then we
- // can merge the two into just the Static symbol to avoid
- // duplicate entries in the symbol table
- ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value);
- if (pos != N_STSYM_addr_to_sym_idx.end())
- {
- if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
- (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
- {
- m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
- // We just need the flags from the linker symbol, so put these flags
- // into the N_STSYM flags to avoid duplicate symbols in the symbol table
- sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
- sym[sym_idx].Clear();
- continue;
- }
- }
+ ConstString const_symbol_name(symbol_name);
+ if (is_gsym)
+ N_GSYM_name_to_sym_idx[const_symbol_name.GetCString()] = sym_idx;
+ sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled);
}
}
if (symbol_section)
@@ -2212,7 +2542,7 @@ struct lldb_copy_dyld_cache_local_symbol
if (func_start_entry)
{
func_start_entry->data = true;
-
+
addr_t symbol_file_addr = func_start_entry->addr;
uint32_t symbol_flags = 0;
if (is_arm)
@@ -2221,7 +2551,7 @@ struct lldb_copy_dyld_cache_local_symbol
symbol_flags = MACHO_NLIST_ARM_SYMBOL_IS_THUMB;
symbol_file_addr &= 0xfffffffffffffffeull;
}
-
+
const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
if (next_func_start_entry)
@@ -2233,31 +2563,98 @@ struct lldb_copy_dyld_cache_local_symbol
next_symbol_file_addr &= 0xfffffffffffffffeull;
symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
}
- else
+ else
+ {
+ symbol_byte_size = section_end_file_addr - symbol_file_addr;
+ }
+ }
+ }
+ symbol_value -= section_file_addr;
+ }
+
+ if (is_debug == false)
+ {
+ if (type == eSymbolTypeCode)
+ {
+ // See if we can find a N_FUN entry for any code symbols.
+ // If we do find a match, and the name matches, then we
+ // can merge the two into just the function symbol to avoid
+ // duplicate entries in the symbol table
+ ValueToSymbolIndexMap::const_iterator pos = N_FUN_addr_to_sym_idx.find (nlist.n_value);
+ if (pos != N_FUN_addr_to_sym_idx.end())
+ {
+ if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
+ (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
+ {
+ m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
+ // We just need the flags from the linker symbol, so put these flags
+ // into the N_FUN flags to avoid duplicate symbols in the symbol table
+ sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+ sym[sym_idx].Clear();
+ continue;
+ }
+ }
+ }
+ else if (type == eSymbolTypeData)
+ {
+ // See if we can find a N_STSYM entry for any data symbols.
+ // If we do find a match, and the name matches, then we
+ // can merge the two into just the Static symbol to avoid
+ // duplicate entries in the symbol table
+ ValueToSymbolIndexMap::const_iterator pos = N_STSYM_addr_to_sym_idx.find (nlist.n_value);
+ if (pos != N_STSYM_addr_to_sym_idx.end())
+ {
+ if ((symbol_name_is_mangled == true && sym[sym_idx].GetMangled().GetMangledName() == sym[pos->second].GetMangled().GetMangledName()) ||
+ (symbol_name_is_mangled == false && sym[sym_idx].GetMangled().GetDemangledName() == sym[pos->second].GetMangled().GetDemangledName()))
+ {
+ m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
+ // We just need the flags from the linker symbol, so put these flags
+ // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+ sym[pos->second].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+ sym[sym_idx].Clear();
+ continue;
+ }
+ }
+ else
+ {
+ // Combine N_GSYM stab entries with the non stab symbol
+ ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetMangledName().GetCString());
+ if (pos != N_GSYM_name_to_sym_idx.end())
{
- symbol_byte_size = section_end_file_addr - symbol_file_addr;
+ const uint32_t GSYM_sym_idx = pos->second;
+ m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
+ // Copy the address, because often the N_GSYM address has an invalid address of zero
+ // when the global is a common symbol
+ sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section);
+ sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value);
+ // We just need the flags from the linker symbol, so put these flags
+ // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+ sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+ sym[sym_idx].Clear();
+ continue;
}
}
}
- symbol_value -= section_file_addr;
}
-
+
sym[sym_idx].SetID (nlist_idx);
sym[sym_idx].SetType (type);
sym[sym_idx].GetAddress().SetSection (symbol_section);
sym[sym_idx].GetAddress().SetOffset (symbol_value);
sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
-
+
if (symbol_byte_size > 0)
sym[sym_idx].SetByteSize(symbol_byte_size);
+ if (demangled_is_synthesized)
+ sym[sym_idx].SetDemangledNameIsSynthesized(true);
++sym_idx;
}
else
{
sym[sym_idx].Clear();
}
-
+
}
/////////////////////////////
}
@@ -2307,22 +2704,21 @@ struct lldb_copy_dyld_cache_local_symbol
SymbolType type = eSymbolTypeInvalid;
const char *symbol_name = NULL;
-
+
if (have_strtab_data)
{
symbol_name = strtab_data.PeekCStr(nlist.n_strx);
-
+
if (symbol_name == NULL)
{
// No symbol should be NULL, even the symbols with no
// string values should have an offset zero which points
// to an empty C-string
Host::SystemLog (Host::eSystemLogError,
- "error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n",
+ "error: symbol[%u] has invalid string table offset 0x%x in %s, ignoring symbol\n",
nlist_idx,
nlist.n_strx,
- module_sp->GetFileSpec().GetDirectory().GetCString(),
- module_sp->GetFileSpec().GetFilename().GetCString());
+ module_sp->GetFileSpec().GetPath().c_str());
continue;
}
if (symbol_name[0] == '\0')
@@ -2338,9 +2734,11 @@ struct lldb_copy_dyld_cache_local_symbol
const char *symbol_name_non_abi_mangled = NULL;
SectionSP symbol_section;
- uint32_t symbol_byte_size = 0;
+ lldb::addr_t symbol_byte_size = 0;
bool add_nlist = true;
+ bool is_gsym = false;
bool is_debug = ((nlist.n_type & NlistMaskStab) != 0);
+ bool demangled_is_synthesized = false;
assert (sym_idx < num_syms);
@@ -2350,24 +2748,25 @@ struct lldb_copy_dyld_cache_local_symbol
{
switch (nlist.n_type)
{
- case StabGlobalSymbol:
+ case StabGlobalSymbol:
// N_GSYM -- global symbol: name,,NO_SECT,type,0
// Sometimes the N_GSYM value contains the address.
-
+
// FIXME: In the .o files, we have a GSYM and a debug symbol for all the ObjC data. They
// have the same address, but we want to ensure that we always find only the real symbol,
// 'cause we don't currently correctly attribute the GSYM one to the ObjCClass/Ivar/MetaClass
// symbol type. This is a temporary hack to make sure the ObjectiveC symbols get treated
// correctly. To do this right, we should coalesce all the GSYM & global symbols that have the
// same address.
-
- if (symbol_name && symbol_name[0] == '_' && symbol_name[1] == 'O'
+
+ if (symbol_name && symbol_name[0] == '_' && symbol_name[1] == 'O'
&& (strncmp (symbol_name, "_OBJC_IVAR_$_", strlen ("_OBJC_IVAR_$_")) == 0
|| strncmp (symbol_name, "_OBJC_CLASS_$_", strlen ("_OBJC_CLASS_$_")) == 0
|| strncmp (symbol_name, "_OBJC_METACLASS_$_", strlen ("_OBJC_METACLASS_$_")) == 0))
add_nlist = false;
else
{
+ is_gsym = true;
sym[sym_idx].SetExternal(true);
if (nlist.n_value != 0)
symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -2380,13 +2779,13 @@ struct lldb_copy_dyld_cache_local_symbol
type = eSymbolTypeCompiler;
break;
- case StabFunction:
+ case StabFunction:
// N_FUN -- procedure: name,,n_sect,linenumber,address
if (symbol_name)
{
type = eSymbolTypeCode;
symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
-
+
N_FUN_addr_to_sym_idx[nlist.n_value] = sym_idx;
// We use the current number of symbols in the symbol table in lieu of
// using nlist_idx in case we ever start trimming entries out
@@ -2411,7 +2810,7 @@ struct lldb_copy_dyld_cache_local_symbol
}
break;
- case StabStaticSymbol:
+ case StabStaticSymbol:
// N_STSYM -- static symbol: name,,n_sect,type,address
N_STSYM_addr_to_sym_idx[nlist.n_value] = sym_idx;
symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
@@ -2539,6 +2938,24 @@ struct lldb_copy_dyld_cache_local_symbol
if (so_path && so_path[0])
{
std::string full_so_path (so_path);
+ const size_t double_slash_pos = full_so_path.find("//");
+ if (double_slash_pos != std::string::npos)
+ {
+ // The linker has been generating bad N_SO entries with doubled up paths
+ // in the format "%s%s" where the first stirng in the DW_AT_comp_dir,
+ // and the second is the directory for the source file so you end up with
+ // a path that looks like "/tmp/src//tmp/src/"
+ FileSpec so_dir(so_path, false);
+ if (!so_dir.Exists())
+ {
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1], false);
+ if (so_dir.Exists())
+ {
+ // Trim off the incorrect path
+ full_so_path.erase(0, double_slash_pos + 1);
+ }
+ }
+ }
if (*full_so_path.rbegin() != '/')
full_so_path += '/';
full_so_path += symbol_name;
@@ -2547,8 +2964,13 @@ struct lldb_copy_dyld_cache_local_symbol
m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
}
}
+ else
+ {
+ // This could be a relative path to a N_SO
+ N_SO_index = sym_idx;
+ }
}
-
+
break;
case StabObjectFileName:
@@ -2596,7 +3018,7 @@ struct lldb_copy_dyld_cache_local_symbol
add_nlist = false;
break;
- case StabCompilerParameters:
+ case StabCompilerParameters:
// N_PARAMS - compiler parameters: name,,NO_SECT,0,0
type = eSymbolTypeCompiler;
break;
@@ -2758,8 +3180,8 @@ struct lldb_copy_dyld_cache_local_symbol
const char *symbol_sect_name = symbol_section->GetName().AsCString();
if (symbol_section->IsDescendant (text_section_sp.get()))
{
- if (symbol_section->IsClear(SectionAttrUserPureInstructions |
- SectionAttrUserSelfModifyingCode |
+ if (symbol_section->IsClear(SectionAttrUserPureInstructions |
+ SectionAttrUserSelfModifyingCode |
SectionAttrSytemSomeInstructions))
type = eSymbolTypeData;
else
@@ -2772,9 +3194,9 @@ struct lldb_copy_dyld_cache_local_symbol
{
type = eSymbolTypeRuntime;
- if (symbol_name &&
- symbol_name[0] == '_' &&
- symbol_name[1] == 'O' &&
+ if (symbol_name &&
+ symbol_name[0] == '_' &&
+ symbol_name[1] == 'O' &&
symbol_name[2] == 'B')
{
llvm::StringRef symbol_name_ref(symbol_name);
@@ -2786,18 +3208,21 @@ struct lldb_copy_dyld_cache_local_symbol
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_class.size();
type = eSymbolTypeObjCClass;
+ demangled_is_synthesized = true;
}
else if (symbol_name_ref.startswith(g_objc_v2_prefix_metaclass))
{
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
type = eSymbolTypeObjCMetaClass;
+ demangled_is_synthesized = true;
}
else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar))
{
symbol_name_non_abi_mangled = symbol_name + 1;
symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
type = eSymbolTypeObjCIVar;
+ demangled_is_synthesized = true;
}
}
}
@@ -2829,6 +3254,7 @@ struct lldb_copy_dyld_cache_local_symbol
symbol_name_non_abi_mangled = symbol_name;
symbol_name = symbol_name + g_objc_v1_prefix_class.size();
type = eSymbolTypeObjCClass;
+ demangled_is_synthesized = true;
}
}
}
@@ -2836,7 +3262,7 @@ struct lldb_copy_dyld_cache_local_symbol
}
}
break;
- }
+ }
}
if (add_nlist)
@@ -2859,8 +3285,58 @@ struct lldb_copy_dyld_cache_local_symbol
if (symbol_name)
{
- sym[sym_idx].GetMangled().SetValue(ConstString(symbol_name), symbol_name_is_mangled);
+ ConstString const_symbol_name(symbol_name);
+ if (is_gsym)
+ N_GSYM_name_to_sym_idx[const_symbol_name.GetCString()] = sym_idx;
+ sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled);
+ }
+ }
+ if (symbol_section)
+ {
+ const addr_t section_file_addr = symbol_section->GetFileAddress();
+ if (symbol_byte_size == 0 && function_starts_count > 0)
+ {
+ addr_t symbol_lookup_file_addr = nlist.n_value;
+ // Do an exact address match for non-ARM addresses, else get the closest since
+ // the symbol might be a thumb symbol which has an address with bit zero set
+ FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm);
+ if (is_arm && func_start_entry)
+ {
+ // Verify that the function start address is the symbol address (ARM)
+ // or the symbol address + 1 (thumb)
+ if (func_start_entry->addr != symbol_lookup_file_addr &&
+ func_start_entry->addr != (symbol_lookup_file_addr + 1))
+ {
+ // Not the right entry, NULL it out...
+ func_start_entry = NULL;
+ }
+ }
+ if (func_start_entry)
+ {
+ func_start_entry->data = true;
+
+ addr_t symbol_file_addr = func_start_entry->addr;
+ if (is_arm)
+ symbol_file_addr &= 0xfffffffffffffffeull;
+
+ const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
+ const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
+ if (next_func_start_entry)
+ {
+ addr_t next_symbol_file_addr = next_func_start_entry->addr;
+ // Be sure the clear the Thumb address bit when we calculate the size
+ // from the current and next address
+ if (is_arm)
+ next_symbol_file_addr &= 0xfffffffffffffffeull;
+ symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
+ }
+ else
+ {
+ symbol_byte_size = section_end_file_addr - symbol_file_addr;
+ }
+ }
}
+ symbol_value -= section_file_addr;
}
if (is_debug == false)
@@ -2906,54 +3382,26 @@ struct lldb_copy_dyld_cache_local_symbol
continue;
}
}
- }
- }
- if (symbol_section)
- {
- const addr_t section_file_addr = symbol_section->GetFileAddress();
- if (symbol_byte_size == 0 && function_starts_count > 0)
- {
- addr_t symbol_lookup_file_addr = nlist.n_value;
- // Do an exact address match for non-ARM addresses, else get the closest since
- // the symbol might be a thumb symbol which has an address with bit zero set
- FunctionStarts::Entry *func_start_entry = function_starts.FindEntry (symbol_lookup_file_addr, !is_arm);
- if (is_arm && func_start_entry)
- {
- // Verify that the function start address is the symbol address (ARM)
- // or the symbol address + 1 (thumb)
- if (func_start_entry->addr != symbol_lookup_file_addr &&
- func_start_entry->addr != (symbol_lookup_file_addr + 1))
- {
- // Not the right entry, NULL it out...
- func_start_entry = NULL;
- }
- }
- if (func_start_entry)
+ else
{
- func_start_entry->data = true;
-
- addr_t symbol_file_addr = func_start_entry->addr;
- if (is_arm)
- symbol_file_addr &= 0xfffffffffffffffeull;
-
- const FunctionStarts::Entry *next_func_start_entry = function_starts.FindNextEntry (func_start_entry);
- const addr_t section_end_file_addr = section_file_addr + symbol_section->GetByteSize();
- if (next_func_start_entry)
- {
- addr_t next_symbol_file_addr = next_func_start_entry->addr;
- // Be sure the clear the Thumb address bit when we calculate the size
- // from the current and next address
- if (is_arm)
- next_symbol_file_addr &= 0xfffffffffffffffeull;
- symbol_byte_size = std::min<lldb::addr_t>(next_symbol_file_addr - symbol_file_addr, section_end_file_addr - symbol_file_addr);
- }
- else
+ // Combine N_GSYM stab entries with the non stab symbol
+ ConstNameToSymbolIndexMap::const_iterator pos = N_GSYM_name_to_sym_idx.find(sym[sym_idx].GetMangled().GetMangledName().GetCString());
+ if (pos != N_GSYM_name_to_sym_idx.end())
{
- symbol_byte_size = section_end_file_addr - symbol_file_addr;
+ const uint32_t GSYM_sym_idx = pos->second;
+ m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
+ // Copy the address, because often the N_GSYM address has an invalid address of zero
+ // when the global is a common symbol
+ sym[GSYM_sym_idx].GetAddress().SetSection (symbol_section);
+ sym[GSYM_sym_idx].GetAddress().SetOffset (symbol_value);
+ // We just need the flags from the linker symbol, so put these flags
+ // into the N_STSYM flags to avoid duplicate symbols in the symbol table
+ sym[GSYM_sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
+ sym[sym_idx].Clear();
+ continue;
}
}
}
- symbol_value -= section_file_addr;
}
sym[sym_idx].SetID (nlist_idx);
@@ -2965,6 +3413,9 @@ struct lldb_copy_dyld_cache_local_symbol
if (symbol_byte_size > 0)
sym[sym_idx].SetByteSize(symbol_byte_size);
+ if (demangled_is_synthesized)
+ sym[sym_idx].SetDemangledNameIsSynthesized(true);
+
++sym_idx;
}
else
@@ -3004,7 +3455,7 @@ struct lldb_copy_dyld_cache_local_symbol
}
}
}
-
+
uint32_t synthetic_sym_id = symtab_load_command.nsyms;
if (function_starts_count > 0)
@@ -3016,7 +3467,7 @@ struct lldb_copy_dyld_cache_local_symbol
if (function_starts.GetEntryRef (i).data == false)
++num_synthetic_function_symbols;
}
-
+
if (num_synthetic_function_symbols > 0)
{
if (num_syms < sym_idx + num_synthetic_function_symbols)
@@ -3092,8 +3543,6 @@ struct lldb_copy_dyld_cache_local_symbol
// Now synthesize indirect symbols
if (m_dysymtab.nindirectsyms != 0)
{
- DataExtractor indirect_symbol_index_data (m_data, m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4);
-
if (indirect_symbol_index_data.GetByteSize())
{
NListIndexToSymbolIndexMap::const_iterator end_index_pos = m_nlist_idx_to_sym_idx.end();
@@ -3116,7 +3565,7 @@ struct lldb_copy_dyld_cache_local_symbol
{
const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx;
const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size);
- uint32_t symbol_stub_offset = symbol_stub_index * 4;
+ lldb::offset_t symbol_stub_offset = symbol_stub_index * 4;
if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4))
{
const uint32_t stub_sym_id = indirect_symbol_index_data.GetU32 (&symbol_stub_offset);
@@ -3131,15 +3580,14 @@ struct lldb_copy_dyld_cache_local_symbol
// a current symbol index, so just look this up by index
stub_symbol = symtab->SymbolAtIndex (index_pos->second);
}
- else
+ else
{
// We need to lookup a symbol using the original nlist
- // symbol index since this index is coming from the
+ // symbol index since this index is coming from the
// S_SYMBOL_STUBS
stub_symbol = symtab->FindSymbolByID (stub_sym_id);
}
- assert (stub_symbol);
if (stub_symbol)
{
Address so_addr(symbol_stub_addr, section_list);
@@ -3173,6 +3621,11 @@ struct lldb_copy_dyld_cache_local_symbol
++sym_idx;
}
}
+ else
+ {
+ if (log)
+ log->Warning ("symbol stub referencing symbol table symbol %u that isn't in our minimal symbol table, fix this!!!", stub_sym_id);
+ }
}
}
}
@@ -3211,48 +3664,59 @@ ObjectFileMachO::Dump (Stream *s)
}
}
-
bool
-ObjectFileMachO::GetUUID (lldb_private::UUID* uuid)
+ObjectFileMachO::GetUUID (const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset,
+ lldb_private::UUID& uuid)
{
- ModuleSP module_sp(GetModule());
- if (module_sp)
+ uint32_t i;
+ struct uuid_command load_cmd;
+
+ lldb::offset_t offset = lc_offset;
+ for (i=0; i<header.ncmds; ++i)
{
- lldb_private::Mutex::Locker locker(module_sp->GetMutex());
- struct uuid_command load_cmd;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
- uint32_t i;
- for (i=0; i<m_header.ncmds; ++i)
+ const lldb::offset_t cmd_offset = offset;
+ if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+
+ if (load_cmd.cmd == LoadCommandUUID)
{
- const uint32_t cmd_offset = offset;
- if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
- break;
-
- if (load_cmd.cmd == LoadCommandUUID)
+ const uint8_t *uuid_bytes = data.PeekData(offset, 16);
+
+ if (uuid_bytes)
{
- const uint8_t *uuid_bytes = m_data.PeekData(offset, 16);
+ // OpenCL on Mac OS X uses the same UUID for each of its object files.
+ // We pretend these object files have no UUID to prevent crashing.
- if (uuid_bytes)
- {
- // OpenCL on Mac OS X uses the same UUID for each of its object files.
- // We pretend these object files have no UUID to prevent crashing.
-
- const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
- 0x3b, 0xa8,
- 0x4b, 0x16,
- 0xb6, 0xa4,
- 0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
-
- if (!memcmp(uuid_bytes, opencl_uuid, 16))
- return false;
-
- uuid->SetBytes (uuid_bytes);
- return true;
- }
- return false;
+ const uint8_t opencl_uuid[] = { 0x8c, 0x8e, 0xb3, 0x9b,
+ 0x3b, 0xa8,
+ 0x4b, 0x16,
+ 0xb6, 0xa4,
+ 0x27, 0x63, 0xbb, 0x14, 0xf0, 0x0d };
+
+ if (!memcmp(uuid_bytes, opencl_uuid, 16))
+ return false;
+
+ uuid.SetBytes (uuid_bytes);
+ return true;
}
- offset = cmd_offset + load_cmd.cmdsize;
+ return false;
}
+ offset = cmd_offset + load_cmd.cmdsize;
+ }
+ return false;
+}
+
+bool
+ObjectFileMachO::GetUUID (lldb_private::UUID* uuid)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ return GetUUID (m_header, m_data, offset, *uuid);
}
return false;
}
@@ -3267,7 +3731,7 @@ ObjectFileMachO::GetDependentModules (Fi
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
struct load_command load_cmd;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
const bool resolve_path = false; // Don't resolve the dependend file paths since they may not reside on this system
uint32_t i;
for (i=0; i<m_header.ncmds; ++i)
@@ -3309,23 +3773,23 @@ ObjectFileMachO::GetDependentModules (Fi
}
lldb_private::Address
-ObjectFileMachO::GetEntryPointAddress ()
+ObjectFileMachO::GetEntryPointAddress ()
{
// If the object file is not an executable it can't hold the entry point. m_entry_point_address
// is initialized to an invalid address, so we can just return that.
// If m_entry_point_address is valid it means we've found it already, so return the cached value.
-
+
if (!IsExecutable() || m_entry_point_address.IsValid())
return m_entry_point_address;
-
- // Otherwise, look for the UnixThread or Thread command. The data for the Thread command is given in
+
+ // Otherwise, look for the UnixThread or Thread command. The data for the Thread command is given in
// /usr/include/mach-o.h, but it is basically:
//
// uint32_t flavor - this is the flavor argument you would pass to thread_get_state
// uint32_t count - this is the count of longs in the thread state data
// struct XXX_thread_state state - this is the structure from <machine/thread_status.h> corresponding to the flavor.
// <repeat this trio>
- //
+ //
// So we just keep reading the various register flavors till we find the GPR one, then read the PC out of there.
// FIXME: We will need to have a "RegisterContext data provider" class at some point that can get all the registers
// out of data in this form & attach them to a given thread. That should underlie the MacOS X User process plugin,
@@ -3340,14 +3804,14 @@ ObjectFileMachO::GetEntryPointAddress ()
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
struct load_command load_cmd;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
lldb::addr_t start_address = LLDB_INVALID_ADDRESS;
bool done = false;
-
+
for (i=0; i<m_header.ncmds; ++i)
{
- const uint32_t cmd_offset = offset;
+ const lldb::offset_t cmd_offset = offset;
if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
@@ -3365,7 +3829,7 @@ ObjectFileMachO::GetEntryPointAddress ()
// We've gotten off somehow, log and exit;
return m_entry_point_address;
}
-
+
switch (m_header.cputype)
{
case llvm::MachO::CPUTypeARM:
@@ -3423,10 +3887,10 @@ ObjectFileMachO::GetEntryPointAddress ()
// Go to the next load command:
offset = cmd_offset + load_cmd.cmdsize;
}
-
+
if (start_address != LLDB_INVALID_ADDRESS)
{
- // We got the start address from the load commands, so now resolve that address in the sections
+ // We got the start address from the load commands, so now resolve that address in the sections
// of this ObjectFile:
if (!m_entry_point_address.ResolveAddressUsingFileSections (start_address, GetSectionList()))
{
@@ -3437,9 +3901,9 @@ ObjectFileMachO::GetEntryPointAddress ()
{
// We couldn't read the UnixThread load command - maybe it wasn't there. As a fallback look for the
// "start" symbol in the main executable.
-
+
ModuleSP module_sp (GetModule());
-
+
if (module_sp)
{
SymbolContextList contexts;
@@ -3452,7 +3916,7 @@ ObjectFileMachO::GetEntryPointAddress ()
}
}
}
-
+
return m_entry_point_address;
}
@@ -3484,7 +3948,7 @@ ObjectFileMachO::GetNumThreadContexts ()
if (!m_thread_context_offsets_valid)
{
m_thread_context_offsets_valid = true;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
FileRangeArray::Entry file_range;
thread_command thread_cmd;
for (uint32_t i=0; i<m_header.ncmds; ++i)
@@ -3492,7 +3956,7 @@ ObjectFileMachO::GetNumThreadContexts ()
const uint32_t cmd_offset = offset;
if (m_data.GetU32(&offset, &thread_cmd, 2) == NULL)
break;
-
+
if (thread_cmd.cmd == LoadCommandThread)
{
file_range.SetRangeBase (offset);
@@ -3519,24 +3983,27 @@ ObjectFileMachO::GetThreadContextAtIndex
GetNumThreadContexts ();
const FileRangeArray::Entry *thread_context_file_range = m_thread_context_offsets.GetEntryAtIndex (idx);
-
- DataExtractor data (m_data,
- thread_context_file_range->GetRangeBase(),
- thread_context_file_range->GetByteSize());
-
- switch (m_header.cputype)
+ if (thread_context_file_range)
{
- case llvm::MachO::CPUTypeARM:
- reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data));
- break;
-
- case llvm::MachO::CPUTypeI386:
- reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data));
- break;
-
- case llvm::MachO::CPUTypeX86_64:
- reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
- break;
+
+ DataExtractor data (m_data,
+ thread_context_file_range->GetRangeBase(),
+ thread_context_file_range->GetByteSize());
+
+ switch (m_header.cputype)
+ {
+ case llvm::MachO::CPUTypeARM:
+ reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data));
+ break;
+
+ case llvm::MachO::CPUTypeI386:
+ reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data));
+ break;
+
+ case llvm::MachO::CPUTypeX86_64:
+ reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
+ break;
+ }
}
}
return reg_ctx_sp;
@@ -3557,7 +4024,7 @@ ObjectFileMachO::CalculateType()
if (GetUUID(&uuid))
{
// this checking for the UUID load command is not enough
- // we could eventually look for the symbol named
+ // we could eventually look for the symbol named
// "OSKextGetCurrentIdentifier" as this is required of kexts
if (m_strata == eStrataInvalid)
m_strata = eStrataKernel;
@@ -3595,7 +4062,7 @@ ObjectFileMachO::CalculateStrata()
if (GetUUID(&uuid))
{
// this checking for the UUID load command is not enough
- // we could eventually look for the symbol named
+ // we could eventually look for the symbol named
// "OSKextGetCurrentIdentifier" as this is required of kexts
if (m_type == eTypeInvalid)
m_type = eTypeSharedLibrary;
@@ -3611,7 +4078,7 @@ ObjectFileMachO::CalculateStrata()
{
return eStrataUser;
}
- else
+ else
{
SectionList *section_list = GetSectionList();
if (section_list)
@@ -3647,16 +4114,16 @@ ObjectFileMachO::GetVersion (uint32_t *v
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
struct dylib_command load_cmd;
- uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t version_cmd = 0;
uint64_t version = 0;
uint32_t i;
for (i=0; i<m_header.ncmds; ++i)
{
- const uint32_t cmd_offset = offset;
+ const lldb::offset_t cmd_offset = offset;
if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
-
+
if (load_cmd.cmd == LoadCommandDylibIdent)
{
if (version_cmd == 0)
@@ -3666,12 +4133,12 @@ ObjectFileMachO::GetVersion (uint32_t *v
break;
version = load_cmd.dylib.current_version;
}
- break; // Break for now unless there is another more complete version
+ break; // Break for now unless there is another more complete version
// number load command in the future.
}
offset = cmd_offset + load_cmd.cmdsize;
}
-
+
if (version_cmd == LoadCommandDylibIdent)
{
if (versions != NULL && num_versions > 0)
@@ -3702,9 +4169,9 @@ ObjectFileMachO::GetArchitecture (ArchSp
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
arch.SetArchitecture (eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
-
+
// Files with type MH_PRELOAD are currently used in cases where the image
- // debugs at the addresses in the file itself. Below we set the OS to
+ // debugs at the addresses in the file itself. Below we set the OS to
// unknown to make sure we use the DynamicLoaderStatic()...
if (m_header.filetype == HeaderFileTypePreloadedExecutable)
{
@@ -3716,18 +4183,82 @@ ObjectFileMachO::GetArchitecture (ArchSp
}
+UUID
+ObjectFileMachO::GetProcessSharedCacheUUID (Process *process)
+{
+ UUID uuid;
+ if (process)
+ {
+ addr_t all_image_infos = process->GetImageInfoAddress();
+
+ // The address returned by GetImageInfoAddress may be the address of dyld (don't want)
+ // or it may be the address of the dyld_all_image_infos structure (want). The first four
+ // bytes will be either the version field (all_image_infos) or a Mach-O file magic constant.
+ // Version 13 and higher of dyld_all_image_infos is required to get the sharedCacheUUID field.
+
+ Error err;
+ uint32_t version_or_magic = process->ReadUnsignedIntegerFromMemory (all_image_infos, 4, -1, err);
+ if (version_or_magic != -1
+ && version_or_magic != HeaderMagic32
+ && version_or_magic != HeaderMagic32Swapped
+ && version_or_magic != HeaderMagic64
+ && version_or_magic != HeaderMagic64Swapped
+ && version_or_magic >= 13)
+ {
+ addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
+ int wordsize = process->GetAddressByteSize();
+ if (wordsize == 8)
+ {
+ sharedCacheUUID_address = all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h>
+ }
+ if (wordsize == 4)
+ {
+ sharedCacheUUID_address = all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h>
+ }
+ if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS)
+ {
+ uuid_t shared_cache_uuid;
+ if (process->ReadMemory (sharedCacheUUID_address, shared_cache_uuid, sizeof (uuid_t), err) == sizeof (uuid_t))
+ {
+ uuid.SetBytes (shared_cache_uuid);
+ }
+ }
+ }
+ }
+ return uuid;
+}
+
+UUID
+ObjectFileMachO::GetLLDBSharedCacheUUID ()
+{
+ UUID uuid;
+#if defined (__APPLE__) && defined (__arm__)
+ uint8_t *(*dyld_get_all_image_infos)(void);
+ dyld_get_all_image_infos = (uint8_t*(*)()) dlsym (RTLD_DEFAULT, "_dyld_get_all_image_infos");
+ if (dyld_get_all_image_infos)
+ {
+ uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos();
+ if (dyld_all_image_infos_address)
+ {
+ uint32_t *version = (uint32_t*) dyld_all_image_infos_address; // version <mach-o/dyld_images.h>
+ if (*version >= 13)
+ {
+ uuid_t *sharedCacheUUID_address = (uuid_t*) ((uint8_t*) dyld_all_image_infos_address + 84); // sharedCacheUUID <mach-o/dyld_images.h>
+ uuid.SetBytes (sharedCacheUUID_address);
+ }
+ }
+ }
+#endif
+ return uuid;
+}
+
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ObjectFileMachO::GetPluginName()
{
- return "ObjectFileMachO";
-}
-
-const char *
-ObjectFileMachO::GetShortPluginName()
-{
return GetPluginNameStatic();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Thu Jun 6 19:06:43 2013
@@ -35,7 +35,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -43,10 +43,11 @@ public:
static lldb_private::ObjectFile *
CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t file_offset,
+ lldb::offset_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (const lldb::ModuleSP &module_sp,
@@ -54,8 +55,16 @@ public:
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
static bool
- MagicBytesMatch (lldb::DataBufferSP& dataSP,
+ MagicBytesMatch (lldb::DataBufferSP& data_sp,
lldb::addr_t offset,
lldb::addr_t length);
@@ -63,13 +72,14 @@ public:
// Member Functions
//------------------------------------------------------------------
ObjectFileMachO (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
ObjectFileMachO (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
@@ -85,7 +95,7 @@ public:
virtual bool
IsExecutable () const;
- virtual size_t
+ virtual uint32_t
GetAddressByteSize () const;
virtual lldb::AddressClass
@@ -112,12 +122,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -143,9 +150,36 @@ public:
GetVersion (uint32_t *versions, uint32_t num_versions);
protected:
+
+ static bool
+ ParseHeader (lldb_private::DataExtractor &data,
+ lldb::offset_t *data_offset_ptr,
+ llvm::MachO::mach_header &header);
+
+
+ static bool
+ GetUUID (const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset, // Offset to the first load command
+ lldb_private::UUID& uuid);
+
+ // Intended for same-host arm device debugging where lldb needs to
+ // detect libraries in the shared cache and augment the nlist entries
+ // with an on-disk dyld_shared_cache file. The process will record
+ // the shared cache UUID so the on-disk cache can be matched or rejected
+ // correctly.
+ lldb_private::UUID
+ GetProcessSharedCacheUUID (lldb_private::Process *);
+
+ // Intended for same-host arm device debugging where lldb will read
+ // shared cache libraries out of its own memory instead of the remote
+ // process' memory as an optimization. If lldb's shared cache UUID
+ // does not match the process' shared cache UUID, this optimization
+ // should not be used.
+ lldb_private::UUID
+ GetLLDBSharedCacheUUID ();
+
llvm::MachO::mach_header m_header;
- mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
- mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
static const lldb_private::ConstString &GetSegmentNameOBJC();
@@ -155,7 +189,7 @@ protected:
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
- typedef lldb_private::RangeArray<uint32_t, uint32_t, 1> FileRangeArray;
+ typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;
lldb_private::Address m_entry_point_address;
FileRangeArray m_thread_context_offsets;
bool m_thread_context_offsets_valid;
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp Thu Jun 6 19:06:43 2013
@@ -16,6 +16,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
@@ -121,7 +122,8 @@ ObjectFilePECOFF::Initialize()
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance,
- CreateMemoryInstance);
+ CreateMemoryInstance,
+ GetModuleSpecifications);
}
void
@@ -131,10 +133,11 @@ ObjectFilePECOFF::Terminate()
}
-const char *
+lldb_private::ConstString
ObjectFilePECOFF::GetPluginNameStatic()
{
- return "object-file.pe-coff";
+ static ConstString g_name("pe-coff");
+ return g_name;
}
const char *
@@ -145,11 +148,25 @@ ObjectFilePECOFF::GetPluginDescriptionSt
ObjectFile *
-ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
+ObjectFilePECOFF::CreateInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec* file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length)
{
- if (ObjectFilePECOFF::MagicBytesMatch(dataSP))
+ if (!data_sp)
{
- std::auto_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, dataSP, file, offset, length));
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_offset = 0;
+ }
+
+ if (ObjectFilePECOFF::MagicBytesMatch(data_sp))
+ {
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length)
+ data_sp = file->MemoryMapFileContents(file_offset, length);
+ std::unique_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, data_sp, data_offset, file, file_offset, length));
if (objfile_ap.get() && objfile_ap->ParseHeader())
return objfile_ap.release();
}
@@ -165,22 +182,35 @@ ObjectFilePECOFF::CreateMemoryInstance (
return NULL;
}
+size_t
+ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+{
+ return 0;
+}
+
+
bool
-ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
+ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
{
- DataExtractor data(dataSP, eByteOrderLittle, 4);
- uint32_t offset = 0;
+ DataExtractor data(data_sp, eByteOrderLittle, 4);
+ lldb::offset_t offset = 0;
uint16_t magic = data.GetU16 (&offset);
return magic == IMAGE_DOS_SIGNATURE;
}
ObjectFilePECOFF::ObjectFilePECOFF (const lldb::ModuleSP &module_sp,
- DataBufferSP& dataSP,
+ DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const FileSpec* file,
- addr_t offset,
- addr_t length) :
- ObjectFile (module_sp, file, offset, length, dataSP),
+ lldb::offset_t file_offset,
+ lldb::offset_t length) :
+ ObjectFile (module_sp, file, file_offset, length, data_sp, data_offset),
m_dos_header (),
m_coff_header (),
m_coff_header_opt (),
@@ -206,7 +236,7 @@ ObjectFilePECOFF::ParseHeader ()
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
m_sect_headers.clear();
m_data.SetByteOrder (eByteOrderLittle);
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
if (ParseDOSHeader())
{
@@ -220,8 +250,6 @@ ObjectFilePECOFF::ParseHeader ()
ParseCOFFOptionalHeader(&offset);
ParseSectionHeaders (offset);
}
- StreamFile s(stdout, false);// REMOVE THIS LINE!!!
- Dump(&s);// REMOVE THIS LINE!!!
return true;
}
}
@@ -241,7 +269,7 @@ ObjectFilePECOFF::IsExecutable() const
return (m_coff_header.flags & IMAGE_FILE_DLL) == 0;
}
-size_t
+uint32_t
ObjectFilePECOFF::GetAddressByteSize () const
{
if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
@@ -273,7 +301,7 @@ bool
ObjectFilePECOFF::ParseDOSHeader ()
{
bool success = false;
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
success = m_data.ValidOffsetForDataOfSize(0, sizeof(m_dos_header));
if (success)
@@ -328,7 +356,7 @@ ObjectFilePECOFF::ParseDOSHeader ()
// ParserCOFFHeader
//----------------------------------------------------------------------
bool
-ObjectFilePECOFF::ParseCOFFHeader(uint32_t* offset_ptr)
+ObjectFilePECOFF::ParseCOFFHeader(lldb::offset_t *offset_ptr)
{
bool success = m_data.ValidOffsetForDataOfSize (*offset_ptr, sizeof(m_coff_header));
if (success)
@@ -347,10 +375,10 @@ ObjectFilePECOFF::ParseCOFFHeader(uint32
}
bool
-ObjectFilePECOFF::ParseCOFFOptionalHeader(uint32_t* offset_ptr)
+ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr)
{
bool success = false;
- const uint32_t end_offset = *offset_ptr + m_coff_header.hdrsize;
+ const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
if (*offset_ptr < end_offset)
{
success = true;
@@ -431,7 +459,7 @@ ObjectFilePECOFF::ParseSectionHeaders (u
DataBufferSP section_header_data_sp(m_file.ReadFileContents (section_header_data_offset, section_header_byte_size));
DataExtractor section_header_data (section_header_data_sp, GetByteOrder(), addr_byte_size);
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
if (section_header_data.ValidOffsetForDataOfSize (offset, section_header_byte_size))
{
m_sect_headers.resize(nsects);
@@ -464,8 +492,8 @@ ObjectFilePECOFF::GetSectionName(std::st
{
if (sect.name[0] == '/')
{
- uint32_t stroff = strtoul(§.name[1], NULL, 10);
- uint32_t string_file_offset = m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
+ lldb::offset_t stroff = strtoul(§.name[1], NULL, 10);
+ lldb::offset_t string_file_offset = m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
const char *name = m_data.GetCStr (&string_file_offset);
if (name)
{
@@ -505,7 +533,7 @@ ObjectFilePECOFF::GetSymtab()
// Include the 4 bytes string table size at the end of the symbols
DataBufferSP symtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff, symbol_data_size + 4));
DataExtractor symtab_data (symtab_data_sp, GetByteOrder(), addr_byte_size);
- uint32_t offset = symbol_data_size;
+ lldb::offset_t offset = symbol_data_size;
const uint32_t strtab_size = symtab_data.GetU32 (&offset);
DataBufferSP strtab_data_sp(m_file.ReadFileContents (m_coff_header.symoff + symbol_data_size + 4, strtab_size));
DataExtractor strtab_data (strtab_data_sp, GetByteOrder(), addr_byte_size);
@@ -789,7 +817,7 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stre
s->Printf (" entry = 0x%8.8x\n", header.entry);
s->Printf (" code_offset = 0x%8.8x\n", header.code_offset);
s->Printf (" data_offset = 0x%8.8x\n", header.data_offset);
- s->Printf (" image_base = 0x%16.16llx\n", header.image_base);
+ s->Printf (" image_base = 0x%16.16" PRIx64 "\n", header.image_base);
s->Printf (" sect_alignment = 0x%8.8x\n", header.sect_alignment);
s->Printf (" file_alignment = 0x%8.8x\n", header.file_alignment);
s->Printf (" major_os_system_version = 0x%4.4x\n", header.major_os_system_version);
@@ -804,10 +832,10 @@ ObjectFilePECOFF::DumpOptCOFFHeader(Stre
s->Printf (" checksum = 0x%8.8x\n", header.checksum);
s->Printf (" subsystem = 0x%4.4x\n", header.subsystem);
s->Printf (" dll_flags = 0x%4.4x\n", header.dll_flags);
- s->Printf (" stack_reserve_size = 0x%16.16llx\n", header.stack_reserve_size);
- s->Printf (" stack_commit_size = 0x%16.16llx\n", header.stack_commit_size);
- s->Printf (" heap_reserve_size = 0x%16.16llx\n", header.heap_reserve_size);
- s->Printf (" heap_commit_size = 0x%16.16llx\n", header.heap_commit_size);
+ s->Printf (" stack_reserve_size = 0x%16.16" PRIx64 "\n", header.stack_reserve_size);
+ s->Printf (" stack_commit_size = 0x%16.16" PRIx64 "\n", header.stack_commit_size);
+ s->Printf (" heap_reserve_size = 0x%16.16" PRIx64 "\n", header.heap_reserve_size);
+ s->Printf (" heap_commit_size = 0x%16.16" PRIx64 "\n", header.heap_commit_size);
s->Printf (" loader_flags = 0x%8.8x\n", header.loader_flags);
s->Printf (" num_data_dir_entries = 0x%8.8zx\n", header.data_dirs.size());
uint32_t i;
@@ -927,15 +955,9 @@ ObjectFilePECOFF::CalculateStrata()
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+ConstString
ObjectFilePECOFF::GetPluginName()
{
- return "ObjectFilePECOFF";
-}
-
-const char *
-ObjectFilePECOFF::GetShortPluginName()
-{
return GetPluginNameStatic();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h Thu Jun 6 19:06:43 2013
@@ -28,7 +28,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -36,25 +36,36 @@ public:
static ObjectFile *
CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t offset,
+ lldb::offset_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (const lldb::ModuleSP &module_sp,
lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
+
+ static size_t
+ GetModuleSpecifications (const lldb_private::FileSpec& file,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
static bool
- MagicBytesMatch (lldb::DataBufferSP& dataSP);
+ MagicBytesMatch (lldb::DataBufferSP& data_sp);
ObjectFilePECOFF (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& dataSP,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
const lldb_private::FileSpec* file,
- lldb::addr_t offset,
- lldb::addr_t length);
+ lldb::offset_t file_offset,
+ lldb::offset_t length);
virtual
~ObjectFilePECOFF();
@@ -68,7 +79,7 @@ public:
virtual bool
IsExecutable () const;
- virtual size_t
+ virtual uint32_t
GetAddressByteSize () const;
// virtual lldb_private::AddressClass
@@ -95,12 +106,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
//
@@ -212,8 +220,8 @@ protected:
} coff_symbol_t;
bool ParseDOSHeader ();
- bool ParseCOFFHeader (uint32_t* offset_ptr);
- bool ParseCOFFOptionalHeader (uint32_t* offset_ptr);
+ bool ParseCOFFHeader (lldb::offset_t *offset_ptr);
+ bool ParseCOFFOptionalHeader (lldb::offset_t *offset_ptr);
bool ParseSectionHeaders (uint32_t offset);
static void DumpDOSHeader(lldb_private::Stream *s, const dos_header_t& header);
@@ -227,8 +235,6 @@ protected:
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
private:
- mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
- mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
dos_header_t m_dos_header;
coff_header_t m_coff_header;
coff_opt_header_t m_coff_header_opt;
Copied: lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (from r182522, lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp&p1=lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp Thu Jun 6 19:06:43 2013
@@ -21,6 +21,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/PythonDataObjects.h"
@@ -134,7 +135,7 @@ OperatingSystemPython::GetDynamicRegiste
{
if (!m_interpreter || !m_python_object_sp)
return NULL;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
if (log)
log->Printf ("OperatingSystemPython::GetDynamicRegisterInfo() fetching thread register definitions from python for pid %" PRIu64, m_process->GetID());
@@ -173,7 +174,7 @@ OperatingSystemPython::UpdateThreadList
if (!m_interpreter || !m_python_object_sp)
return false;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
// First thing we have to do is get the API lock, and the run lock. We're going to change the thread
// content of the process, and we're going to use python, which requires the API lock to do it.
@@ -191,6 +192,12 @@ OperatingSystemPython::UpdateThreadList
PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
if (threads_list)
{
+ if (log)
+ {
+ StreamString strm;
+ threads_list.Dump(strm);
+ log->Printf("threads_list = %s", strm.GetString().c_str());
+ }
uint32_t i;
const uint32_t num_threads = threads_list.GetSize();
if (num_threads > 0)
@@ -200,21 +207,6 @@ OperatingSystemPython::UpdateThreadList
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
{
- if (thread_dict.GetItemForKey("core"))
- {
- // We have some threads that are saying they are on a "core", which means
- // they map the threads that are gotten from the lldb_private::Process subclass
- // so clear the new threads list so the core threads don't show up
- new_thread_list.Clear();
- break;
- }
- }
- }
- for (i=0; i<num_threads; ++i)
- {
- PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
- if (thread_dict)
- {
ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
if (thread_sp)
new_thread_list.AddThread(thread_sp);
@@ -223,8 +215,10 @@ OperatingSystemPython::UpdateThreadList
}
}
+ // No new threads added from the thread info array gotten from python, just
+ // display the core threads.
if (new_thread_list.GetSize(false) == 0)
- new_thread_list = old_thread_list;
+ new_thread_list = core_thread_list;
return new_thread_list.GetSize(false) > 0;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "PlatformFreeBSD.h"
// C Includes
@@ -18,6 +20,8 @@
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
@@ -41,10 +45,14 @@ PlatformFreeBSD::CreateInstance (bool fo
create = true;
break;
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ // Only accept "unknown" for the vendor if the host is BSD and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
-
+#endif
default:
break;
}
@@ -57,10 +65,14 @@ PlatformFreeBSD::CreateInstance (bool fo
case llvm::Triple::KFreeBSD:
break;
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ // Only accept "unknown" for the OS if the host is BSD and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownOS:
create = arch->TripleOSWasSpecified();
break;
-
+#endif
default:
create = false;
break;
@@ -73,19 +85,19 @@ PlatformFreeBSD::CreateInstance (bool fo
}
-const char *
-PlatformFreeBSD::GetPluginNameStatic()
-{
- return "plugin.platform.freebsd";
-}
-
-const char *
-PlatformFreeBSD::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformFreeBSD::GetPluginNameStatic (bool is_host)
{
if (is_host)
- return Platform::GetHostPlatformName ();
+ {
+ static ConstString g_host_name(Platform::GetHostPlatformName ());
+ return g_host_name;
+ }
else
- return "remote-freebsd";
+ {
+ static ConstString g_remote_name("remote-freebsd");
+ return g_remote_name;
+ }
}
const char *
@@ -110,7 +122,7 @@ PlatformFreeBSD::Initialize ()
default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
Platform::SetDefaultPlatform (default_platform_sp);
#endif
- PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false),
+ PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
PlatformFreeBSD::GetDescriptionStatic(false),
PlatformFreeBSD::CreateInstance);
}
@@ -168,23 +180,128 @@ PlatformFreeBSD::ResolveExecutable (cons
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
+ Error error;
// Nothing special to do here, just use the actual file and architecture
-
- if (lldb_private::IsLogVerbose())
+
+ char exe_path[PATH_MAX];
+ FileSpec resolved_exe_file (exe_file);
+
+ if (IsHost())
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_VERBOSE));
- log->Printf("Resolve executable '%s/%s'", exe_file.GetDirectory().AsCString(), exe_file.GetFilename().AsCString());
- log->Printf("Resolve executable arch '%s'", exe_arch.GetArchitectureName());
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ if (!resolved_exe_file.Exists())
+ {
+ exe_file.GetPath(exe_path, sizeof(exe_path));
+ resolved_exe_file.SetFile(exe_path, true);
}
-
- if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->ResolveExecutable (exe_file,
+
+ if (!resolved_exe_file.Exists())
+ resolved_exe_file.ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ //Host::ResolveExecutableInBundle (resolved_exe_file);
+
+ if (resolved_exe_file.Exists())
+ error.Clear();
+ else
+ {
+ exe_file.GetPath(exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->ResolveExecutable (exe_file,
exe_arch,
exe_module_sp,
module_search_paths_ptr);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_exe_file);
+
+ if (resolved_exe_file.Exists()) {
+ error.Clear();
+ }
+ else
+ {
+ exe_file.GetPath(exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+ }
+ }
+ }
+
+
+ if (error.Success())
+ {
+ ModuleSpec module_spec (resolved_exe_file, exe_arch);
+ if (module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
- return Platform::ResolveExecutable(exe_file, exe_arch, exe_module_sp, module_search_paths_ptr);
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ exe_file.GetPath().c_str(),
+ exe_arch.GetArchitectureName());
}
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ ArchSpec platform_arch;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+ {
+ error = ModuleList::GetSharedModule (module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (platform_arch.GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ exe_file.GetPath().c_str());
+ }
+
+ return error;
+}
size_t
PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
@@ -280,7 +397,7 @@ PlatformFreeBSD::ConnectRemote (Args& ar
Error error;
if (IsHost())
{
- error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
}
else
{
@@ -318,7 +435,7 @@ PlatformFreeBSD::DisconnectRemote ()
if (IsHost())
{
- error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
}
else
{
@@ -397,11 +514,10 @@ PlatformFreeBSD::Attach(ProcessAttachInf
if (target == NULL)
{
TargetSP new_target_sp;
- FileSpec emptyFileSpec;
ArchSpec emptyArchSpec;
error = debugger.GetTargetList().CreateTarget (debugger,
- emptyFileSpec,
+ NULL,
emptyArchSpec,
false,
m_remote_platform_sp,
@@ -528,7 +644,7 @@ PlatformFreeBSD::GetSupportedArchitectur
{
ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
- if (platform_arch == platform_arch64)
+ if (platform_arch.IsExactMatch(platform_arch64))
{
// This freebsd platform supports both 32 and 64 bit. Since we already
// returned the 64 bit arch for idx == 0, return the 32 bit arch
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h Thu Jun 6 19:06:43 2013
@@ -33,14 +33,11 @@ public:
static void
Terminate ();
- static const char *
- GetPluginNameStatic();
-
- static const char *
- GetShortPluginNameStatic(bool is_host);
+ static lldb_private::ConstString
+ GetPluginNameStatic (bool is_host);
static const char *
- GetDescriptionStatic(bool is_host);
+ GetDescriptionStatic (bool is_host);
//------------------------------------------------------------
// Class Methods
@@ -53,16 +50,10 @@ public:
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
- return GetPluginNameStatic();
- }
-
- virtual const char *
- GetShortPluginName()
- {
- return GetShortPluginNameStatic (IsHost());
+ return GetPluginNameStatic (IsHost());
}
virtual uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "PlatformLinux.h"
// C Includes
@@ -20,6 +22,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
@@ -45,10 +48,14 @@ PlatformLinux::CreateInstance (bool forc
create = true;
break;
+#if defined(__linux__)
+ // Only accept "unknown" for the vendor if the host is linux and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified_
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
-
+#endif
default:
break;
}
@@ -60,10 +67,14 @@ PlatformLinux::CreateInstance (bool forc
case llvm::Triple::Linux:
break;
+#if defined(__linux__)
+ // Only accept "unknown" for the OS if the host is linux and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
-
+#endif
default:
create = false;
break;
@@ -75,19 +86,20 @@ PlatformLinux::CreateInstance (bool forc
return NULL;
}
-const char *
-PlatformLinux::GetPluginNameStatic()
-{
- return "plugin.platform.linux";
-}
-const char *
-PlatformLinux::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformLinux::GetPluginNameStatic (bool is_host)
{
if (is_host)
- return Platform::GetHostPlatformName ();
+ {
+ static ConstString g_host_name(Platform::GetHostPlatformName ());
+ return g_host_name;
+ }
else
- return "remote-linux";
+ {
+ static ConstString g_remote_name("remote-linux");
+ return g_remote_name;
+ }
}
const char *
@@ -99,6 +111,12 @@ PlatformLinux::GetPluginDescriptionStati
return "Remote Linux user platform plug-in.";
}
+lldb_private::ConstString
+PlatformLinux::GetPluginName()
+{
+ return GetPluginNameStatic(IsHost());
+}
+
void
PlatformLinux::Initialize ()
{
@@ -109,7 +127,7 @@ PlatformLinux::Initialize ()
default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
Platform::SetDefaultPlatform (default_platform_sp);
#endif
- PluginManager::RegisterPlugin(PlatformLinux::GetShortPluginNameStatic(false),
+ PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false),
PlatformLinux::GetPluginDescriptionStatic(false),
PlatformLinux::CreateInstance);
}
@@ -190,14 +208,36 @@ PlatformLinux::ResolveExecutable (const
NULL,
NULL,
NULL);
+ if (error.Fail())
+ {
+ // If we failed, it may be because the vendor and os aren't known. If that is the
+ // case, try setting them to the host architecture and give it another try.
+ llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple();
+ bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
+ bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
+ if (!is_vendor_specified || !is_os_specified)
+ {
+ const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple();
+
+ if (!is_vendor_specified)
+ module_triple.setVendorName (host_triple.getVendorName());
+ if (!is_os_specified)
+ module_triple.setOSName (host_triple.getOSName());
+
+ error = ModuleList::GetSharedModule (module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ }
+ }
- if (exe_module_sp->GetObjectFile() == NULL)
+ // TODO find out why exe_module_sp might be NULL
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
- error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""),
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ exe_file.GetPath().c_str(),
exe_arch.GetArchitectureName());
}
}
@@ -230,11 +270,9 @@ PlatformLinux::ResolveExecutable (const
if (error.Fail() || !exe_module_sp)
{
- error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""),
- GetShortPluginName(),
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
arch_names.GetString().c_str());
}
}
@@ -302,6 +340,17 @@ PlatformLinux::GetSupportedArchitectureA
arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
return arch.IsValid();
}
+ else if (idx == 1)
+ {
+ // If the default host architecture is 64-bit, look for a 32-bit variant
+ ArchSpec hostArch
+ = Host::GetArchitecture(Host::eSystemDefaultArchitecture);
+ if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
+ {
+ arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+ return arch.IsValid();
+ }
+ }
return false;
}
@@ -310,12 +359,14 @@ PlatformLinux::GetStatus (Stream &strm)
{
struct utsname un;
- if (uname(&un)) {
- strm << "Linux";
+ Platform::GetStatus(strm);
+
+ if (uname(&un))
return;
- }
- strm << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+ strm.Printf (" Kernel: %s\n", un.sysname);
+ strm.Printf (" Release: %s\n", un.release);
+ strm.Printf (" Version: %s\n", un.version);
}
size_t
@@ -387,11 +438,10 @@ PlatformLinux::Attach(ProcessAttachInfo
if (target == NULL)
{
TargetSP new_target_sp;
- FileSpec emptyFileSpec;
ArchSpec emptyArchSpec;
error = debugger.GetTargetList().CreateTarget (debugger,
- emptyFileSpec,
+ NULL,
emptyArchSpec,
false,
m_remote_platform_sp,
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/Linux/PlatformLinux.h Thu Jun 6 19:06:43 2013
@@ -39,26 +39,14 @@ namespace lldb_private {
static Platform *
CreateInstance (bool force, const lldb_private::ArchSpec *arch);
- static const char *
- GetPluginNameStatic();
-
- static const char *
- GetShortPluginNameStatic(bool is_host);
+ static lldb_private::ConstString
+ GetPluginNameStatic (bool is_host);
static const char *
- GetPluginDescriptionStatic(bool is_host);
+ GetPluginDescriptionStatic (bool is_host);
- virtual const char *
- GetPluginName()
- {
- return GetPluginNameStatic();
- }
-
- virtual const char *
- GetShortPluginName()
- {
- return "PlatformLinux";
- }
+ virtual lldb_private::ConstString
+ GetPluginName();
virtual uint32_t
GetPluginVersion()
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "PlatformDarwin.h"
// C Includes
@@ -16,7 +18,14 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -42,6 +51,75 @@ PlatformDarwin::~PlatformDarwin()
{
}
+FileSpecList
+PlatformDarwin::LocateExecutableScriptingResources (Target *target,
+ Module &module)
+{
+ FileSpecList file_list;
+ if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
+ {
+ // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
+ // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
+ // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
+ // which should be stripped while leaving "this.binary.file" as-is.
+ FileSpec module_spec = module.GetFileSpec();
+
+ if (module_spec)
+ {
+ SymbolVendor *symbols = module.GetSymbolVendor ();
+ if (symbols)
+ {
+ SymbolFile *symfile = symbols->GetSymbolFile();
+ if (symfile)
+ {
+ ObjectFile *objfile = symfile->GetObjectFile();
+ if (objfile)
+ {
+ FileSpec symfile_spec (objfile->GetFileSpec());
+ if (symfile_spec && symfile_spec.Exists())
+ {
+ while (module_spec.GetFilename())
+ {
+ std::string module_basename (module_spec.GetFilename().GetCString());
+
+ // FIXME: for Python, we cannot allow certain characters in module
+ // filenames we import. Theoretically, different scripting languages may
+ // have different sets of forbidden tokens in filenames, and that should
+ // be dealt with by each ScriptInterpreter. For now, we just replace dots
+ // with underscores, but if we ever support anything other than Python
+ // we will need to rework this
+ std::replace(module_basename.begin(), module_basename.end(), '.', '_');
+ std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
+ std::replace(module_basename.begin(), module_basename.end(), '-', '_');
+
+
+ StreamString path_string;
+ // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
+ // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
+ path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
+ FileSpec script_fspec(path_string.GetData(), true);
+ if (script_fspec.Exists())
+ {
+ file_list.Append (script_fspec);
+ break;
+ }
+
+ // If we didn't find the python file, then keep
+ // stripping the extensions and try again
+ ConstString filename_no_extension (module_spec.GetFileNameStrippingExtension());
+ if (module_spec.GetFilename() == filename_no_extension)
+ break;
+
+ module_spec.GetFilename() = filename_no_extension;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return file_list;
+}
Error
PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
@@ -117,10 +195,8 @@ PlatformDarwin::ResolveExecutable (const
if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
- error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""),
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ exe_file.GetPath().c_str(),
exe_arch.GetArchitectureName());
}
}
@@ -153,11 +229,9 @@ PlatformDarwin::ResolveExecutable (const
if (error.Fail() || !exe_module_sp)
{
- error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""),
- GetShortPluginName(),
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
arch_names.GetString().c_str());
}
}
@@ -166,6 +240,32 @@ PlatformDarwin::ResolveExecutable (const
return error;
}
+Error
+PlatformDarwin::ResolveSymbolFile (Target &target,
+ const ModuleSpec &sym_spec,
+ FileSpec &sym_file)
+{
+ Error error;
+ sym_file = sym_spec.GetSymbolFileSpec();
+ if (sym_file.Exists())
+ {
+ if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
+ {
+ sym_file = Symbols::FindSymbolFileInBundle (sym_file,
+ sym_spec.GetUUIDPtr(),
+ sym_spec.GetArchitecturePtr());
+ }
+ }
+ else
+ {
+ if (sym_spec.GetUUID().IsValid())
+ {
+
+ }
+ }
+ return error;
+
+}
static lldb_private::Error
MakeCacheFolderForFile (const FileSpec& module_cache_spec)
@@ -209,8 +309,7 @@ PlatformDarwin::GetSharedModuleWithLocal
module_spec.GetSymbolFileSpec().GetFilename().AsCString());
std::string cache_path(GetLocalCacheDirectory());
- std::string module_path;
- module_spec.GetFileSpec().GetPath(module_path);
+ std::string module_path (module_spec.GetFileSpec().GetPath());
cache_path.append(module_path);
FileSpec module_cache_spec(cache_path.c_str(),false);
@@ -337,33 +436,52 @@ PlatformDarwin::GetSharedModule (const M
FileSpec bundle_directory;
if (Host::GetBundleDirectory (platform_file, bundle_directory))
{
- char platform_path[PATH_MAX];
- char bundle_dir[PATH_MAX];
- platform_file.GetPath (platform_path, sizeof(platform_path));
- const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
- char new_path[PATH_MAX];
- size_t num_module_search_paths = module_search_paths_ptr->GetSize();
- for (size_t i=0; i<num_module_search_paths; ++i)
+ if (platform_file == bundle_directory)
{
- const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
- if (search_path_len < sizeof(new_path))
+ ModuleSpec new_module_spec (module_spec);
+ new_module_spec.GetFileSpec() = bundle_directory;
+ if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
{
- snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
- FileSpec new_file_spec (new_path, false);
- if (new_file_spec.Exists())
+ Error new_error (Platform::GetSharedModule (new_module_spec,
+ module_sp,
+ NULL,
+ old_module_sp_ptr,
+ did_create_ptr));
+
+ if (module_sp)
+ return new_error;
+ }
+ }
+ else
+ {
+ char platform_path[PATH_MAX];
+ char bundle_dir[PATH_MAX];
+ platform_file.GetPath (platform_path, sizeof(platform_path));
+ const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
+ char new_path[PATH_MAX];
+ size_t num_module_search_paths = module_search_paths_ptr->GetSize();
+ for (size_t i=0; i<num_module_search_paths; ++i)
+ {
+ const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
+ if (search_path_len < sizeof(new_path))
{
- ModuleSpec new_module_spec (module_spec);
- new_module_spec.GetFileSpec() = new_file_spec;
- Error new_error (Platform::GetSharedModule (new_module_spec,
- module_sp,
- NULL,
- old_module_sp_ptr,
- did_create_ptr));
-
- if (module_sp)
+ snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
+ FileSpec new_file_spec (new_path, false);
+ if (new_file_spec.Exists())
{
- module_sp->SetPlatformFileSpec(new_file_spec);
- return new_error;
+ ModuleSpec new_module_spec (module_spec);
+ new_module_spec.GetFileSpec() = new_file_spec;
+ Error new_error (Platform::GetSharedModule (new_module_spec,
+ module_sp,
+ NULL,
+ old_module_sp_ptr,
+ did_create_ptr));
+
+ if (module_sp)
+ {
+ module_sp->SetPlatformFileSpec(new_file_spec);
+ return new_error;
+ }
}
}
}
@@ -508,7 +626,7 @@ PlatformDarwin::ConnectRemote (Args& arg
Error error;
if (IsHost())
{
- error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
}
else
{
@@ -528,7 +646,7 @@ PlatformDarwin::ConnectRemote (Args& arg
{
if (m_options.get())
{
- OptionGroupOptions* options = (OptionGroupOptions*)m_options.get();
+ OptionGroupOptions* options = m_options.get();
OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
@@ -559,7 +677,7 @@ PlatformDarwin::DisconnectRemote ()
if (IsHost())
{
- error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
}
else
{
@@ -642,10 +760,9 @@ PlatformDarwin::Attach (ProcessAttachInf
if (target == NULL)
{
TargetSP new_target_sp;
- FileSpec emptyFileSpec;
error = debugger.GetTargetList().CreateTarget (debugger,
- emptyFileSpec,
+ NULL,
NULL,
false,
NULL,
@@ -730,7 +847,7 @@ PlatformDarwin::x86GetSupportedArchitect
{
ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
- if (platform_arch == platform_arch64)
+ if (platform_arch.IsExactMatch(platform_arch64))
{
// This macosx platform supports both 32 and 64 bit. Since we already
// returned the 64 bit arch for idx == 0, return the 32 bit arch
@@ -759,18 +876,22 @@ PlatformDarwin::ARMGetSupportedArchitect
case 1: arch.SetTriple ("armv7f-apple-ios"); return true;
case 2: arch.SetTriple ("armv7k-apple-ios"); return true;
case 3: arch.SetTriple ("armv7s-apple-ios"); return true;
- case 4: arch.SetTriple ("armv6-apple-ios"); return true;
- case 5: arch.SetTriple ("armv5-apple-ios"); return true;
- case 6: arch.SetTriple ("armv4-apple-ios"); return true;
- case 7: arch.SetTriple ("arm-apple-ios"); return true;
- case 8: arch.SetTriple ("thumbv7-apple-ios"); return true;
- case 9: arch.SetTriple ("thumbv7f-apple-ios"); return true;
- case 10: arch.SetTriple ("thumbv7k-apple-ios"); return true;
- case 11: arch.SetTriple ("thumbv7s-apple-ios"); return true;
- case 12: arch.SetTriple ("thumbv6-apple-ios"); return true;
- case 13: arch.SetTriple ("thumbv5-apple-ios"); return true;
- case 14: arch.SetTriple ("thumbv4t-apple-ios"); return true;
- case 15: arch.SetTriple ("thumb-apple-ios"); return true;
+ case 4: arch.SetTriple ("armv7m-apple-ios"); return true;
+ case 5: arch.SetTriple ("armv7em-apple-ios"); return true;
+ case 6: arch.SetTriple ("armv6-apple-ios"); return true;
+ case 7: arch.SetTriple ("armv5-apple-ios"); return true;
+ case 8: arch.SetTriple ("armv4-apple-ios"); return true;
+ case 9: arch.SetTriple ("arm-apple-ios"); return true;
+ case 10: arch.SetTriple ("thumbv7-apple-ios"); return true;
+ case 11: arch.SetTriple ("thumbv7f-apple-ios"); return true;
+ case 12: arch.SetTriple ("thumbv7k-apple-ios"); return true;
+ case 13: arch.SetTriple ("thumbv7s-apple-ios"); return true;
+ case 14: arch.SetTriple ("thumbv7m-apple-ios"); return true;
+ case 15: arch.SetTriple ("thumbv7em-apple-ios"); return true;
+ case 16: arch.SetTriple ("thumbv6-apple-ios"); return true;
+ case 17: arch.SetTriple ("thumbv5-apple-ios"); return true;
+ case 18: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+ case 19: arch.SetTriple ("thumb-apple-ios"); return true;
default: break;
}
break;
@@ -832,6 +953,44 @@ PlatformDarwin::ARMGetSupportedArchitect
}
break;
+ case ArchSpec::eCore_arm_armv7m:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7m-apple-ios"); return true;
+ case 1: arch.SetTriple ("armv7-apple-ios"); return true;
+ case 2: arch.SetTriple ("armv6-apple-ios"); return true;
+ case 3: arch.SetTriple ("armv5-apple-ios"); return true;
+ case 4: arch.SetTriple ("armv4-apple-ios"); return true;
+ case 5: arch.SetTriple ("arm-apple-ios"); return true;
+ case 6: arch.SetTriple ("thumbv7m-apple-ios"); return true;
+ case 7: arch.SetTriple ("thumbv7-apple-ios"); return true;
+ case 8: arch.SetTriple ("thumbv6-apple-ios"); return true;
+ case 9: arch.SetTriple ("thumbv5-apple-ios"); return true;
+ case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+ case 11: arch.SetTriple ("thumb-apple-ios"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7em:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7em-apple-ios"); return true;
+ case 1: arch.SetTriple ("armv7-apple-ios"); return true;
+ case 2: arch.SetTriple ("armv6-apple-ios"); return true;
+ case 3: arch.SetTriple ("armv5-apple-ios"); return true;
+ case 4: arch.SetTriple ("armv4-apple-ios"); return true;
+ case 5: arch.SetTriple ("arm-apple-ios"); return true;
+ case 6: arch.SetTriple ("thumbv7em-apple-ios"); return true;
+ case 7: arch.SetTriple ("thumbv7-apple-ios"); return true;
+ case 8: arch.SetTriple ("thumbv6-apple-ios"); return true;
+ case 9: arch.SetTriple ("thumbv5-apple-ios"); return true;
+ case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true;
+ case 11: arch.SetTriple ("thumb-apple-ios"); return true;
+ default: break;
+ }
+ break;
+
case ArchSpec::eCore_arm_armv7:
switch (idx)
{
@@ -944,6 +1103,43 @@ PlatformDarwin::GetDeveloperDirectory()
}
}
+ if (!developer_dir_path_valid)
+ {
+ FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
+ if (xcode_select_cmd.Exists())
+ {
+ int exit_status = -1;
+ int signo = -1;
+ std::string command_output;
+ Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path",
+ NULL, // current working directory
+ &exit_status,
+ &signo,
+ &command_output,
+ 2, // short timeout
+ NULL); // don't run in a shell
+ if (error.Success() && exit_status == 0 && !command_output.empty())
+ {
+ const char *cmd_output_ptr = command_output.c_str();
+ developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
+ int i;
+ for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
+ {
+ if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
+ break;
+ developer_dir_path[i] = cmd_output_ptr[i];
+ }
+ developer_dir_path[i] = '\0';
+
+ FileSpec devel_dir (developer_dir_path, false);
+ if (devel_dir.Exists() && devel_dir.IsDirectory())
+ {
+ developer_dir_path_valid = true;
+ }
+ }
+ }
+ }
+
if (developer_dir_path_valid)
{
temp_file_spec.SetFile (developer_dir_path, false);
@@ -1000,7 +1196,19 @@ PlatformDarwin::SetThreadCreationBreakpo
eFunctionNameTypeFull,
skip_prologue,
internal);
+ bp_sp->SetBreakpointKind("thread-creation");
return bp_sp;
}
+size_t
+PlatformDarwin::GetEnvironment (StringList &env)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetEnvironment(env);
+ return 0;
+ }
+ return Host::GetEnvironment(env);
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformDarwin.h Thu Jun 6 19:06:43 2013
@@ -34,6 +34,15 @@ public:
const lldb_private::FileSpecList *module_search_paths_ptr);
virtual lldb_private::Error
+ ResolveSymbolFile (lldb_private::Target &target,
+ const lldb_private::ModuleSpec &sym_spec,
+ lldb_private::FileSpec &sym_file);
+
+ lldb_private::FileSpecList
+ LocateExecutableScriptingResources (lldb_private::Target *target,
+ lldb_private::Module &module);
+
+ virtual lldb_private::Error
GetSharedModule (const lldb_private::ModuleSpec &module_spec,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
@@ -98,7 +107,10 @@ public:
virtual bool
ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp);
-
+
+ virtual size_t
+ GetEnvironment (lldb_private::StringList &environment);
+
bool
ARMGetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp Thu Jun 6 19:06:43 2013
@@ -46,7 +46,7 @@ PlatformMacOSX::Initialize ()
default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
Platform::SetDefaultPlatform (default_platform_sp);
#endif
- PluginManager::RegisterPlugin (PlatformMacOSX::GetShortPluginNameStatic(false),
+ PluginManager::RegisterPlugin (PlatformMacOSX::GetPluginNameStatic(false),
PlatformMacOSX::GetDescriptionStatic(false),
PlatformMacOSX::CreateInstance);
}
@@ -82,10 +82,14 @@ PlatformMacOSX::CreateInstance (bool for
create = true;
break;
+#if defined(__APPLE__)
+ // Only accept "unknown" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
-
+#endif
default:
break;
}
@@ -97,11 +101,14 @@ PlatformMacOSX::CreateInstance (bool for
case llvm::Triple::Darwin: // Deprecated, but still support Darwin for historical reasons
case llvm::Triple::MacOSX:
break;
-
+#if defined(__APPLE__)
+ // Only accept "vendor" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
-
+#endif
default:
create = false;
break;
@@ -113,20 +120,19 @@ PlatformMacOSX::CreateInstance (bool for
return NULL;
}
-
-const char *
-PlatformMacOSX::GetPluginNameStatic ()
-{
- return "PlatformMacOSX";
-}
-
-const char *
-PlatformMacOSX::GetShortPluginNameStatic (bool is_host)
+lldb_private::ConstString
+PlatformMacOSX::GetPluginNameStatic (bool is_host)
{
if (is_host)
- return Platform::GetHostPlatformName ();
+ {
+ static ConstString g_host_name(Platform::GetHostPlatformName ());
+ return g_host_name;
+ }
else
- return "remote-macosx";
+ {
+ static ConstString g_remote_name("remote-macosx");
+ return g_remote_name;
+ }
}
const char *
@@ -193,8 +199,7 @@ PlatformMacOSX::GetFile (const lldb_priv
{
// try to find the file in the cache
std::string cache_path(GetLocalCacheDirectory());
- std::string module_path;
- platform_file.GetPath(module_path);
+ std::string module_path (platform_file.GetPath());
cache_path.append(module_path);
FileSpec module_cache_spec(cache_path.c_str(),false);
if (module_cache_spec.Exists())
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformMacOSX.h Thu Jun 6 19:06:43 2013
@@ -32,11 +32,8 @@ public:
static void
Terminate ();
- static const char *
- GetPluginNameStatic ();
-
- static const char *
- GetShortPluginNameStatic(bool is_host);
+ static lldb_private::ConstString
+ GetPluginNameStatic (bool is_host);
static const char *
GetDescriptionStatic(bool is_host);
@@ -52,16 +49,10 @@ public:
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
- return GetPluginNameStatic ();
- }
-
- virtual const char *
- GetShortPluginName()
- {
- return GetShortPluginNameStatic (IsHost());
+ return GetPluginNameStatic (IsHost());
}
virtual uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp Thu Jun 6 19:06:43 2013
@@ -18,6 +18,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
@@ -64,7 +65,7 @@ PlatformRemoteiOS::Initialize ()
{
if (g_initialize_count++ == 0)
{
- PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(),
+ PluginManager::RegisterPlugin (PlatformRemoteiOS::GetPluginNameStatic(),
PlatformRemoteiOS::GetDescriptionStatic(),
PlatformRemoteiOS::CreateInstance);
}
@@ -101,14 +102,18 @@ PlatformRemoteiOS::CreateInstance (bool
create = true;
break;
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
+#endif
default:
break;
}
-
if (create)
{
switch (triple.getOS())
@@ -117,10 +122,14 @@ PlatformRemoteiOS::CreateInstance (bool
case llvm::Triple::IOS: // This is the right triple value for iOS debugging
break;
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
-
+#endif
default:
create = false;
break;
@@ -139,16 +148,11 @@ PlatformRemoteiOS::CreateInstance (bool
}
-const char *
+lldb_private::ConstString
PlatformRemoteiOS::GetPluginNameStatic ()
{
- return "PlatformRemoteiOS";
-}
-
-const char *
-PlatformRemoteiOS::GetShortPluginNameStatic()
-{
- return "remote-ios";
+ static ConstString g_name("remote-ios");
+ return g_name;
}
const char *
@@ -196,14 +200,93 @@ PlatformRemoteiOS::GetStatus (Stream &st
for (uint32_t i=0; i<num_sdk_infos; ++i)
{
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
- strm.Printf (" SDK Roots: [%2u] \"%s/%s\"\n",
+ strm.Printf (" SDK Roots: [%2u] \"%s\"\n",
i,
- sdk_dir_info.directory.GetDirectory().GetCString(),
- sdk_dir_info.directory.GetFilename().GetCString());
+ sdk_dir_info.directory.GetPath().c_str());
}
}
+Error
+PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
+ const ArchSpec &exe_arch,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ FileSpec resolved_exe_file (exe_file);
+
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ // TODO: resolve bare executables in the Platform SDK
+// if (!resolved_exe_file.Exists())
+// resolved_exe_file.ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_exe_file);
+
+ if (resolved_exe_file.Exists())
+ {
+ if (exe_arch.IsValid())
+ {
+ ModuleSpec module_spec (resolved_exe_file, exe_arch);
+ error = ModuleList::GetSharedModule (module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ ArchSpec platform_arch;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+ {
+ ModuleSpec module_spec (resolved_exe_file, platform_arch);
+ error = ModuleList::GetSharedModule (module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (platform_arch.GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ exe_file.GetPath().c_str());
+ }
+
+ return error;
+}
+
FileSpec::EnumerateDirectoryResult
PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
FileSpec::FileType file_type,
@@ -573,7 +656,7 @@ PlatformRemoteiOS::GetSymbolFile (const
error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
platform_file_path,
- GetPluginName());
+ GetPluginName().GetCString());
}
else
{
@@ -619,7 +702,7 @@ PlatformRemoteiOS::GetSharedModule (cons
{
if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, local_file))
{
- //printf ("sdk[%u] last: '%s/%s'\n", m_last_module_sdk_idx, local_file.GetDirectory().GetCString(), local_file.GetFilename().GetCString());
+ //printf ("sdk[%u] last: '%s'\n", m_last_module_sdk_idx, local_file.GetPath().c_str());
module_sp.reset();
error = ResolveExecutable (local_file,
module_spec.GetArchitecture(),
@@ -645,7 +728,7 @@ PlatformRemoteiOS::GetSharedModule (cons
}
if (GetFileInSDK (platform_file_path, sdk_idx, local_file))
{
- //printf ("sdk[%u]: '%s/%s'\n", sdk_idx, local_file.GetDirectory().GetCString(), local_file.GetFilename().GetCString());
+ //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
error = ResolveExecutable (local_file,
module_spec.GetArchitecture(),
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h Thu Jun 6 19:06:43 2013
@@ -34,13 +34,10 @@ public:
static void
Terminate ();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic ();
static const char *
- GetShortPluginNameStatic();
-
- static const char *
GetDescriptionStatic();
//------------------------------------------------------------
@@ -54,18 +51,12 @@ public:
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
return GetPluginNameStatic();
}
- virtual const char *
- GetShortPluginName()
- {
- return GetShortPluginNameStatic();
- }
-
virtual uint32_t
GetPluginVersion()
{
@@ -75,6 +66,12 @@ public:
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
+ virtual lldb_private::Error
+ ResolveExecutable (const lldb_private::FileSpec &exe_file,
+ const lldb_private::ArchSpec &arch,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr);
+
virtual const char *
GetDescription ()
{
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp Thu Jun 6 19:06:43 2013
@@ -18,6 +18,7 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
@@ -41,7 +42,7 @@ PlatformiOSSimulator::Initialize ()
{
if (g_initialize_count++ == 0)
{
- PluginManager::RegisterPlugin (PlatformiOSSimulator::GetShortPluginNameStatic(),
+ PluginManager::RegisterPlugin (PlatformiOSSimulator::GetPluginNameStatic(),
PlatformiOSSimulator::GetDescriptionStatic(),
PlatformiOSSimulator::CreateInstance);
}
@@ -77,10 +78,14 @@ PlatformiOSSimulator::CreateInstance (bo
create = true;
break;
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
-
+#endif
default:
break;
}
@@ -94,10 +99,14 @@ PlatformiOSSimulator::CreateInstance (bo
case llvm::Triple::IOS: // IOS is not used for simulator triples, but accept it just in case
break;
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned becasue it
+ // was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
-
+#endif
default:
create = false;
break;
@@ -115,16 +124,11 @@ PlatformiOSSimulator::CreateInstance (bo
}
-const char *
+lldb_private::ConstString
PlatformiOSSimulator::GetPluginNameStatic ()
{
- return "PlatformiOSSimulator";
-}
-
-const char *
-PlatformiOSSimulator::GetShortPluginNameStatic()
-{
- return "ios-simulator";
+ static ConstString g_name("ios-simulator");
+ return g_name;
}
const char *
@@ -138,7 +142,7 @@ PlatformiOSSimulator::GetDescriptionStat
/// Default Constructor
//------------------------------------------------------------------
PlatformiOSSimulator::PlatformiOSSimulator () :
- PlatformDarwin (false),
+ PlatformDarwin (true),
m_sdk_directory ()
{
}
@@ -198,7 +202,7 @@ PlatformiOSSimulator::ResolveExecutable
NULL,
NULL);
- if (exe_module_sp->GetObjectFile())
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
@@ -231,20 +235,16 @@ PlatformiOSSimulator::ResolveExecutable
if (error.Fail() || !exe_module_sp)
{
- error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""),
- GetShortPluginName(),
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ exe_file.GetPath().c_str(),
+ GetPluginName().GetCString(),
arch_names.GetString().c_str());
}
}
else
{
- error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
- exe_file.GetDirectory().AsCString(""),
- exe_file.GetDirectory() ? "/" : "",
- exe_file.GetFilename().AsCString(""));
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ exe_file.GetPath().c_str());
}
return error;
@@ -347,7 +347,7 @@ PlatformiOSSimulator::GetSymbolFile (con
}
error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
platform_file_path,
- GetPluginName());
+ GetPluginName().GetCString());
}
else
{
@@ -403,14 +403,6 @@ PlatformiOSSimulator::FindProcesses (con
}
bool
-PlatformiOSSimulator::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
- // TODO: if connected, send a packet to get the remote process info
- process_info.Clear();
- return false;
-}
-
-bool
PlatformiOSSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
if (idx == 0)
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h Thu Jun 6 19:06:43 2013
@@ -32,13 +32,10 @@ public:
static void
Terminate ();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic ();
static const char *
- GetShortPluginNameStatic();
-
- static const char *
GetDescriptionStatic();
//------------------------------------------------------------
@@ -52,18 +49,12 @@ public:
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
return GetPluginNameStatic();
}
- virtual const char *
- GetShortPluginName()
- {
- return GetShortPluginNameStatic();
- }
-
virtual uint32_t
GetPluginVersion()
{
@@ -105,10 +96,6 @@ public:
lldb_private::ProcessInstanceInfoList &process_infos);
virtual bool
- GetProcessInfo (lldb::pid_t pid,
- lldb_private::ProcessInstanceInfo &proc_info);
-
- virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx,
lldb_private::ArchSpec &arch);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp Thu Jun 6 19:06:43 2013
@@ -16,6 +16,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/File.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
@@ -89,54 +90,62 @@ PlatformPOSIX::MakeDirectory (const std:
lldb::user_id_t
PlatformPOSIX::OpenFile (const FileSpec& file_spec,
- uint32_t flags,
- mode_t mode)
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
{
if (IsHost())
{
- return Host::OpenFile(file_spec, flags, mode);
+ return Host::OpenFile(file_spec, flags, mode, error);
}
if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->OpenFile(file_spec, flags, mode);
- return Platform::OpenFile(file_spec, flags, mode);
+ return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
+ return Platform::OpenFile(file_spec, flags, mode, error);
}
bool
-PlatformPOSIX::CloseFile (lldb::user_id_t fd)
+PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
{
if (IsHost())
{
- return Host::CloseFile(fd);
+ return Host::CloseFile(fd, error);
}
if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->CloseFile(fd);
- return Platform::CloseFile(fd);
+ return m_remote_platform_sp->CloseFile(fd, error);
+ return Platform::CloseFile(fd, error);
}
-uint32_t
-PlatformPOSIX::ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len)
+uint64_t
+PlatformPOSIX::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
{
if (IsHost())
{
- return Host::ReadFile(fd, offset, data_ptr, len);
+ return Host::ReadFile(fd, offset, dst, dst_len, error);
}
if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->ReadFile(fd, offset, data_ptr, len);
- return Platform::ReadFile(fd, offset, data_ptr, len);
+ return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
+ return Platform::ReadFile(fd, offset, dst, dst_len, error);
}
-uint32_t
-PlatformPOSIX::WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len)
+uint64_t
+PlatformPOSIX::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
{
if (IsHost())
{
- return Host::WriteFile(fd, offset, data, len);
+ return Host::WriteFile(fd, offset, src, src_len, error);
}
if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->WriteFile(fd, offset, data, len);
- return Platform::WriteFile(fd, offset, data, len);
+ return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
+
+ return Platform::WriteFile(fd, offset, src, src_len, error);
}
static uint32_t
@@ -174,18 +183,17 @@ PlatformPOSIX::PutFile (const lldb_priva
uint32_t uid,
uint32_t gid)
{
-#define PUTFILE_CHUNK_SIZE 1024
if (IsHost())
{
if (FileSpec::Equal(source, destination, true))
return Error();
// cp src dst
// chown uid:gid dst
- std::string src_path;
- if (source.GetPath(src_path) == 0)
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
return Error("unable to get file path for source");
- std::string dst_path;
- if (destination.GetPath(dst_path) == 0)
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
return Error("unable to get file path for destination");
StreamString command;
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
@@ -204,15 +212,15 @@ PlatformPOSIX::PutFile (const lldb_priva
return Error("unable to perform chown");
return Error();
}
- if (IsRemote() && m_remote_platform_sp)
+ else if (IsRemote() && m_remote_platform_sp)
{
if (GetSupportsRSync())
{
- std::string src_path;
- if (source.GetPath(src_path) == 0)
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
return Error("unable to get file path for source");
- std::string dst_path;
- if (destination.GetPath(dst_path) == 0)
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
return Error("unable to get file path for destination");
StreamString command;
if (GetIgnoresRemoteHostname())
@@ -245,8 +253,9 @@ PlatformPOSIX::PutFile (const lldb_priva
60);
if (retcode == 0)
{
- if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
- return Error("unable to perform chown");
+ // Don't chown a local file for a remote system
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
return Error();
}
// if we are still here rsync has failed - let's try the slow way before giving up
@@ -259,33 +268,38 @@ PlatformPOSIX::PutFile (const lldb_priva
File source_file(source, File::eOpenOptionRead, File::ePermissionsUserRW);
if (!source_file.IsValid())
return Error("unable to open source file");
- lldb::user_id_t dest_file = OpenFile(destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
- File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX);
+ Error error;
+ lldb::user_id_t dest_file = OpenFile (destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX,
+ error);
+ printf ("dest_file = %lli\n", dest_file);
+ if (error.Fail())
+ return error;
if (dest_file == UINT64_MAX)
return Error("unable to open target file");
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(PUTFILE_CHUNK_SIZE, 0));
- Error err;
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
uint64_t offset = 0;
- while (err.Success())
+ while (error.Success())
{
- size_t read_data = PUTFILE_CHUNK_SIZE;
- err = source_file.Read(buffer_sp->GetBytes(), read_data);
- if (read_data)
+ size_t bytes_read = buffer_sp->GetByteSize();
+ error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
+ if (bytes_read)
{
- WriteFile(dest_file, offset, buffer_sp->GetBytes(), read_data);
- offset += read_data;
+ WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
+ offset += bytes_read;
}
else
break;
}
- CloseFile(dest_file);
+ CloseFile(dest_file, error);
if (uid == UINT32_MAX && gid == UINT32_MAX)
- return Error();
- std::string dst_path;
- destination.GetPath(dst_path);
- if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
- return Error("unable to perform chown");
- return Error();
+ return error;
+ // This is remopve, don't chown a local file...
+// std::string dst_path (destination.GetPath());
+// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
+// return Error("unable to perform chown");
+ return error;
}
return Platform::PutFile(source,destination,uid,gid);
}
@@ -314,17 +328,31 @@ PlatformPOSIX::GetFileExists (const File
return Platform::GetFileExists(file_spec);
}
+uint32_t
+PlatformPOSIX::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
+{
+ if (IsHost())
+ {
+ return File::GetPermissions(file_spec.GetPath().c_str(), error);
+ }
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetFilePermissions(file_spec, error);
+ return Platform::GetFilePermissions(file_spec, error);
+
+}
+
+
lldb_private::Error
PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
const lldb_private::FileSpec& destination /* local file path */)
{
-#define GETFILE_CHUNK_SIZE 1024
- // Check the args, first.
- std::string src_path;
- if (source.GetPath(src_path) == 0)
+ // Check the args, first.
+ std::string src_path (source.GetPath());
+ if (src_path.empty())
return Error("unable to get file path for source");
- std::string dst_path;
- if (destination.GetPath(dst_path) == 0)
+ std::string dst_path (destination.GetPath());
+ if (dst_path.empty())
return Error("unable to get file path for destination");
if (IsHost())
{
@@ -386,41 +414,71 @@ PlatformPOSIX::GetFile (const lldb_priva
// close src
// close dst
printf("[GetFile] Using block by block transfer....\n");
- user_id_t fd_src = OpenFile(source, File::eOpenOptionRead, File::ePermissionsDefault);
- user_id_t fd_dst = Host::OpenFile(destination,
- File::eOpenOptionCanCreate|File::eOpenOptionWrite,
- File::ePermissionsDefault);
+ Error error;
+ user_id_t fd_src = OpenFile (source,
+ File::eOpenOptionRead,
+ File::ePermissionsDefault,
+ error);
+
if (fd_src == UINT64_MAX)
return Error("unable to open source file");
- if (fd_dst == UINT64_MAX)
- return Error("unable to open destination file");
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(GETFILE_CHUNK_SIZE, 0));
- uint8_t *cursor = buffer_sp->GetBytes();
- Error err;
- uint64_t offset = 0;
- while (err.Success())
- {
- user_id_t n_read = ReadFile(fd_src, offset, cursor, GETFILE_CHUNK_SIZE);
- if (n_read == UINT32_MAX)
- return Error("error during read operation");
- // Break out of the loop once we reach end of file.
- if (n_read == 0)
- break;
+ uint32_t permissions = GetFilePermissions(source, error);
+
+ if (permissions == 0)
+ permissions = File::ePermissionsDefault;
- if (!Host::WriteFile(fd_dst, offset, cursor, n_read))
- return Error("unable to write to destination file");
+ user_id_t fd_dst = Host::OpenFile(destination,
+ File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
+ permissions,
+ error);
- offset += n_read;
- cursor += n_read;
+ if (fd_dst == UINT64_MAX)
+ {
+ if (error.Success())
+ error.SetErrorString("unable to open destination file");
+ }
+ if (error.Success())
+ {
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ uint64_t offset = 0;
+ error.Clear();
+ while (error.Success())
+ {
+ const uint64_t n_read = ReadFile (fd_src,
+ offset,
+ buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(),
+ error);
+ if (error.Fail())
+ break;
+ if (n_read == 0)
+ break;
+ if (Host::WriteFile(fd_dst,
+ offset,
+ buffer_sp->GetBytes(),
+ n_read,
+ error) != n_read)
+ {
+ if (!error.Fail())
+ error.SetErrorString("unable to write to destination file");
+ break;
+ }
+ offset += n_read;
+ }
}
// Ignore the close error of src.
- CloseFile(fd_src);
+ if (fd_src != UINT64_MAX)
+ CloseFile(fd_src, error);
// And close the dst file descriptot.
- if (!Host::CloseFile(fd_dst))
- return Error("unable to close destination file");
- return Error();
+ if (fd_dst != UINT64_MAX && !Host::CloseFile(fd_dst, error))
+ {
+ if (!error.Fail())
+ error.SetErrorString("unable to close destination file");
+
+ }
+ return error;
}
return Platform::GetFile(source,destination);
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/POSIX/PlatformPOSIX.h Thu Jun 6 19:06:43 2013
@@ -43,18 +43,26 @@ public:
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode);
+ mode_t mode,
+ lldb_private::Error &error);
virtual bool
- CloseFile (lldb::user_id_t fd);
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
- virtual uint32_t
- ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len);
-
- virtual uint32_t
- WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len);
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
virtual lldb::user_id_t
GetFileSize (const lldb_private::FileSpec& file_spec);
@@ -78,6 +86,10 @@ public:
virtual bool
GetFileExists (const lldb_private::FileSpec& file_spec);
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
virtual std::string
GetPlatformSpecificConnectionInformation();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "PlatformRemoteGDBServer.h"
// C Includes
@@ -39,7 +41,7 @@ PlatformRemoteGDBServer::Initialize ()
if (g_initialized == false)
{
g_initialized = true;
- PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetShortPluginNameStatic(),
+ PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(),
PlatformRemoteGDBServer::GetDescriptionStatic(),
PlatformRemoteGDBServer::CreateInstance);
}
@@ -69,10 +71,11 @@ PlatformRemoteGDBServer::CreateInstance
}
-const char *
-PlatformRemoteGDBServer::GetShortPluginNameStatic()
+lldb_private::ConstString
+PlatformRemoteGDBServer::GetPluginNameStatic()
{
- return "remote-gdb-server";
+ static ConstString g_name("remote-gdb-server");
+ return g_name;
}
const char *
@@ -372,9 +375,10 @@ PlatformRemoteGDBServer::Attach (lldb_pr
{
if (IsConnected())
{
- uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
- if (port == 0)
+ if (port == 0 || debugserver_pid == LLDB_INVALID_PROCESS_ID)
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
}
@@ -383,10 +387,9 @@ PlatformRemoteGDBServer::Attach (lldb_pr
if (target == NULL)
{
TargetSP new_target_sp;
- FileSpec emptyFileSpec;
error = debugger.GetTargetList().CreateTarget (debugger,
- emptyFileSpec,
+ NULL,
NULL,
false,
NULL,
@@ -416,9 +419,14 @@ PlatformRemoteGDBServer::Attach (lldb_pr
override_hostname ? override_hostname : GetHostname (),
port + port_offset);
assert (connect_url_len < sizeof(connect_url));
- error = process_sp->ConnectRemote (connect_url);
+ error = process_sp->ConnectRemote (NULL, connect_url);
if (error.Success())
error = process_sp->Attach(attach_info);
+ else
+ {
+ bool success = m_gdb_client.KillSpawnedProcess(debugserver_pid);
+ printf ("success = %i\n", success);
+ }
}
}
}
@@ -441,35 +449,49 @@ PlatformRemoteGDBServer::MakeDirectory (
lldb::user_id_t
PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode)
+ mode_t mode,
+ Error &error)
{
- return m_gdb_client.OpenFile (file_spec, flags, mode);
+ return m_gdb_client.OpenFile (file_spec, flags, mode, error);
}
bool
-PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd)
+PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error)
{
- return m_gdb_client.CloseFile (fd);
+ return m_gdb_client.CloseFile (fd, error);
}
lldb::user_id_t
-PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& source)
+PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec)
{
- return m_gdb_client.GetFileSize(source);
+ return m_gdb_client.GetFileSize(file_spec);
}
uint32_t
-PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len)
+PlatformRemoteGDBServer::GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error)
{
- return m_gdb_client.ReadFile (fd, offset, data_ptr, len);
+ return m_gdb_client.GetFilePermissions(file_spec, error);
}
-uint32_t
-PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len)
+uint64_t
+PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error);
+}
+
+uint64_t
+PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
{
- return m_gdb_client.WriteFile (fd, offset, data, len);
+ return m_gdb_client.WriteFile (fd, offset, src, src_len, error);
}
lldb_private::Error
Modified: lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h Thu Jun 6 19:06:43 2013
@@ -32,8 +32,8 @@ public:
static lldb_private::Platform*
CreateInstance (bool force, const lldb_private::ArchSpec *arch);
- static const char *
- GetShortPluginNameStatic();
+ static lldb_private::ConstString
+ GetPluginNameStatic();
static const char *
GetDescriptionStatic();
@@ -47,16 +47,10 @@ public:
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
- return "PlatformRemoteGDBServer";
- }
-
- virtual const char *
- GetShortPluginName()
- {
- return GetShortPluginNameStatic();
+ return GetPluginNameStatic();
}
virtual uint32_t
@@ -148,22 +142,30 @@ public:
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode);
+ mode_t mode,
+ lldb_private::Error &error);
virtual bool
- CloseFile (lldb::user_id_t fd);
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *data_ptr,
+ uint64_t len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* data,
+ uint64_t len,
+ lldb_private::Error &error);
+
virtual lldb::user_id_t
GetFileSize (const lldb_private::FileSpec& file_spec);
- virtual uint32_t
- ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len);
-
- virtual uint32_t
- WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len);
-
virtual lldb_private::Error
PutFile (const lldb_private::FileSpec& source,
const lldb_private::FileSpec& destination,
@@ -173,6 +175,10 @@ public:
virtual bool
GetFileExists (const lldb_private::FileSpec& file_spec);
+ virtual uint32_t
+ GetFilePermissions (const lldb_private::FileSpec &file_spec,
+ lldb_private::Error &error);
+
virtual lldb_private::Error
RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt (from r182522, lldb/trunk/source/Plugins/Process/CMakeLists.txt)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt&p1=lldb/trunk/source/Plugins/Process/CMakeLists.txt&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/CMakeLists.txt (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/CMakeLists.txt Thu Jun 6 19:06:43 2013
@@ -2,7 +2,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
add_subdirectory(Linux)
add_subdirectory(POSIX)
elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
- #add_subdirectory(FreeBSD)
+ add_subdirectory(FreeBSD)
add_subdirectory(POSIX)
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX-Kernel)
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt (from r182522, lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt&p1=lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/CMakeLists.txt Thu Jun 6 19:06:43 2013
@@ -1,5 +1,8 @@
set(LLVM_NO_RTTI 1)
+include_directories(.)
+include_directories(../POSIX)
+
add_lldb_library(lldbPluginProcessFreeBSD
ProcessFreeBSD.cpp
ProcessMonitor.cpp
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp Thu Jun 6 19:06:43 2013
@@ -64,10 +64,11 @@ ProcessFreeBSD::Initialize()
}
}
-const char *
+lldb_private::ConstString
ProcessFreeBSD::GetPluginNameStatic()
{
- return "freebsd";
+ static ConstString g_name("freebsd");
+ return g_name;
}
const char *
@@ -79,16 +80,10 @@ ProcessFreeBSD::GetPluginDescriptionStat
//------------------------------------------------------------------------------
// ProcessInterface protocol.
-const char *
+lldb_private::ConstString
ProcessFreeBSD::GetPluginName()
{
- return "process.freebsd";
-}
-
-const char *
-ProcessFreeBSD::GetShortPluginName()
-{
- return "process.freebsd";
+ return GetPluginNameStatic();
}
uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h Thu Jun 6 19:06:43 2013
@@ -42,7 +42,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -60,12 +60,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Jun 6 19:06:43 2013
@@ -58,13 +58,15 @@ Get_PT_IO_OP(int op)
}
}
+// Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 is reserved as a valid result.
extern long
-PtraceWrapper(int req, ::pid_t pid, void *addr, int data,
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
const char* reqName, const char* file, int line)
{
long int result;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
if (log) {
log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d",
@@ -84,7 +86,7 @@ PtraceWrapper(int req, ::pid_t pid, void
//PtraceDisplayBytes(req, data);
- if (log && (result == -1 || errno != 0))
+ if (log && errno != 0)
{
const char* str;
switch (errno)
@@ -112,10 +114,21 @@ PtraceWrapper(int req, ::pid_t pid, void
return result;
}
+// Wrapper for ptrace when logging is not required.
+// Sets errno to 0 prior to calling ptrace.
+extern long
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data)
+{
+ long result = 0;
+ errno = 0;
+ result = ptrace(req, pid, (caddr_t)addr, data);
+ return result;
+}
+
#define PTRACE(req, pid, addr, data) \
PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
#else
-#define PTRACE ptrace
+ PtraceWrapper((req), (pid), (addr), (data))
#endif
//------------------------------------------------------------------------------
@@ -502,8 +515,8 @@ SingleStepOperation::Execute(ProcessMoni
class SiginfoOperation : public Operation
{
public:
- SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
- : m_tid(tid), m_info(info), m_result(result) { }
+ SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
+ : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
void Execute(ProcessMonitor *monitor);
@@ -511,6 +524,7 @@ private:
lldb::tid_t m_tid;
void *m_info;
bool &m_result;
+ int &m_err;
};
void
@@ -518,9 +532,10 @@ SiginfoOperation::Execute(ProcessMonitor
{
struct ptrace_lwpinfo plwp;
- if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
+ if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
m_result = false;
- else {
+ m_err = errno;
+ } else {
memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t));
m_result = true;
}
@@ -625,14 +640,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(P
char const **envp,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path)
+ const char *stderr_path,
+ const char *working_dir)
: OperationArgs(monitor),
m_module(module),
m_argv(argv),
m_envp(envp),
m_stdin_path(stdin_path),
m_stdout_path(stdout_path),
- m_stderr_path(stderr_path) { }
+ m_stderr_path(stderr_path),
+ m_working_dir(working_dir) { }
ProcessMonitor::LaunchArgs::~LaunchArgs()
{ }
@@ -663,6 +680,7 @@ ProcessMonitor::ProcessMonitor(ProcessPO
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
+ const char *working_dir,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
@@ -673,10 +691,10 @@ ProcessMonitor::ProcessMonitor(ProcessPO
m_client_fd(-1),
m_server_fd(-1)
{
- std::auto_ptr<LaunchArgs> args;
+ std::unique_ptr<LaunchArgs> args;
args.reset(new LaunchArgs(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path));
+ stdin_path, stdout_path, stderr_path, working_dir));
// Server/client descriptors.
@@ -734,7 +752,7 @@ ProcessMonitor::ProcessMonitor(ProcessPO
m_client_fd(-1),
m_server_fd(-1)
{
- std::auto_ptr<AttachArgs> args;
+ std::unique_ptr<AttachArgs> args;
args.reset(new AttachArgs(this, pid));
@@ -837,6 +855,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
const char *stdin_path = args->m_stdin_path;
const char *stdout_path = args->m_stdout_path;
const char *stderr_path = args->m_stderr_path;
+ const char *working_dir = args->m_working_dir;
lldb::pid_t pid;
lldb::ThreadSP inferior;
@@ -851,6 +870,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdinFailed,
eDupStdoutFailed,
eDupStderrFailed,
+ eChdirFailed,
eExecFailed
};
@@ -885,6 +905,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
exit(eDupStderrFailed);
+ // Change working directory
+ if (working_dir != NULL && working_dir[0])
+ if (0 != ::chdir(working_dir))
+ exit(eChdirFailed);
+
// Execute. We should never return.
execve(argv[0],
const_cast<char *const *>(argv),
@@ -918,6 +943,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
case eDupStderrFailed:
args->m_error.SetErrorString("Child open stderr failed.");
break;
+ case eChdirFailed:
+ args->m_error.SetErrorString("Child failed to set working directory.");
+ break;
case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;
@@ -952,7 +980,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
goto FINISH;
// Update the process thread list with this new thread.
- inferior.reset(new POSIXThread(processSP, pid));
+ inferior.reset(new POSIXThread(*processSP, pid));
process.GetThreadList().AddThread(inferior);
// Let our process instance know the thread has stopped.
@@ -1038,7 +1066,7 @@ ProcessMonitor::Attach(AttachArgs *args)
}
// Update the process thread list with the attached thread.
- inferior.reset(new POSIXThread(processSP, pid));
+ inferior.reset(new POSIXThread(*processSP, pid));
tl.AddThread(inferior);
// Let our process instance know the thread has stopped.
@@ -1060,8 +1088,9 @@ ProcessMonitor::MonitorCallback(void *ca
ProcessFreeBSD *process = monitor->m_process;
bool stop_monitoring;
siginfo_t info;
+ int ptrace_err;
- if (!monitor->GetSignalInfo(pid, &info))
+ if (!monitor->GetSignalInfo(pid, &info, ptrace_err))
stop_monitoring = true; // pid is gone. Bail.
else {
switch (info.si_signo)
@@ -1088,7 +1117,8 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
{
ProcessMessage message;
- assert(info->si_signo == SIGTRAP && "Unexpected child signal!");
+ assert(monitor);
+ assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
switch (info->si_code)
{
@@ -1407,7 +1437,8 @@ ProcessMonitor::WriteMemory(lldb::addr_t
}
bool
-ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
+ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
+ unsigned size, RegisterValue &value)
{
bool result;
ReadRegOperation op(offset, size, value, result);
@@ -1416,7 +1447,8 @@ ProcessMonitor::ReadRegisterValue(unsign
}
bool
-ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)
+ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char* reg_name, const RegisterValue &value)
{
bool result;
WriteRegOperation op(offset, value, result);
@@ -1425,7 +1457,20 @@ ProcessMonitor::WriteRegisterValue(unsig
}
bool
-ProcessMonitor::ReadGPR(void *buf)
+ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+ return false;
+}
+
+bool
+ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+ return false;
+}
+
+
+bool
+ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
ReadGPROperation op(buf, result);
@@ -1434,7 +1479,7 @@ ProcessMonitor::ReadGPR(void *buf)
}
bool
-ProcessMonitor::ReadFPR(void *buf)
+ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
ReadFPROperation op(buf, result);
@@ -1443,7 +1488,7 @@ ProcessMonitor::ReadFPR(void *buf)
}
bool
-ProcessMonitor::WriteGPR(void *buf)
+ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
WriteGPROperation op(buf, result);
@@ -1452,7 +1497,7 @@ ProcessMonitor::WriteGPR(void *buf)
}
bool
-ProcessMonitor::WriteFPR(void *buf)
+ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
WriteFPROperation op(buf, result);
@@ -1488,10 +1533,10 @@ ProcessMonitor::BringProcessIntoLimbo()
}
bool
-ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
{
bool result;
- SiginfoOperation op(tid, siginfo, result);
+ SiginfoOperation op(tid, siginfo, result, ptrace_err);
DoOperation(&op);
return result;
}
@@ -1506,7 +1551,7 @@ ProcessMonitor::GetEventMessage(lldb::ti
}
Error
-ProcessMonitor::Detach()
+ProcessMonitor::Detach(lldb::tid_t tid)
{
Error result;
DetachOperation op(result);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessMonitor.h Thu Jun 6 19:06:43 2013
@@ -54,6 +54,7 @@ public:
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
+ const char *working_dir,
lldb_private::Error &error);
ProcessMonitor(ProcessPOSIX *process,
@@ -103,36 +104,66 @@ public:
/// dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
+ ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ unsigned size, lldb_private::RegisterValue &value);
/// Writes the given value to the register identified by the given
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);
+ WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- ReadGPR(void *buf);
+ ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads all floating point registers into the specified buffer.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- ReadFPR(void *buf);
+ ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Reads the specified register set into the specified buffer.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
+ bool
+ ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes all general purpose registers into the specified buffer.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- WriteGPR(void *buf);
+ WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes all floating point registers into the specified buffer.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
bool
- WriteFPR(void *buf);
+ WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Writes the specified register set into the specified buffer.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
+ bool
+ WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes a siginfo_t structure corresponding to the given thread ID to the
/// memory region pointed to by @p siginfo.
bool
- GetSignalInfo(lldb::tid_t tid, void *siginfo);
+ GetSignalInfo(lldb::tid_t tid, void *siginfo, int &error_no);
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
/// corresponding to the given thread IDto the memory pointed to by @p
@@ -157,7 +188,7 @@ public:
BringProcessIntoLimbo();
lldb_private::Error
- Detach();
+ Detach(lldb::tid_t tid);
private:
@@ -196,7 +227,8 @@ private:
char const **envp,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path);
+ const char *stderr_path,
+ const char *working_dir);
~LaunchArgs();
@@ -206,6 +238,7 @@ private:
const char *m_stdin_path; // Redirect stdin or NULL.
const char *m_stdout_path; // Redirect stdout or NULL.
const char *m_stderr_path; // Redirect stderr or NULL.
+ const char *m_working_dir; // Working directory or NULL.
};
void
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h Thu Jun 6 19:06:43 2013
@@ -1,43 +0,0 @@
-//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
-#define liblldb_RegisterContextFreeBSD_x86_64_H_
-
- typedef struct _GPR
- {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rdi;
- uint64_t rsi;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t rdx;
- uint64_t rcx;
- uint64_t rax;
- uint32_t trapno;
- uint16_t fs;
- uint16_t gs;
- uint32_t err;
- uint16_t es;
- uint16_t ds;
- uint64_t rip;
- uint64_t cs;
- uint64_t rflags;
- uint64_t rsp;
- uint64_t ss;
- } GPR;
-
-#endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp Thu Jun 6 19:06:43 2013
@@ -64,7 +64,7 @@ ProcessLinux::Initialize()
// Constructors and destructors.
ProcessLinux::ProcessLinux(Target& target, Listener &listener)
- : ProcessPOSIX(target, listener)
+ : ProcessPOSIX(target, listener), m_stopping_threads(false)
{
#if 0
// FIXME: Putting this code in the ctor and saving the byte order in a
@@ -81,10 +81,11 @@ void
ProcessLinux::Terminate()
{
}
-const char *
+lldb_private::ConstString
ProcessLinux::GetPluginNameStatic()
{
- return "linux";
+ static ConstString g_name("linux");
+ return g_name;
}
const char *
@@ -97,23 +98,7 @@ ProcessLinux::GetPluginDescriptionStatic
bool
ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
-
- // Update the process thread list with this new thread.
- // FIXME: We should be using tid, not pid.
- assert(m_monitor);
- ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
- if (!thread_sp) {
- ProcessSP me = this->shared_from_this();
- thread_sp.reset(new POSIXThread(me, GetID()));
- }
-
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
- new_thread_list.AddThread(thread_sp);
-
+ new_thread_list = old_thread_list;
return new_thread_list.GetSize(false) > 0;
}
@@ -121,16 +106,10 @@ ProcessLinux::UpdateThreadList(ThreadLis
//------------------------------------------------------------------------------
// ProcessInterface protocol.
-const char *
+lldb_private::ConstString
ProcessLinux::GetPluginName()
{
- return "process.linux";
-}
-
-const char *
-ProcessLinux::GetShortPluginName()
-{
- return "process.linux";
+ return GetPluginNameStatic();
}
uint32_t
@@ -155,3 +134,39 @@ ProcessLinux::EnablePluginLogging(Stream
{
return NULL;
}
+
+// ProcessPOSIX override
+void
+ProcessLinux::StopAllThreads(lldb::tid_t stop_tid)
+{
+ // If a breakpoint occurs while we're stopping threads, we'll get back
+ // here, but we don't want to do it again. Only the MonitorChildProcess
+ // thread calls this function, so we don't need to protect this flag.
+ if (m_stopping_threads)
+ return;
+ m_stopping_threads = true;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log)
+ log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__);
+
+ // Walk the thread list and stop the other threads. The thread that caused
+ // the stop should already be marked as stopped before we get here.
+ Mutex::Locker thread_list_lock(m_thread_list.GetMutex());
+
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ assert(thread);
+ lldb::tid_t tid = thread->GetID();
+ if (!StateIsStoppedState(thread->GetState(), false))
+ m_monitor->StopThread(tid);
+ }
+
+ m_stopping_threads = false;
+
+ if (log)
+ log->Printf ("ProcessLinux::%s() finished", __FUNCTION__);
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h Thu Jun 6 19:06:43 2013
@@ -41,7 +41,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -58,12 +58,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -78,11 +75,28 @@ public:
EnablePluginLogging(lldb_private::Stream *strm,
lldb_private::Args &command);
+ //------------------------------------------------------------------
+ // Plug-in process overrides
+ //------------------------------------------------------------------
+ virtual lldb_private::UnixSignals &
+ GetUnixSignals ()
+ {
+ return m_linux_signals;
+ }
+
+ //------------------------------------------------------------------
+ // ProcessPOSIX overrides
+ //------------------------------------------------------------------
+ virtual void
+ StopAllThreads(lldb::tid_t stop_tid);
+
private:
/// Linux-specific signal set.
LinuxSignals m_linux_signals;
+ // Flag to avoid recursion when stopping all threads.
+ bool m_stopping_threads;
};
#endif // liblldb_MacOSXProcess_H_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.cpp Thu Jun 6 19:06:43 2013
@@ -7,15 +7,18 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
// C Includes
#include <errno.h>
#include <poll.h>
#include <string.h>
+#include <stdint.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
+#include <sys/syscall.h>
#include <sys/types.h>
-#include <sys/user.h>
#include <sys/wait.h>
// C++ Includes
@@ -37,6 +40,23 @@
#define DEBUG_PTRACE_MAXBYTES 20
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef PTRACE_GETREGSET
+ #define PTRACE_GETREGSET 0x4204
+#endif
+#ifndef PTRACE_SETREGSET
+ #define PTRACE_SETREGSET 0x4205
+#endif
+
+// Support hardware breakpoints in case it has not been defined
+#ifndef TRAP_HWBKPT
+ #define TRAP_HWBKPT 4
+#endif
+
+// Try to define a macro to encapsulate the tgkill syscall
+// fall back on kill() if tgkill isn't available
+#define tgkill(pid, tid, sig) syscall(SYS_tgkill, pid, tid, sig)
+
using namespace lldb_private;
// FIXME: this code is host-dependent with respect to types and
@@ -61,10 +81,10 @@ DisplayBytes (lldb_private::StreamString
}
}
-static void PtraceDisplayBytes(__ptrace_request &req, void *data)
+static void PtraceDisplayBytes(int &req, void *data, size_t data_size)
{
StreamString buf;
- LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
+ Log *verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (
POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE));
if (verbose_log)
@@ -77,36 +97,43 @@ static void PtraceDisplayBytes(__ptrace_
verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData());
break;
}
- case PTRACE_POKEDATA:
+ case PTRACE_POKEDATA:
{
DisplayBytes(buf, &data, 8);
verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData());
break;
}
- case PTRACE_POKEUSER:
+ case PTRACE_POKEUSER:
{
DisplayBytes(buf, &data, 8);
verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData());
break;
}
- case PTRACE_SETREGS:
+ case PTRACE_SETREGS:
{
- DisplayBytes(buf, data, sizeof(user_regs_struct));
+ DisplayBytes(buf, data, data_size);
verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData());
break;
}
case PTRACE_SETFPREGS:
{
- DisplayBytes(buf, data, sizeof(user_fpregs_struct));
+ DisplayBytes(buf, data, data_size);
verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData());
break;
}
- case PTRACE_SETSIGINFO:
+ case PTRACE_SETSIGINFO:
{
DisplayBytes(buf, data, sizeof(siginfo_t));
verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData());
break;
}
+ case PTRACE_SETREGSET:
+ {
+ // Extract iov_base from data, which is a pointer to the struct IOVEC
+ DisplayBytes(buf, *(void **)data, data_size);
+ verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData());
+ break;
+ }
default:
{
}
@@ -115,26 +142,30 @@ static void PtraceDisplayBytes(__ptrace_
}
// Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
extern long
-PtraceWrapper(__ptrace_request req, pid_t pid, void *addr, void *data,
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size,
const char* reqName, const char* file, int line)
{
long int result;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
if (log)
- log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d",
- reqName, pid, addr, data, file, line);
-
- PtraceDisplayBytes(req, data);
+ log->Printf("ptrace(%s, %lu, %p, %p, %zu) called from file %s line %d",
+ reqName, pid, addr, data, data_size, file, line);
+
+ PtraceDisplayBytes(req, data, data_size);
errno = 0;
- result = ptrace(req, pid, addr, data);
+ if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
+ result = ptrace(static_cast<__ptrace_request>(req), pid, *(unsigned int *)addr, data);
+ else
+ result = ptrace(static_cast<__ptrace_request>(req), pid, addr, data);
- PtraceDisplayBytes(req, data);
+ PtraceDisplayBytes(req, data, data_size);
- if (log && (result == -1 || errno != 0))
+ if (log && errno != 0)
{
const char* str;
switch (errno)
@@ -151,10 +182,24 @@ PtraceWrapper(__ptrace_request req, pid_
return result;
}
-#define PTRACE(req, pid, addr, data) \
- PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
+// Wrapper for ptrace when logging is not required.
+// Sets errno to 0 prior to calling ptrace.
+extern long
+PtraceWrapper(int req, pid_t pid, void *addr, void *data, size_t data_size)
+{
+ long result = 0;
+ errno = 0;
+ if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
+ result = ptrace(static_cast<__ptrace_request>(req), pid, *(unsigned int *)addr, data);
+ else
+ result = ptrace(static_cast<__ptrace_request>(req), pid, addr, data);
+ return result;
+}
+
+#define PTRACE(req, pid, addr, data, data_size) \
+ PtraceWrapper((req), (pid), (addr), (data), (data_size), #req, __FILE__, __LINE__)
#else
-#define PTRACE ptrace
+ PtraceWrapper((req), (pid), (addr), (data), (data_size))
#endif
//------------------------------------------------------------------------------
@@ -163,28 +208,29 @@ PtraceWrapper(__ptrace_request req, pid_
// functions without needed to go thru the thread funnel.
static size_t
-DoReadMemory(lldb::pid_t pid, unsigned word_size,
+DoReadMemory(lldb::pid_t pid,
lldb::addr_t vm_addr, void *buf, size_t size, Error &error)
{
+ // ptrace word size is determined by the host, not the child
+ static const unsigned word_size = sizeof(void*);
unsigned char *dst = static_cast<unsigned char*>(buf);
size_t bytes_read;
size_t remainder;
long data;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
if (log)
ProcessPOSIXLog::IncNestLevel();
if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+ log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
pid, word_size, (void*)vm_addr, buf, size);
assert(sizeof(data) >= word_size);
- assert(sizeof(void*) == word_size);
for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
{
errno = 0;
- data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL);
- if (data == -1L && errno)
+ data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL, 0);
+ if (errno)
{
error.SetErrorToErrno();
if (log)
@@ -196,8 +242,6 @@ DoReadMemory(lldb::pid_t pid, unsigned w
remainder = remainder > word_size ? word_size : remainder;
// Copy the data into our buffer
- if (log)
- memset(dst, 0, sizeof(dst));
for (unsigned i = 0; i < remainder; ++i)
dst[i] = ((data >> i*8) & 0xFF);
@@ -205,8 +249,14 @@ DoReadMemory(lldb::pid_t pid, unsigned w
(log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
(log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
- log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data);
+ {
+ uintptr_t print_dst = 0;
+ // Format bytes from data by moving into print_dst for log output
+ for (unsigned i = 0; i < remainder; ++i)
+ print_dst |= (((data >> i*8) & 0xFF) << i*8);
+ log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+ (void*)vm_addr, print_dst, (unsigned long)data);
+ }
vm_addr += word_size;
dst += word_size;
@@ -218,21 +268,22 @@ DoReadMemory(lldb::pid_t pid, unsigned w
}
static size_t
-DoWriteMemory(lldb::pid_t pid, unsigned word_size,
+DoWriteMemory(lldb::pid_t pid,
lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
{
+ // ptrace word size is determined by the host, not the child
+ static const unsigned word_size = sizeof(void*);
const unsigned char *src = static_cast<const unsigned char*>(buf);
size_t bytes_written = 0;
size_t remainder;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
if (log)
ProcessPOSIXLog::IncNestLevel();
if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+ log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
pid, word_size, (void*)vm_addr, buf, size);
- assert(sizeof(void*) == word_size);
for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
{
remainder = size - bytes_written;
@@ -252,7 +303,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
(void*)vm_addr, *(unsigned long*)src, data);
- if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data))
+ if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0))
{
error.SetErrorToErrno();
if (log)
@@ -263,7 +314,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
else
{
unsigned char buff[8];
- if (DoReadMemory(pid, word_size, vm_addr,
+ if (DoReadMemory(pid, vm_addr,
buff, word_size, error) != word_size)
{
if (log)
@@ -273,7 +324,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned
memcpy(buff, src, remainder);
- if (DoWriteMemory(pid, word_size, vm_addr,
+ if (DoWriteMemory(pid, vm_addr,
buff, word_size, error) != word_size)
{
if (log)
@@ -333,6 +384,7 @@ EnsureFDFlags(int fd, int flags, Error &
class Operation
{
public:
+ virtual ~Operation() {}
virtual void Execute(ProcessMonitor *monitor) = 0;
};
@@ -361,10 +413,9 @@ private:
void
ReadOperation::Execute(ProcessMonitor *monitor)
{
- const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
lldb::pid_t pid = monitor->GetPID();
- m_result = DoReadMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
+ m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
}
//------------------------------------------------------------------------------
@@ -392,10 +443,9 @@ private:
void
WriteOperation::Execute(ProcessMonitor *monitor)
{
- const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
lldb::pid_t pid = monitor->GetPID();
- m_result = DoWriteMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
+ m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
}
@@ -405,14 +455,18 @@ WriteOperation::Execute(ProcessMonitor *
class ReadRegOperation : public Operation
{
public:
- ReadRegOperation(unsigned offset, RegisterValue &value, bool &result)
- : m_offset(offset), m_value(value), m_result(result)
+ ReadRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ RegisterValue &value, bool &result)
+ : m_tid(tid), m_offset(offset), m_reg_name(reg_name),
+ m_value(value), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
- unsigned m_offset;
+ lldb::tid_t m_tid;
+ uintptr_t m_offset;
+ const char *m_reg_name;
RegisterValue &m_value;
bool &m_result;
};
@@ -420,13 +474,12 @@ private:
void
ReadRegOperation::Execute(ProcessMonitor *monitor)
{
- lldb::pid_t pid = monitor->GetPID();
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
// Set errno to zero so that we can detect a failed peek.
errno = 0;
- lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, pid, (void*)m_offset, NULL);
- if (data == -1UL && errno)
+ lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, NULL, 0);
+ if (errno)
m_result = false;
else
{
@@ -434,8 +487,8 @@ ReadRegOperation::Execute(ProcessMonitor
m_result = true;
}
if (log)
- log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__,
- POSIXThread::GetRegisterNameFromOffset(m_offset), data);
+ log->Printf ("ProcessMonitor::%s() reg %s: 0x%" PRIx64, __FUNCTION__,
+ m_reg_name, data);
}
//------------------------------------------------------------------------------
@@ -444,14 +497,18 @@ ReadRegOperation::Execute(ProcessMonitor
class WriteRegOperation : public Operation
{
public:
- WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result)
- : m_offset(offset), m_value(value), m_result(result)
+ WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ const RegisterValue &value, bool &result)
+ : m_tid(tid), m_offset(offset), m_reg_name(reg_name),
+ m_value(value), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
- unsigned m_offset;
+ lldb::tid_t m_tid;
+ uintptr_t m_offset;
+ const char *m_reg_name;
const RegisterValue &m_value;
bool &m_result;
};
@@ -460,21 +517,17 @@ void
WriteRegOperation::Execute(ProcessMonitor *monitor)
{
void* buf;
- lldb::pid_t pid = monitor->GetPID();
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
- if (sizeof(void*) == sizeof(uint64_t))
- buf = (void*) m_value.GetAsUInt64();
- else
- {
- assert(sizeof(void*) == sizeof(uint32_t));
- buf = (void*) m_value.GetAsUInt32();
- }
+#if __WORDSIZE == 32
+ buf = (void*) m_value.GetAsUInt32();
+#else
+ buf = (void*) m_value.GetAsUInt64();
+#endif
if (log)
- log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__,
- POSIXThread::GetRegisterNameFromOffset(m_offset), buf);
- if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf))
+ log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf);
+ if (PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0))
m_result = false;
else
m_result = true;
@@ -486,21 +539,23 @@ WriteRegOperation::Execute(ProcessMonito
class ReadGPROperation : public Operation
{
public:
- ReadGPROperation(void *buf, bool &result)
- : m_buf(buf), m_result(result)
+ ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
+ lldb::tid_t m_tid;
void *m_buf;
+ size_t m_buf_size;
bool &m_result;
};
void
ReadGPROperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_GETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+ if (PTRACE(PTRACE_GETREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
m_result = false;
else
m_result = true;
@@ -512,21 +567,52 @@ ReadGPROperation::Execute(ProcessMonitor
class ReadFPROperation : public Operation
{
public:
- ReadFPROperation(void *buf, bool &result)
- : m_buf(buf), m_result(result)
+ ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
+ lldb::tid_t m_tid;
void *m_buf;
+ size_t m_buf_size;
bool &m_result;
};
void
ReadFPROperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_GETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+ if (PTRACE(PTRACE_GETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadRegisterSetOperation
+/// @brief Implements ProcessMonitor::ReadRegisterSet.
+class ReadRegisterSetOperation : public Operation
+{
+public:
+ ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ void *m_buf;
+ size_t m_buf_size;
+ const unsigned int m_regset;
+ bool &m_result;
+};
+
+void
+ReadRegisterSetOperation::Execute(ProcessMonitor *monitor)
+{
+ if (PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0)
m_result = false;
else
m_result = true;
@@ -538,21 +624,23 @@ ReadFPROperation::Execute(ProcessMonitor
class WriteGPROperation : public Operation
{
public:
- WriteGPROperation(void *buf, bool &result)
- : m_buf(buf), m_result(result)
+ WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
+ lldb::tid_t m_tid;
void *m_buf;
+ size_t m_buf_size;
bool &m_result;
};
void
WriteGPROperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_SETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+ if (PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
m_result = false;
else
m_result = true;
@@ -564,21 +652,52 @@ WriteGPROperation::Execute(ProcessMonito
class WriteFPROperation : public Operation
{
public:
- WriteFPROperation(void *buf, bool &result)
- : m_buf(buf), m_result(result)
+ WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result)
{ }
void Execute(ProcessMonitor *monitor);
private:
+ lldb::tid_t m_tid;
void *m_buf;
+ size_t m_buf_size;
bool &m_result;
};
void
WriteFPROperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_SETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+ if (PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteRegisterSetOperation
+/// @brief Implements ProcessMonitor::WriteRegisterSet.
+class WriteRegisterSetOperation : public Operation
+{
+public:
+ WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result)
+ : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ void *m_buf;
+ size_t m_buf_size;
+ const unsigned int m_regset;
+ bool &m_result;
+};
+
+void
+WriteRegisterSetOperation::Execute(ProcessMonitor *monitor)
+{
+ if (PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0)
m_result = false;
else
m_result = true;
@@ -604,13 +723,19 @@ private:
void
ResumeOperation::Execute(ProcessMonitor *monitor)
{
- int data = 0;
+ intptr_t data = 0;
if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
data = m_signo;
- if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data))
+ if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data, 0))
+ {
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ if (log)
+ log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", m_tid, strerror(errno));
m_result = false;
+ }
else
m_result = true;
}
@@ -635,12 +760,12 @@ private:
void
SingleStepOperation::Execute(ProcessMonitor *monitor)
{
- int data = 0;
+ intptr_t data = 0;
if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
data = m_signo;
- if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data))
+ if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data, 0))
m_result = false;
else
m_result = true;
@@ -652,8 +777,8 @@ SingleStepOperation::Execute(ProcessMoni
class SiginfoOperation : public Operation
{
public:
- SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
- : m_tid(tid), m_info(info), m_result(result) { }
+ SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
+ : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
void Execute(ProcessMonitor *monitor);
@@ -661,13 +786,16 @@ private:
lldb::tid_t m_tid;
void *m_info;
bool &m_result;
+ int &m_err;
};
void
SiginfoOperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info))
+ if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info, 0)) {
m_result = false;
+ m_err = errno;
+ }
else
m_result = true;
}
@@ -692,7 +820,7 @@ private:
void
EventMessageOperation::Execute(ProcessMonitor *monitor)
{
- if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message))
+ if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message, 0))
m_result = false;
else
m_result = true;
@@ -717,7 +845,7 @@ KillOperation::Execute(ProcessMonitor *m
{
lldb::pid_t pid = monitor->GetPID();
- if (PTRACE(PTRACE_KILL, pid, NULL, NULL))
+ if (PTRACE(PTRACE_KILL, pid, NULL, NULL, 0))
m_result = false;
else
m_result = true;
@@ -729,22 +857,20 @@ KillOperation::Execute(ProcessMonitor *m
class DetachOperation : public Operation
{
public:
- DetachOperation(Error &result) : m_error(result) { }
+ DetachOperation(lldb::tid_t tid, Error &result) : m_tid(tid), m_error(result) { }
void Execute(ProcessMonitor *monitor);
private:
+ lldb::tid_t m_tid;
Error &m_error;
};
void
DetachOperation::Execute(ProcessMonitor *monitor)
{
- lldb::pid_t pid = monitor->GetPID();
-
- if (ptrace(PT_DETACH, pid, NULL, 0) < 0)
+ if (ptrace(PT_DETACH, m_tid, NULL, 0) < 0)
m_error.SetErrorToErrno();
-
}
ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
@@ -764,14 +890,16 @@ ProcessMonitor::LaunchArgs::LaunchArgs(P
char const **envp,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path)
+ const char *stderr_path,
+ const char *working_dir)
: OperationArgs(monitor),
m_module(module),
m_argv(argv),
m_envp(envp),
m_stdin_path(stdin_path),
m_stdout_path(stdout_path),
- m_stderr_path(stderr_path) { }
+ m_stderr_path(stderr_path),
+ m_working_dir(working_dir) { }
ProcessMonitor::LaunchArgs::~LaunchArgs()
{ }
@@ -802,19 +930,20 @@ ProcessMonitor::ProcessMonitor(ProcessPO
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
+ const char *working_dir,
lldb_private::Error &error)
: m_process(static_cast<ProcessLinux *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
+ m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
m_terminal_fd(-1),
- m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_client_fd(-1),
m_server_fd(-1)
{
- std::auto_ptr<LaunchArgs> args;
+ std::unique_ptr<LaunchArgs> args;
args.reset(new LaunchArgs(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path));
+ stdin_path, stdout_path, stderr_path, working_dir));
// Server/client descriptors.
if (!EnableIPC())
@@ -843,7 +972,7 @@ WAIT_AGAIN:
// Check that the launch was a success.
if (!args->m_error.Success())
{
- StopLaunchOpThread();
+ StopOpThread();
error = args->m_error;
return;
}
@@ -864,13 +993,14 @@ ProcessMonitor::ProcessMonitor(ProcessPO
lldb_private::Error &error)
: m_process(static_cast<ProcessLinux *>(process)),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
+ m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
m_terminal_fd(-1),
- m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+
m_client_fd(-1),
m_server_fd(-1)
{
- std::auto_ptr<AttachArgs> args;
+ std::unique_ptr<AttachArgs> args;
args.reset(new AttachArgs(this, pid));
@@ -898,10 +1028,10 @@ WAIT_AGAIN:
}
}
- // Check that the launch was a success.
+ // Check that the attach was a success.
if (!args->m_error.Success())
{
- StopAttachOpThread();
+ StopOpThread();
error = args->m_error;
return;
}
@@ -936,18 +1066,6 @@ ProcessMonitor::StartLaunchOpThread(Laun
Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
}
-void
-ProcessMonitor::StopLaunchOpThread()
-{
- lldb::thread_result_t result;
-
- if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
- return;
-
- Host::ThreadCancel(m_operation_thread, NULL);
- Host::ThreadJoin(m_operation_thread, &result, NULL);
-}
-
void *
ProcessMonitor::LaunchOpThread(void *arg)
{
@@ -967,12 +1085,12 @@ ProcessMonitor::Launch(LaunchArgs *args)
{
ProcessMonitor *monitor = args->m_monitor;
ProcessLinux &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
const char **argv = args->m_argv;
const char **envp = args->m_envp;
const char *stdin_path = args->m_stdin_path;
const char *stdout_path = args->m_stdout_path;
const char *stderr_path = args->m_stderr_path;
+ const char *working_dir = args->m_working_dir;
lldb_utility::PseudoTerminal terminal;
const size_t err_len = 1024;
@@ -980,7 +1098,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
lldb::pid_t pid;
lldb::ThreadSP inferior;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
// Propagate the environment if one is not supplied.
if (envp == NULL || envp[0] == NULL)
@@ -994,7 +1112,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
goto FINISH;
}
- if ((pid = terminal.Fork(err_str, err_len)) < 0)
+ if ((pid = terminal.Fork(err_str, err_len)) == -1)
{
args->m_error.SetErrorToGenericError();
args->m_error.SetErrorString("Process fork failed.");
@@ -1007,6 +1125,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdinFailed,
eDupStdoutFailed,
eDupStderrFailed,
+ eChdirFailed,
eExecFailed
};
@@ -1014,7 +1133,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (pid == 0)
{
// Trace this process.
- if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL) < 0)
+ if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL, 0) < 0)
exit(ePtraceFailed);
// Do not inherit setgid powers.
@@ -1039,6 +1158,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
exit(eDupStderrFailed);
+ // Change working directory
+ if (working_dir != NULL && working_dir[0])
+ if (0 != ::chdir(working_dir))
+ exit(eChdirFailed);
+
// Execute. We should never return.
execve(argv[0],
const_cast<char *const *>(argv),
@@ -1060,22 +1184,25 @@ ProcessMonitor::Launch(LaunchArgs *args)
args->m_error.SetErrorToGenericError();
switch (WEXITSTATUS(status))
{
- case ePtraceFailed:
+ case ePtraceFailed:
args->m_error.SetErrorString("Child ptrace failed.");
break;
- case eDupStdinFailed:
+ case eDupStdinFailed:
args->m_error.SetErrorString("Child open stdin failed.");
break;
- case eDupStdoutFailed:
+ case eDupStdoutFailed:
args->m_error.SetErrorString("Child open stdout failed.");
break;
- case eDupStderrFailed:
+ case eDupStderrFailed:
args->m_error.SetErrorString("Child open stderr failed.");
break;
- case eExecFailed:
+ case eChdirFailed:
+ args->m_error.SetErrorString("Child failed to set working directory.");
+ break;
+ case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;
- default:
+ default:
args->m_error.SetErrorString("Child returned unknown exit status.");
break;
}
@@ -1084,9 +1211,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
assert(WIFSTOPPED(status) && wpid == pid &&
"Could not sync with inferior process.");
- // Have the child raise an event on exit. This is used to keep the child in
- // limbo until it is destroyed.
- if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)PTRACE_O_TRACEEXIT) < 0)
+ if (!SetDefaultPtraceOpts(pid))
{
args->m_error.SetErrorToErrno();
goto FINISH;
@@ -1106,9 +1231,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
// Update the process thread list with this new thread.
// FIXME: should we be letting UpdateThreadList handle this?
// FIXME: by using pids instead of tids, we can only support one thread.
- inferior.reset(new POSIXThread(processSP, pid));
+ inferior.reset(new POSIXThread(process, pid));
if (log)
- log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid);
+ log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
process.GetThreadList().AddThread(inferior);
// Let our process instance know the thread has stopped.
@@ -1143,19 +1268,15 @@ ProcessMonitor::StartAttachOpThread(Atta
Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
}
-void
-ProcessMonitor::StopAttachOpThread()
-{
- assert(!"Not implemented yet!!!");
-}
-
void *
ProcessMonitor::AttachOpThread(void *arg)
{
AttachArgs *args = static_cast<AttachArgs*>(arg);
- if (!Attach(args))
+ if (!Attach(args)) {
+ sem_post(&args->m_semaphore);
return NULL;
+ }
ServeOperation(args);
return NULL;
@@ -1168,9 +1289,11 @@ ProcessMonitor::Attach(AttachArgs *args)
ProcessMonitor *monitor = args->m_monitor;
ProcessLinux &process = monitor->GetProcess();
- lldb::ProcessSP processSP = process.shared_from_this();
lldb::ThreadSP inferior;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ // Use a map to keep track of the threads which we have attached/need to attach.
+ Host::TidMap tids_to_attach;
if (pid <= 1)
{
@@ -1179,34 +1302,106 @@ ProcessMonitor::Attach(AttachArgs *args)
goto FINISH;
}
- // Attach to the requested process.
- if (PTRACE(PTRACE_ATTACH, pid, NULL, NULL) < 0)
+ while (Host::FindProcessThreads(pid, tids_to_attach))
{
- args->m_error.SetErrorToErrno();
- goto FINISH;
+ for (Host::TidMap::iterator it = tids_to_attach.begin();
+ it != tids_to_attach.end(); ++it)
+ {
+ if (it->second == false)
+ {
+ lldb::tid_t tid = it->first;
+
+ // Attach to the requested process.
+ // An attach will cause the thread to stop with a SIGSTOP.
+ if (PTRACE(PTRACE_ATTACH, tid, NULL, NULL, 0) < 0)
+ {
+ // No such thread. The thread may have exited.
+ // More error handling may be needed.
+ if (errno == ESRCH)
+ {
+ tids_to_attach.erase(it);
+ continue;
+ }
+ else
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+ }
+
+ int status;
+ // Need to use __WALL otherwise we receive an error with errno=ECHLD
+ // At this point we should have a thread stopped if waitpid succeeds.
+ if ((status = waitpid(tid, NULL, __WALL)) < 0)
+ {
+ // No such thread. The thread may have exited.
+ // More error handling may be needed.
+ if (errno == ESRCH)
+ {
+ tids_to_attach.erase(it);
+ continue;
+ }
+ else
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+ }
+
+ if (!SetDefaultPtraceOpts(tid))
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+ }
+
+ // Update the process thread list with the attached thread.
+ inferior.reset(new POSIXThread(process, tid));
+ if (log)
+ log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, tid);
+ process.GetThreadList().AddThread(inferior);
+ it->second = true;
+ }
+ }
}
- int status;
- if ((status = waitpid(pid, NULL, 0)) < 0)
+ if (tids_to_attach.size() > 0)
{
- args->m_error.SetErrorToErrno();
- goto FINISH;
+ monitor->m_pid = pid;
+ // Let our process instance know the thread has stopped.
+ process.SendMessage(ProcessMessage::Trace(pid));
+ }
+ else
+ {
+ args->m_error.SetErrorToGenericError();
+ args->m_error.SetErrorString("No such process.");
}
-
- // Update the process thread list with the attached thread.
- inferior.reset(new POSIXThread(processSP, pid));
- if (log)
- log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid);
- process.GetThreadList().AddThread(inferior);
-
- // Let our process instance know the thread has stopped.
- process.SendMessage(ProcessMessage::Trace(pid));
FINISH:
return args->m_error.Success();
}
bool
+ProcessMonitor::SetDefaultPtraceOpts(lldb::pid_t pid)
+{
+ long ptrace_opts = 0;
+
+ // Have the child raise an event on exit. This is used to keep the child in
+ // limbo until it is destroyed.
+ ptrace_opts |= PTRACE_O_TRACEEXIT;
+
+ // Have the tracer trace threads which spawn in the inferior process.
+ // TODO: if we want to support tracing the inferiors' child, add the
+ // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
+ ptrace_opts |= PTRACE_O_TRACECLONE;
+
+ // Have the tracer notify us before execve returns
+ // (needed to disable legacy SIGTRAP generation)
+ ptrace_opts |= PTRACE_O_TRACEEXEC;
+
+ return PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0) >= 0;
+}
+
+bool
ProcessMonitor::MonitorCallback(void *callback_baton,
lldb::pid_t pid,
bool exited,
@@ -1219,23 +1414,52 @@ ProcessMonitor::MonitorCallback(void *ca
assert(process);
bool stop_monitoring;
siginfo_t info;
+ int ptrace_err;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (!monitor->GetSignalInfo(pid, &info))
- stop_monitoring = true; // pid is gone. Bail.
+ if (exited)
+ {
+ if (log)
+ log->Printf ("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, __FUNCTION__, pid);
+ message = ProcessMessage::Exit(pid, status);
+ process->SendMessage(message);
+ return pid == process->GetID();
+ }
+
+ if (!monitor->GetSignalInfo(pid, &info, ptrace_err)) {
+ if (ptrace_err == EINVAL) {
+ if (log)
+ log->Printf ("ProcessMonitor::%s() resuming from group-stop", __FUNCTION__);
+ // inferior process is in 'group-stop', so deliver SIGSTOP signal
+ if (!monitor->Resume(pid, SIGSTOP)) {
+ assert(0 && "SIGSTOP delivery failed while in 'group-stop' state");
+ }
+ stop_monitoring = false;
+ } else {
+ // ptrace(GETSIGINFO) failed (but not due to group-stop). Most likely,
+ // this means the child pid is gone (or not being debugged) therefore
+ // stop the monitor thread if this is the main pid.
+ if (log)
+ log->Printf ("ProcessMonitor::%s() GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d",
+ __FUNCTION__, strerror(ptrace_err), pid, signal, status);
+ stop_monitoring = pid == monitor->m_process->GetID();
+ }
+ }
else {
switch (info.si_signo)
{
case SIGTRAP:
message = MonitorSIGTRAP(monitor, &info, pid);
break;
-
+
default:
message = MonitorSignal(monitor, &info, pid);
break;
}
process->SendMessage(message);
- stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
+ stop_monitoring = false;
}
return stop_monitoring;
@@ -1247,6 +1471,8 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
{
ProcessMessage message;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
assert(monitor);
assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
@@ -1256,27 +1482,61 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
assert(false && "Unexpected SIGTRAP code!");
break;
+ // TODO: these two cases are required if we want to support tracing
+ // of the inferiors' children
+ // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
+ // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+
+ case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
+ {
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received thread creation event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);
+
+ unsigned long tid = 0;
+ if (!monitor->GetEventMessage(pid, &tid))
+ tid = -1;
+ message = ProcessMessage::NewThread(pid, tid);
+ break;
+ }
+
+ case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
+ // Don't follow the child by default and resume
+ monitor->Resume(pid, SIGCONT);
+ break;
+
case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
{
- // The inferior process is about to exit. Maintain the process in a
- // state of "limbo" until we are explicitly commanded to detach,
- // destroy, resume, etc.
+ // The inferior process or one of its threads is about to exit.
+ // Maintain the process or thread in a state of "limbo" until we are
+ // explicitly commanded to detach, destroy, resume, etc.
unsigned long data = 0;
if (!monitor->GetEventMessage(pid, &data))
data = -1;
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received exit event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
message = ProcessMessage::Limbo(pid, (data >> 8));
break;
}
case 0:
case TRAP_TRACE:
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid);
message = ProcessMessage::Trace(pid);
break;
case SI_KERNEL:
case TRAP_BRKPT:
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid);
message = ProcessMessage::Break(pid);
break;
+
+ case TRAP_HWBKPT:
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received watchpoint event, pid = %" PRIu64, __FUNCTION__, pid);
+ message = ProcessMessage::Watch(pid, (lldb::addr_t)info->si_addr);
+ break;
}
return message;
@@ -1289,6 +1549,8 @@ ProcessMonitor::MonitorSignal(ProcessMon
ProcessMessage message;
int signo = info->si_signo;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
// POSIX says that process behaviour is undefined after it ignores a SIGFPE,
// SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
// kill(2) or raise(3). Similarly for tgkill(2) on Linux.
@@ -1299,12 +1561,22 @@ ProcessMonitor::MonitorSignal(ProcessMon
// Similarly, ACK signals generated by this monitor.
if (info->si_code == SI_TKILL || info->si_code == SI_USER)
{
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d",
+ __FUNCTION__,
+ monitor->m_process->GetUnixSignals().GetSignalAsCString (signo),
+ (info->si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"),
+ info->si_pid);
+
if (info->si_pid == getpid())
return ProcessMessage::SignalDelivered(pid, signo);
else
return ProcessMessage::Signal(pid, signo);
}
+ if (log)
+ log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
+
if (signo == SIGSEGV) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
@@ -1334,6 +1606,144 @@ ProcessMonitor::MonitorSignal(ProcessMon
return ProcessMessage::Signal(pid, signo);
}
+bool
+ProcessMonitor::StopThread(lldb::tid_t tid)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ // FIXME: Try to use tgkill or tkill
+ int ret = tgkill(m_pid, tid, SIGSTOP);
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) stopping thread, tid = %" PRIu64 ", ret = %d", __FUNCTION__, tid, ret);
+
+ // This can happen if a thread exited while we were trying to stop it. That's OK.
+ // We'll get the signal for that later.
+ if (ret < 0)
+ return false;
+
+ // Wait for the thread to stop
+ while (true)
+ {
+ int status = -1;
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) waitpid...", __FUNCTION__);
+ lldb::pid_t wait_pid = ::waitpid (-1*m_pid, &status, __WALL);
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) waitpid, pid = %" PRIu64 ", status = %d", __FUNCTION__, wait_pid, status);
+
+ if (wait_pid == -1)
+ {
+ // If we got interrupted by a signal (in our process, not the
+ // inferior) try again.
+ if (errno == EINTR)
+ continue;
+ else
+ return false; // This is bad, but there's nothing we can do.
+ }
+
+ // If this is a thread exit, we won't get any more information.
+ if (WIFEXITED(status))
+ {
+ m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status)));
+ if (wait_pid == tid)
+ return true;
+ continue;
+ }
+
+ siginfo_t info;
+ int ptrace_err;
+ if (!GetSignalInfo(wait_pid, &info, ptrace_err))
+ {
+ if (log)
+ {
+ log->Printf ("ProcessMonitor::%s() GetSignalInfo failed.", __FUNCTION__);
+
+ // This would be a particularly interesting case
+ if (ptrace_err == EINVAL)
+ log->Printf ("ProcessMonitor::%s() in group-stop", __FUNCTION__);
+ }
+ return false;
+ }
+
+ // Handle events from other threads
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) handling event, tid == %" PRIu64, __FUNCTION__, wait_pid);
+
+ ProcessMessage message;
+ if (info.si_signo == SIGTRAP)
+ message = MonitorSIGTRAP(this, &info, wait_pid);
+ else
+ message = MonitorSignal(this, &info, wait_pid);
+
+ POSIXThread *thread = static_cast<POSIXThread*>(m_process->GetThreadList().FindThreadByID(wait_pid).get());
+
+ // When a new thread is created, we may get a SIGSTOP for the new thread
+ // just before we get the SIGTRAP that we use to add the thread to our
+ // process thread list. We don't need to worry about that signal here.
+ assert(thread || message.GetKind() == ProcessMessage::eSignalMessage);
+
+ if (!thread)
+ {
+ m_process->SendMessage(message);
+ continue;
+ }
+
+ switch (message.GetKind())
+ {
+ case ProcessMessage::eInvalidMessage:
+ break;
+
+ // These need special handling because we don't want to send a
+ // resume even if we already sent a SIGSTOP to this thread. In
+ // this case the resume will cause the thread to disappear. It is
+ // unlikely that we'll ever get eExitMessage here, but the same
+ // reasoning applies.
+ case ProcessMessage::eLimboMessage:
+ case ProcessMessage::eExitMessage:
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
+ // SendMessage will set the thread state as needed.
+ m_process->SendMessage(message);
+ // If this is the thread we're waiting for, stop waiting. Even
+ // though this wasn't the signal we expected, it's the last
+ // signal we'll see while this thread is alive.
+ if (wait_pid == tid)
+ return true;
+ break;
+
+ case ProcessMessage::eSignalDeliveredMessage:
+ // This is the stop we're expecting.
+ if (wait_pid == tid && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP && info.si_code == SI_TKILL)
+ {
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) received signal, done waiting", __FUNCTION__);
+ thread->SetState(lldb::eStateStopped);
+ return true;
+ }
+ // else fall-through
+ case ProcessMessage::eSignalMessage:
+ case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eTraceMessage:
+ case ProcessMessage::eWatchpointMessage:
+ case ProcessMessage::eCrashMessage:
+ case ProcessMessage::eNewThreadMessage:
+ if (log)
+ log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
+ // SendMessage will set the thread state as needed.
+ m_process->SendMessage(message);
+ // This isn't the stop we were expecting, but the thread is
+ // stopped. SendMessage will handle processing of this event,
+ // but we need to resume here to get the stop we are waiting
+ // for (otherwise the thread will stop again immediately when
+ // we try to resume).
+ if (wait_pid == tid)
+ Resume(wait_pid, eResumeSignalNone);
+ break;
+ }
+ }
+ return false;
+}
+
ProcessMessage::CrashReason
ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
{
@@ -1342,7 +1752,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV
reason = ProcessMessage::eInvalidCrashReason;
- switch (info->si_code)
+ switch (info->si_code)
{
default:
assert(false && "unexpected si_code for SIGSEGV");
@@ -1354,7 +1764,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV
reason = ProcessMessage::ePrivilegedAddress;
break;
}
-
+
return reason;
}
@@ -1513,7 +1923,8 @@ ProcessMonitor::ServeOperation(Operation
assert(errno == EINTR);
goto READ_AGAIN;
}
-
+ if (status == 0)
+ continue; // Poll again. The connection probably terminated.
assert(status == sizeof(op));
op->Execute(monitor);
write(fdset.fd, &op, sizeof(op));
@@ -1567,55 +1978,75 @@ ProcessMonitor::WriteMemory(lldb::addr_t
}
bool
-ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value)
+ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
+ unsigned size, RegisterValue &value)
{
bool result;
- ReadRegOperation op(offset, value, result);
+ ReadRegOperation op(tid, offset, reg_name, value, result);
DoOperation(&op);
return result;
}
bool
-ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value)
+ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char* reg_name, const RegisterValue &value)
{
bool result;
- WriteRegOperation op(offset, value, result);
+ WriteRegOperation op(tid, offset, reg_name, value, result);
DoOperation(&op);
return result;
}
bool
-ProcessMonitor::ReadGPR(void *buf)
+ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
- ReadGPROperation op(buf, result);
+ ReadGPROperation op(tid, buf, buf_size, result);
DoOperation(&op);
return result;
}
bool
-ProcessMonitor::ReadFPR(void *buf)
+ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
- ReadFPROperation op(buf, result);
+ ReadFPROperation op(tid, buf, buf_size, result);
DoOperation(&op);
return result;
}
bool
-ProcessMonitor::WriteGPR(void *buf)
+ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
{
bool result;
- WriteGPROperation op(buf, result);
+ ReadRegisterSetOperation op(tid, buf, buf_size, regset, result);
DoOperation(&op);
return result;
}
bool
-ProcessMonitor::WriteFPR(void *buf)
+ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
- WriteFPROperation op(buf, result);
+ WriteGPROperation op(tid, buf, buf_size, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+ bool result;
+ WriteFPROperation op(tid, buf, buf_size, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+ bool result;
+ WriteRegisterSetOperation op(tid, buf, buf_size, regset, result);
DoOperation(&op);
return result;
}
@@ -1624,8 +2055,15 @@ bool
ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
{
bool result;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ if (log)
+ log->Printf ("ProcessMonitor::%s() resuming thread = %" PRIu64 " with signal %s", __FUNCTION__, tid,
+ m_process->GetUnixSignals().GetSignalAsCString (signo));
ResumeOperation op(tid, signo, result);
DoOperation(&op);
+ if (log)
+ log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false");
return result;
}
@@ -1648,10 +2086,10 @@ ProcessMonitor::BringProcessIntoLimbo()
}
bool
-ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
+ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
{
bool result;
- SiginfoOperation op(tid, siginfo, result);
+ SiginfoOperation op(tid, siginfo, result, ptrace_err);
DoOperation(&op);
return result;
}
@@ -1665,17 +2103,17 @@ ProcessMonitor::GetEventMessage(lldb::ti
return result;
}
-bool
-ProcessMonitor::Detach()
+lldb_private::Error
+ProcessMonitor::Detach(lldb::tid_t tid)
{
- bool result;
lldb_private::Error error;
- DetachOperation op(error);
- result = error.Success();
- DoOperation(&op);
- StopMonitor();
- return result;
-}
+ if (tid != LLDB_INVALID_THREAD_ID)
+ {
+ DetachOperation op(tid, error);
+ DoOperation(&op);
+ }
+ return error;
+}
bool
ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
@@ -1705,13 +2143,26 @@ void
ProcessMonitor::StopMonitor()
{
StopMonitoringChildProcess();
- StopLaunchOpThread();
+ StopOpThread();
CloseFD(m_terminal_fd);
CloseFD(m_client_fd);
CloseFD(m_server_fd);
}
void
+ProcessMonitor::StopOpThread()
+{
+ lldb::thread_result_t result;
+
+ if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+ return;
+
+ Host::ThreadCancel(m_operation_thread, NULL);
+ Host::ThreadJoin(m_operation_thread, &result, NULL);
+ m_operation_thread = LLDB_INVALID_HOST_THREAD;
+}
+
+void
ProcessMonitor::CloseFD(int &fd)
{
if (fd != -1)
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessMonitor.h Thu Jun 6 19:06:43 2013
@@ -24,12 +24,10 @@ namespace lldb_private
class Error;
class Module;
class Scalar;
-
} // End lldb_private namespace.
class ProcessLinux;
class Operation;
-class ProcessPOSIX;
/// @class ProcessMonitor
/// @brief Manages communication with the inferior (debugee) process.
@@ -56,6 +54,7 @@ public:
const char *stdin_path,
const char *stdout_path,
const char *stderr_path,
+ const char *working_dir,
lldb_private::Error &error);
ProcessMonitor(ProcessPOSIX *process,
@@ -64,6 +63,11 @@ public:
~ProcessMonitor();
+ enum ResumeSignals
+ {
+ eResumeSignalNone = 0
+ };
+
/// Provides the process number of debugee.
lldb::pid_t
GetPID() const { return m_pid; }
@@ -106,35 +110,47 @@ public:
///
/// This method is provided for use by RegisterContextLinux derivatives.
bool
- ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value);
+ ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ unsigned size, lldb_private::RegisterValue &value);
/// Writes the given value to the register identified by the given
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextLinux derivatives.
bool
- WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value);
+ WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
bool
- ReadGPR(void *buf);
+ ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Reads generic floating point registers into the specified buffer.
+ bool
+ ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
- /// Reads all floating point registers into the specified buffer.
+ /// Reads the specified register set into the specified buffer.
+ /// For instance, the extended floating-point register set.
bool
- ReadFPR(void *buf);
+ ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes all general purpose registers into the specified buffer.
bool
- WriteGPR(void *buf);
+ WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
- /// Writes all floating point registers into the specified buffer.
+ /// Writes generic floating point registers into the specified buffer.
bool
- WriteFPR(void *buf);
+ WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Writes the specified register set into the specified buffer.
+ /// For instance, the extended floating-point register set.
+ bool
+ WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes a siginfo_t structure corresponding to the given thread ID to the
/// memory region pointed to by @p siginfo.
bool
- GetSignalInfo(lldb::tid_t tid, void *siginfo);
+ GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err);
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
/// corresponding to the given thread IDto the memory pointed to by @p
@@ -158,18 +174,21 @@ public:
bool
BringProcessIntoLimbo();
- bool
- Detach();
+ lldb_private::Error
+ Detach(lldb::tid_t tid);
+ /// Stops the requested thread and waits for the stop signal.
+ bool
+ StopThread(lldb::tid_t tid);
private:
ProcessLinux *m_process;
lldb::thread_t m_operation_thread;
+ lldb::thread_t m_monitor_thread;
lldb::pid_t m_pid;
int m_terminal_fd;
- lldb::thread_t m_monitor_thread;
lldb_private::Mutex m_server_mutex;
int m_client_fd;
@@ -198,7 +217,8 @@ private:
char const **envp,
const char *stdin_path,
const char *stdout_path,
- const char *stderr_path);
+ const char *stderr_path,
+ const char *working_dir);
~LaunchArgs();
@@ -208,14 +228,12 @@ private:
const char *m_stdin_path; // Redirect stdin or NULL.
const char *m_stdout_path; // Redirect stdout or NULL.
const char *m_stderr_path; // Redirect stderr or NULL.
+ const char *m_working_dir; // Working directory or NULL.
};
void
StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
- void
- StopLaunchOpThread();
-
static void *
LaunchOpThread(void *arg);
@@ -238,15 +256,15 @@ private:
void
StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
- void
- StopAttachOpThread();
-
static void *
AttachOpThread(void *args);
static bool
Attach(AttachArgs *args);
+ static bool
+ SetDefaultPtraceOpts(const lldb::pid_t);
+
static void
ServeOperation(OperationArgs *args);
@@ -287,6 +305,10 @@ private:
void
StopMonitor();
+ /// Stops the operation thread used to attach/launch a process.
+ void
+ StopOpThread();
+
void
CloseFD(int &fd);
};
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h Thu Jun 6 19:06:43 2013
@@ -1,44 +0,0 @@
-//===-- RegisterContextLinux_x86_64.h ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextLinux_x86_64_H_
-#define liblldb_RegisterContextLinux_x86_64_H_
-
-typedef struct _GPR
-{
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t rbp;
- uint64_t rbx;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t orig_ax;
- uint64_t rip;
- uint64_t cs;
- uint64_t rflags;
- uint64_t rsp;
- uint64_t ss;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ds;
- uint64_t es;
- uint64_t fs;
- uint64_t gs;
-} GPR;
-
-#endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Thu Jun 6 19:06:43 2013
@@ -11,6 +11,7 @@
#include "CommunicationKDP.h"
// C Includes
+#include <errno.h>
#include <limits.h>
#include <string.h>
@@ -22,6 +23,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
@@ -42,7 +44,7 @@ CommunicationKDP::CommunicationKDP (cons
m_byte_order (eByteOrderLittle),
m_packet_timeout (1),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
- m_private_is_running (false),
+ m_is_running (false),
m_session_key (0u),
m_request_sequence_id (0u),
m_exception_sequence_id (0u),
@@ -82,7 +84,7 @@ typedef struct {
#endif
void
-CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
+CommunicationKDP::MakeRequestPacketHeader (CommandType request_type,
PacketStreamType &request_packet,
uint16_t request_length)
{
@@ -95,23 +97,47 @@ CommunicationKDP::MakeRequestPacketHeade
bool
CommunicationKDP::SendRequestAndGetReply (const CommandType command,
- const uint8_t request_sequence_id,
- const PacketStreamType &request_packet,
+ const PacketStreamType &request_packet,
DataExtractor &reply_packet)
{
+ if (IsRunning())
+ {
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+ if (log)
+ {
+ PacketStreamType log_strm;
+ DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize());
+ log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData());
+ }
+ return false;
+ }
- Mutex::Locker locker(m_sequence_mutex);
- if (SendRequestPacketNoLock(request_packet))
+ Mutex::Locker locker(m_sequence_mutex);
+#ifdef LLDB_CONFIGURATION_DEBUG
+ // NOTE: this only works for packets that are in native endian byte order
+ assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2)));
+#endif
+ lldb::offset_t offset = 1;
+ const uint32_t num_retries = 3;
+ for (uint32_t i=0; i<num_retries; ++i)
{
- if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
+ if (SendRequestPacketNoLock(request_packet))
{
- uint32_t offset = 0;
- const uint8_t reply_command = reply_packet.GetU8 (&offset);
- const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
- if ((reply_command & eCommandTypeMask) == command)
+ const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1];
+ if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
{
- if (request_sequence_id == reply_sequence_id)
- return true;
+ offset = 0;
+ const uint8_t reply_command = reply_packet.GetU8 (&offset);
+ const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset);
+ if ((reply_command & eCommandTypeMask) == command)
+ {
+ if (request_sequence_id == reply_sequence_id)
+ {
+ if (command == KDP_RESUMECPUS)
+ m_is_running.SetValue(true, eBroadcastAlways);
+ return true;
+ }
+ }
}
}
}
@@ -127,7 +153,7 @@ CommunicationKDP::SendRequestPacketNoLoc
const char *packet_data = request_packet.GetData();
const size_t packet_size = request_packet.GetSize();
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (log)
{
PacketStreamType log_strm;
@@ -145,7 +171,7 @@ CommunicationKDP::SendRequestPacketNoLoc
return true;
if (log)
- log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
+ log->Printf ("error: failed to send packet entire packet %" PRIu64 " of %" PRIu64 " bytes sent", (uint64_t)bytes_written, (uint64_t)packet_size);
}
return false;
}
@@ -160,7 +186,7 @@ CommunicationKDP::GetSequenceMutex (Mute
bool
CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
{
- return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+ return m_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
}
size_t
@@ -176,7 +202,7 @@ CommunicationKDP::WaitForPacketWithTimeo
uint8_t buffer[8192];
Error error;
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
// Check for a packet from our cache first without trying any reading...
if (CheckForPacket (NULL, 0, packet))
@@ -189,12 +215,12 @@ CommunicationKDP::WaitForPacketWithTimeo
size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
if (log)
- log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
+ log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
__PRETTY_FUNCTION__,
timeout_usec,
Communication::ConnectionStatusAsCString (status),
error.AsCString(),
- bytes_read);
+ (uint64_t)bytes_read);
if (bytes_read > 0)
{
@@ -231,7 +257,7 @@ CommunicationKDP::CheckForPacket (const
// Put the packet data into the buffer in a thread safe fashion
Mutex::Locker locker(m_bytes_mutex);
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
if (src && src_len > 0)
{
@@ -252,10 +278,25 @@ CommunicationKDP::CheckForPacket (const
if (bytes_available >= 8)
{
packet.SetData (&m_bytes[0], bytes_available, m_byte_order);
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
uint8_t reply_command = packet.GetU8(&offset);
switch (reply_command)
{
+ case ePacketTypeRequest | KDP_EXCEPTION:
+ case ePacketTypeRequest | KDP_TERMINATION:
+ // We got an exception request, so be sure to send an ACK
+ {
+ PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+ // Set the reply but and make the ACK packet
+ request_ack_packet.PutHex8 (reply_command | ePacketTypeReply);
+ request_ack_packet.PutHex8 (packet.GetU8(&offset));
+ request_ack_packet.PutHex16 (packet.GetU16(&offset));
+ request_ack_packet.PutHex32 (packet.GetU32(&offset));
+ m_is_running.SetValue(false, eBroadcastAlways);
+ // Ack to the exception or termination
+ SendRequestPacketNoLock (request_ack_packet);
+ }
+ // Fall through to case below to get packet contents
case ePacketTypeReply | KDP_CONNECT:
case ePacketTypeReply | KDP_DISCONNECT:
case ePacketTypeReply | KDP_HOSTINFO:
@@ -269,8 +310,6 @@ CommunicationKDP::CheckForPacket (const
case ePacketTypeReply | KDP_IMAGEPATH:
case ePacketTypeReply | KDP_SUSPEND:
case ePacketTypeReply | KDP_RESUMECPUS:
- case ePacketTypeReply | KDP_EXCEPTION:
- case ePacketTypeReply | KDP_TERMINATION:
case ePacketTypeReply | KDP_BREAKPOINT_SET:
case ePacketTypeReply | KDP_BREAKPOINT_REMOVE:
case ePacketTypeReply | KDP_REGIONS:
@@ -281,6 +320,13 @@ CommunicationKDP::CheckForPacket (const
case ePacketTypeReply | KDP_BREAKPOINT_SET64:
case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64:
case ePacketTypeReply | KDP_KERNELVERSION:
+ case ePacketTypeReply | KDP_READPHYSMEM64:
+ case ePacketTypeReply | KDP_WRITEPHYSMEM64:
+ case ePacketTypeReply | KDP_READIOPORT:
+ case ePacketTypeReply | KDP_WRITEIOPORT:
+ case ePacketTypeReply | KDP_READMSR64:
+ case ePacketTypeReply | KDP_WRITEMSR64:
+ case ePacketTypeReply | KDP_DUMPINFO:
{
offset = 2;
const uint16_t length = packet.GetU16 (&offset);
@@ -331,7 +377,6 @@ CommunicationKDP::SendRequestConnect (ui
const CommandType command = KDP_CONNECT;
// Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
// Always send connect ports as little endian
request_packet.SetByteOrder (eByteOrderLittle);
@@ -340,7 +385,7 @@ CommunicationKDP::SendRequestConnect (ui
request_packet.SetByteOrder (m_byte_order);
request_packet.PutCString (greeting);
DataExtractor reply_packet;
- return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
+ return SendRequestAndGetReply (command, request_packet, reply_packet);
}
void
@@ -361,18 +406,17 @@ CommunicationKDP::SendRequestReattach (u
const CommandType command = KDP_REATTACH;
// Length is 8 bytes for the header plus 2 bytes for the reply UDP port
const uint32_t command_length = 8 + 2;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
// Always send connect ports as little endian
request_packet.SetByteOrder (eByteOrderLittle);
request_packet.PutHex16(reply_port);
request_packet.SetByteOrder (m_byte_order);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
// Reset the sequence ID to zero for reattach
ClearKDPSettings ();
- uint32_t offset = 4;
+ lldb::offset_t offset = 4;
m_session_key = reply_packet.GetU32 (&offset);
return true;
}
@@ -401,12 +445,11 @@ CommunicationKDP::SendRequestVersion ()
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_VERSION;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
m_kdp_version_version = reply_packet.GetU32 (&offset);
m_kdp_version_feature = reply_packet.GetU32 (&offset);
return true;
@@ -429,10 +472,9 @@ CommunicationKDP::SendRequestImagePath (
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_IMAGEPATH;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
const char *path = reply_packet.PeekCStr(8);
if (path && path[0])
@@ -467,18 +509,84 @@ CommunicationKDP::GetCPUSubtype ()
return m_kdp_hostinfo_cpu_subtype;
}
+lldb_private::UUID
+CommunicationKDP::GetUUID ()
+{
+ UUID uuid;
+ if (GetKernelVersion() == NULL)
+ return uuid;
+
+ if (m_kernel_version.find("UUID=") == std::string::npos)
+ return uuid;
+
+ size_t p = m_kernel_version.find("UUID=") + strlen ("UUID=");
+ std::string uuid_str = m_kernel_version.substr(p, 36);
+ if (uuid_str.size() < 32)
+ return uuid;
+
+ if (uuid.SetFromCString (uuid_str.c_str()) == 0)
+ {
+ UUID invalid_uuid;
+ return invalid_uuid;
+ }
+
+ return uuid;
+}
+
+bool
+CommunicationKDP::RemoteIsEFI ()
+{
+ if (GetKernelVersion() == NULL)
+ return false;
+ if (strncmp (m_kernel_version.c_str(), "EFI", 3) == 0)
+ return true;
+ else
+ return false;
+}
+
+bool
+CommunicationKDP::RemoteIsDarwinKernel ()
+{
+ if (GetKernelVersion() == NULL)
+ return false;
+ if (m_kernel_version.find("Darwin Kernel") != std::string::npos)
+ return true;
+ else
+ return false;
+}
+
+lldb::addr_t
+CommunicationKDP::GetLoadAddress ()
+{
+ if (GetKernelVersion() == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ if (m_kernel_version.find("stext=") == std::string::npos)
+ return LLDB_INVALID_ADDRESS;
+ size_t p = m_kernel_version.find("stext=") + strlen ("stext=");
+ if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x')
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t kernel_load_address;
+ errno = 0;
+ kernel_load_address = ::strtoul (m_kernel_version.c_str() + p, NULL, 16);
+ if (errno != 0 || kernel_load_address == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ return kernel_load_address;
+}
+
bool
CommunicationKDP::SendRequestHostInfo ()
{
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_HOSTINFO;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset);
m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset);
@@ -509,10 +617,9 @@ CommunicationKDP::SendRequestKernelVersi
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_KERNELVERSION;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
const char *kernel_version_cstr = reply_packet.PeekCStr(8);
if (kernel_version_cstr && kernel_version_cstr[0])
@@ -528,10 +635,9 @@ CommunicationKDP::SendRequestDisconnect
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_DISCONNECT;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
// Are we supposed to get a reply for disconnect?
}
@@ -551,14 +657,13 @@ CommunicationKDP::SendRequestReadMemory
const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM;
// Size is header + address size + uint32_t length
const uint32_t command_length = 8 + command_addr_byte_size + 4;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutMaxHex64 (addr, command_addr_byte_size);
request_packet.PutHex32 (dst_len);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
uint32_t src_len = reply_packet.GetByteSize() - 12;
@@ -577,6 +682,10 @@ CommunicationKDP::SendRequestReadMemory
else
error.SetErrorString ("kdp read memory failed");
}
+ else
+ {
+ error.SetErrorString ("failed to send packet");
+ }
return 0;
}
@@ -592,17 +701,16 @@ CommunicationKDP::SendRequestWriteMemory
uint32_t command_addr_byte_size = use_64 ? 8 : 4;
const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
// Size is header + address size + uint32_t length
- const uint32_t command_length = 8 + command_addr_byte_size + 4;
- const uint32_t request_sequence_id = m_request_sequence_id;
+ const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutMaxHex64 (addr, command_addr_byte_size);
request_packet.PutHex32 (src_len);
- request_packet.PutBytesAsRawHex8(src, src_len);
+ request_packet.PutRawBytes(src, src_len);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
if (kdp_error)
error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
@@ -612,9 +720,47 @@ CommunicationKDP::SendRequestWriteMemory
return src_len;
}
}
+ else
+ {
+ error.SetErrorString ("failed to send packet");
+ }
return 0;
}
+bool
+CommunicationKDP::SendRawRequest (uint8_t command_byte,
+ const void *src, // Raw packet payload bytes
+ uint32_t src_len, // Raw packet payload length
+ DataExtractor &reply_packet,
+ Error &error)
+{
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+ // Size is header + address size + uint32_t length
+ const uint32_t command_length = 8 + src_len;
+ const CommandType command = (CommandType)command_byte;
+ MakeRequestPacketHeader (command, request_packet, command_length);
+ request_packet.PutRawBytes(src, src_len);
+
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
+ {
+ lldb::offset_t offset = 8;
+ uint32_t kdp_error = reply_packet.GetU32 (&offset);
+ if (kdp_error && (command_byte != KDP_DUMPINFO))
+ error.SetErrorStringWithFormat ("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error);
+ else
+ {
+ error.Clear();
+ return true;
+ }
+ }
+ else
+ {
+ error.SetErrorString ("failed to send packet");
+ }
+ return false;
+}
+
+
const char *
CommunicationKDP::GetCommandAsCString (uint8_t command)
{
@@ -645,6 +791,13 @@ CommunicationKDP::GetCommandAsCString (u
case KDP_BREAKPOINT_SET64: return "KDP_BREAKPOINT64_SET";
case KDP_BREAKPOINT_REMOVE64: return "KDP_BREAKPOINT64_REMOVE";
case KDP_KERNELVERSION: return "KDP_KERNELVERSION";
+ case KDP_READPHYSMEM64: return "KDP_READPHYSMEM64";
+ case KDP_WRITEPHYSMEM64: return "KDP_WRITEPHYSMEM64";
+ case KDP_READIOPORT: return "KDP_READIOPORT";
+ case KDP_WRITEIOPORT: return "KDP_WRITEIOPORT";
+ case KDP_READMSR64: return "KDP_READMSR64";
+ case KDP_WRITEMSR64: return "KDP_WRITEMSR64";
+ case KDP_DUMPINFO: return "KDP_DUMPINFO";
}
return NULL;
}
@@ -666,7 +819,7 @@ CommunicationKDP::DumpPacket (Stream &s,
}
else
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
const uint8_t first_packet_byte = packet.GetU8 (&offset);
const uint8_t sequence_id = packet.GetU8 (&offset);
const uint16_t length = packet.GetU16 (&offset);
@@ -676,12 +829,14 @@ CommunicationKDP::DumpPacket (Stream &s,
if (command_name)
{
const bool is_reply = ExtractIsReply(first_packet_byte);
- s.Printf ("%s {%u:%u} <0x%4.4x> %s",
- is_reply ? "<--" : "-->",
- key,
+ s.Printf ("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ",
+ IsRunning(),
+ is_reply ? "<--" : "-->",
+ command_name,
+ first_packet_byte,
sequence_id,
length,
- command_name);
+ key);
if (is_reply)
{
@@ -698,6 +853,8 @@ CommunicationKDP::DumpPacket (Stream &s,
case KDP_BREAKPOINT_REMOVE64:
case KDP_WRITEREGS:
case KDP_LOAD:
+ case KDP_WRITEIOPORT:
+ case KDP_WRITEMSR64:
{
const uint32_t error = packet.GetU32 (&offset);
s.Printf(" (error=0x%8.8x)", error);
@@ -741,13 +898,14 @@ CommunicationKDP::DumpPacket (Stream &s,
const addr_t region_addr = packet.GetPointer (&offset);
const uint32_t region_size = packet.GetU32 (&offset);
const uint32_t region_prot = packet.GetU32 (&offset);
- s.Printf("\n\tregion[%llu] = { range = [0x%16.16llx - 0x%16.16llx), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
+ s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString (region_prot));
}
}
break;
case KDP_READMEM:
case KDP_READMEM64:
+ case KDP_READPHYSMEM64:
{
const uint32_t error = packet.GetU32 (&offset);
const uint32_t count = packet.GetByteSize() - offset;
@@ -800,6 +958,41 @@ CommunicationKDP::DumpPacket (Stream &s,
s.Printf(" (path = \"%s\")", path);
}
break;
+
+ case KDP_READIOPORT:
+ case KDP_READMSR64:
+ {
+ const uint32_t error = packet.GetU32 (&offset);
+ const uint32_t count = packet.GetByteSize() - offset;
+ s.Printf(" (error = 0x%8.8x io:\n", error);
+ if (count > 0)
+ packet.Dump (&s, // Stream to dump to
+ offset, // Offset within "packet"
+ eFormatHex, // Format to use
+ 1, // Size of each item in bytes
+ count, // Number of items
+ 16, // Number per line
+ LLDB_INVALID_ADDRESS, // Don't show addresses before each line
+ 0, 0); // No bitfields
+ }
+ break;
+ case KDP_DUMPINFO:
+ {
+ const uint32_t count = packet.GetByteSize() - offset;
+ s.Printf(" (count = %u, bytes = \n", count);
+ if (count > 0)
+ packet.Dump (&s, // Stream to dump to
+ offset, // Offset within "packet"
+ eFormatHex, // Format to use
+ 1, // Size of each item in bytes
+ count, // Number of items
+ 16, // Number per line
+ LLDB_INVALID_ADDRESS, // Don't show addresses before each line
+ 0, 0); // No bitfields
+
+ }
+ break;
+
default:
s.Printf(" (add support for dumping this packet reply!!!");
break;
@@ -862,7 +1055,17 @@ CommunicationKDP::DumpPacket (Stream &s,
{
const uint64_t addr = packet.GetU64 (&offset);
const uint32_t size = packet.GetU32 (&offset);
- s.Printf(" (addr = 0x%16.16llx, size = %u)", addr, size);
+ s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size);
+ m_last_read_memory_addr = addr;
+ }
+ break;
+
+ case KDP_READPHYSMEM64:
+ {
+ const uint64_t addr = packet.GetU64 (&offset);
+ const uint32_t size = packet.GetU32 (&offset);
+ const uint32_t lcpu = packet.GetU16 (&offset);
+ s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu);
m_last_read_memory_addr = addr;
}
break;
@@ -871,7 +1074,18 @@ CommunicationKDP::DumpPacket (Stream &s,
{
const uint64_t addr = packet.GetU64 (&offset);
const uint32_t size = packet.GetU32 (&offset);
- s.Printf(" (addr = 0x%16.16llx, size = %u, bytes = \n", addr, size);
+ s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size);
+ if (size > 0)
+ DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
+ }
+ break;
+
+ case KDP_WRITEPHYSMEM64:
+ {
+ const uint64_t addr = packet.GetU64 (&offset);
+ const uint32_t size = packet.GetU32 (&offset);
+ const uint32_t lcpu = packet.GetU16 (&offset);
+ s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu);
if (size > 0)
DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr);
}
@@ -916,7 +1130,7 @@ CommunicationKDP::DumpPacket (Stream &s,
case KDP_BREAKPOINT_REMOVE64:
{
const uint64_t addr = packet.GetU64 (&offset);
- s.Printf(" (addr = 0x%16.16llx)", addr);
+ s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr);
}
break;
@@ -932,7 +1146,6 @@ CommunicationKDP::DumpPacket (Stream &s,
{
const uint32_t count = packet.GetU32 (&offset);
- s.Printf(" (count = %u:", count);
for (uint32_t i=0; i<count; ++i)
{
const uint32_t cpu = packet.GetU32 (&offset);
@@ -956,7 +1169,7 @@ CommunicationKDP::DumpPacket (Stream &s,
break;
}
- s.Printf ("\n cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)\n",
+ s.Printf ("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), subcode = %u (0x%8.8x)} ",
cpu, exc_cstr, exc, code, code, subcode, subcode);
}
}
@@ -976,7 +1189,78 @@ CommunicationKDP::DumpPacket (Stream &s,
s.Printf(" (reply_port = %u)", reply_port);
}
break;
- }
+
+ case KDP_READMSR64:
+ {
+ const uint32_t address = packet.GetU32 (&offset);
+ const uint16_t lcpu = packet.GetU16 (&offset);
+ s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu);
+ }
+ break;
+
+ case KDP_WRITEMSR64:
+ {
+ const uint32_t address = packet.GetU32 (&offset);
+ const uint16_t lcpu = packet.GetU16 (&offset);
+ const uint32_t nbytes = packet.GetByteSize() - offset;
+ s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes);
+ if (nbytes > 0)
+ packet.Dump (&s, // Stream to dump to
+ offset, // Offset within "packet"
+ eFormatHex, // Format to use
+ 1, // Size of each item in bytes
+ nbytes, // Number of items
+ 16, // Number per line
+ LLDB_INVALID_ADDRESS, // Don't show addresses before each line
+ 0, 0); // No bitfields
+ }
+ break;
+
+ case KDP_READIOPORT:
+ {
+ const uint16_t lcpu = packet.GetU16 (&offset);
+ const uint16_t address = packet.GetU16 (&offset);
+ const uint16_t nbytes = packet.GetU16 (&offset);
+ s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes);
+ }
+ break;
+
+ case KDP_WRITEIOPORT:
+ {
+ const uint16_t lcpu = packet.GetU16 (&offset);
+ const uint16_t address = packet.GetU16 (&offset);
+ const uint16_t nbytes = packet.GetU16 (&offset);
+ s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes);
+ if (nbytes > 0)
+ packet.Dump (&s, // Stream to dump to
+ offset, // Offset within "packet"
+ eFormatHex, // Format to use
+ 1, // Size of each item in bytes
+ nbytes, // Number of items
+ 16, // Number per line
+ LLDB_INVALID_ADDRESS, // Don't show addresses before each line
+ 0, 0); // No bitfields
+ }
+ break;
+
+ case KDP_DUMPINFO:
+ {
+ const uint32_t count = packet.GetByteSize() - offset;
+ s.Printf(" (count = %u, bytes = \n", count);
+ if (count > 0)
+ packet.Dump (&s, // Stream to dump to
+ offset, // Offset within "packet"
+ eFormatHex, // Format to use
+ 1, // Size of each item in bytes
+ count, // Number of items
+ 16, // Number per line
+ LLDB_INVALID_ADDRESS, // Don't show addresses before each line
+ 0, 0); // No bitfields
+
+ }
+ break;
+
+ }
}
}
else
@@ -1003,7 +1287,7 @@ CommunicationKDP::DumpPacket (Stream &s,
uint32_t
CommunicationKDP::SendRequestReadRegisters (uint32_t cpu,
uint32_t flavor,
- void *dst,
+ void *dst,
uint32_t dst_len,
Error &error)
{
@@ -1011,14 +1295,13 @@ CommunicationKDP::SendRequestReadRegiste
const CommandType command = KDP_READREGS;
// Size is header + 4 byte cpu and 4 byte flavor
const uint32_t command_length = 8 + 4 + 4;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutHex32 (cpu);
request_packet.PutHex32 (flavor);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
uint32_t src_len = reply_packet.GetByteSize() - 12;
@@ -1032,7 +1315,7 @@ CommunicationKDP::SendRequestReadRegiste
error.Clear();
// Return the number of bytes we could have returned regardless if
// we copied them or not, just so we know when things don't match up
- return src_len;
+ return src_len;
}
}
if (kdp_error)
@@ -1040,24 +1323,56 @@ CommunicationKDP::SendRequestReadRegiste
else
error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
}
+ else
+ {
+ error.SetErrorString ("failed to send packet");
+ }
+ return 0;
+}
+
+uint32_t
+CommunicationKDP::SendRequestWriteRegisters (uint32_t cpu,
+ uint32_t flavor,
+ const void *src,
+ uint32_t src_len,
+ Error &error)
+{
+ PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
+ const CommandType command = KDP_WRITEREGS;
+ // Size is header + 4 byte cpu and 4 byte flavor
+ const uint32_t command_length = 8 + 4 + 4 + src_len;
+ MakeRequestPacketHeader (command, request_packet, command_length);
+ request_packet.PutHex32 (cpu);
+ request_packet.PutHex32 (flavor);
+ request_packet.Write(src, src_len);
+ DataExtractor reply_packet;
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
+ {
+ lldb::offset_t offset = 8;
+ uint32_t kdp_error = reply_packet.GetU32 (&offset);
+ if (kdp_error == 0)
+ return src_len;
+ error.SetErrorStringWithFormat("failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error);
+ }
+ else
+ {
+ error.SetErrorString ("failed to send packet");
+ }
return 0;
}
bool
-CommunicationKDP::SendRequestResume (uint32_t cpu_mask)
+CommunicationKDP::SendRequestResume ()
{
- if (cpu_mask == 0)
- cpu_mask = GetCPUMask();
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_RESUMECPUS;
const uint32_t command_length = 12;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
- request_packet.PutHex32(cpu_mask);
+ request_packet.PutHex32(GetCPUMask());
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
return true;
return false;
}
@@ -1072,14 +1387,13 @@ CommunicationKDP::SendRequestBreakpoint
(use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE);
const uint32_t command_length = 8 + command_addr_byte_size;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
request_packet.PutMaxHex64 (addr, command_addr_byte_size);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
{
- uint32_t offset = 8;
+ lldb::offset_t offset = 8;
uint32_t kdp_error = reply_packet.GetU32 (&offset);
if (kdp_error == 0)
return true;
@@ -1093,10 +1407,9 @@ CommunicationKDP::SendRequestSuspend ()
PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
const CommandType command = KDP_SUSPEND;
const uint32_t command_length = 8;
- const uint32_t request_sequence_id = m_request_sequence_id;
MakeRequestPacketHeader (command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
+ if (SendRequestAndGetReply (command, request_packet, reply_packet))
return true;
return false;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Thu Jun 6 19:06:43 2013
@@ -62,7 +62,14 @@ public:
KDP_WRITEMEM64,
KDP_BREAKPOINT_SET64,
KDP_BREAKPOINT_REMOVE64,
- KDP_KERNELVERSION
+ KDP_KERNELVERSION,
+ KDP_READPHYSMEM64,
+ KDP_WRITEPHYSMEM64,
+ KDP_READIOPORT,
+ KDP_WRITEIOPORT,
+ KDP_READMSR64,
+ KDP_WRITEMSR64,
+ KDP_DUMPINFO
} CommandType;
enum
@@ -111,7 +118,7 @@ public:
bool
IsRunning() const
{
- return m_public_is_running.GetValue();
+ return m_is_running.GetValue();
}
//------------------------------------------------------------------
@@ -171,13 +178,27 @@ public:
uint32_t src_len,
lldb_private::Error &error);
+ bool
+ SendRawRequest (uint8_t command_byte,
+ const void *src,
+ uint32_t src_len,
+ lldb_private::DataExtractor &reply,
+ lldb_private::Error &error);
+
uint32_t
SendRequestReadRegisters (uint32_t cpu,
uint32_t flavor,
void *dst,
uint32_t dst_size,
lldb_private::Error &error);
-
+
+ uint32_t
+ SendRequestWriteRegisters (uint32_t cpu,
+ uint32_t flavor,
+ const void *src,
+ uint32_t src_size,
+ lldb_private::Error &error);
+
const char *
GetKernelVersion ();
@@ -206,9 +227,20 @@ public:
uint32_t
GetCPUSubtype ();
- // If cpu_mask is zero, then we will resume all CPUs
+ lldb_private::UUID
+ GetUUID ();
+
+ bool
+ RemoteIsEFI ();
+
+ bool
+ RemoteIsDarwinKernel ();
+
+ lldb::addr_t
+ GetLoadAddress ();
+
bool
- SendRequestResume (uint32_t cpu_mask = 0);
+ SendRequestResume ();
bool
SendRequestSuspend ();
@@ -293,7 +325,6 @@ protected:
bool
SendRequestAndGetReply (const CommandType command,
- const uint8_t request_sequence_id,
const PacketStreamType &request_packet,
lldb_private::DataExtractor &reply_packet);
//------------------------------------------------------------------
@@ -303,8 +334,7 @@ protected:
lldb::ByteOrder m_byte_order;
uint32_t m_packet_timeout;
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
- lldb_private::Predicate<bool> m_public_is_running;
- lldb_private::Predicate<bool> m_private_is_running;
+ lldb_private::Predicate<bool> m_is_running;
uint32_t m_session_key;
uint8_t m_request_sequence_id;
uint8_t m_exception_sequence_id;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Thu Jun 6 19:06:43 2013
@@ -16,8 +16,20 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/UUID.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionGroupString.h"
+#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -25,15 +37,20 @@
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
#include "ThreadKDP.h"
-#include "StopInfoMachException.h"
+#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
+#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
+#include "Utility/StringExtractor.h"
using namespace lldb;
using namespace lldb_private;
-const char *
+static const lldb::tid_t g_kernel_tid = 1;
+
+ConstString
ProcessKDP::GetPluginNameStatic()
{
- return "kdp-remote";
+ static ConstString g_name("kdp-remote");
+ return g_name;
}
const char *
@@ -99,10 +116,14 @@ ProcessKDP::ProcessKDP(Target& target, L
Process (target, listener),
m_comm("lldb.process.kdp-remote.communication"),
m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
- m_async_thread (LLDB_INVALID_HOST_THREAD)
+ m_async_thread (LLDB_INVALID_HOST_THREAD),
+ m_dyld_plugin_name (),
+ m_kernel_load_addr (LLDB_INVALID_ADDRESS),
+ m_command_sp(),
+ m_kernel_thread_wp()
{
-// m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
-// m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
+ m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
+ m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
}
//----------------------------------------------------------------------
@@ -121,15 +142,9 @@ ProcessKDP::~ProcessKDP()
//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ProcessKDP::GetPluginName()
{
- return "Process debugging plug-in that uses the Darwin KDP remote protocol";
-}
-
-const char *
-ProcessKDP::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -164,15 +179,22 @@ ProcessKDP::WillAttachToProcessWithName
}
Error
-ProcessKDP::DoConnectRemote (const char *remote_url)
+ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
{
- // TODO: fill in the remote connection to the remote KDP here!
Error error;
-
+
+ // Don't let any JIT happen when doing KDP as we can't allocate
+ // memory and we don't want to be mucking with threads that might
+ // already be handling exceptions
+ SetCanJIT(false);
+
if (remote_url == NULL || remote_url[0] == '\0')
- remote_url = "udp://localhost:41139";
+ {
+ error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url);
+ return error;
+ }
- std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
if (conn_ap.get())
{
// Only try once for now.
@@ -204,6 +226,28 @@ ProcessKDP::DoConnectRemote (const char
ArchSpec kernel_arch;
kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
m_target.SetArchitecture(kernel_arch);
+
+ /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet. */
+ /* An EFI kdp session has neither UUID nor load address. */
+
+ UUID kernel_uuid = m_comm.GetUUID ();
+ addr_t kernel_load_addr = m_comm.GetLoadAddress ();
+
+ if (m_comm.RemoteIsEFI ())
+ {
+ m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
+ }
+ else if (m_comm.RemoteIsDarwinKernel ())
+ {
+ m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+ if (kernel_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ m_kernel_load_addr = kernel_load_addr;
+ }
+ }
+
+ // Set the thread ID
+ UpdateThreadListIfNeeded ();
SetID (1);
GetThreadList ();
SetPrivateState (eStateStopped);
@@ -223,10 +267,14 @@ ProcessKDP::DoConnectRemote (const char
// }
}
}
+ else
+ {
+ error.SetErrorString("KDP_REATTACH failed");
+ }
}
else
{
- error.SetErrorString("KDP reattach failed");
+ error.SetErrorString("KDP_REATTACH failed");
}
}
else
@@ -286,7 +334,7 @@ ProcessKDP::DoAttachToProcessWithName (c
void
ProcessKDP::DidAttach ()
{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
if (log)
log->Printf ("ProcessKDP::DidAttach()");
if (GetID() != LLDB_INVALID_PROCESS_ID)
@@ -295,6 +343,20 @@ ProcessKDP::DidAttach ()
}
}
+addr_t
+ProcessKDP::GetImageInfoAddress()
+{
+ return m_kernel_load_addr;
+}
+
+lldb_private::DynamicLoader *
+ProcessKDP::GetDynamicLoader ()
+{
+ if (m_dyld_ap.get() == NULL)
+ m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
+ return m_dyld_ap.get();
+}
+
Error
ProcessKDP::WillResume ()
{
@@ -305,42 +367,129 @@ Error
ProcessKDP::DoResume ()
{
Error error;
- if (!m_comm.SendRequestResume ())
- error.SetErrorString ("KDP resume failed");
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+ // Only start the async thread if we try to do any process control
+ if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+ StartAsyncThread ();
+
+ bool resume = false;
+
+ // With KDP there is only one thread we can tell what to do
+ ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid));
+
+ if (kernel_thread_sp)
+ {
+ const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
+
+ if (log)
+ log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state));
+ switch (thread_resume_state)
+ {
+ case eStateSuspended:
+ // Nothing to do here when a thread will stay suspended
+ // we just leave the CPU mask bit set to zero for the thread
+ if (log)
+ log->Printf ("ProcessKDP::DoResume() = suspended???");
+ break;
+
+ case eStateStepping:
+ {
+ lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
+
+ if (reg_ctx_sp)
+ {
+ if (log)
+ log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
+ reg_ctx_sp->HardwareSingleStep (true);
+ resume = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
+ }
+ }
+ break;
+
+ case eStateRunning:
+ {
+ lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
+
+ if (reg_ctx_sp)
+ {
+ if (log)
+ log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);");
+ reg_ctx_sp->HardwareSingleStep (false);
+ resume = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
+ }
+ }
+ break;
+
+ default:
+ // The only valid thread resume states are listed above
+ assert (!"invalid thread resume state");
+ break;
+ }
+ }
+
+ if (resume)
+ {
+ if (log)
+ log->Printf ("ProcessKDP::DoResume () sending resume");
+
+ if (m_comm.SendRequestResume ())
+ {
+ m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
+ SetPrivateState(eStateRunning);
+ }
+ else
+ error.SetErrorString ("KDP resume failed");
+ }
+ else
+ {
+ error.SetErrorString ("kernel thread is suspended");
+ }
+
return error;
}
-bool
-ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
+lldb::ThreadSP
+ProcessKDP::GetKernelThread()
{
- // locker will keep a mutex locked until it goes out of scope
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
- if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
- log->Printf ("ProcessKDP::%s (pid = %llu)", __FUNCTION__, GetID());
+ // KDP only tells us about one thread/core. Any other threads will usually
+ // be the ones that are read from memory by the OS plug-ins.
- // We currently are making only one thread per core and we
- // actually don't know about actual threads. Eventually we
- // want to get the thread list from memory and note which
- // threads are on CPU as those are the only ones that we
- // will be able to resume.
- const uint32_t cpu_mask = m_comm.GetCPUMask();
- for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
- {
- lldb::tid_t tid = cpu_mask_bit;
- ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
- if (!thread_sp)
- thread_sp.reset(new ThreadKDP (shared_from_this(), tid));
- new_thread_list.AddThread(thread_sp);
+ ThreadSP thread_sp (m_kernel_thread_wp.lock());
+ if (!thread_sp)
+ {
+ thread_sp.reset(new ThreadKDP (*this, g_kernel_tid));
+ m_kernel_thread_wp = thread_sp;
}
- return new_thread_list.GetSize(false) > 0;
+ return thread_sp;
}
-StateType
-ProcessKDP::SetThreadStopInfo (StringExtractor& stop_packet)
+
+
+bool
+ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- // TODO: figure out why we stopped given the packet that tells us we stopped...
- return eStateStopped;
+ // locker will keep a mutex locked until it goes out of scope
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
+ if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
+ log->Printf ("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+
+ // Even though there is a CPU mask, it doesn't mean we can see each CPU
+ // indivudually, there is really only one. Lets call this thread 1.
+ ThreadSP thread_sp (old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));
+ if (!thread_sp)
+ thread_sp = GetKernelThread ();
+ new_thread_list.AddThread(thread_sp);
+
+ return new_thread_list.GetSize(false) > 0;
}
void
@@ -349,7 +498,6 @@ ProcessKDP::RefreshStateAfterStop ()
// Let all threads recover from stopping and do any clean up based
// on the previous thread state (if any).
m_thread_list.RefreshStateAfterStop();
- //SetThreadStopInfo (m_last_stop_packet);
}
Error
@@ -357,140 +505,57 @@ ProcessKDP::DoHalt (bool &caused_stop)
{
Error error;
-// bool timed_out = false;
- Mutex::Locker locker;
-
- if (m_public_state.GetValue() == eStateAttaching)
+ if (m_comm.IsRunning())
{
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
- m_comm.Disconnect();
- }
- else
- {
- if (!m_comm.SendRequestSuspend ())
- error.SetErrorString ("KDP halt failed");
+ if (m_destroy_in_process)
+ {
+ // If we are attemping to destroy, we need to not return an error to
+ // Halt or DoDestroy won't get called.
+ // We are also currently running, so send a process stopped event
+ SetPrivateState (eStateStopped);
+ }
+ else
+ {
+ error.SetErrorString ("KDP cannot interrupt a running kernel");
+ }
}
return error;
}
Error
-ProcessKDP::InterruptIfRunning (bool discard_thread_plans,
- bool catch_stop_event,
- EventSP &stop_event_sp)
+ProcessKDP::DoDetach(bool keep_stopped)
{
Error error;
-
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-
- bool paused_private_state_thread = false;
- const bool is_running = m_comm.IsRunning();
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i",
- discard_thread_plans,
- catch_stop_event,
- is_running);
+ log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
- if (discard_thread_plans)
+ if (m_comm.IsRunning())
{
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() discarding all thread plans");
- m_thread_list.DiscardThreadPlans();
+ // We are running and we can't interrupt a running kernel, so we need
+ // to just close the connection to the kernel and hope for the best
}
- if (is_running)
+ else
{
- if (catch_stop_event)
- {
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() pausing private state thread");
- PausePrivateStateThread();
- paused_private_state_thread = true;
- }
-
- bool timed_out = false;
-// bool sent_interrupt = false;
- Mutex::Locker locker;
-
- // TODO: implement halt in CommunicationKDP
-// if (!m_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
-// {
-// if (timed_out)
-// error.SetErrorString("timed out sending interrupt packet");
-// else
-// error.SetErrorString("unknown error sending interrupt packet");
-// if (paused_private_state_thread)
-// ResumePrivateStateThread();
-// return error;
-// }
+ DisableAllBreakpointSites ();
- if (catch_stop_event)
- {
- // LISTEN HERE
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(5);
- StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
-
- timed_out = state == eStateInvalid;
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
-
- if (timed_out)
- error.SetErrorString("unable to verify target stopped");
- }
+ m_thread_list.DiscardThreadPlans();
- if (paused_private_state_thread)
+ // If we are going to keep the target stopped, then don't send the disconnect message.
+ if (!keep_stopped && m_comm.IsConnected())
{
+ const bool success = m_comm.SendRequestDisconnect();
if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread");
- ResumePrivateStateThread();
- }
- }
- return error;
-}
-
-Error
-ProcessKDP::WillDetach ()
-{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessKDP::WillDetach()");
-
- bool discard_thread_plans = true;
- bool catch_stop_event = true;
- EventSP event_sp;
- return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
-}
-
-Error
-ProcessKDP::DoDetach()
-{
- Error error;
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessKDP::DoDetach()");
-
- DisableAllBreakpointSites ();
-
- m_thread_list.DiscardThreadPlans();
-
- if (m_comm.IsConnected())
- {
-
- m_comm.SendRequestDisconnect();
-
- size_t response_size = m_comm.Disconnect ();
- if (log)
- {
- if (response_size)
- log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
- else
- log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+ {
+ if (success)
+ log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
+ else
+ log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed");
+ }
+ m_comm.Disconnect ();
}
}
- // Sleep for one second to let the process get all detached...
- StopAsyncThread ();
-
+ StopAsyncThread ();
m_comm.Clear();
SetPrivateState (eStateDetached);
@@ -503,34 +568,9 @@ ProcessKDP::DoDetach()
Error
ProcessKDP::DoDestroy ()
{
- Error error;
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessKDP::DoDestroy()");
-
- // Interrupt if our inferior is running...
- if (m_comm.IsConnected())
- {
- if (m_public_state.GetValue() == eStateAttaching)
- {
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
- m_comm.Disconnect();
- }
- else
- {
- DisableAllBreakpointSites ();
-
- m_comm.SendRequestDisconnect();
-
- StringExtractor response;
- // TODO: Send kill packet?
- SetExitStatus(SIGABRT, NULL);
- }
- }
- StopAsyncThread ();
- m_comm.Clear();
- return error;
+ // For KDP there really is no difference between destroy and detach
+ bool keep_stopped = false;
+ return DoDetach(keep_stopped);
}
//------------------------------------------------------------------
@@ -558,7 +598,9 @@ ProcessKDP::DoReadMemory (addr_t addr, v
size_t
ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
- error.SetErrorString ("ProcessKDP::DoReadMemory not implemented");
+ if (m_comm.IsConnected())
+ return m_comm.SendRequestWriteMemory (addr, buf, size, error);
+ error.SetErrorString ("not connected");
return 0;
}
@@ -578,7 +620,7 @@ ProcessKDP::DoDeallocateMemory (lldb::ad
}
Error
-ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
+ProcessKDP::EnableBreakpointSite (BreakpointSite *bp_site)
{
if (m_comm.LocalBreakpointsAreSupported ())
{
@@ -601,7 +643,7 @@ ProcessKDP::EnableBreakpoint (Breakpoint
}
Error
-ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
+ProcessKDP::DisableBreakpointSite (BreakpointSite *bp_site)
{
if (m_comm.LocalBreakpointsAreSupported ())
{
@@ -611,10 +653,18 @@ ProcessKDP::DisableBreakpoint (Breakpoin
BreakpointSite::Type bp_type = bp_site->GetType();
if (bp_type == BreakpointSite::eExternal)
{
- if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+ if (m_destroy_in_process && m_comm.IsRunning())
+ {
+ // We are trying to destroy our connection and we are running
bp_site->SetEnabled(false);
+ }
else
- error.SetErrorString ("KDP remove breakpoint failed");
+ {
+ if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+ bp_site->SetEnabled(false);
+ else
+ error.SetErrorString ("KDP remove breakpoint failed");
+ }
}
else
{
@@ -627,7 +677,7 @@ ProcessKDP::DisableBreakpoint (Breakpoin
}
Error
-ProcessKDP::EnableWatchpoint (Watchpoint *wp)
+ProcessKDP::EnableWatchpoint (Watchpoint *wp, bool notify)
{
Error error;
error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
@@ -635,7 +685,7 @@ ProcessKDP::EnableWatchpoint (Watchpoint
}
Error
-ProcessKDP::DisableWatchpoint (Watchpoint *wp)
+ProcessKDP::DisableWatchpoint (Watchpoint *wp, bool notify)
{
Error error;
error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
@@ -681,13 +731,14 @@ ProcessKDP::Initialize()
bool
ProcessKDP::StartAsyncThread ()
{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
if (log)
- log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+ log->Printf ("ProcessKDP::StartAsyncThread ()");
- // Create a thread that watches our internal state and controls which
- // events make it to clients (into the DCProcess event queue).
+ if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+ return true;
+
m_async_thread = Host::ThreadCreate ("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
}
@@ -695,10 +746,10 @@ ProcessKDP::StartAsyncThread ()
void
ProcessKDP::StopAsyncThread ()
{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
if (log)
- log->Printf ("ProcessKDP::%s ()", __FUNCTION__);
+ log->Printf ("ProcessKDP::StopAsyncThread ()");
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
@@ -706,6 +757,7 @@ ProcessKDP::StopAsyncThread ()
if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
{
Host::ThreadJoin (m_async_thread, NULL, NULL);
+ m_async_thread = LLDB_INVALID_HOST_THREAD;
}
}
@@ -715,116 +767,291 @@ ProcessKDP::AsyncThread (void *arg)
{
ProcessKDP *process = (ProcessKDP*) arg;
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
+ const lldb::pid_t pid = process->GetID();
+
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) thread starting...", __FUNCTION__, arg, process->GetID());
+ log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid);
Listener listener ("ProcessKDP::AsyncThread");
EventSP event_sp;
const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
eBroadcastBitAsyncThreadShouldExit;
+
if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
{
- listener.StartListeningForEvents (&process->m_comm, Communication::eBroadcastBitReadThreadDidExit);
-
bool done = false;
while (!done)
{
if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+ log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...",
+ pid);
if (listener.WaitForEvent (NULL, event_sp))
{
- const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+ uint32_t event_type = event_sp->GetType();
+ if (log)
+ log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") Got an event of type: %d...",
+ pid,
+ event_type);
+
+ // When we are running, poll for 1 second to try and get an exception
+ // to indicate the process has stopped. If we don't get one, check to
+ // make sure no one asked us to exit
+ bool is_running = false;
+ DataExtractor exc_reply_packet;
+ do
{
- if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
-
switch (event_type)
{
- case eBroadcastBitAsyncContinue:
+ case eBroadcastBitAsyncContinue:
{
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
-
- if (continue_packet)
+ is_running = true;
+ if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
+ {
+ ThreadSP thread_sp (process->GetKernelThread());
+ if (thread_sp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
+ if (reg_ctx_sp)
+ reg_ctx_sp->InvalidateAllRegisters();
+ static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
+ }
+
+ // TODO: parse the stop reply packet
+ is_running = false;
+ process->SetPrivateState(eStateStopped);
+ }
+ else
{
- // TODO: do continue support here
-
-// const char *continue_cstr = (const char *)continue_packet->GetBytes ();
-// const size_t continue_cstr_len = continue_packet->GetByteSize ();
-// if (log)
-// log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-//
-// if (::strstr (continue_cstr, "vAttach") == NULL)
-// process->SetPrivateState(eStateRunning);
-// StringExtractor response;
-// StateType stop_state = process->GetCommunication().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
-//
-// switch (stop_state)
-// {
-// case eStateStopped:
-// case eStateCrashed:
-// case eStateSuspended:
-// process->m_last_stop_packet = response;
-// process->SetPrivateState (stop_state);
-// break;
-//
-// case eStateExited:
-// process->m_last_stop_packet = response;
-// response.SetFilePos(1);
-// process->SetExitStatus(response.GetHexU8(), NULL);
-// done = true;
-// break;
-//
-// case eStateInvalid:
-// process->SetExitStatus(-1, "lost connection");
-// break;
-//
-// default:
-// process->SetPrivateState (stop_state);
-// break;
-// }
+ // Check to see if we are supposed to exit. There is no way to
+ // interrupt a running kernel, so all we can do is wait for an
+ // exception or detach...
+ if (listener.GetNextEvent(event_sp))
+ {
+ // We got an event, go through the loop again
+ event_type = event_sp->GetType();
+ }
}
}
- break;
+ break;
- case eBroadcastBitAsyncThreadShouldExit:
- if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
- done = true;
- break;
+ case eBroadcastBitAsyncThreadShouldExit:
+ if (log)
+ log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...",
+ pid);
+ done = true;
+ is_running = false;
+ break;
- default:
- if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
- }
- }
- else if (event_sp->BroadcasterIs (&process->m_comm))
- {
- if (event_type & Communication::eBroadcastBitReadThreadDidExit)
- {
- process->SetExitStatus (-1, "lost connection");
+ default:
+ if (log)
+ log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got unknown event 0x%8.8x",
+ pid,
+ event_type);
done = true;
+ is_running = false;
+ break;
}
- }
+ } while (is_running);
}
else
{
if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+ log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false",
+ pid);
done = true;
}
}
}
if (log)
- log->Printf ("ProcessKDP::%s (arg = %p, pid = %llu) thread exiting...", __FUNCTION__, arg, process->GetID());
+ log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread exiting...",
+ arg,
+ pid);
process->m_async_thread = LLDB_INVALID_HOST_THREAD;
return NULL;
}
+class CommandObjectProcessKDPPacketSend : public CommandObjectParsed
+{
+private:
+
+ OptionGroupOptions m_option_group;
+ OptionGroupUInt64 m_command_byte;
+ OptionGroupString m_packet_data;
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+
+public:
+ CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "process plugin packet send",
+ "Send a custom packet through the KDP protocol by specifying the command byte and the packet payload data. A packet will be sent with a correct header and payload, and the raw result bytes will be displayed as a string value. ",
+ NULL),
+ m_option_group (interpreter),
+ m_command_byte(LLDB_OPT_SET_1, true , "command", 'c', 0, eArgTypeNone, "Specify the command byte to use when sending the KDP request packet.", 0),
+ m_packet_data (LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, "Specify packet payload bytes as a hex ASCII string with no spaces or hex prefixes.", NULL)
+ {
+ m_option_group.Append (&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append (&m_packet_data , LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectProcessKDPPacketSend ()
+ {
+ }
+
+ bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0)
+ {
+ if (!m_command_byte.GetOptionValue().OptionWasSet())
+ {
+ result.AppendError ("the --command option must be set to a valid command byte");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0);
+ if (command_byte > 0 && command_byte <= UINT8_MAX)
+ {
+ ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process)
+ {
+ const StateType state = process->GetState();
+
+ if (StateIsStoppedState (state, true))
+ {
+ std::vector<uint8_t> payload_bytes;
+ const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue();
+ if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0])
+ {
+ StringExtractor extractor(ascii_hex_bytes_cstr);
+ const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size();
+ if (ascii_hex_bytes_cstr_len & 1)
+ {
+ result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ payload_bytes.resize(ascii_hex_bytes_cstr_len/2);
+ if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size())
+ {
+ result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ Error error;
+ DataExtractor reply;
+ process->GetCommunication().SendRawRequest (command_byte,
+ payload_bytes.empty() ? NULL : payload_bytes.data(),
+ payload_bytes.size(),
+ reply,
+ error);
+
+ if (error.Success())
+ {
+ // Copy the binary bytes into a hex ASCII string for the result
+ StreamString packet;
+ packet.PutBytesAsRawHex8(reply.GetDataStart(),
+ reply.GetByteSize(),
+ lldb::endian::InlHostByteOrder(),
+ lldb::endian::InlHostByteOrder());
+ result.AppendMessage(packet.GetString().c_str());
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ else
+ {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr && error_cstr[0])
+ result.AppendError (error_cstr);
+ else
+ result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid process");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return false;
+ }
+};
+
+class CommandObjectProcessKDPPacket : public CommandObjectMultiword
+{
+private:
+
+public:
+ CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "process plugin packet",
+ "Commands that deal with KDP remote packets.",
+ NULL)
+ {
+ LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessKDPPacketSend (interpreter)));
+ }
+
+ ~CommandObjectProcessKDPPacket ()
+ {
+ }
+};
+
+class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordProcessKDP (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "process plugin",
+ "A set of commands for operating on a ProcessKDP process.",
+ "process plugin <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket (interpreter)));
+ }
+
+ ~CommandObjectMultiwordProcessKDP ()
+ {
+ }
+};
+
+CommandObject *
+ProcessKDP::GetPluginCommandObject()
+{
+ if (!m_command_sp)
+ m_command_sp.reset (new CommandObjectMultiwordProcessKDP (GetTarget().GetDebugger().GetCommandInterpreter()));
+ return m_command_sp.get();
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Thu Jun 6 19:06:43 2013
@@ -19,6 +19,7 @@
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/StreamString.h"
@@ -49,7 +50,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -70,8 +71,8 @@ public:
CanDebug (lldb_private::Target &target,
bool plugin_specified_by_name);
- // virtual uint32_t
- // ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids);
+ virtual lldb_private::CommandObject *
+ GetPluginCommandObject();
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
@@ -90,7 +91,7 @@ public:
WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
virtual lldb_private::Error
- DoConnectRemote (const char *remote_url);
+ DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
virtual lldb_private::Error
DoAttachToProcessWithID (lldb::pid_t pid);
@@ -104,15 +105,18 @@ public:
virtual void
DidAttach ();
+ lldb::addr_t
+ GetImageInfoAddress();
+
+ lldb_private::DynamicLoader *
+ GetDynamicLoader ();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -129,10 +133,7 @@ public:
DoHalt (bool &caused_stop);
virtual lldb_private::Error
- WillDetach ();
-
- virtual lldb_private::Error
- DoDetach ();
+ DoDetach (bool keep_stopped);
virtual lldb_private::Error
DoSignal (int signal);
@@ -168,19 +169,19 @@ public:
// Process Breakpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
- EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
+ EnableBreakpointSite (lldb_private::BreakpointSite *bp_site);
virtual lldb_private::Error
- DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
+ DisableBreakpointSite (lldb_private::BreakpointSite *bp_site);
//----------------------------------------------------------------------
// Process Watchpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
- EnableWatchpoint (lldb_private::Watchpoint *wp);
+ EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
virtual lldb_private::Error
- DisableWatchpoint (lldb_private::Watchpoint *wp);
+ DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
CommunicationKDP &
GetCommunication()
@@ -222,12 +223,6 @@ protected:
bool
ProcessIDIsValid ( ) const;
- // static void
- // STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
- // void
- // AppendSTDOUT (const char* s, size_t len);
-
void
Clear ( );
@@ -240,11 +235,9 @@ protected:
eBroadcastBitAsyncContinue = (1 << 0),
eBroadcastBitAsyncThreadShouldExit = (1 << 1)
};
-
- lldb_private::Error
- InterruptIfRunning (bool discard_thread_plans,
- bool catch_stop_event,
- lldb::EventSP &stop_event_sp);
+
+ lldb::ThreadSP
+ GetKernelThread ();
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
@@ -252,6 +245,11 @@ protected:
CommunicationKDP m_comm;
lldb_private::Broadcaster m_async_broadcaster;
lldb::thread_t m_async_thread;
+ lldb_private::ConstString m_dyld_plugin_name;
+ lldb::addr_t m_kernel_load_addr;
+ lldb::CommandObjectSP m_command_sp;
+ lldb::ThreadWP m_kernel_thread_wp;
+
bool
StartAsyncThread ();
@@ -262,9 +260,6 @@ protected:
static void *
AsyncThread (void *arg);
- lldb::StateType
- SetThreadStopInfo (StringExtractor& stop_packet);
-
private:
//------------------------------------------------------------------
// For ProcessKDP only
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp Thu Jun 6 19:06:43 2013
@@ -20,24 +20,27 @@ using namespace lldb_private;
// We want to avoid global constructors where code needs to be run so here we
// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
+// that will construct the static g_log_sp the first time this function is
// called.
-static LogSP &
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
GetLog ()
{
- static LogSP g_log_sp;
- return g_log_sp;
+ if (!g_log_enabled)
+ return NULL;
+ return g_log;
}
-LogSP
+Log *
ProcessKDPLog::GetLogIfAllCategoriesSet (uint32_t mask)
{
- LogSP log(GetLog ());
+ Log *log(GetLog ());
if (log && mask)
{
uint32_t log_mask = log->GetMask().Get();
if ((log_mask & mask) != mask)
- return LogSP();
+ return NULL;
}
return log;
}
@@ -45,7 +48,7 @@ ProcessKDPLog::GetLogIfAllCategoriesSet
void
ProcessKDPLog::DisableLog (const char **categories, Stream *feedback_strm)
{
- LogSP log (GetLog ());
+ Log *log (GetLog ());
if (log)
{
uint32_t flag_bits = 0;
@@ -81,33 +84,33 @@ ProcessKDPLog::DisableLog (const char **
}
}
+ log->GetMask().Reset (flag_bits);
if (flag_bits == 0)
- GetLog ().reset();
- else
- log->GetMask().Reset (flag_bits);
+ g_log_enabled = false;
}
return;
}
-LogSP
+Log *
ProcessKDPLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
{
// Try see if there already is a log - that way we can reuse its settings.
// We could reuse the log in toto, but we don't know that the stream is the same.
uint32_t flag_bits = 0;
- LogSP log(GetLog ());
- if (log)
- flag_bits = log->GetMask().Get();
+ if (g_log)
+ flag_bits = g_log->GetMask().Get();
// Now make a new log with this stream if one was provided
if (log_stream_sp)
{
- log.reset (new Log(log_stream_sp));
- GetLog () = log;
+ if (g_log)
+ g_log->SetStream(log_stream_sp);
+ else
+ g_log = new Log(log_stream_sp);
}
- if (log)
+ if (g_log)
{
bool got_unknown_category = false;
for (size_t i=0; categories[i] != NULL; ++i)
@@ -140,10 +143,11 @@ ProcessKDPLog::EnableLog (StreamSP &log_
}
if (flag_bits == 0)
flag_bits = KDP_LOG_DEFAULT;
- log->GetMask().Reset(flag_bits);
- log->GetOptions().Reset(log_options);
+ g_log->GetMask().Reset(flag_bits);
+ g_log->GetOptions().Reset(log_options);
}
- return log;
+ g_log_enabled = true;
+ return g_log;
}
void
@@ -163,14 +167,15 @@ ProcessKDPLog::ListLogCategories (Stream
" thread - log thread events and activities\n"
" step - log step related activities\n"
" verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n", ProcessKDP::GetPluginNameStatic());
+ " watch - log watchpoint related activities\n",
+ ProcessKDP::GetPluginNameStatic().GetCString());
}
void
ProcessKDPLog::LogIf (uint32_t mask, const char *format, ...)
{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask));
+ Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask));
if (log)
{
va_list args;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Thu Jun 6 19:06:43 2013
@@ -35,13 +35,13 @@
class ProcessKDPLog
{
public:
- static lldb::LogSP
+ static lldb_private::Log *
GetLogIfAllCategoriesSet(uint32_t mask = 0);
static void
DisableLog (const char **categories, lldb_private::Stream *feedback_strm);
- static lldb::LogSP
+ static lldb_private::Log *
EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, lldb_private::Stream *feedback_strm);
static void
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp Thu Jun 6 19:06:43 2013
@@ -97,24 +97,64 @@ RegisterContextKDP_arm::DoReadDBG (lldb:
int
RegisterContextKDP_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, DBGRegSet, &dbg, sizeof(dbg), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp Thu Jun 6 19:06:43 2013
@@ -81,18 +81,48 @@ RegisterContextKDP_i386::DoReadEXC (lldb
int
RegisterContextKDP_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -33,35 +33,95 @@ RegisterContextKDP_x86_64::~RegisterCont
int
RegisterContextKDP_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestReadRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, GPRRegSet, &gpr, sizeof(gpr), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, FPURegSet, &fpu, sizeof(fpu), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
int
RegisterContextKDP_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
+ ProcessSP process_sp (CalculateProcess());
+ if (process_sp)
+ {
+ Error error;
+ if (static_cast<ProcessKDP *>(process_sp.get())->GetCommunication().SendRequestWriteRegisters (tid, EXCRegSet, &exc, sizeof(exc), error))
+ {
+ if (error.Success())
+ return 0;
+ }
+ }
return -1;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp Thu Jun 6 19:06:43 2013
@@ -28,6 +28,7 @@
#include "RegisterContextKDP_arm.h"
#include "RegisterContextKDP_i386.h"
#include "RegisterContextKDP_x86_64.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
using namespace lldb;
using namespace lldb_private;
@@ -36,8 +37,8 @@ using namespace lldb_private;
// Thread Registers
//----------------------------------------------------------------------
-ThreadKDP::ThreadKDP (const lldb::ProcessSP &process_sp, lldb::tid_t tid) :
- Thread(process_sp, tid),
+ThreadKDP::ThreadKDP (Process &process, lldb::tid_t tid) :
+ Thread(process, tid),
m_thread_name (),
m_dispatch_queue_name (),
m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
@@ -65,37 +66,6 @@ ThreadKDP::GetQueueName ()
return NULL;
}
-bool
-ThreadKDP::WillResume (StateType resume_state)
-{
- ClearStackFrames();
- // Call the Thread::WillResume first. If we stop at a signal, the stop info
- // class for signal will set the resume signal that we need below. The signal
- // stuff obeys the Process::UnixSignal defaults.
- Thread::WillResume(resume_state);
-
- lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
- if (log)
- log->Printf ("Resuming thread: %4.4llx with state: %s.", GetID(), StateAsCString(resume_state));
-
-// ProcessKDP &process = GetKDPProcess();
-// switch (resume_state)
-// {
-// case eStateSuspended:
-// case eStateStopped:
-// // Don't append anything for threads that should stay stopped.
-// break;
-//
-// case eStateRunning:
-// case eStateStepping:
-// break;
-//
-// default:
-// break;
-// }
- return true;
-}
-
void
ThreadKDP::RefreshStateAfterStop()
{
@@ -108,19 +78,11 @@ ThreadKDP::RefreshStateAfterStop()
// register supply functions where they check the process stop ID and do
// the right thing.
const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
+ lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
+ if (reg_ctx_sp)
+ reg_ctx_sp->InvalidateIfNeeded (force);
}
-void
-ThreadKDP::ClearStackFrames ()
-{
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- unwinder->Clear();
- Thread::ClearStackFrames();
-}
-
-
bool
ThreadKDP::ThreadIDIsValid (lldb::tid_t thread)
{
@@ -177,40 +139,69 @@ ThreadKDP::CreateRegisterContextForFrame
}
}
}
- else if (m_unwinder_ap.get())
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ else
+ {
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+ }
return reg_ctx_sp;
}
-lldb::StopInfoSP
-ThreadKDP::GetPrivateStopReason ()
+bool
+ThreadKDP::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- const uint32_t process_stop_id = process_sp->GetStopID();
- if (m_thread_stop_reason_stop_id != process_stop_id ||
- (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+ if (m_cached_stop_info_sp)
+ {
+ SetStopInfo (m_cached_stop_info_sp);
+ }
+ else
{
- // TODO: can we query the initial state of the thread here?
- // For now I am just going to pretend that a SIGSTOP happened.
-
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
-
- // If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
- // for this thread, then m_actual_stop_info_sp will not ever contain
- // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
- // check will never be able to tell us if we have the correct stop info
- // for this thread and we will continually send qThreadStopInfo packets
- // down to the remote KDP server, so we need to keep our own notion
- // of the stop ID that m_actual_stop_info_sp is valid for (even if it
- // contains nothing). We use m_thread_stop_reason_stop_id for this below.
- // m_thread_stop_reason_stop_id = process_stop_id;
- // m_actual_stop_info_sp.reset();
-
}
+ return true;
}
- return m_actual_stop_info_sp;
+ return false;
}
+void
+ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet)
+{
+ lldb::offset_t offset = 0;
+ uint8_t reply_command = exc_reply_packet.GetU8(&offset);
+ if (reply_command == CommunicationKDP::KDP_EXCEPTION)
+ {
+ offset = 8;
+ const uint32_t count = exc_reply_packet.GetU32 (&offset);
+ if (count >= 1)
+ {
+ //const uint32_t cpu = exc_reply_packet.GetU32 (&offset);
+ offset += 4; // Skip the useless CPU field
+ const uint32_t exc_type = exc_reply_packet.GetU32 (&offset);
+ const uint32_t exc_code = exc_reply_packet.GetU32 (&offset);
+ const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset);
+ // We have to make a copy of the stop info because the thread list
+ // will iterate through the threads and clear all stop infos..
+
+ // Let the StopInfoMachException::CreateStopReasonWithMachException()
+ // function update the PC if needed as we might hit a software breakpoint
+ // and need to decrement the PC (i386 and x86_64 need this) and KDP
+ // doesn't do this for us.
+ const bool pc_already_adjusted = false;
+ const bool adjust_pc_if_needed = true;
+
+ m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this,
+ exc_type,
+ 2,
+ exc_code,
+ exc_subcode,
+ 0,
+ pc_already_adjusted,
+ adjust_pc_if_needed);
+ }
+ }
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h Thu Jun 6 19:06:43 2013
@@ -20,15 +20,12 @@ class ProcessKDP;
class ThreadKDP : public lldb_private::Thread
{
public:
- ThreadKDP (const lldb::ProcessSP &process_sp,
+ ThreadKDP (lldb_private::Process &process,
lldb::tid_t tid);
virtual
~ThreadKDP ();
- virtual bool
- WillResume (lldb::StateType resume_state);
-
virtual void
RefreshStateAfterStop();
@@ -44,9 +41,6 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
- virtual void
- ClearStackFrames ();
-
void
Dump (lldb_private::Log *log, uint32_t index);
@@ -79,6 +73,9 @@ public:
{
m_thread_dispatch_qaddr = thread_dispatch_qaddr;
}
+
+ void
+ SetStopInfoFrom_KDP_EXCEPTION (const lldb_private::DataExtractor &exc_reply_packet);
protected:
@@ -90,14 +87,12 @@ protected:
std::string m_thread_name;
std::string m_dispatch_queue_name;
lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::StopInfoSP m_cached_stop_info_sp;
//------------------------------------------------------------------
- // Member variables.
+ // Protected member functions.
//------------------------------------------------------------------
-
- virtual lldb::StopInfoSP
- GetPrivateStopReason ();
-
-
+ virtual bool
+ CalculateStopInfo ();
};
#endif // liblldb_ThreadKDP_h_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/Makefile Thu Jun 6 19:06:43 2013
@@ -18,6 +18,10 @@ CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEV
ifeq ($(HOST_OS),Linux)
CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux
+
+# Disable warning for now as offsetof is used with an index into a structure member array
+# in defining register info tables.
+CPPFLAGS += -Wno-extended-offsetof
endif
ifeq ($(HOST_OS),FreeBSD)
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.cpp Thu Jun 6 19:06:43 2013
@@ -21,7 +21,7 @@ POSIXLimboStopInfo::~POSIXLimboStopInfo(
lldb::StopReason
POSIXLimboStopInfo::GetStopReason() const
{
- return lldb::eStopReasonTrace;
+ return lldb::eStopReasonThreadExiting;
}
const char *
@@ -33,13 +33,13 @@ POSIXLimboStopInfo::GetDescription()
bool
POSIXLimboStopInfo::ShouldStop(Event *event_ptr)
{
- return true;
+ return false;
}
bool
POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
{
- return true;
+ return false;
}
//===----------------------------------------------------------------------===//
@@ -58,3 +58,32 @@ POSIXCrashStopInfo::GetDescription()
{
return ProcessMessage::GetCrashReasonString(m_crash_reason);
}
+
+//===----------------------------------------------------------------------===//
+// POSIXNewThreadStopInfo
+
+POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { }
+
+lldb::StopReason
+POSIXNewThreadStopInfo::GetStopReason() const
+{
+ return lldb::eStopReasonNone;
+}
+
+const char *
+POSIXNewThreadStopInfo::GetDescription()
+{
+ return "thread spawned";
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr)
+{
+ return false;
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr)
+{
+ return false;
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXStopInfo.h Thu Jun 6 19:06:43 2013
@@ -89,4 +89,32 @@ private:
ProcessMessage::CrashReason m_crash_reason;
};
+//===----------------------------------------------------------------------===//
+/// @class POSIXNewThreadStopInfo
+/// @brief Represents the stop state of process when a new thread is spawned.
+///
+
+class POSIXNewThreadStopInfo
+ : public POSIXStopInfo
+{
+public:
+ POSIXNewThreadStopInfo (POSIXThread &thread)
+ : POSIXStopInfo (thread, 0)
+ { }
+
+ ~POSIXNewThreadStopInfo();
+
+ lldb::StopReason
+ GetStopReason() const;
+
+ const char *
+ GetDescription();
+
+ bool
+ ShouldStop(lldb_private::Event *event_ptr);
+
+ bool
+ ShouldNotify(lldb_private::Event *event_ptr);
+};
+
#endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.cpp Thu Jun 6 19:06:43 2013
@@ -7,13 +7,17 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
// C Includes
#include <errno.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
@@ -26,6 +30,8 @@
#include "RegisterContext_i386.h"
#include "RegisterContext_x86_64.h"
#include "RegisterContextPOSIX.h"
+#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_x86_64.h"
#include "UnwindLLDB.h"
@@ -33,13 +39,27 @@ using namespace lldb;
using namespace lldb_private;
-POSIXThread::POSIXThread(ProcessSP &process, lldb::tid_t tid)
+POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
: Thread(process, tid),
- m_frame_ap(0)
+ m_frame_ap()
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid);
+ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
+
+ // Set the current watchpoints for this thread.
+ Target &target = GetProcess()->GetTarget();
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ size_t wp_size = wp_list.GetSize();
+
+ for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
+ {
+ lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
+ if (wp.get() && wp->IsEnabled())
+ {
+ assert(EnableHardwareWatchpoint(wp.get()));
+ }
+ }
}
POSIXThread::~POSIXThread()
@@ -58,15 +78,24 @@ POSIXThread::GetMonitor()
void
POSIXThread::RefreshStateAfterStop()
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
-
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- ProcessSP base = GetProcess();
- ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
- process.GetThreadList().RefreshStateAfterStop();
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ //if (StateIsStoppedState(GetState())
+ {
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
+ }
+ // FIXME: This should probably happen somewhere else.
+ SetResumeState(eStateRunning);
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID());
}
const char *
@@ -95,7 +124,14 @@ POSIXThread::GetRegisterContext()
break;
case ArchSpec::eCore_x86_64_x86_64:
- m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));
+// TODO: Use target OS/architecture detection rather than ifdefs so that
+// lldb built on FreeBSD can debug on Linux and vice-versa.
+#ifdef __linux__
+ m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
+#endif
+#ifdef __FreeBSD__
+ m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
+#endif
break;
}
}
@@ -108,7 +144,7 @@ POSIXThread::CreateRegisterContextForFra
lldb::RegisterContextSP reg_ctx_sp;
uint32_t concrete_frame_idx = 0;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("POSIXThread::%s ()", __FUNCTION__);
@@ -126,10 +162,11 @@ POSIXThread::CreateRegisterContextForFra
return reg_ctx_sp;
}
-lldb::StopInfoSP
-POSIXThread::GetPrivateStopReason()
+bool
+POSIXThread::CalculateStopInfo()
{
- return m_stop_info;
+ SetStopInfo (m_stop_info_sp);
+ return true;
}
Unwind *
@@ -141,16 +178,21 @@ POSIXThread::GetUnwinder()
return m_unwinder_ap.get();
}
-bool
+void
POSIXThread::WillResume(lldb::StateType resume_state)
{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state));
+ // TODO: the line below shouldn't really be done, but
+ // the POSIXThread might rely on this so I will leave this in for now
SetResumeState(resume_state);
+}
- ClearStackFrames();
- if (m_unwinder_ap.get())
- m_unwinder_ap->Clear();
-
- return Thread::WillResume(resume_state);
+void
+POSIXThread::DidStop()
+{
+ // Don't set the thread state to stopped unless we really stopped.
}
bool
@@ -160,9 +202,10 @@ POSIXThread::Resume()
ProcessMonitor &monitor = GetMonitor();
bool status;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
+ StateAsCString(resume_state));
switch (resume_state)
{
@@ -180,6 +223,10 @@ POSIXThread::Resume()
SetState(resume_state);
status = monitor.SingleStep(GetID(), GetResumeSignal());
break;
+ case lldb::eStateStopped:
+ case lldb::eStateSuspended:
+ status = true;
+ break;
}
return status;
@@ -188,7 +235,7 @@ POSIXThread::Resume()
void
POSIXThread::Notify(const ProcessMessage &message)
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log)
log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
@@ -198,10 +245,14 @@ POSIXThread::Notify(const ProcessMessage
assert(false && "Unexpected message kind!");
break;
+ case ProcessMessage::eExitMessage:
+ // Nothing to be done.
+ break;
+
case ProcessMessage::eLimboMessage:
LimboNotify(message);
break;
-
+
case ProcessMessage::eSignalMessage:
SignalNotify(message);
break;
@@ -218,17 +269,88 @@ POSIXThread::Notify(const ProcessMessage
BreakNotify(message);
break;
+ case ProcessMessage::eWatchpointMessage:
+ WatchNotify(message);
+ break;
+
case ProcessMessage::eCrashMessage:
CrashNotify(message);
break;
+
+ case ProcessMessage::eNewThreadMessage:
+ ThreadNotify(message);
+ break;
+ }
+}
+
+bool
+POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool wp_set = false;
+ if (wp)
+ {
+ addr_t wp_addr = wp->GetLoadAddress();
+ size_t wp_size = wp->GetByteSize();
+ bool wp_read = wp->WatchpointRead();
+ bool wp_write = wp->WatchpointWrite();
+ uint32_t wp_hw_index = wp->GetHardwareIndex();
+ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ if (reg_ctx)
+ wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
+ wp_read, wp_write,
+ wp_hw_index);
+ }
+ return wp_set;
+}
+
+bool
+POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool result = false;
+ if (wp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
}
+ return result;
+}
+
+uint32_t
+POSIXThread::NumSupportedHardwareWatchpoints()
+{
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ return reg_ctx_sp->NumSupportedHardwareWatchpoints();
+ return 0;
+}
+
+uint32_t
+POSIXThread::FindVacantWatchpointIndex()
+{
+ uint32_t hw_index = LLDB_INVALID_INDEX32;
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ if (reg_ctx)
+ {
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointVacant(wp_idx))
+ {
+ hw_index = wp_idx;
+ break;
+ }
+ }
+ }
+ return hw_index;
}
void
POSIXThread::BreakNotify(const ProcessMessage &message)
{
bool status;
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
assert(GetRegisterContext());
status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
@@ -239,27 +361,82 @@ POSIXThread::BreakNotify(const ProcessMe
assert(GetRegisterContext());
lldb::addr_t pc = GetRegisterContext()->GetPC();
if (log)
- log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
+ log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
assert(bp_site);
lldb::break_id_t bp_id = bp_site->GetID();
assert(bp_site && bp_site->ValidForThisThread(this));
-
+ // Make this thread the selected thread
+ GetProcess()->GetThreadList().SetSelectedThreadByID(GetID());
+
m_breakpoint = bp_site;
- m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+}
+
+void
+POSIXThread::WatchNotify(const ProcessMessage &message)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ lldb::addr_t halt_addr = message.GetHWAddress();
+ if (log)
+ log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
+ PRIx64, __FUNCTION__, halt_addr);
+
+ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ // Clear the watchpoint hit here
+ reg_ctx->ClearWatchpointHits();
+ break;
+ }
+ }
+
+ if (wp_idx == num_hw_wps)
+ return;
+
+ Target &target = GetProcess()->GetTarget();
+ lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
+
+ if (wp_sp)
+ SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
+ wp_sp->GetID()));
+ }
}
void
POSIXThread::TraceNotify(const ProcessMessage &message)
{
- m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ WatchNotify(message);
+ return;
+ }
+ }
+ }
+ SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
}
void
POSIXThread::LimboNotify(const ProcessMessage &message)
{
- m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this));
+ SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
}
void
@@ -267,7 +444,7 @@ POSIXThread::SignalNotify(const ProcessM
{
int signo = message.GetSignal();
- m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
SetResumeSignal(signo);
}
@@ -276,27 +453,32 @@ POSIXThread::SignalDeliveredNotify(const
{
int signo = message.GetSignal();
- // Just treat debugger generated signal events like breakpoints for now.
- m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
SetResumeSignal(signo);
}
void
POSIXThread::CrashNotify(const ProcessMessage &message)
{
+ // FIXME: Update stop reason as per bugzilla 14598
int signo = message.GetSignal();
assert(message.GetKind() == ProcessMessage::eCrashMessage);
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log)
log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
- m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo(
- *this, signo, message.GetCrashReason()));
+ SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, message.GetCrashReason())));
SetResumeSignal(signo);
}
+void
+POSIXThread::ThreadNotify(const ProcessMessage &message)
+{
+ SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)));
+}
+
unsigned
POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
{
@@ -312,11 +494,14 @@ POSIXThread::GetRegisterIndexFromOffset(
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_32_i486:
case ArchSpec::eCore_x86_32_i486sx:
- reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
- break;
-
case ArchSpec::eCore_x86_64_x86_64:
- reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
+ {
+ RegisterContextSP base = GetRegisterContext();
+ if (base) {
+ RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
+ reg = context.GetRegisterIndexFromOffset(offset);
+ }
+ }
break;
}
return reg;
@@ -325,7 +510,7 @@ POSIXThread::GetRegisterIndexFromOffset(
const char *
POSIXThread::GetRegisterName(unsigned reg)
{
- const char * name;
+ const char * name = nullptr;
ArchSpec arch = Host::GetArchitecture();
switch (arch.GetCore())
@@ -337,11 +522,8 @@ POSIXThread::GetRegisterName(unsigned re
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_32_i486:
case ArchSpec::eCore_x86_32_i486sx:
- name = RegisterContext_i386::GetRegisterName(reg);
- break;
-
case ArchSpec::eCore_x86_64_x86_64:
- name = RegisterContext_x86_64::GetRegisterName(reg);
+ name = GetRegisterContext()->GetRegisterName(reg);
break;
}
return name;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/POSIXThread.h Thu Jun 6 19:06:43 2013
@@ -29,16 +29,20 @@ class POSIXThread
: public lldb_private::Thread
{
public:
- POSIXThread(lldb::ProcessSP &process, lldb::tid_t tid);
+ POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
virtual ~POSIXThread();
void
RefreshStateAfterStop();
- bool
+ virtual void
WillResume(lldb::StateType resume_state);
+ // This notifies the thread when a private stop occurs.
+ virtual void
+ DidStop ();
+
const char *
GetInfo();
@@ -49,17 +53,17 @@ public:
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
//--------------------------------------------------------------------------
- // These static functions provide a mapping from the register offset
+ // These functions provide a mapping from the register offset
// back to the register index or name for use in debugging or log
// output.
- static unsigned
+ unsigned
GetRegisterIndexFromOffset(unsigned offset);
- static const char *
+ const char *
GetRegisterName(unsigned reg);
- static const char *
+ const char *
GetRegisterNameFromOffset(unsigned offset);
//--------------------------------------------------------------------------
@@ -69,6 +73,17 @@ public:
void Notify(const ProcessMessage &message);
+ //--------------------------------------------------------------------------
+ // These methods provide an interface to watchpoints
+ //
+ bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ uint32_t NumSupportedHardwareWatchpoints();
+
+ uint32_t FindVacantWatchpointIndex();
+
private:
RegisterContextPOSIX *
GetRegisterContextPOSIX ()
@@ -81,23 +96,25 @@ private:
return (RegisterContextPOSIX *)m_reg_context_sp.get();
}
- std::auto_ptr<lldb_private::StackFrame> m_frame_ap;
+ std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
lldb::BreakpointSiteSP m_breakpoint;
- lldb::StopInfoSP m_stop_info;
ProcessMonitor &
GetMonitor();
- lldb::StopInfoSP
- GetPrivateStopReason();
+ virtual bool
+ CalculateStopInfo();
void BreakNotify(const ProcessMessage &message);
+ void WatchNotify(const ProcessMessage &message);
void TraceNotify(const ProcessMessage &message);
void LimboNotify(const ProcessMessage &message);
void SignalNotify(const ProcessMessage &message);
void SignalDeliveredNotify(const ProcessMessage &message);
void CrashNotify(const ProcessMessage &message);
+ void ThreadNotify(const ProcessMessage &message);
+ void ExitNotify(const ProcessMessage &message);
lldb_private::Unwind *
GetUnwinder();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.cpp Thu Jun 6 19:06:43 2013
@@ -102,10 +102,6 @@ ProcessMessage::PrintCrashReason(CrashRe
switch (reason)
{
- default:
- assert(false && "invalid CrashReason");
- break;
-
case eInvalidCrashReason:
str = "eInvalidCrashReason";
break;
@@ -204,10 +200,6 @@ ProcessMessage::PrintKind(Kind kind)
switch (kind)
{
- default:
- assert(false && "invalid Kind");
- break;
-
case eInvalidMessage:
str = "eInvalidMessage";
break;
@@ -229,9 +221,15 @@ ProcessMessage::PrintKind(Kind kind)
case eBreakpointMessage:
str = "eBreakpointMessage";
break;
+ case eWatchpointMessage:
+ str = "eWatchpointMessage";
+ break;
case eCrashMessage:
str = "eCrashMessage";
break;
+ case eNewThreadMessage:
+ str = "eNewThreadMessage";
+ break;
}
#endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessMessage.h Thu Jun 6 19:06:43 2013
@@ -29,7 +29,9 @@ public:
eSignalDeliveredMessage,
eTraceMessage,
eBreakpointMessage,
- eCrashMessage
+ eWatchpointMessage,
+ eCrashMessage,
+ eNewThreadMessage
};
enum CrashReason
@@ -103,6 +105,10 @@ public:
return ProcessMessage(tid, eBreakpointMessage);
}
+ static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) {
+ return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr);
+ }
+
/// Indicates that the thread @p tid crashed.
static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
int signo, lldb::addr_t fault_addr) {
@@ -111,6 +117,16 @@ public:
return message;
}
+ /// Indicates that the thread @p child_tid was spawned.
+ static ProcessMessage NewThread(lldb::tid_t parent_tid, lldb::tid_t child_tid) {
+ return ProcessMessage(parent_tid, eNewThreadMessage, child_tid);
+ }
+
+ /// Indicates that the thread @p tid is about to exit with status @p status.
+ static ProcessMessage Exit(lldb::tid_t tid, int status) {
+ return ProcessMessage(tid, eExitMessage, status);
+ }
+
int GetExitStatus() const {
assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
return m_status;
@@ -137,6 +153,16 @@ public:
return m_addr;
}
+ lldb::addr_t GetHWAddress() const {
+ assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage);
+ return m_addr;
+ }
+
+ lldb::tid_t GetChildTID() const {
+ assert(GetKind() == eNewThreadMessage);
+ return m_child_tid;
+ }
+
static const char *
GetCrashReasonString(CrashReason reason);
@@ -159,13 +185,23 @@ private:
m_kind(kind),
m_crash_reason(eInvalidCrashReason),
m_status(status),
- m_addr(addr) { }
+ m_addr(addr),
+ m_child_tid(0) { }
+
+ ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid)
+ : m_tid(tid),
+ m_kind(kind),
+ m_crash_reason(eInvalidCrashReason),
+ m_status(0),
+ m_addr(0),
+ m_child_tid(child_tid) { }
lldb::tid_t m_tid;
Kind m_kind : 8;
CrashReason m_crash_reason : 8;
int m_status;
lldb::addr_t m_addr;
+ lldb::tid_t m_child_tid;
};
#endif // #ifndef liblldb_ProcessMessage_H_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Thu Jun 6 19:06:43 2013
@@ -7,16 +7,22 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
// C Includes
#include <errno.h>
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"
#include "ProcessPOSIX.h"
@@ -69,6 +75,7 @@ ProcessPOSIX::ProcessPOSIX(Target& targe
m_byte_order(lldb::endian::InlHostByteOrder()),
m_monitor(NULL),
m_module(NULL),
+ m_message_mutex (Mutex::eMutexTypeRecursive),
m_in_limbo(false),
m_exit_now(false)
{
@@ -94,7 +101,8 @@ ProcessPOSIX::CanDebug(Target &target, b
ModuleSP exe_module_sp(target.GetExecutableModule());
if (exe_module_sp.get())
return exe_module_sp->GetFileSpec().Exists();
- return false;
+ // If there is no executable module, we return true since we might be preparing to attach.
+ return true;
}
Error
@@ -103,20 +111,57 @@ ProcessPOSIX::DoAttachToProcessWithID(ll
Error error;
assert(m_monitor == NULL);
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID());
+ log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
m_monitor = new ProcessMonitor(this, pid, error);
if (!error.Success())
return error;
+ PlatformSP platform_sp (m_target.GetPlatform ());
+ assert (platform_sp.get());
+ if (!platform_sp)
+ return error; // FIXME: Detatch?
+
+ // Find out what we can about this process
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo (pid, process_info);
+
+ // Resolve the executable module
+ ModuleSP exe_module_sp;
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+ m_target.GetArchitecture(),
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+
+ // Fix the target architecture if necessary
+ const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+ if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
+ m_target.SetArchitecture(module_arch);
+
+ // Initialize the target module list
+ m_target.SetExecutableModule (exe_module_sp, true);
+
+ if (!error.Success())
+ return error;
+
+ SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
SetID(pid);
+
return error;
}
Error
+ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
+{
+ return DoAttachToProcessWithID(pid);
+}
+
+Error
ProcessPOSIX::WillLaunch(Module* module)
{
Error error;
@@ -153,6 +198,16 @@ ProcessPOSIX::DoLaunch (Module *module,
Error error;
assert(m_monitor == NULL);
+ const char* working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir) {
+ FileSpec WorkingDir(working_dir, true);
+ if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
+ {
+ error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
+ return error;
+ }
+ }
+
SetPrivateState(eStateLaunching);
const lldb_private::ProcessLaunchInfo::FileAction *file_action;
@@ -161,7 +216,7 @@ ProcessPOSIX::DoLaunch (Module *module,
const char *stdin_path = NULL;
const char *stdout_path = NULL;
const char *stderr_path = NULL;
-
+
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
stdin_path = GetFilePath(file_action, stdin_path);
@@ -178,6 +233,7 @@ ProcessPOSIX::DoLaunch (Module *module,
stdin_path,
stdout_path,
stderr_path,
+ working_dir,
error);
m_module = module;
@@ -185,6 +241,8 @@ ProcessPOSIX::DoLaunch (Module *module,
if (!error.Success())
return error;
+ SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
SetID(m_monitor->GetPID());
return error;
}
@@ -256,16 +314,29 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
{
caused_stop = true;
}
-
return error;
}
Error
-ProcessPOSIX::DoDetach()
+ProcessPOSIX::DoDetach(bool keep_stopped)
{
Error error;
+ if (keep_stopped)
+ {
+ // FIXME: If you want to implement keep_stopped on Linux,
+ // this would be the place to do it.
+ error.SetErrorString("Detaching with keep_stopped true is not currently supported on Linux.");
+ return error;
+ }
+
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ error = m_monitor->Detach(thread->GetID());
+ }
- error = m_monitor->Detach();
if (error.Success())
SetPrivateState(eStateDetached);
@@ -311,83 +382,147 @@ ProcessPOSIX::SendMessage(const ProcessM
{
Mutex::Locker lock(m_message_mutex);
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.FindThreadByID(message.GetTID(), false).get());
+
switch (message.GetKind())
{
- default:
- assert(false && "Unexpected process message!");
- break;
-
case ProcessMessage::eInvalidMessage:
return;
case ProcessMessage::eLimboMessage:
- m_in_limbo = true;
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
+ assert(thread);
+ thread->SetState(eStateStopped);
+ if (message.GetTID() == GetID())
{
- SetPrivateState(eStateExited);
- m_monitor->Detach();
+ m_in_limbo = true;
+ m_exit_status = message.GetExitStatus();
+ if (m_exit_now)
+ {
+ SetPrivateState(eStateExited);
+ m_monitor->Detach(GetID());
+ }
+ else
+ {
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ }
}
else
+ {
+ StopAllThreads(message.GetTID());
SetPrivateState(eStateStopped);
+ }
break;
case ProcessMessage::eExitMessage:
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
+ assert(thread);
+ thread->SetState(eStateExited);
+ // FIXME: I'm not sure we need to do this.
+ if (message.GetTID() == GetID())
+ {
+ m_exit_status = message.GetExitStatus();
+ SetExitStatus(m_exit_status, NULL);
+ }
break;
- case ProcessMessage::eTraceMessage:
case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eTraceMessage:
+ case ProcessMessage::eWatchpointMessage:
+ case ProcessMessage::eNewThreadMessage:
+ case ProcessMessage::eCrashMessage:
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
SetPrivateState(eStateStopped);
break;
case ProcessMessage::eSignalMessage:
case ProcessMessage::eSignalDeliveredMessage:
- SetPrivateState(eStateStopped);
- break;
+ {
+ lldb::tid_t tid = message.GetTID();
+ lldb::tid_t pid = GetID();
+ if (tid == pid) {
+ assert(thread);
+ thread->SetState(eStateStopped);
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
+ } else {
+ // FIXME: Ignore any signals generated by children.
+ return;
+ }
+ }
- case ProcessMessage::eCrashMessage:
- SetPrivateState(eStateCrashed);
- break;
}
m_message_queue.push(message);
}
+void
+ProcessPOSIX::StopAllThreads(lldb::tid_t stop_tid)
+{
+ // FIXME: Will this work the same way on FreeBSD and Linux?
+}
+
void
ProcessPOSIX::RefreshStateAfterStop()
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);
+ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
Mutex::Locker lock(m_message_mutex);
- if (m_message_queue.empty())
- return;
- ProcessMessage &message = m_message_queue.front();
+ // This method used to only handle one message. Changing it to loop allows
+ // it to handle the case where we hit a breakpoint while handling a different
+ // breakpoint.
+ while (!m_message_queue.empty())
+ {
+ ProcessMessage &message = m_message_queue.front();
+
+ // Resolve the thread this message corresponds to and pass it along.
+ lldb::tid_t tid = message.GetTID();
+ if (log)
+ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
- // Resolve the thread this message corresponds to and pass it along.
- // FIXME: we're really dealing with the pid here. This should get
- // fixed when this code is fixed to handle multiple threads.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid);
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
+ if (message.GetKind() == ProcessMessage::eNewThreadMessage)
+ {
+ if (log)
+ log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
+ ThreadSP thread_sp;
+ thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
+ m_thread_list.AddThread(thread_sp);
+ }
+
+ m_thread_list.RefreshStateAfterStop();
+
+ if (thread)
+ thread->Notify(message);
- assert(thread);
- thread->Notify(message);
+ if (message.GetKind() == ProcessMessage::eExitMessage)
+ {
+ // FIXME: We should tell the user about this, but the limbo message is probably better for that.
+ if (log)
+ log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
+ ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+ thread_sp.reset();
+ }
- m_message_queue.pop();
+ m_message_queue.pop();
+ }
}
bool
ProcessPOSIX::IsAlive()
{
StateType state = GetPrivateState();
- return state != eStateDetached && state != eStateExited && state != eStateInvalid;
+ return state != eStateDetached
+ && state != eStateExited
+ && state != eStateInvalid
+ && state != eStateUnloaded;
}
size_t
@@ -441,11 +576,25 @@ ProcessPOSIX::DoDeallocateMemory(lldb::a
InferiorCallMunmap(this, addr, pos->second))
m_addr_to_mmap_size.erase (pos);
else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
+ error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
return error;
}
+addr_t
+ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
+{
+ addr_t function_addr = LLDB_INVALID_ADDRESS;
+ if (address == NULL) {
+ error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
+ } else if (!InferiorCall(this, address, function_addr)) {
+ function_addr = LLDB_INVALID_ADDRESS;
+ error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
+ address->CalculateSymbolContextSymbol()->GetName().AsCString());
+ }
+ return function_addr;
+}
+
size_t
ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
@@ -473,23 +622,170 @@ ProcessPOSIX::GetSoftwareBreakpointTrapO
}
Error
-ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site)
+ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
{
return EnableSoftwareBreakpoint(bp_site);
}
Error
-ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site)
+ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
{
return DisableSoftwareBreakpoint(bp_site);
}
+Error
+ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+ watchID, (uint64_t)addr);
+ return error;
+ }
+
+ // Try to find a vacant watchpoint slot in the inferiors' main thread
+ uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+
+ if (thread)
+ wp_hw_index = thread->FindVacantWatchpointIndex();
+
+ if (wp_hw_index == LLDB_INVALID_INDEX32)
+ {
+ error.SetErrorString("Setting hardware watchpoint failed.");
+ }
+ else
+ {
+ wp->SetHardwareIndex(wp_hw_index);
+ bool wp_enabled = true;
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_enabled &= thread->EnableHardwareWatchpoint(wp);
+ else
+ wp_enabled = false;
+ }
+ if (wp_enabled)
+ {
+ wp->SetEnabled(true, notify);
+ return error;
+ }
+ else
+ {
+ // Watchpoint enabling failed on at least one
+ // of the threads so roll back all of them
+ DisableWatchpoint(wp, false);
+ error.SetErrorString("Setting hardware watchpoint failed");
+ }
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (!wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
+ watchID, (uint64_t)addr);
+ // This is needed (for now) to keep watchpoints disabled correctly
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+
+ if (wp->IsHardware())
+ {
+ bool wp_disabled = true;
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_disabled &= thread->DisableHardwareWatchpoint(wp);
+ else
+ wp_disabled = false;
+ }
+ if (wp_disabled)
+ {
+ wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+ else
+ error.SetErrorString("Disabling hardware watchpoint failed");
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
+{
+ Error error;
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+ if (thread)
+ num = thread->NumSupportedHardwareWatchpoints();
+ else
+ error.SetErrorString("Process does not exist.");
+ return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
+{
+ Error error = GetWatchpointSupportInfo(num);
+ // Watchpoints trigger and halt the inferior after
+ // the corresponding instruction has been executed.
+ after = true;
+ return error;
+}
+
+uint32_t
+ProcessPOSIX::UpdateThreadListIfNeeded()
+{
+ // Do not allow recursive updates.
+ return m_thread_list.GetSize(false);
+}
+
bool
ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID());
+ log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
bool has_updated = false;
// Update the process thread list with this new thread.
@@ -497,13 +793,12 @@ ProcessPOSIX::UpdateThreadList(ThreadLis
assert(m_monitor);
ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
if (!thread_sp) {
- ProcessSP me = this->shared_from_this();
- thread_sp.reset(new POSIXThread(me, GetID()));
+ thread_sp.reset(new POSIXThread(*this, GetID()));
has_updated = true;
}
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID());
+ log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
new_thread_list.AddThread(thread_sp);
return has_updated; // the list has been updated
@@ -529,27 +824,6 @@ ProcessPOSIX::PutSTDIN(const char *buf,
return status;
}
-size_t
-ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error)
-{
- ssize_t bytes_read;
-
- // The terminal file descriptor is always in non-block mode.
- if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- if (errno != EAGAIN)
- error.SetErrorToErrno();
- return 0;
- }
- return bytes_read;
-}
-
-size_t
-ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error)
-{
- return GetSTDOUT(buf, len, error);
-}
-
UnixSignals &
ProcessPOSIX::GetUnixSignals()
{
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h Thu Jun 6 19:06:43 2013
@@ -49,6 +49,9 @@ public:
DoAttachToProcessWithID(lldb::pid_t pid);
virtual lldb_private::Error
+ DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+
+ virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
const lldb_private::ProcessLaunchInfo &launch_info);
@@ -62,7 +65,7 @@ public:
DoHalt(bool &caused_stop);
virtual lldb_private::Error
- DoDetach();
+ DoDetach(bool keep_stopped);
virtual lldb_private::Error
DoSignal(int signal);
@@ -93,14 +96,32 @@ public:
virtual lldb_private::Error
DoDeallocateMemory(lldb::addr_t ptr);
+ virtual lldb::addr_t
+ ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error);
+
virtual size_t
GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
virtual lldb_private::Error
- EnableBreakpoint(lldb_private::BreakpointSite *bp_site);
+ EnableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+ virtual lldb_private::Error
+ DisableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+ virtual lldb_private::Error
+ EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+
+ virtual lldb_private::Error
+ DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
virtual lldb_private::Error
- DisableBreakpoint(lldb_private::BreakpointSite *bp_site);
+ GetWatchpointSupportInfo(uint32_t &num);
+
+ virtual lldb_private::Error
+ GetWatchpointSupportInfo(uint32_t &num, bool &after);
+
+ virtual uint32_t
+ UpdateThreadListIfNeeded();
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list,
@@ -115,12 +136,6 @@ public:
virtual size_t
PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
- virtual size_t
- GetSTDOUT(char *buf, size_t len, lldb_private::Error &error);
-
- virtual size_t
- GetSTDERR(char *buf, size_t len, lldb_private::Error &error);
-
//--------------------------------------------------------------------------
// ProcessPOSIX internal API.
@@ -137,6 +152,11 @@ public:
GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,
const char *default_path);
+ /// Stops all threads in the process.
+ /// The \p stop_tid parameter indicates the thread which initiated the stop.
+ virtual void
+ StopAllThreads(lldb::tid_t stop_tid);
+
protected:
/// Target byte order.
lldb::ByteOrder m_byte_order;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp Thu Jun 6 19:06:43 2013
@@ -21,24 +21,28 @@ using namespace lldb_private;
// We want to avoid global constructors where code needs to be run so here we
// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
+// that will construct the static g_log_sp the first time this function is
// called.
-static LogSP &
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
GetLog ()
{
- static LogSP g_log_sp;
- return g_log_sp;
+ if (!g_log_enabled)
+ return NULL;
+ return g_log;
}
-LogSP
+
+Log *
ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)
{
- LogSP log(GetLog ());
+ Log *log(GetLog ());
if (log && mask)
{
uint32_t log_mask = log->GetMask().Get();
if ((log_mask & mask) != mask)
- return LogSP();
+ return NULL;
}
return log;
}
@@ -46,7 +50,7 @@ ProcessPOSIXLog::GetLogIfAllCategoriesSe
void
ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm)
{
- LogSP log (GetLog ());
+ Log *log (GetLog ());
if (log)
{
uint32_t flag_bits = 0;
@@ -79,33 +83,33 @@ ProcessPOSIXLog::DisableLog (const char
}
}
+ log->GetMask().Reset (flag_bits);
if (flag_bits == 0)
- GetLog ().reset();
- else
- log->GetMask().Reset (flag_bits);
+ g_log_enabled = false;
}
return;
}
-LogSP
+Log *
ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
{
// Try see if there already is a log - that way we can reuse its settings.
// We could reuse the log in toto, but we don't know that the stream is the same.
uint32_t flag_bits = 0;
- LogSP log(GetLog ());
- if (log)
- flag_bits = log->GetMask().Get();
+ if (g_log)
+ flag_bits = g_log->GetMask().Get();
// Now make a new log with this stream if one was provided
if (log_stream_sp)
{
- log = LogSP(new Log(log_stream_sp));
- GetLog () = log;
+ if (g_log)
+ g_log->SetStream(log_stream_sp);
+ else
+ g_log = new Log(log_stream_sp);
}
- if (log)
+ if (g_log)
{
bool got_unknown_category = false;
for (; args[0]; args++)
@@ -140,10 +144,11 @@ ProcessPOSIXLog::EnableLog (StreamSP &lo
}
if (flag_bits == 0)
flag_bits = POSIX_LOG_DEFAULT;
- log->GetMask().Reset(flag_bits);
- log->GetOptions().Reset(log_options);
+ g_log->GetMask().Reset(flag_bits);
+ g_log->GetOptions().Reset(log_options);
+ g_log_enabled = true;
}
- return log;
+ return g_log;
}
void
@@ -174,7 +179,7 @@ ProcessPOSIXLog::ListLogCategories (Stre
void
ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
if (log)
{
va_list args;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIXLog.h Thu Jun 6 19:06:43 2013
@@ -49,14 +49,19 @@ public:
m_pluginname = pluginName;
}
+ static void
+ RegisterPluginName(lldb_private::ConstString pluginName)
+ {
+ m_pluginname = pluginName.GetCString();
+ }
- static lldb::LogSP
+ static lldb_private::Log *
GetLogIfAllCategoriesSet(uint32_t mask = 0);
static void
DisableLog (const char **args, lldb_private::Stream *feedback_strm);
- static lldb::LogSP
+ static lldb_private::Log *
EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
const char **args, lldb_private::Stream *feedback_strm);
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -8,6 +8,7 @@
//===---------------------------------------------------------------------===//
#include "RegisterContextFreeBSD_x86_64.h"
+#include <vector>
using namespace lldb_private;
@@ -18,13 +19,13 @@ using namespace lldb_private;
// Update the FreeBSD specific information (offset and size).
#define UPDATE_GPR_INFO(reg) \
do { \
- m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg); \
- m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
+ GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
+ GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
} while(false);
#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
do { \
- m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
+ GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
} while(false);
typedef struct _GPR
@@ -57,20 +58,18 @@ typedef struct _GPR
uint64_t ss;
} GPR;
-RegisterInfo *RegisterContextFreeBSD_x86_64::m_register_infos = nullptr;
+// Use a singleton function to avoid global constructors in shared libraries.
+static std::vector<RegisterInfo> & GetRegisterContext () {
+ static std::vector<RegisterInfo> g_register_infos;
+ return g_register_infos;
+}
+
RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx):
RegisterContext_x86_64(thread, concrete_frame_idx)
{
}
-RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
-{
- if (m_register_infos)
- delete m_register_infos;
- m_register_infos = nullptr;
-}
-
size_t
RegisterContextFreeBSD_x86_64::GetGPRSize()
{
@@ -81,19 +80,18 @@ const RegisterInfo *
RegisterContextFreeBSD_x86_64::GetRegisterInfo()
{
// Allocate RegisterInfo only once
- if (!m_register_infos)
+ if (GetRegisterContext().empty())
{
- m_register_infos = new RegisterInfo[k_num_registers];
// Copy the register information from base class
- if (m_register_infos)
+ const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+ if (base_info)
{
- memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
- sizeof(RegisterInfo) * k_num_registers);
- // Update the Linux specific register information (offset and size).
+ GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
+ // Update the FreeBSD specific register information (offset and size).
UpdateRegisterInfo();
}
}
- return m_register_infos;
+ return &GetRegisterContext()[0];
}
void
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h Thu Jun 6 19:06:43 2013
@@ -17,7 +17,6 @@ class RegisterContextFreeBSD_x86_64:
{
public:
RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual ~RegisterContextFreeBSD_x86_64();
size_t
GetGPRSize();
@@ -28,9 +27,6 @@ protected:
virtual void
UpdateRegisterInfo();
-
-private:
- static lldb_private::RegisterInfo *m_register_infos;
};
#endif
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -8,6 +8,7 @@
//===---------------------------------------------------------------------===//
#include "RegisterContextLinux_x86_64.h"
+#include <vector>
using namespace lldb_private;
@@ -18,13 +19,13 @@ using namespace lldb_private;
// Update the Linux specific information (offset and size).
#define UPDATE_GPR_INFO(reg) \
do { \
- m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg); \
- m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
+ GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
+ GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
} while(false);
#define UPDATE_I386_GPR_INFO(i386_reg, reg) \
do { \
- m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
+ GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
} while(false);
#define DR_OFFSET(reg_index) \
@@ -32,8 +33,8 @@ do {
#define UPDATE_DR_INFO(reg_index) \
do { \
- m_register_infos[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
- m_register_infos[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
+ GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
+ GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
} while(false);
typedef struct _GPR
@@ -92,20 +93,17 @@ struct UserArea
uint64_t fault_address; // Control register CR3.
};
-RegisterInfo *RegisterContextLinux_x86_64::m_register_infos = nullptr;
+// Use a singleton function to avoid global constructors in shared libraries.
+static std::vector<RegisterInfo> & GetRegisterContext () {
+ static std::vector<RegisterInfo> g_register_infos;
+ return g_register_infos;
+}
RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
RegisterContext_x86_64(thread, concrete_frame_idx)
{
}
-RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
-{
- if (m_register_infos)
- delete m_register_infos;
- m_register_infos = nullptr;
-}
-
size_t
RegisterContextLinux_x86_64::GetGPRSize()
{
@@ -116,19 +114,18 @@ const RegisterInfo *
RegisterContextLinux_x86_64::GetRegisterInfo()
{
// Allocate RegisterInfo only once
- if (!m_register_infos)
+ if (GetRegisterContext().empty())
{
- m_register_infos = new RegisterInfo[k_num_registers];
// Copy the register information from base class
- if (m_register_infos)
+ const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+ if (base_info)
{
- memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
- sizeof(RegisterInfo) * k_num_registers);
+ GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
// Update the Linux specific register information (offset and size).
UpdateRegisterInfo();
}
}
- return m_register_infos;
+ return &GetRegisterContext()[0];
}
void
Copied: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (from r182522, lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h?p2=lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h&p1=lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h Thu Jun 6 19:06:43 2013
@@ -17,7 +17,6 @@ class RegisterContextLinux_x86_64:
{
public:
RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual ~RegisterContextLinux_x86_64();
size_t
GetGPRSize();
@@ -28,9 +27,6 @@ protected:
virtual void
UpdateRegisterInfo();
-
-private:
- static lldb_private::RegisterInfo *m_register_infos;
};
#endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContextPOSIX.h Thu Jun 6 19:06:43 2013
@@ -25,7 +25,8 @@ class RegisterContextPOSIX
public:
RegisterContextPOSIX(lldb_private::Thread &thread,
uint32_t concrete_frame_idx)
- : RegisterContext(thread, concrete_frame_idx) { }
+ : RegisterContext(thread, concrete_frame_idx)
+ { m_watchpoints_initialized = false; }
/// Updates the register state of the associated thread after hitting a
/// breakpoint (if that make sense for the architecture). Default
@@ -35,6 +36,35 @@ public:
/// @return
/// True if the operation succeeded and false otherwise.
virtual bool UpdateAfterBreakpoint() { return true; }
+
+ /// Determines the index in lldb's register file given a kernel byte offset.
+ virtual unsigned
+ GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; }
+
+ // Checks to see if a watchpoint specified by hw_index caused the inferior
+ // to stop.
+ virtual bool
+ IsWatchpointHit (uint32_t hw_index) { return false; }
+
+ // Resets any watchpoints that have been hit.
+ virtual bool
+ ClearWatchpointHits () { return false; }
+
+ // Returns the watchpoint address associated with a watchpoint hardware
+ // index.
+ virtual lldb::addr_t
+ GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
+
+ virtual bool
+ IsWatchpointVacant (uint32_t hw_index) { return false; }
+
+ virtual bool
+ SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index) { return false; }
+
+protected:
+ bool m_watchpoints_initialized;
};
#endif // #ifndef liblldb_RegisterContextPOSIX_H_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.cpp Thu Jun 6 19:06:43 2013
@@ -15,6 +15,7 @@
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
#include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
using namespace lldb_private;
using namespace lldb;
@@ -82,103 +83,6 @@ enum
k_num_register_sets = 2
};
-enum
-{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
-};
-
-enum
-{
- dwarf_eax = 0,
- dwarf_ecx,
- dwarf_edx,
- dwarf_ebx,
- dwarf_esp,
- dwarf_ebp,
- dwarf_esi,
- dwarf_edi,
- dwarf_eip,
- dwarf_eflags,
- dwarf_stmm0 = 11,
- dwarf_stmm1,
- dwarf_stmm2,
- dwarf_stmm3,
- dwarf_stmm4,
- dwarf_stmm5,
- dwarf_stmm6,
- dwarf_stmm7,
- dwarf_xmm0 = 21,
- dwarf_xmm1,
- dwarf_xmm2,
- dwarf_xmm3,
- dwarf_xmm4,
- dwarf_xmm5,
- dwarf_xmm6,
- dwarf_xmm7
-};
-
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fcw = 24,
- gdb_fsw = 25,
- gdb_ftw = 26,
- gdb_fpu_cs = 27,
- gdb_ip = 28,
- gdb_fpu_ds = 29,
- gdb_dp = 30,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48
-};
-
static const
uint32_t g_gpr_regnums[k_num_gpr_registers] =
{
@@ -387,7 +291,7 @@ RegisterContext_i386::GetRegisterCount()
}
const RegisterInfo *
-RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg)
+RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
{
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
@@ -403,7 +307,7 @@ RegisterContext_i386::GetRegisterSetCoun
}
const RegisterSet *
-RegisterContext_i386::GetRegisterSet(uint32_t set)
+RegisterContext_i386::GetRegisterSet(size_t set)
{
if (set < k_num_register_sets)
return &g_reg_sets[set];
@@ -437,7 +341,8 @@ RegisterContext_i386::ReadRegister(const
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+ return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+ GetRegisterName(reg), GetRegSize(reg), value);
}
bool
@@ -447,11 +352,12 @@ RegisterContext_i386::ReadAllRegisterVal
}
bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
- const RegisterValue &value)
+ const RegisterValue &value)
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+ return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+ GetRegisterName(reg), value);
}
bool
@@ -612,7 +518,7 @@ RegisterContext_i386::HardwareSingleStep
void
RegisterContext_i386::LogGPR(const char *title)
{
- LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
if (log)
{
if (title)
@@ -620,7 +526,7 @@ RegisterContext_i386::LogGPR(const char
for (uint32_t i=0; i<k_num_gpr_registers; i++)
{
uint32_t reg = gpr_eax + i;
- log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);
+ log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
}
}
}
@@ -631,7 +537,7 @@ RegisterContext_i386::ReadGPR()
bool result;
ProcessMonitor &monitor = GetMonitor();
- result = monitor.ReadGPR(&user.regs);
+ result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
LogGPR("RegisterContext_i386::ReadGPR()");
return result;
}
@@ -640,5 +546,5 @@ bool
RegisterContext_i386::ReadFPR()
{
ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(&user.i387);
+ return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_i386.h Thu Jun 6 19:06:43 2013
@@ -35,18 +35,18 @@ public:
GetRegisterCount();
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(uint32_t reg);
+ GetRegisterInfoAtIndex(size_t reg);
size_t
GetRegisterSetCount();
const lldb_private::RegisterSet *
- GetRegisterSet(uint32_t set);
+ GetRegisterSet(size_t set);
- static unsigned
+ unsigned
GetRegisterIndexFromOffset(unsigned offset);
- static const char *
+ const char *
GetRegisterName(unsigned reg);
bool
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -13,97 +13,28 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Host/Endian.h"
#include "ProcessPOSIX.h"
#include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
#include "RegisterContext_x86_64.h"
using namespace lldb_private;
using namespace lldb;
-// Internal codes for all x86_64 registers.
-enum
-{
- k_first_gpr,
- gpr_rax = k_first_gpr,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_ss,
- gpr_ds,
- gpr_es,
- k_last_gpr = gpr_es,
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+ #define NT_X86_XSTATE 0x202
+#endif
- k_first_fpr,
- fpu_fcw = k_first_fpr,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15,
- k_last_fpr = fpu_xmm15,
-
- k_num_registers,
- k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
- k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
-};
-
-// Number of register sets provided by this context.
enum
{
- k_num_register_sets = 2
-};
-
-enum gcc_dwarf_regnums
-{
gcc_dwarf_gpr_rax = 0,
gcc_dwarf_gpr_rdx,
gcc_dwarf_gpr_rcx,
@@ -144,10 +75,26 @@ enum gcc_dwarf_regnums
gcc_dwarf_fpu_stmm4,
gcc_dwarf_fpu_stmm5,
gcc_dwarf_fpu_stmm6,
- gcc_dwarf_fpu_stmm7
+ gcc_dwarf_fpu_stmm7,
+ gcc_dwarf_fpu_ymm0,
+ gcc_dwarf_fpu_ymm1,
+ gcc_dwarf_fpu_ymm2,
+ gcc_dwarf_fpu_ymm3,
+ gcc_dwarf_fpu_ymm4,
+ gcc_dwarf_fpu_ymm5,
+ gcc_dwarf_fpu_ymm6,
+ gcc_dwarf_fpu_ymm7,
+ gcc_dwarf_fpu_ymm8,
+ gcc_dwarf_fpu_ymm9,
+ gcc_dwarf_fpu_ymm10,
+ gcc_dwarf_fpu_ymm11,
+ gcc_dwarf_fpu_ymm12,
+ gcc_dwarf_fpu_ymm13,
+ gcc_dwarf_fpu_ymm14,
+ gcc_dwarf_fpu_ymm15
};
-enum gdb_regnums
+enum
{
gdb_gpr_rax = 0,
gdb_gpr_rbx = 1,
@@ -184,9 +131,9 @@ enum gdb_regnums
gdb_fpu_fcw = 32,
gdb_fpu_fsw = 33,
gdb_fpu_ftw = 34,
- gdb_fpu_cs = 35,
+ gdb_fpu_cs_64 = 35,
gdb_fpu_ip = 36,
- gdb_fpu_ds = 37,
+ gdb_fpu_ds_64 = 37,
gdb_fpu_dp = 38,
gdb_fpu_fop = 39,
gdb_fpu_xmm0 = 40,
@@ -205,7 +152,23 @@ enum gdb_regnums
gdb_fpu_xmm13 = 53,
gdb_fpu_xmm14 = 54,
gdb_fpu_xmm15 = 55,
- gdb_fpu_mxcsr = 56
+ gdb_fpu_mxcsr = 56,
+ gdb_fpu_ymm0 = 57,
+ gdb_fpu_ymm1 = 58,
+ gdb_fpu_ymm2 = 59,
+ gdb_fpu_ymm3 = 60,
+ gdb_fpu_ymm4 = 61,
+ gdb_fpu_ymm5 = 62,
+ gdb_fpu_ymm6 = 63,
+ gdb_fpu_ymm7 = 64,
+ gdb_fpu_ymm8 = 65,
+ gdb_fpu_ymm9 = 66,
+ gdb_fpu_ymm10 = 67,
+ gdb_fpu_ymm11 = 68,
+ gdb_fpu_ymm12 = 69,
+ gdb_fpu_ymm13 = 70,
+ gdb_fpu_ymm14 = 71,
+ gdb_fpu_ymm15 = 72
};
static const
@@ -234,11 +197,21 @@ uint32_t g_gpr_regnums[k_num_gpr_registe
gpr_gs,
gpr_ss,
gpr_ds,
- gpr_es
+ gpr_es,
+ gpr_eax,
+ gpr_ebx,
+ gpr_ecx,
+ gpr_edx,
+ gpr_edi,
+ gpr_esi,
+ gpr_ebp,
+ gpr_esp,
+ gpr_eip,
+ gpr_eflags
};
static const uint32_t
-g_fpu_regnums[k_num_fpu_registers] =
+g_fpu_regnums[k_num_fpr_registers] =
{
fpu_fcw,
fpu_fsw,
@@ -276,28 +249,56 @@ g_fpu_regnums[k_num_fpu_registers] =
fpu_xmm15
};
+static const uint32_t
+g_avx_regnums[k_num_avx_registers] =
+{
+ fpu_ymm0,
+ fpu_ymm1,
+ fpu_ymm2,
+ fpu_ymm3,
+ fpu_ymm4,
+ fpu_ymm5,
+ fpu_ymm6,
+ fpu_ymm7,
+ fpu_ymm8,
+ fpu_ymm9,
+ fpu_ymm10,
+ fpu_ymm11,
+ fpu_ymm12,
+ fpu_ymm13,
+ fpu_ymm14,
+ fpu_ymm15
+};
+
+// Number of register sets provided by this context.
+enum
+{
+ k_num_extended_register_sets = 1,
+ k_num_register_sets = 3
+};
+
static const RegisterSet
g_reg_sets[k_num_register_sets] =
{
- { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
- { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums }
+ { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
+ { "Floating Point Registers", "fpu", k_num_fpr_registers, g_fpu_regnums },
+ { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums }
};
-// Computes the offset of the given GPR in the user data area.
-#define GPR_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::UserArea, regs) + \
- offsetof(GPR, regname))
-
-// Computes the offset of the given FPR in the user data area.
+// Computes the offset of the given FPR in the extended data area.
#define FPR_OFFSET(regname) \
- (offsetof(RegisterContext_x86_64::UserArea, i387) + \
- offsetof(RegisterContext_x86_64::FPU, regname))
+ (offsetof(RegisterContext_x86_64::FPR, xstate) + \
+ offsetof(RegisterContext_x86_64::FXSAVE, regname))
-// Number of bytes needed to represent a GPR.
-#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg)
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+ (offsetof(RegisterContext_x86_64::YMM, regname))
+
+// Number of bytes needed to represent a i386 GPR
+#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
// Number of bytes needed to represent a FPR.
-#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg)
+#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg)
// Number of bytes needed to represent the i'th FP register.
#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
@@ -305,12 +306,23 @@ g_reg_sets[k_num_register_sets] =
// Number of bytes needed to represent an XMM register.
#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg)
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, 0, 0, eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
-#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
- { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet.
+static uint32_t value_regs = LLDB_INVALID_REGNUM;
+
+#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \
+ { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
+ { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
#define DEFINE_FP(reg, i) \
@@ -325,7 +337,18 @@ g_reg_sets[k_num_register_sets] =
{ gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
-#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU))
+#define DEFINE_YMM(reg, i) \
+ { #reg#i, NULL, YMM_SIZE, YMM_OFFSET(reg[i]), eEncodingVector, \
+ eFormatVectorOfUInt8, \
+ { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
+ LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_DR(reg, i) \
+ { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex, \
+ { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR))
static RegisterInfo
g_register_infos[k_num_registers] =
@@ -355,7 +378,17 @@ g_register_infos[k_num_registers] =
DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss),
DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds),
DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es),
-
+ // i386 registers
+ DEFINE_GPR_i386(eax, rax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax),
+ DEFINE_GPR_i386(ebx, rbx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx),
+ DEFINE_GPR_i386(ecx, rcx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx),
+ DEFINE_GPR_i386(edx, rdx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx),
+ DEFINE_GPR_i386(edi, rdi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi),
+ DEFINE_GPR_i386(esi, rsi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi),
+ DEFINE_GPR_i386(ebp, rbp, "fp", gcc_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, gdb_ebp),
+ DEFINE_GPR_i386(esp, rsp, "sp", gcc_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, gdb_esp),
+ DEFINE_GPR_i386(eip, rip, "pc", gcc_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, gdb_eip),
+ DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags),
// i387 Floating point registers.
DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
@@ -363,10 +396,10 @@ g_register_infos[k_num_registers] =
DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
// FIXME: Extract segment from ip.
- DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
+ DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64),
DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
// FIXME: Extract segment from dp.
- DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
+ DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64),
DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
@@ -396,35 +429,77 @@ g_register_infos[k_num_registers] =
DEFINE_XMM(xmm, 12),
DEFINE_XMM(xmm, 13),
DEFINE_XMM(xmm, 14),
- DEFINE_XMM(xmm, 15)
+ DEFINE_XMM(xmm, 15),
+
+ // Copy of YMM registers assembled from xmm and ymmh
+ DEFINE_YMM(ymm, 0),
+ DEFINE_YMM(ymm, 1),
+ DEFINE_YMM(ymm, 2),
+ DEFINE_YMM(ymm, 3),
+ DEFINE_YMM(ymm, 4),
+ DEFINE_YMM(ymm, 5),
+ DEFINE_YMM(ymm, 6),
+ DEFINE_YMM(ymm, 7),
+ DEFINE_YMM(ymm, 8),
+ DEFINE_YMM(ymm, 9),
+ DEFINE_YMM(ymm, 10),
+ DEFINE_YMM(ymm, 11),
+ DEFINE_YMM(ymm, 12),
+ DEFINE_YMM(ymm, 13),
+ DEFINE_YMM(ymm, 14),
+ DEFINE_YMM(ymm, 15),
+
+ // Debug registers for lldb internal use
+ DEFINE_DR(dr, 0),
+ DEFINE_DR(dr, 1),
+ DEFINE_DR(dr, 2),
+ DEFINE_DR(dr, 3),
+ DEFINE_DR(dr, 4),
+ DEFINE_DR(dr, 5),
+ DEFINE_DR(dr, 6),
+ DEFINE_DR(dr, 7)
};
-static unsigned GetRegOffset(unsigned reg)
+static bool IsGPR(unsigned reg)
{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_offset;
+ return reg <= k_last_gpr; // GPR's come first.
}
-static unsigned GetRegSize(unsigned reg)
+static bool IsAVX(unsigned reg)
{
- assert(reg < k_num_registers && "Invalid register number.");
- return g_register_infos[reg].byte_size;
+ return (k_first_avx <= reg && reg <= k_last_avx);
}
-
-static bool IsGPR(unsigned reg)
+static bool IsFPR(unsigned reg)
{
- return reg <= k_last_gpr; // GPR's come first.
+ return (k_first_fpr <= reg && reg <= k_last_fpr);
}
-static bool IsFPR(unsigned reg)
+
+bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type)
{
- return (k_first_fpr <= reg && reg <= k_last_fpr);
+ bool generic_fpr = ::IsFPR(reg);
+ if (fpr_type == eXSAVE)
+ return generic_fpr || IsAVX(reg);
+
+ return generic_fpr;
}
RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
- uint32_t concrete_frame_idx)
+ uint32_t concrete_frame_idx)
: RegisterContextPOSIX(thread, concrete_frame_idx)
{
+ // Initialize m_iovec to point to the buffer and buffer size
+ // using the conventions of Berkeley style UIO structures, as required
+ // by PTRACE extensions.
+ m_iovec.iov_base = &m_fpr.xstate.xsave;
+ m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+ ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR));
+
+ // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
+ m_fpr_type = eXSAVE; // extended floating-point registers, if available
+ if (false == ReadFPR())
+ m_fpr_type = eFXSAVE; // assume generic floating-point registers
}
RegisterContext_x86_64::~RegisterContext_x86_64()
@@ -449,17 +524,42 @@ RegisterContext_x86_64::InvalidateAllReg
{
}
+unsigned
+RegisterContext_x86_64::GetRegisterOffset(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterSize(unsigned reg)
+{
+ assert(reg < k_num_registers && "Invalid register number.");
+ return GetRegisterInfo()[reg].byte_size;
+}
+
size_t
RegisterContext_x86_64::GetRegisterCount()
{
- return k_num_registers;
+ size_t num_registers = k_num_gpr_registers + k_num_fpr_registers;
+ if (m_fpr_type == eXSAVE)
+ return num_registers + k_num_avx_registers;
+ return num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_x86_64::GetRegisterInfo()
+{
+ // Commonly, this method is overridden and g_register_infos is copied and specialized.
+ // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ return g_register_infos;
}
const RegisterInfo *
-RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg)
+RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg)
{
if (reg < k_num_registers)
- return &g_register_infos[reg];
+ return &GetRegisterInfo()[reg];
else
return NULL;
}
@@ -467,13 +567,18 @@ RegisterContext_x86_64::GetRegisterInfoA
size_t
RegisterContext_x86_64::GetRegisterSetCount()
{
- return k_num_register_sets;
+ size_t sets = 0;
+ for (size_t set = 0; set < k_num_register_sets; ++set)
+ if (IsRegisterSetAvailable(set))
+ ++sets;
+
+ return sets;
}
const RegisterSet *
-RegisterContext_x86_64::GetRegisterSet(uint32_t set)
+RegisterContext_x86_64::GetRegisterSet(size_t set)
{
- if (set < k_num_register_sets)
+ if (IsRegisterSetAvailable(set))
return &g_reg_sets[set];
else
return NULL;
@@ -485,7 +590,7 @@ RegisterContext_x86_64::GetRegisterIndex
unsigned reg;
for (reg = 0; reg < k_num_registers; reg++)
{
- if (g_register_infos[reg].byte_offset == offset)
+ if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers && "Invalid register offset.");
@@ -496,56 +601,322 @@ const char *
RegisterContext_x86_64::GetRegisterName(unsigned reg)
{
assert(reg < k_num_registers && "Invalid register offset.");
- return g_register_infos[reg].name;
+ return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContext_x86_64::GetByteOrder()
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = eByteOrderInvalid;
+ Process *process = CalculateProcess().get();
+
+ if (process)
+ byte_order = process->GetByteOrder();
+ return byte_order;
+}
+
+// Parse ymm registers and into xmm.bytes and ymmh.bytes.
+bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle) {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+ m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+ m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+ sizeof(RegisterContext_x86_64::YMMHReg));
+ return true;
+ }
+
+ if (byte_order == eByteOrderBig) {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+ m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+ sizeof(RegisterContext_x86_64::XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+ m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
}
+// Concatenate xmm.bytes with ymmh.bytes
+bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
+{
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == eByteOrderLittle) {
+ ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+ m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+ m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::YMMHReg));
+ return true;
+ }
+ if (byte_order == eByteOrderBig) {
+ ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+ m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+ m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+ sizeof(RegisterContext_x86_64::YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
+}
+
+bool
+RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index)
+{
+ // Note: Extended register sets are assumed to be at the end of g_reg_sets...
+ size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+ if (m_fpr_type == eXSAVE) // ...and to start with AVX registers.
+ ++num_sets;
+
+ return (set_index < num_sets);
+}
+
bool
-RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue &value)
+RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
+ if (!reg_info)
+ return false;
+
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value);
+
+ if (IsFPR(reg, m_fpr_type)) {
+ if (!ReadFPR())
+ return false;
+ }
+ else {
+ ProcessMonitor &monitor = GetMonitor();
+ bool success = monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
+ GetRegisterName(reg), GetRegisterSize(reg), value);
+
+ // If an i386 register should be parsed from an x86_64 register...
+ if (success && reg >= k_first_i386 && reg <= k_last_i386)
+ if (value.GetByteSize() > reg_info->byte_size)
+ value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default
+ return success;
+ }
+
+ if (reg_info->encoding == eEncodingVector) {
+ ByteOrder byte_order = GetByteOrder();
+
+ if (byte_order != ByteOrder::eByteOrderInvalid) {
+ if (reg >= fpu_stmm0 && reg <= fpu_stmm7) {
+ value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order);
+ }
+ if (reg >= fpu_xmm0 && reg <= fpu_xmm15) {
+ value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order);
+ }
+ if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+ // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+ value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order);
+ else
+ return false;
+ }
+ return value.GetType() == RegisterValue::eTypeBytes;
+ }
+ return false;
+ }
+
+ // Note that lldb uses slightly different naming conventions from sys/user.h
+ switch (reg)
+ {
+ default:
+ return false;
+ case fpu_dp:
+ value = m_fpr.xstate.fxsave.dp;
+ break;
+ case fpu_fcw:
+ value = m_fpr.xstate.fxsave.fcw;
+ break;
+ case fpu_fsw:
+ value = m_fpr.xstate.fxsave.fsw;
+ break;
+ case fpu_ip:
+ value = m_fpr.xstate.fxsave.ip;
+ break;
+ case fpu_fop:
+ value = m_fpr.xstate.fxsave.fop;
+ break;
+ case fpu_ftw:
+ value = m_fpr.xstate.fxsave.ftw;
+ break;
+ case fpu_mxcsr:
+ value = m_fpr.xstate.fxsave.mxcsr;
+ break;
+ case fpu_mxcsrmask:
+ value = m_fpr.xstate.fxsave.mxcsrmask;
+ break;
+ }
+ return true;
}
bool
RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
{
+ bool success = false;
data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR () && ReadFPR ())
{
uint8_t *dst = data_sp->GetBytes();
- ::memcpy (dst, &user.regs, sizeof(user.regs));
- dst += sizeof(user.regs);
+ success = dst != 0;
- ::memcpy (dst, &user.i387, sizeof(user.i387));
- return true;
+ if (success) {
+ ::memcpy (dst, &m_gpr, GetGPRSize());
+ dst += GetGPRSize();
+ }
+ if (m_fpr_type == eFXSAVE)
+ ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (m_fpr_type == eXSAVE) {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Assemble the YMM register content from the register halves.
+ for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+ success = CopyXSTATEtoYMM(reg, byte_order);
+
+ if (success) {
+ // Copy the extended register state including the assembled ymm registers.
+ ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+ }
+ }
}
- return false;
+ return success;
}
bool
RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value)
+ const lldb_private::RegisterValue &value)
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+ if (IsGPR(reg)) {
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg), value);
+ }
+
+ if (IsFPR(reg, m_fpr_type)) {
+ switch (reg)
+ {
+ default:
+ if (reg_info->encoding != eEncodingVector)
+ return false;
+
+ if (reg >= fpu_stmm0 && reg <= fpu_stmm7)
+ ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= fpu_xmm0 && reg <= fpu_xmm15)
+ ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
+
+ if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+ if (m_fpr_type != eXSAVE)
+ return false; // the target processor does not support AVX
+
+ // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
+ ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize());
+ if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
+ return false;
+ }
+ break;
+ case fpu_dp:
+ m_fpr.xstate.fxsave.dp = value.GetAsUInt64();
+ break;
+ case fpu_fcw:
+ m_fpr.xstate.fxsave.fcw = value.GetAsUInt16();
+ break;
+ case fpu_fsw:
+ m_fpr.xstate.fxsave.fsw = value.GetAsUInt16();
+ break;
+ case fpu_ip:
+ m_fpr.xstate.fxsave.ip = value.GetAsUInt64();
+ break;
+ case fpu_fop:
+ m_fpr.xstate.fxsave.fop = value.GetAsUInt16();
+ break;
+ case fpu_ftw:
+ m_fpr.xstate.fxsave.ftw = value.GetAsUInt16();
+ break;
+ case fpu_mxcsr:
+ m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32();
+ break;
+ case fpu_mxcsrmask:
+ m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32();
+ break;
+ }
+ if (WriteFPR()) {
+ if (IsAVX(reg))
+ return CopyYMMtoXSTATE(reg, GetByteOrder());
+ return true;
+ }
+ }
+ return false;
}
bool
RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
{
+ bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
{
- const uint8_t *src = data_sp->GetBytes();
- ::memcpy (&user.regs, src, sizeof(user.regs));
- src += sizeof(user.regs);
-
- ::memcpy (&user.i387, src, sizeof(user.i387));
- return WriteGPR() & WriteFPR();
+ uint8_t *src = data_sp->GetBytes();
+ if (src) {
+ ::memcpy (&m_gpr, src, GetGPRSize());
+
+ if (WriteGPR()) {
+ src += GetGPRSize();
+ if (m_fpr_type == eFXSAVE)
+ ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+ if (m_fpr_type == eXSAVE)
+ ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+
+ success = WriteFPR();
+ if (success) {
+ success = true;
+
+ if (m_fpr_type == eXSAVE) {
+ ByteOrder byte_order = GetByteOrder();
+
+ // Parse the YMM register content from the register halves.
+ for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+ success = CopyYMMtoXSTATE(reg, byte_order);
+ }
+ }
+ }
+ }
}
- return false;
+ return success;
+}
+
+bool
+RegisterContext_x86_64::ReadRegister(const unsigned reg,
+ RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.ReadRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const unsigned reg,
+ const RegisterValue &value)
+{
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ value);
}
bool
@@ -565,141 +936,500 @@ uint32_t
RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
uint32_t num)
{
- if (kind == eRegisterKindGeneric)
+ const Process *process = CalculateProcess().get();
+ if (process)
{
- switch (num)
+ const ArchSpec arch = process->GetTarget().GetArchitecture();;
+ switch (arch.GetCore())
{
- case LLDB_REGNUM_GENERIC_PC: return gpr_rip;
- case LLDB_REGNUM_GENERIC_SP: return gpr_rsp;
- case LLDB_REGNUM_GENERIC_FP: return gpr_rbp;
- case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
- case LLDB_REGNUM_GENERIC_RA:
default:
- return LLDB_INVALID_REGNUM;
+ assert(false && "CPU type not supported!");
+ break;
+
+ case ArchSpec::eCore_x86_32_i386:
+ case ArchSpec::eCore_x86_32_i486:
+ case ArchSpec::eCore_x86_32_i486sx:
+ {
+ if (kind == eRegisterKindGeneric)
+ {
+ switch (num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return gpr_eip;
+ case LLDB_REGNUM_GENERIC_SP: return gpr_esp;
+ case LLDB_REGNUM_GENERIC_FP: return gpr_ebp;
+ case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+ case LLDB_REGNUM_GENERIC_RA:
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ {
+ switch (num)
+ {
+ case dwarf_eax: return gpr_eax;
+ case dwarf_edx: return gpr_edx;
+ case dwarf_ecx: return gpr_ecx;
+ case dwarf_ebx: return gpr_ebx;
+ case dwarf_esi: return gpr_esi;
+ case dwarf_edi: return gpr_edi;
+ case dwarf_ebp: return gpr_ebp;
+ case dwarf_esp: return gpr_esp;
+ case dwarf_eip: return gpr_eip;
+ case dwarf_xmm0: return fpu_xmm0;
+ case dwarf_xmm1: return fpu_xmm1;
+ case dwarf_xmm2: return fpu_xmm2;
+ case dwarf_xmm3: return fpu_xmm3;
+ case dwarf_xmm4: return fpu_xmm4;
+ case dwarf_xmm5: return fpu_xmm5;
+ case dwarf_xmm6: return fpu_xmm6;
+ case dwarf_xmm7: return fpu_xmm7;
+ case dwarf_stmm0: return fpu_stmm0;
+ case dwarf_stmm1: return fpu_stmm1;
+ case dwarf_stmm2: return fpu_stmm2;
+ case dwarf_stmm3: return fpu_stmm3;
+ case dwarf_stmm4: return fpu_stmm4;
+ case dwarf_stmm5: return fpu_stmm5;
+ case dwarf_stmm6: return fpu_stmm6;
+ case dwarf_stmm7: return fpu_stmm7;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGDB)
+ {
+ switch (num)
+ {
+ case gdb_eax : return gpr_eax;
+ case gdb_ebx : return gpr_ebx;
+ case gdb_ecx : return gpr_ecx;
+ case gdb_edx : return gpr_edx;
+ case gdb_esi : return gpr_esi;
+ case gdb_edi : return gpr_edi;
+ case gdb_ebp : return gpr_ebp;
+ case gdb_esp : return gpr_esp;
+ case gdb_eip : return gpr_eip;
+ case gdb_eflags : return gpr_eflags;
+ case gdb_cs : return gpr_cs;
+ case gdb_ss : return gpr_ss;
+ case gdb_ds : return gpr_ds;
+ case gdb_es : return gpr_es;
+ case gdb_fs : return gpr_fs;
+ case gdb_gs : return gpr_gs;
+ case gdb_stmm0 : return fpu_stmm0;
+ case gdb_stmm1 : return fpu_stmm1;
+ case gdb_stmm2 : return fpu_stmm2;
+ case gdb_stmm3 : return fpu_stmm3;
+ case gdb_stmm4 : return fpu_stmm4;
+ case gdb_stmm5 : return fpu_stmm5;
+ case gdb_stmm6 : return fpu_stmm6;
+ case gdb_stmm7 : return fpu_stmm7;
+ case gdb_fcw : return fpu_fcw;
+ case gdb_fsw : return fpu_fsw;
+ case gdb_ftw : return fpu_ftw;
+ case gdb_fpu_cs : return fpu_cs;
+ case gdb_ip : return fpu_ip;
+ case gdb_fpu_ds : return fpu_ds; //fpu_fos
+ case gdb_dp : return fpu_dp; //fpu_foo
+ case gdb_fop : return fpu_fop;
+ case gdb_xmm0 : return fpu_xmm0;
+ case gdb_xmm1 : return fpu_xmm1;
+ case gdb_xmm2 : return fpu_xmm2;
+ case gdb_xmm3 : return fpu_xmm3;
+ case gdb_xmm4 : return fpu_xmm4;
+ case gdb_xmm5 : return fpu_xmm5;
+ case gdb_xmm6 : return fpu_xmm6;
+ case gdb_xmm7 : return fpu_xmm7;
+ case gdb_mxcsr : return fpu_mxcsr;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+ else if (kind == eRegisterKindLLDB)
+ {
+ return num;
+ }
+
+ break;
+ }
+
+ case ArchSpec::eCore_x86_64_x86_64:
+ {
+ if (kind == eRegisterKindGeneric)
+ {
+ switch (num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return gpr_rip;
+ case LLDB_REGNUM_GENERIC_SP: return gpr_rsp;
+ case LLDB_REGNUM_GENERIC_FP: return gpr_rbp;
+ case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+ case LLDB_REGNUM_GENERIC_RA:
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ {
+ switch (num)
+ {
+ case gcc_dwarf_gpr_rax: return gpr_rax;
+ case gcc_dwarf_gpr_rdx: return gpr_rdx;
+ case gcc_dwarf_gpr_rcx: return gpr_rcx;
+ case gcc_dwarf_gpr_rbx: return gpr_rbx;
+ case gcc_dwarf_gpr_rsi: return gpr_rsi;
+ case gcc_dwarf_gpr_rdi: return gpr_rdi;
+ case gcc_dwarf_gpr_rbp: return gpr_rbp;
+ case gcc_dwarf_gpr_rsp: return gpr_rsp;
+ case gcc_dwarf_gpr_r8: return gpr_r8;
+ case gcc_dwarf_gpr_r9: return gpr_r9;
+ case gcc_dwarf_gpr_r10: return gpr_r10;
+ case gcc_dwarf_gpr_r11: return gpr_r11;
+ case gcc_dwarf_gpr_r12: return gpr_r12;
+ case gcc_dwarf_gpr_r13: return gpr_r13;
+ case gcc_dwarf_gpr_r14: return gpr_r14;
+ case gcc_dwarf_gpr_r15: return gpr_r15;
+ case gcc_dwarf_gpr_rip: return gpr_rip;
+ case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+ case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+ case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+ case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+ case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+ case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+ case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+ case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+ case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+ case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+ case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+ case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+ case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+ case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+ case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+ case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+ case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+ case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+ case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+ case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+ case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+ case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+ case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+ case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+ case gcc_dwarf_fpu_ymm0: return fpu_ymm0;
+ case gcc_dwarf_fpu_ymm1: return fpu_ymm1;
+ case gcc_dwarf_fpu_ymm2: return fpu_ymm2;
+ case gcc_dwarf_fpu_ymm3: return fpu_ymm3;
+ case gcc_dwarf_fpu_ymm4: return fpu_ymm4;
+ case gcc_dwarf_fpu_ymm5: return fpu_ymm5;
+ case gcc_dwarf_fpu_ymm6: return fpu_ymm6;
+ case gcc_dwarf_fpu_ymm7: return fpu_ymm7;
+ case gcc_dwarf_fpu_ymm8: return fpu_ymm8;
+ case gcc_dwarf_fpu_ymm9: return fpu_ymm9;
+ case gcc_dwarf_fpu_ymm10: return fpu_ymm10;
+ case gcc_dwarf_fpu_ymm11: return fpu_ymm11;
+ case gcc_dwarf_fpu_ymm12: return fpu_ymm12;
+ case gcc_dwarf_fpu_ymm13: return fpu_ymm13;
+ case gcc_dwarf_fpu_ymm14: return fpu_ymm14;
+ case gcc_dwarf_fpu_ymm15: return fpu_ymm15;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+
+ if (kind == eRegisterKindGDB)
+ {
+ switch (num)
+ {
+ case gdb_gpr_rax : return gpr_rax;
+ case gdb_gpr_rbx : return gpr_rbx;
+ case gdb_gpr_rcx : return gpr_rcx;
+ case gdb_gpr_rdx : return gpr_rdx;
+ case gdb_gpr_rsi : return gpr_rsi;
+ case gdb_gpr_rdi : return gpr_rdi;
+ case gdb_gpr_rbp : return gpr_rbp;
+ case gdb_gpr_rsp : return gpr_rsp;
+ case gdb_gpr_r8 : return gpr_r8;
+ case gdb_gpr_r9 : return gpr_r9;
+ case gdb_gpr_r10 : return gpr_r10;
+ case gdb_gpr_r11 : return gpr_r11;
+ case gdb_gpr_r12 : return gpr_r12;
+ case gdb_gpr_r13 : return gpr_r13;
+ case gdb_gpr_r14 : return gpr_r14;
+ case gdb_gpr_r15 : return gpr_r15;
+ case gdb_gpr_rip : return gpr_rip;
+ case gdb_gpr_rflags : return gpr_rflags;
+ case gdb_gpr_cs : return gpr_cs;
+ case gdb_gpr_ss : return gpr_ss;
+ case gdb_gpr_ds : return gpr_ds;
+ case gdb_gpr_es : return gpr_es;
+ case gdb_gpr_fs : return gpr_fs;
+ case gdb_gpr_gs : return gpr_gs;
+ case gdb_fpu_stmm0 : return fpu_stmm0;
+ case gdb_fpu_stmm1 : return fpu_stmm1;
+ case gdb_fpu_stmm2 : return fpu_stmm2;
+ case gdb_fpu_stmm3 : return fpu_stmm3;
+ case gdb_fpu_stmm4 : return fpu_stmm4;
+ case gdb_fpu_stmm5 : return fpu_stmm5;
+ case gdb_fpu_stmm6 : return fpu_stmm6;
+ case gdb_fpu_stmm7 : return fpu_stmm7;
+ case gdb_fpu_fcw : return fpu_fcw;
+ case gdb_fpu_fsw : return fpu_fsw;
+ case gdb_fpu_ftw : return fpu_ftw;
+ case gdb_fpu_cs_64 : return fpu_cs;
+ case gdb_fpu_ip : return fpu_ip;
+ case gdb_fpu_ds_64 : return fpu_ds;
+ case gdb_fpu_dp : return fpu_dp;
+ case gdb_fpu_fop : return fpu_fop;
+ case gdb_fpu_xmm0 : return fpu_xmm0;
+ case gdb_fpu_xmm1 : return fpu_xmm1;
+ case gdb_fpu_xmm2 : return fpu_xmm2;
+ case gdb_fpu_xmm3 : return fpu_xmm3;
+ case gdb_fpu_xmm4 : return fpu_xmm4;
+ case gdb_fpu_xmm5 : return fpu_xmm5;
+ case gdb_fpu_xmm6 : return fpu_xmm6;
+ case gdb_fpu_xmm7 : return fpu_xmm7;
+ case gdb_fpu_xmm8 : return fpu_xmm8;
+ case gdb_fpu_xmm9 : return fpu_xmm9;
+ case gdb_fpu_xmm10 : return fpu_xmm10;
+ case gdb_fpu_xmm11 : return fpu_xmm11;
+ case gdb_fpu_xmm12 : return fpu_xmm12;
+ case gdb_fpu_xmm13 : return fpu_xmm13;
+ case gdb_fpu_xmm14 : return fpu_xmm14;
+ case gdb_fpu_xmm15 : return fpu_xmm15;
+ case gdb_fpu_mxcsr : return fpu_mxcsr;
+ case gdb_fpu_ymm0 : return fpu_ymm0;
+ case gdb_fpu_ymm1 : return fpu_ymm1;
+ case gdb_fpu_ymm2 : return fpu_ymm2;
+ case gdb_fpu_ymm3 : return fpu_ymm3;
+ case gdb_fpu_ymm4 : return fpu_ymm4;
+ case gdb_fpu_ymm5 : return fpu_ymm5;
+ case gdb_fpu_ymm6 : return fpu_ymm6;
+ case gdb_fpu_ymm7 : return fpu_ymm7;
+ case gdb_fpu_ymm8 : return fpu_ymm8;
+ case gdb_fpu_ymm9 : return fpu_ymm9;
+ case gdb_fpu_ymm10 : return fpu_ymm10;
+ case gdb_fpu_ymm11 : return fpu_ymm11;
+ case gdb_fpu_ymm12 : return fpu_ymm12;
+ case gdb_fpu_ymm13 : return fpu_ymm13;
+ case gdb_fpu_ymm14 : return fpu_ymm14;
+ case gdb_fpu_ymm15 : return fpu_ymm15;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ }
+ else if (kind == eRegisterKindLLDB)
+ {
+ return num;
+ }
+ }
+ }
+ }
+
+ return LLDB_INVALID_REGNUM;
+}
+
+uint32_t
+RegisterContext_x86_64::NumSupportedHardwareWatchpoints()
+{
+ // Available debug address registers: dr0, dr1, dr2, dr3
+ return 4;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index)
+{
+ bool is_vacant = false;
+ RegisterValue value;
+
+ assert(hw_index < NumSupportedHardwareWatchpoints());
+
+ if (ReadRegister(dr7, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+ is_vacant = (val & (3 << 2*hw_index)) == 0;
+ }
+
+ return is_vacant;
+}
+
+static uint32_t
+size_and_rw_bits(size_t size, bool read, bool write)
+{
+ uint32_t rw;
+ if (read) {
+ rw = 0x3; // READ or READ/WRITE
+ } else if (write) {
+ rw = 0x1; // WRITE
+ } else {
+ assert(0 && "read and write cannot both be false");
+ }
+
+ switch (size) {
+ case 1:
+ return rw;
+ case 2:
+ return (0x1 << 2) | rw;
+ case 4:
+ return (0x3 << 2) | rw;
+ case 8:
+ return (0x2 << 2) | rw;
+ default:
+ assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+ }
+}
+
+uint32_t
+RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
+ bool read, bool write)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ uint32_t hw_index;
+
+ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+ {
+ if (IsWatchpointVacant(hw_index))
+ return SetHardwareWatchpointWithIndex(addr, size,
+ read, write,
+ hw_index);
+ }
+
+ return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+ bool read, bool write,
+ uint32_t hw_index)
+{
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+ if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
+ return false;
+
+ if (!(size == 1 || size == 2 || size == 4 || size == 8))
+ return false;
+
+ if (read == false && write == false)
+ return false;
+
+ if (m_watchpoints_initialized == false)
+ {
+ // Reset the debug status and debug control registers
+ RegisterValue zero_bits = RegisterValue(uint64_t(0));
+ if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
+ return false;
+ m_watchpoints_initialized = true;
+ }
+
+ if (!IsWatchpointVacant(hw_index))
+ return false;
+
+ // Set both dr7 (debug control register) and dri (debug address register).
+
+ // dr7{7-0} encodes the local/gloabl enable bits:
+ // global enable --. .-- local enable
+ // | |
+ // v v
+ // dr0 -> bits{1-0}
+ // dr1 -> bits{3-2}
+ // dr2 -> bits{5-4}
+ // dr3 -> bits{7-6}
+ //
+ // dr7{31-16} encodes the rw/len bits:
+ // b_x+3, b_x+2, b_x+1, b_x
+ // where bits{x+1, x} => rw
+ // 0b00: execute, 0b01: write, 0b11: read-or-write,
+ // 0b10: io read-or-write (unused)
+ // and bits{x+3, x+2} => len
+ // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+ //
+ // dr0 -> bits{19-16}
+ // dr1 -> bits{23-20}
+ // dr2 -> bits{27-24}
+ // dr3 -> bits{31-28}
+ if (hw_index < num_hw_watchpoints)
+ {
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(dr7, current_dr7_bits))
+ {
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
+ (1 << (2*hw_index) |
+ size_and_rw_bits(size, read, write) <<
+ (16+4*hw_index));
+
+ if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
+ WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+ return true;
}
}
- if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ return false;
+}
+
+bool
+RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+ if (hw_index < NumSupportedHardwareWatchpoints())
{
- switch (num)
+ RegisterValue current_dr7_bits;
+
+ if (ReadRegister(dr7, current_dr7_bits))
{
- case gcc_dwarf_gpr_rax: return gpr_rax;
- case gcc_dwarf_gpr_rdx: return gpr_rdx;
- case gcc_dwarf_gpr_rcx: return gpr_rcx;
- case gcc_dwarf_gpr_rbx: return gpr_rbx;
- case gcc_dwarf_gpr_rsi: return gpr_rsi;
- case gcc_dwarf_gpr_rdi: return gpr_rdi;
- case gcc_dwarf_gpr_rbp: return gpr_rbp;
- case gcc_dwarf_gpr_rsp: return gpr_rsp;
- case gcc_dwarf_gpr_r8: return gpr_r8;
- case gcc_dwarf_gpr_r9: return gpr_r9;
- case gcc_dwarf_gpr_r10: return gpr_r10;
- case gcc_dwarf_gpr_r11: return gpr_r11;
- case gcc_dwarf_gpr_r12: return gpr_r12;
- case gcc_dwarf_gpr_r13: return gpr_r13;
- case gcc_dwarf_gpr_r14: return gpr_r14;
- case gcc_dwarf_gpr_r15: return gpr_r15;
- case gcc_dwarf_gpr_rip: return gpr_rip;
- case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
- case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
- case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
- case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
- case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
- case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
- case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
- case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
- case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
- case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
- case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
- case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
- case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
- case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
- case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
- case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
- case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
- case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
- case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
- case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
- case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
- case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
- case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
- case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
- default:
- return LLDB_INVALID_REGNUM;
+ uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
+
+ if (WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+ return true;
}
}
- if (kind == eRegisterKindGDB)
+ return false;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index)
+{
+ bool is_hit = false;
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
{
- switch (num)
+ RegisterValue value;
+
+ if (ReadRegister(dr6, value))
{
- case gdb_gpr_rax : return gpr_rax;
- case gdb_gpr_rbx : return gpr_rbx;
- case gdb_gpr_rcx : return gpr_rcx;
- case gdb_gpr_rdx : return gpr_rdx;
- case gdb_gpr_rsi : return gpr_rsi;
- case gdb_gpr_rdi : return gpr_rdi;
- case gdb_gpr_rbp : return gpr_rbp;
- case gdb_gpr_rsp : return gpr_rsp;
- case gdb_gpr_r8 : return gpr_r8;
- case gdb_gpr_r9 : return gpr_r9;
- case gdb_gpr_r10 : return gpr_r10;
- case gdb_gpr_r11 : return gpr_r11;
- case gdb_gpr_r12 : return gpr_r12;
- case gdb_gpr_r13 : return gpr_r13;
- case gdb_gpr_r14 : return gpr_r14;
- case gdb_gpr_r15 : return gpr_r15;
- case gdb_gpr_rip : return gpr_rip;
- case gdb_gpr_rflags : return gpr_rflags;
- case gdb_gpr_cs : return gpr_cs;
- case gdb_gpr_ss : return gpr_ss;
- case gdb_gpr_ds : return gpr_ds;
- case gdb_gpr_es : return gpr_es;
- case gdb_gpr_fs : return gpr_fs;
- case gdb_gpr_gs : return gpr_gs;
- case gdb_fpu_stmm0 : return fpu_stmm0;
- case gdb_fpu_stmm1 : return fpu_stmm1;
- case gdb_fpu_stmm2 : return fpu_stmm2;
- case gdb_fpu_stmm3 : return fpu_stmm3;
- case gdb_fpu_stmm4 : return fpu_stmm4;
- case gdb_fpu_stmm5 : return fpu_stmm5;
- case gdb_fpu_stmm6 : return fpu_stmm6;
- case gdb_fpu_stmm7 : return fpu_stmm7;
- case gdb_fpu_fcw : return fpu_fcw;
- case gdb_fpu_fsw : return fpu_fsw;
- case gdb_fpu_ftw : return fpu_ftw;
- case gdb_fpu_cs : return fpu_cs;
- case gdb_fpu_ip : return fpu_ip;
- case gdb_fpu_ds : return fpu_ds;
- case gdb_fpu_dp : return fpu_dp;
- case gdb_fpu_fop : return fpu_fop;
- case gdb_fpu_xmm0 : return fpu_xmm0;
- case gdb_fpu_xmm1 : return fpu_xmm1;
- case gdb_fpu_xmm2 : return fpu_xmm2;
- case gdb_fpu_xmm3 : return fpu_xmm3;
- case gdb_fpu_xmm4 : return fpu_xmm4;
- case gdb_fpu_xmm5 : return fpu_xmm5;
- case gdb_fpu_xmm6 : return fpu_xmm6;
- case gdb_fpu_xmm7 : return fpu_xmm7;
- case gdb_fpu_xmm8 : return fpu_xmm8;
- case gdb_fpu_xmm9 : return fpu_xmm9;
- case gdb_fpu_xmm10 : return fpu_xmm10;
- case gdb_fpu_xmm11 : return fpu_xmm11;
- case gdb_fpu_xmm12 : return fpu_xmm12;
- case gdb_fpu_xmm13 : return fpu_xmm13;
- case gdb_fpu_xmm14 : return fpu_xmm14;
- case gdb_fpu_xmm15 : return fpu_xmm15;
- case gdb_fpu_mxcsr : return fpu_mxcsr;
- default:
- return LLDB_INVALID_REGNUM;
+ uint64_t val = value.GetAsUInt64();
+ is_hit = val & (1 << hw_index);
}
}
- else if (kind == eRegisterKindLLDB)
+
+ return is_hit;
+}
+
+addr_t
+RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index)
+{
+ addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
+
+ if (hw_index < NumSupportedHardwareWatchpoints())
{
- return num;
+ if (!IsWatchpointVacant(hw_index))
+ {
+ RegisterValue value;
+
+ if (ReadRegister(dr0 + hw_index, value))
+ wp_monitor_addr = value.GetAsUInt64();
+ }
}
- return LLDB_INVALID_REGNUM;
+ return wp_monitor_addr;
+}
+
+
+bool
+RegisterContext_x86_64::ClearWatchpointHits()
+{
+ return WriteRegister(dr6, RegisterValue((uint64_t)0));
}
bool
@@ -733,26 +1463,37 @@ bool
RegisterContext_x86_64::ReadGPR()
{
ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(&user.regs);
+ return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
}
bool
RegisterContext_x86_64::ReadFPR()
{
ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(&user.i387);
+ if (m_fpr_type == eFXSAVE)
+ return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (m_fpr_type == eXSAVE)
+ return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
}
bool
RegisterContext_x86_64::WriteGPR()
{
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(&user.regs);
+ ProcessMonitor &monitor = GetMonitor();
+ return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
}
bool
RegisterContext_x86_64::WriteFPR()
{
ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(&user.i387);
+ if (m_fpr_type == eFXSAVE)
+ return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+ if (m_fpr_type == eXSAVE)
+ return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ return false;
}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Thu Jun 6 19:06:43 2013
@@ -13,22 +13,126 @@
#include "lldb/Core/Log.h"
#include "RegisterContextPOSIX.h"
-#ifdef __FreeBSD__
-#include "RegisterContextFreeBSD_x86_64.h"
-#endif
-
-#ifdef __linux__
-#include "RegisterContextLinux_x86_64.h"
-#endif
-
class ProcessMonitor;
+// Internal codes for all x86_64 registers.
+enum
+{
+ k_first_gpr,
+ gpr_rax = k_first_gpr,
+ gpr_rbx,
+ gpr_rcx,
+ gpr_rdx,
+ gpr_rdi,
+ gpr_rsi,
+ gpr_rbp,
+ gpr_rsp,
+ gpr_r8,
+ gpr_r9,
+ gpr_r10,
+ gpr_r11,
+ gpr_r12,
+ gpr_r13,
+ gpr_r14,
+ gpr_r15,
+ gpr_rip,
+ gpr_rflags,
+ gpr_cs,
+ gpr_fs,
+ gpr_gs,
+ gpr_ss,
+ gpr_ds,
+ gpr_es,
+ k_first_i386,
+ gpr_eax = k_first_i386,
+ gpr_ebx,
+ gpr_ecx,
+ gpr_edx,
+ gpr_edi,
+ gpr_esi,
+ gpr_ebp,
+ gpr_esp,
+ gpr_eip,
+ gpr_eflags, // eRegisterKindLLDB == 33
+ k_last_i386 = gpr_eflags,
+ k_last_gpr = gpr_eflags,
+
+ k_first_fpr,
+ fpu_fcw = k_first_fpr,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_dp,
+ fpu_ds,
+ fpu_mxcsr,
+ fpu_mxcsrmask,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+ fpu_xmm8,
+ fpu_xmm9,
+ fpu_xmm10,
+ fpu_xmm11,
+ fpu_xmm12,
+ fpu_xmm13,
+ fpu_xmm14,
+ fpu_xmm15,
+ k_last_fpr = fpu_xmm15,
+ k_first_avx,
+ fpu_ymm0 = k_first_avx,
+ fpu_ymm1,
+ fpu_ymm2,
+ fpu_ymm3,
+ fpu_ymm4,
+ fpu_ymm5,
+ fpu_ymm6,
+ fpu_ymm7,
+ fpu_ymm8,
+ fpu_ymm9,
+ fpu_ymm10,
+ fpu_ymm11,
+ fpu_ymm12,
+ fpu_ymm13,
+ fpu_ymm14,
+ fpu_ymm15,
+ k_last_avx = fpu_ymm15,
+
+ dr0,
+ dr1,
+ dr2,
+ dr3,
+ dr4,
+ dr5,
+ dr6,
+ dr7,
+
+ k_num_registers,
+ k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+ k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
+ k_num_avx_registers = k_last_avx - k_first_avx + 1
+};
+
class RegisterContext_x86_64
: public RegisterContextPOSIX
{
public:
RegisterContext_x86_64 (lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
+ uint32_t concrete_frame_idx);
~RegisterContext_x86_64();
@@ -41,19 +145,28 @@ public:
size_t
GetRegisterCount();
+ virtual size_t
+ GetGPRSize() = 0;
+
+ virtual unsigned
+ GetRegisterSize(unsigned reg);
+
+ virtual unsigned
+ GetRegisterOffset(unsigned reg);
+
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(uint32_t reg);
+ GetRegisterInfoAtIndex(size_t reg);
size_t
GetRegisterSetCount();
const lldb_private::RegisterSet *
- GetRegisterSet(uint32_t set);
+ GetRegisterSet(size_t set);
- static unsigned
+ unsigned
GetRegisterIndexFromOffset(unsigned offset);
- static const char *
+ const char *
GetRegisterName(unsigned reg);
virtual bool
@@ -73,12 +186,41 @@ public:
uint32_t
ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+ uint32_t
+ NumSupportedHardwareWatchpoints();
+
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
+
+ bool
+ SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
+ bool write, uint32_t hw_index);
+
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index);
+
bool
HardwareSingleStep(bool enable);
bool
UpdateAfterBreakpoint();
+ bool
+ IsWatchpointVacant(uint32_t hw_index);
+
+ bool
+ IsWatchpointHit (uint32_t hw_index);
+
+ lldb::addr_t
+ GetWatchpointAddress (uint32_t hw_index);
+
+ bool
+ ClearWatchpointHits();
+
+ //---------------------------------------------------------------------------
+ // Generic floating-point registers
+ //---------------------------------------------------------------------------
+
struct MMSReg
{
uint8_t bytes[10];
@@ -87,10 +229,10 @@ public:
struct XMMReg
{
- uint8_t bytes[16];
+ uint8_t bytes[16]; // 128-bits for each XMM register
};
- struct FPU
+ struct FXSAVE
{
uint16_t fcw;
uint16_t fsw;
@@ -105,33 +247,95 @@ public:
uint32_t padding[24];
};
- struct UserArea
+ //---------------------------------------------------------------------------
+ // Extended floating-point registers
+ //---------------------------------------------------------------------------
+ struct YMMHReg
+ {
+ uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register
+ };
+
+ struct YMMReg
{
- GPR regs; // General purpose registers.
- int32_t fpvalid; // True if FPU is being used.
- int32_t pad0;
- FPU i387; // FPU registers.
- uint64_t tsize; // Text segment size.
- uint64_t dsize; // Data segment size.
- uint64_t ssize; // Stack segment size.
- uint64_t start_code; // VM address of text.
- uint64_t start_stack; // VM address of stack bottom (top in rsp).
- int64_t signal; // Signal causing core dump.
- int32_t reserved; // Unused.
- int32_t pad1;
- uint64_t ar0; // Location of GPR's.
- FPU* fpstate; // Location of FPR's.
- uint64_t magic; // Identifier for core dumps.
- char u_comm[32]; // Command causing core dump.
- uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
- uint64_t error_code; // CPU error code.
- uint64_t fault_address; // Control register CR3.
+ uint8_t bytes[32]; // 16 * 16 bits for each YMM register
};
+ struct YMM
+ {
+ YMMReg ymm[16]; // assembled from ymmh and xmm registers
+ };
+
+ struct XSAVE_HDR
+ {
+ uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor
+ uint64_t reserved1[2];
+ uint64_t reserved2[5];
+ } __attribute__((packed));
+
+ // x86 extensions to FXSAVE (i.e. for AVX processors)
+ struct XSAVE
+ {
+ FXSAVE i387; // floating point registers typical in i387_fxsave_struct
+ XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable
+ YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
+ // Slot any extensions to the register file here
+ } __attribute__((packed, aligned (64)));
+
+ struct IOVEC
+ {
+ void *iov_base; // pointer to XSAVE
+ size_t iov_len; // sizeof(XSAVE)
+ };
+
+ //---------------------------------------------------------------------------
+ // Note: prefer kernel definitions over user-land
+ //---------------------------------------------------------------------------
+ enum FPRType
+ {
+ eNotValid = 0,
+ eFSAVE, // TODO
+ eFXSAVE,
+ eSOFT, // TODO
+ eXSAVE
+ };
+
+ // Floating-point registers
+ struct FPR
+ {
+ // Thread state for the floating-point unit of the processor read by ptrace.
+ union XSTATE {
+ FXSAVE fxsave; // Generic floating-point registers.
+ XSAVE xsave; // x86 extended processor state.
+ } xstate;
+ };
+
+protected:
+ // Determines if an extended register set is supported on the processor running the inferior process.
+ virtual bool
+ IsRegisterSetAvailable(size_t set_index);
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfo();
+
+ virtual bool
+ ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+ virtual bool
+ WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
private:
- UserArea user;
+ uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers.
+ FPRType m_fpr_type; // determines the type of data stored by union FPR, if any.
+ FPR m_fpr; // floating-point registers including extended register sets.
+ IOVEC m_iovec; // wrapper for xsave.
+ YMM m_ymm_set; // copy of ymmh and xmm register halves.
ProcessMonitor &GetMonitor();
+ lldb::ByteOrder GetByteOrder();
+
+ bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
+ bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
+ bool IsFPR(unsigned reg, FPRType fpr_type);
bool ReadGPR();
bool ReadFPR();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp Thu Jun 6 19:06:43 2013
@@ -7,12 +7,19 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "DynamicRegisterInfo.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Interpreter/Args.h"
+
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
using namespace lldb;
using namespace lldb_private;
@@ -21,26 +28,158 @@ DynamicRegisterInfo::DynamicRegisterInfo
m_regs (),
m_sets (),
m_set_reg_nums (),
- m_reg_names (),
- m_reg_alt_names (),
m_set_names (),
m_reg_data_byte_size (0)
{
}
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+ m_regs (),
+ m_sets (),
+ m_set_reg_nums (),
+ m_set_names (),
+ m_reg_data_byte_size (0)
+{
+ SetRegisterInfo (dict);
+}
+
DynamicRegisterInfo::~DynamicRegisterInfo ()
{
}
+
+size_t
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ PythonList sets (dict.GetItemForKey("sets"));
+ if (sets)
+ {
+ const uint32_t num_sets = sets.GetSize();
+ for (uint32_t i=0; i<num_sets; ++i)
+ {
+ PythonString py_set_name(sets.GetItemAtIndex(i));
+ ConstString set_name;
+ if (py_set_name)
+ set_name.SetCString(py_set_name.GetString());
+ if (set_name)
+ {
+ RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+ m_sets.push_back (new_set);
+ }
+ else
+ {
+ Clear();
+ return 0;
+ }
+ }
+ m_set_reg_nums.resize(m_sets.size());
+ }
+ PythonList regs (dict.GetItemForKey("registers"));
+ if (regs)
+ {
+ const uint32_t num_regs = regs.GetSize();
+ PythonString name_pystr("name");
+ PythonString altname_pystr("alt-name");
+ PythonString bitsize_pystr("bitsize");
+ PythonString offset_pystr("offset");
+ PythonString encoding_pystr("encoding");
+ PythonString format_pystr("format");
+ PythonString set_pystr("set");
+ PythonString gcc_pystr("gcc");
+ PythonString dwarf_pystr("dwarf");
+ PythonString generic_pystr("generic");
+ for (uint32_t i=0; i<num_regs; ++i)
+ {
+ PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
+ if (reg_info_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;
+ bzero (®_info, sizeof(reg_info));
+
+ reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
+ if (reg_info.name == NULL)
+ {
+ Clear();
+ return 0;
+ }
+
+ reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
+
+ reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
+
+ if (reg_info.byte_offset == UINT32_MAX)
+ {
+ Clear();
+ return 0;
+ }
+ reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
+
+ if (reg_info.byte_size == 0)
+ {
+ Clear();
+ return 0;
+ }
+
+ const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
+ if (format_cstr)
+ {
+ if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
+ {
+ Clear();
+ return 0;
+ }
+ }
+ else
+ reg_info.format = 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;
+
+ const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
+ if (set >= m_sets.size())
+ {
+ Clear();
+ return 0;
+ }
+
+ 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 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;
+
+ m_regs.push_back (reg_info);
+ m_set_reg_nums[set].push_back(i);
+
+ }
+ else
+ {
+ Clear();
+ return 0;
+ }
+ }
+ Finalize ();
+ }
+#endif
+ return 0;
+}
+
+
void
-DynamicRegisterInfo::AddRegister (RegisterInfo ®_info,
+DynamicRegisterInfo::AddRegister (RegisterInfo ®_info,
ConstString ®_name,
ConstString ®_alt_name,
ConstString &set_name)
{
const uint32_t reg_num = m_regs.size();
- m_reg_names.push_back (reg_name);
- m_reg_alt_names.push_back (reg_alt_name);
reg_info.name = reg_name.AsCString();
assert (reg_info.name);
reg_info.alt_name = reg_alt_name.AsCString(NULL);
@@ -136,7 +275,5 @@ DynamicRegisterInfo::Clear()
m_regs.clear();
m_sets.clear();
m_set_reg_nums.clear();
- m_reg_names.clear();
- m_reg_alt_names.clear();
m_set_names.clear();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/DynamicRegisterInfo.h Thu Jun 6 19:06:43 2013
@@ -24,9 +24,14 @@ class DynamicRegisterInfo
public:
DynamicRegisterInfo ();
+ DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+
virtual
~DynamicRegisterInfo ();
+ size_t
+ SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+
void
AddRegister (lldb_private::RegisterInfo ®_info,
lldb_private::ConstString ®_name,
@@ -73,8 +78,6 @@ protected:
reg_collection m_regs;
set_collection m_sets;
set_reg_num_collection m_set_reg_nums;
- name_collection m_reg_names;
- name_collection m_reg_alt_names;
name_collection m_set_names;
size_t m_reg_data_byte_size; // The number of bytes required to store all registers
};
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp Thu Jun 6 19:06:43 2013
@@ -8,8 +8,10 @@
//===----------------------------------------------------------------------===//
#include "InferiorCallPOSIX.h"
+#include "lldb/Core/Address.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
@@ -47,9 +49,10 @@ bool lldb_private::InferiorCallMmap(Proc
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
const bool stop_other_threads = true;
- const bool discard_on_error = true;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
const bool try_all_threads = true;
- const uint32_t single_thread_timeout_usec = 500000;
+ const uint32_t timeout_usec = 500000;
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
@@ -79,7 +82,8 @@ bool lldb_private::InferiorCallMmap(Proc
mmap_range.GetBaseAddress(),
ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
stop_other_threads,
- discard_on_error,
+ unwind_on_error,
+ ignore_breakpoints,
&addr,
&length,
&prot_arg,
@@ -103,8 +107,9 @@ bool lldb_private::InferiorCallMmap(Proc
call_plan_sp,
stop_other_threads,
try_all_threads,
- discard_on_error,
- single_thread_timeout_usec,
+ unwind_on_error,
+ ignore_breakpoints,
+ timeout_usec,
error_strm);
if (result == eExecutionCompleted)
{
@@ -115,6 +120,11 @@ bool lldb_private::InferiorCallMmap(Proc
if (allocated_addr == UINT32_MAX)
return false;
}
+ else if (process->GetAddressByteSize() == 8)
+ {
+ if (allocated_addr == UINT64_MAX)
+ return false;
+ }
return true;
}
}
@@ -151,9 +161,10 @@ bool lldb_private::InferiorCallMunmap(Pr
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
const bool stop_other_threads = true;
- const bool discard_on_error = true;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
const bool try_all_threads = true;
- const uint32_t single_thread_timeout_usec = 500000;
+ const uint32_t timeout_usec = 500000;
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
@@ -162,7 +173,8 @@ bool lldb_private::InferiorCallMunmap(Pr
munmap_range.GetBaseAddress(),
ClangASTType(),
stop_other_threads,
- discard_on_error,
+ unwind_on_error,
+ ignore_breakpoints,
&addr,
&length));
if (call_plan_sp)
@@ -181,8 +193,9 @@ bool lldb_private::InferiorCallMunmap(Pr
call_plan_sp,
stop_other_threads,
try_all_threads,
- discard_on_error,
- single_thread_timeout_usec,
+ unwind_on_error,
+ ignore_breakpoints,
+ timeout_usec,
error_strm);
if (result == eExecutionCompleted)
{
@@ -196,3 +209,66 @@ bool lldb_private::InferiorCallMunmap(Pr
return false;
}
+
+bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
+ Thread *thread = process->GetThreadList().GetSelectedThread().get();
+ if (thread == NULL || address == NULL)
+ return false;
+
+ const bool stop_other_threads = true;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
+ const bool try_all_threads = true;
+ const uint32_t timeout_usec = 500000;
+
+ ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+ lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
+ ThreadPlanCallFunction *call_function_thread_plan
+ = new ThreadPlanCallFunction (*thread,
+ *address,
+ ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
+ stop_other_threads,
+ unwind_on_error,
+ ignore_breakpoints);
+ lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+ if (call_plan_sp)
+ {
+ StreamFile error_strm;
+ // This plan is a utility plan, so set it to discard itself when done.
+ call_plan_sp->SetIsMasterPlan (true);
+ call_plan_sp->SetOkayToDiscard(true);
+
+ StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+ if (frame)
+ {
+ ExecutionContext exe_ctx;
+ frame->CalculateExecutionContext (exe_ctx);
+ ExecutionResults result = process->RunThreadPlan (exe_ctx,
+ call_plan_sp,
+ stop_other_threads,
+ try_all_threads,
+ unwind_on_error,
+ ignore_breakpoints,
+ timeout_usec,
+ error_strm);
+ if (result == eExecutionCompleted)
+ {
+ returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (process->GetAddressByteSize() == 4)
+ {
+ if (returned_func == UINT32_MAX)
+ return false;
+ }
+ else if (process->GetAddressByteSize() == 8)
+ {
+ if (returned_func == UINT64_MAX)
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/InferiorCallPOSIX.h Thu Jun 6 19:06:43 2013
@@ -36,6 +36,8 @@ bool InferiorCallMmap(Process *proc, lld
bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length);
+bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func);
+
} // namespace lldb_private
#endif // lldb_InferiorCallPOSIX_h_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp Thu Jun 6 19:06:43 2013
@@ -416,7 +416,7 @@ RegisterContextDarwin_arm::GetRegisterCo
}
const RegisterInfo *
-RegisterContextDarwin_arm::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_arm::GetRegisterInfoAtIndex (size_t reg)
{
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
@@ -464,7 +464,7 @@ RegisterContextDarwin_arm::GetRegisterSe
}
const RegisterSet *
-RegisterContextDarwin_arm::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set)
{
if (reg_set < k_num_regsets)
return &g_reg_sets[reg_set];
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h Thu Jun 6 19:06:43 2013
@@ -64,13 +64,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t set);
+ GetRegisterSet (size_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info,
@@ -114,11 +114,17 @@ public:
};
+ struct QReg
+ {
+ uint8_t bytes[16];
+ };
+
struct FPU
{
union {
uint32_t s[32];
- uint64_t d[16];
+ uint64_t d[32];
+ QReg q[16]; // the 128-bit NEON registers
} floats;
uint32_t fpscr;
};
@@ -160,10 +166,10 @@ protected:
enum
{
- GPRRegSet = 1,
- FPURegSet = 2,
- EXCRegSet = 3,
- DBGRegSet = 4
+ GPRRegSet = 1, // ARM_THREAD_STATE
+ FPURegSet = 2, // ARM_VFP_STATE
+ EXCRegSet = 3, // ARM_EXCEPTION_STATE
+ DBGRegSet = 4 // ARM_DEBUG_STATE
};
enum
@@ -284,47 +290,26 @@ protected:
return -1;
}
- int
- DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
- {
- return -1;
- }
+ virtual int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
- int
- DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
- {
- return -1;
- }
+ virtual int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
- int
- DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
- {
- return -1;
- }
+ virtual int
+ DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0;
- int
- DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
- {
- return -1;
- }
+ virtual int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
- int
- DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
- {
- return -1;
- }
+ virtual int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
- int
- DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
- {
- return -1;
- }
+ virtual int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
- int
- DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
- {
- return -1;
- }
+ virtual int
+ DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0;
int
ReadRegisterSet (uint32_t set, bool force);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp Thu Jun 6 19:06:43 2013
@@ -298,7 +298,7 @@ RegisterContextDarwin_i386::GetRegisterC
}
const RegisterInfo *
-RegisterContextDarwin_i386::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_i386::GetRegisterInfoAtIndex (size_t reg)
{
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
@@ -410,7 +410,7 @@ RegisterContextDarwin_i386::GetRegisterS
}
const RegisterSet *
-RegisterContextDarwin_i386::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_i386::GetRegisterSet (size_t reg_set)
{
if (reg_set < k_num_regsets)
return &g_reg_sets[reg_set];
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h Thu Jun 6 19:06:43 2013
@@ -34,13 +34,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t set);
+ GetRegisterSet (size_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -230,40 +230,22 @@ protected:
// Subclasses override these to do the actual reading.
virtual int
- DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
- {
- return -1;
- }
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
- int
- DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
- {
- return -1;
- }
+ virtual int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
- int
- DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
- {
- return -1;
- }
+ virtual int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
- int
- DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
- {
- return -1;
- }
+ virtual int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
- int
- DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
- {
- return -1;
- }
+ virtual int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
- int
- DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
- {
- return -1;
- }
+ virtual int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
int
ReadRegisterSet (uint32_t set, bool force);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -336,7 +336,7 @@ RegisterContextDarwin_x86_64::GetRegiste
const RegisterInfo *
-RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (size_t reg)
{
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
@@ -457,7 +457,7 @@ RegisterContextDarwin_x86_64::GetRegiste
}
const RegisterSet *
-RegisterContextDarwin_x86_64::GetRegisterSet (uint32_t reg_set)
+RegisterContextDarwin_x86_64::GetRegisterSet (size_t reg_set)
{
if (reg_set < k_num_regsets)
return &g_reg_sets[reg_set];
@@ -491,7 +491,7 @@ RegisterContextDarwin_x86_64::LogGPR(Log
for (uint32_t i=0; i<k_num_gpr_registers; i++)
{
uint32_t reg = gpr_rax + i;
- log->Printf("%12s = 0x%16.16llx", g_register_infos[reg].name, (&gpr.rax)[reg]);
+ log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, (&gpr.rax)[reg]);
}
}
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h Thu Jun 6 19:06:43 2013
@@ -33,13 +33,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t set);
+ GetRegisterSet (size_t set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -234,40 +234,22 @@ protected:
// Subclasses override these to do the actual reading.
virtual int
- DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
- {
- return -1;
- }
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
virtual int
- DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
- {
- return -1;
- }
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
virtual int
- DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
- {
- return -1;
- }
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
virtual int
- DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
- {
- return -1;
- }
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
virtual int
- DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
- {
- return -1;
- }
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
virtual int
- DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
- {
- return -1;
- }
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
int
ReadRegisterSet (uint32_t set, bool force);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Thu Jun 6 19:06:43 2013
@@ -13,13 +13,15 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
@@ -33,24 +35,24 @@
using namespace lldb;
using namespace lldb_private;
-RegisterContextLLDB::RegisterContextLLDB
+RegisterContextLLDB::RegisterContextLLDB
(
- Thread& thread,
+ Thread& thread,
const SharedPtr &next_frame,
SymbolContext& sym_ctx,
uint32_t frame_number,
UnwindLLDB& unwind_lldb
) :
- RegisterContext (thread, frame_number),
- m_thread(thread),
+ RegisterContext (thread, frame_number),
+ m_thread(thread),
m_fast_unwind_plan_sp (),
m_full_unwind_plan_sp (),
m_all_registers_available(false),
m_frame_type (-1),
m_cfa (LLDB_INVALID_ADDRESS),
- m_start_pc (),
- m_current_pc (),
- m_current_offset (0),
+ m_start_pc (),
+ m_current_pc (),
+ m_current_offset (0),
m_current_offset_backed_up_one (0),
m_sym_ctx(sym_ctx),
m_sym_ctx_valid (false),
@@ -58,7 +60,7 @@ RegisterContextLLDB::RegisterContextLLDB
m_registers(),
m_parent_unwind (unwind_lldb)
{
- m_sym_ctx.Clear();
+ m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
if (IsFrameZero ())
@@ -71,8 +73,8 @@ RegisterContextLLDB::RegisterContextLLDB
}
// This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
- if (IsFrameZero()
- || next_frame->m_frame_type == eSigtrampFrame
+ if (IsFrameZero()
+ || next_frame->m_frame_type == eSigtrampFrame
|| next_frame->m_frame_type == eDebuggerFrame)
{
m_all_registers_available = true;
@@ -85,11 +87,10 @@ RegisterContextLLDB::RegisterContextLLDB
void
RegisterContextLLDB::InitializeZerothFrame()
{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
ExecutionContext exe_ctx(m_thread.shared_from_this());
RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
if (reg_ctx_sp.get() == NULL)
{
m_frame_type = eNotAValidFrame;
@@ -122,11 +123,7 @@ RegisterContextLLDB::InitializeZerothFra
ModuleSP pc_module_sp (m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp)
{
- if (log)
- {
- log->Printf("%*sFrame %u using architectural default unwind method",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("using architectural default unwind method");
}
// We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
@@ -138,7 +135,7 @@ RegisterContextLLDB::InitializeZerothFra
AddressRange addr_range;
m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
-
+
static ConstString g_sigtramp_name ("_sigtramp");
if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
(m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == g_sigtramp_name))
@@ -180,8 +177,8 @@ RegisterContextLLDB::InitializeZerothFra
// We've set m_frame_type and m_sym_ctx before these calls.
m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
- m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
-
+ m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
UnwindPlan::RowSP active_row;
int cfa_offset = 0;
int row_register_kind = -1;
@@ -193,8 +190,7 @@ RegisterContextLLDB::InitializeZerothFra
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("%s", active_row_strm.GetString().c_str());
}
}
@@ -204,7 +200,7 @@ RegisterContextLLDB::InitializeZerothFra
return;
}
-
+
addr_t cfa_regval;
if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
{
@@ -218,23 +214,11 @@ RegisterContextLLDB::InitializeZerothFra
m_cfa = cfa_regval + cfa_offset;
- if (log)
- {
- log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- m_cfa, cfa_regval, cfa_offset);
- }
-
- if (log)
- {
- log->Printf("%*sThread %d Frame %u initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "",
- m_thread.GetIndexID(),
- m_frame_number,
- (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
- (uint64_t) m_cfa,
- m_full_unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+ UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
+ (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
+ (uint64_t) m_cfa,
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
}
// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it
@@ -243,14 +227,13 @@ RegisterContextLLDB::InitializeZerothFra
void
RegisterContextLLDB::InitializeNonZerothFrame()
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (IsFrameZero ())
{
m_frame_type = eNotAValidFrame;
return;
}
-
+
if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
{
m_frame_type = eNotAValidFrame;
@@ -265,27 +248,19 @@ RegisterContextLLDB::InitializeNonZeroth
addr_t pc;
if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not get pc value",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not get pc value");
m_frame_type = eNotAValidFrame;
return;
}
-
+
if (log)
{
- log->Printf("%*sFrame %u pc = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, pc);
+ UnwindLogMsg ("pc = 0x%16.16" PRIx64, pc);
addr_t reg_val;
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
- log->Printf("%*sFrame %u fp = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
-
+ UnwindLogMsg ("fp = 0x%16.16" PRIx64, reg_val);
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
- log->Printf("%*sFrame %u sp = 0x%16.16llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
+ UnwindLogMsg ("sp = 0x%16.16" PRIx64, reg_val);
}
// A pc of 0x0 means it's the end of the stack crawl
@@ -294,11 +269,11 @@ RegisterContextLLDB::InitializeNonZeroth
m_frame_type = eNotAValidFrame;
return;
}
-
+
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
// 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.
+ // 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);
@@ -310,12 +285,8 @@ RegisterContextLLDB::InitializeNonZeroth
ModuleSP pc_module_sp (m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp)
{
- if (log)
- {
- log->Printf("%*sFrame %u using architectural default unwind method",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
-
+ UnwindLogMsg ("using architectural default unwind method");
+
// Test the pc value to see if we know it's in an unmapped/non-executable region of memory.
uint32_t permissions;
if (process->GetLoadAddressPermissions(pc, permissions)
@@ -327,11 +298,8 @@ RegisterContextLLDB::InitializeNonZeroth
// pc and see if we can get any further.
if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero())
{
- if (log)
- {
- log->Printf("%*sFrame %u had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, (uint64_t) pc);
- }
+ UnwindLogMsg ("had a pc of 0x%" PRIx64 " which is not in executable memory but on frame 1 -- allowing it once.",
+ (uint64_t) pc);
m_frame_type = eSkipFrame;
}
else
@@ -363,11 +331,7 @@ RegisterContextLLDB::InitializeNonZeroth
int cfa_offset = row->GetCFAOffset();
if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
{
- if (log)
- {
- log->Printf("%*sFrame %u failed to get cfa value",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
m_frame_type = eNormalFrame;
@@ -379,11 +343,7 @@ RegisterContextLLDB::InitializeNonZeroth
// A couple of sanity checks..
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
{
- if (log)
- {
- log->Printf("%*sFrame %u could not find a valid cfa address",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
@@ -399,21 +359,12 @@ RegisterContextLLDB::InitializeNonZeroth
}
else
{
- if (log)
- {
- log->Printf("%*sFrame %u could not find a row for function offset zero",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("could not find a row for function offset zero");
m_frame_type = eNotAValidFrame;
return;
}
- if (log)
- {
- log->Printf("%*sFrame %u initialized frame cfa is 0x%llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- (uint64_t) m_cfa);
- }
+ UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa);
return;
}
m_frame_type = eNotAValidFrame;
@@ -454,11 +405,11 @@ RegisterContextLLDB::InitializeNonZeroth
// 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)
+ 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();
+ m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
{
@@ -520,11 +471,10 @@ RegisterContextLLDB::InitializeNonZeroth
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
}
}
- else
+ else
{
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
@@ -535,8 +485,7 @@ RegisterContextLLDB::InitializeNonZeroth
{
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
- log->Printf("%*sFrame %u active row: %s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+ UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
}
}
}
@@ -550,12 +499,7 @@ RegisterContextLLDB::InitializeNonZeroth
addr_t cfa_regval;
if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
{
- if (log)
- {
- log->Printf("%*sFrame %u failed to get cfa reg %d/%d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- row_register_kind, active_row->GetCFARegister());
- }
+ UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
m_frame_type = eNotAValidFrame;
return;
}
@@ -563,21 +507,12 @@ RegisterContextLLDB::InitializeNonZeroth
m_cfa = cfa_regval + cfa_offset;
- if (log)
- {
- log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- m_cfa, cfa_regval, cfa_offset);
- }
+ UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
// A couple of sanity checks..
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
- {
- if (log)
- {
- log->Printf("%*sFrame %u could not find a valid cfa address",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ {
+ UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
@@ -602,24 +537,16 @@ RegisterContextLLDB::InitializeNonZeroth
repeating_frames = true;
}
}
- if (repeating_frames)
+ if (repeating_frames && abi->FunctionCallsChangeCFA())
{
- if (log)
- {
- log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
- }
+ UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
m_frame_type = eNotAValidFrame;
return;
}
}
- if (log)
- {
- log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
- }
+ UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
+ (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
}
@@ -632,9 +559,9 @@ RegisterContextLLDB::IsFrameZero () cons
// Find a fast unwind plan for this frame, if possible.
//
-// On entry to this method,
+// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -655,7 +582,7 @@ RegisterContextLLDB::GetFastUnwindPlanFo
if (!func_unwinders_sp)
return unwind_plan_sp;
- // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
+ // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
return unwind_plan_sp;
@@ -664,19 +591,18 @@ RegisterContextLLDB::GetFastUnwindPlanFo
{
if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (log && log->GetVerbose())
{
- const char *has_fast = "";
if (m_fast_unwind_plan_sp)
- has_fast = ", and has a fast UnwindPlan";
- log->Printf("%*sFrame %u frame%s",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, has_fast);
+ UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
+ else
+ UnwindLogMsgVerbose ("frame");
}
m_frame_type = eNormalFrame;
return unwind_plan_sp;
}
- else
+ else
{
unwind_plan_sp.reset();
}
@@ -684,9 +610,9 @@ RegisterContextLLDB::GetFastUnwindPlanFo
return unwind_plan_sp;
}
-// On entry to this method,
+// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -695,7 +621,6 @@ UnwindPlanSP
RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{
UnwindPlanSP unwind_plan_sp;
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
UnwindPlanSP arch_default_unwind_plan_sp;
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
@@ -707,12 +632,12 @@ RegisterContextLLDB::GetFullUnwindPlanFo
}
bool behaves_like_zeroth_frame = false;
- if (IsFrameZero ()
+ if (IsFrameZero ()
|| GetNextFrame()->m_frame_type == eSigtrampFrame
|| GetNextFrame()->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
- // If this frame behaves like a 0th frame (currently executing or
+ // If this frame behaves like a 0th frame (currently executing or
// interrupted asynchronously), all registers can be retrieved.
m_all_registers_available = true;
}
@@ -721,7 +646,7 @@ RegisterContextLLDB::GetFullUnwindPlanFo
// 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 the symbol context has a function for the symbol, then we don't need to do this check.
if ((!m_sym_ctx_valid || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
{
@@ -777,17 +702,13 @@ RegisterContextLLDB::GetFullUnwindPlanFo
// right thing. It'd be nice if there was a way to ask the eh_frame directly if it is asynchronous
// (can be trusted at every instruction point) or synchronous (the normal case - only at call sites).
// But there is not.
- if (process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
+ if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
{
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
+ unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
}
@@ -798,12 +719,7 @@ RegisterContextLLDB::GetFullUnwindPlanFo
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
}
@@ -812,36 +728,21 @@ RegisterContextLLDB::GetFullUnwindPlanFo
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
}
-
+
// We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
// struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- unwind_plan_sp->GetSourceName().GetCString());
- }
+ 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.
- if (log && log->GetVerbose())
- {
- log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- arch_default_unwind_plan_sp->GetSourceName().GetCString());
- }
+ UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
return arch_default_unwind_plan_sp;
}
@@ -859,7 +760,7 @@ RegisterContextLLDB::GetRegisterCount ()
}
const RegisterInfo *
-RegisterContextLLDB::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextLLDB::GetRegisterInfoAtIndex (size_t reg)
{
return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg);
}
@@ -871,7 +772,7 @@ RegisterContextLLDB::GetRegisterSetCount
}
const RegisterSet *
-RegisterContextLLDB::GetRegisterSet (uint32_t reg_set)
+RegisterContextLLDB::GetRegisterSet (size_t reg_set)
{
return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
}
@@ -883,7 +784,7 @@ RegisterContextLLDB::ConvertRegisterKind
}
bool
-RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const RegisterInfo *reg_info,
RegisterValue &value)
{
@@ -896,11 +797,11 @@ RegisterContextLLDB::ReadRegisterValueFr
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-
+
if (!other_reg_info)
return false;
-
- if (IsFrameZero ())
+
+ if (IsFrameZero ())
{
success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
}
@@ -913,7 +814,7 @@ RegisterContextLLDB::ReadRegisterValueFr
case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
break;
-
+
case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
@@ -921,9 +822,9 @@ RegisterContextLLDB::ReadRegisterValueFr
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
{
- Error error (ReadRegisterValueFromMemory(reg_info,
- regloc.location.target_memory_location,
- reg_info->byte_size,
+ Error error (ReadRegisterValueFromMemory(reg_info,
+ regloc.location.target_memory_location,
+ reg_info->byte_size,
value));
success = error.Success();
}
@@ -936,7 +837,7 @@ RegisterContextLLDB::ReadRegisterValueFr
}
bool
-RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const RegisterInfo *reg_info,
const RegisterValue &value)
{
@@ -944,13 +845,13 @@ RegisterContextLLDB::WriteRegisterValueT
return false;
bool success = false;
-
+
switch (regloc.type)
{
case UnwindLLDB::RegisterLocation::eRegisterInRegister:
{
const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
- if (IsFrameZero ())
+ if (IsFrameZero ())
{
success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
}
@@ -968,9 +869,9 @@ RegisterContextLLDB::WriteRegisterValueT
break;
case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
{
- Error error (WriteRegisterValueToMemory (reg_info,
- regloc.location.target_memory_location,
- reg_info->byte_size,
+ Error error (WriteRegisterValueToMemory (reg_info,
+ regloc.location.target_memory_location,
+ reg_info->byte_size,
value));
success = error.Success();
}
@@ -992,7 +893,7 @@ RegisterContextLLDB::IsValid () const
// A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
// up the stack if we keep looking. It's always the second frame in an unwind (i.e. the first frame after
// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of their real program in the
+// user knows we're displaying bad data and we may have skipped one frame of their real program in the
// process of getting back on track.
bool
@@ -1003,11 +904,9 @@ RegisterContextLLDB::IsSkipFrame () cons
// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
-bool
-RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, bool check_next_frame)
+enum UnwindLLDB::RegisterSearchResult
+RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
// Have we already found this register location?
if (!m_registers.empty())
{
@@ -1016,22 +915,32 @@ RegisterContextLLDB::SavedLocationForReg
if (iterator != m_registers.end())
{
regloc = iterator->second;
- return true;
+ UnwindLogMsg ("supplying caller's saved reg %d's location, cached", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
}
+ static uint32_t sp_regnum = LLDB_INVALID_REGNUM;
+ static uint32_t pc_regnum = LLDB_INVALID_REGNUM;
+ static bool generic_registers_initialized = false;
+ if (!generic_registers_initialized)
+ {
+ m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
+ m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
+ generic_registers_initialized = true;
+ }
+
// Are we looking for the CALLER's stack pointer? The stack pointer is defined to be the same as THIS frame's
// CFA so just return the CFA value. This is true on x86-32/x86-64 at least.
- uint32_t sp_regnum;
- if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum)
- && sp_regnum == lldb_regnum)
+ if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
{
// make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
assert (sizeof (addr_t) <= sizeof (uint64_t));
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = m_cfa;
m_registers[lldb_regnum] = regloc;
- return true;
+ UnwindLogMsg ("supplying caller's stack pointer (%d) value, computed from CFA", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
// Look through the available UnwindPlans for the register location.
@@ -1047,22 +956,13 @@ RegisterContextLLDB::SavedLocationForReg
uint32_t row_regnum;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, (int) unwindplan_registerkind);
- }
- return false;
+ UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+ lldb_regnum, (int) unwindplan_registerkind);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
{
- if (log)
- {
- log->Printf("%*sFrame %u supplying caller's saved reg %d's location using FastUnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
have_unwindplan_regloc = true;
}
}
@@ -1078,41 +978,111 @@ RegisterContextLLDB::SavedLocationForReg
UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
uint32_t row_regnum;
- if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+ bool row_register_rewritten_to_return_address_reg = false;
+
+ // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
+ // look for the return address register number in the UnwindPlan's row.
+ if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
+ {
+ row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
+ row_register_rewritten_to_return_address_reg = true;
+ UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
+ row_regnum);
+ }
+ else
{
- if (log)
+ if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{
if (unwindplan_registerkind == eRegisterKindGeneric)
- log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
+ UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
else
- log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, (int) unwindplan_registerkind);
+ UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+ lldb_regnum, (int) unwindplan_registerkind);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
- return false;
}
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
{
have_unwindplan_regloc = true;
- if (log)
- {
- log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString());
+ UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
+ }
+
+ // This is frame 0 and we're retrieving the PC and it's saved in a Return Address register and
+ // it hasn't been saved anywhere yet -- that is, it's still live in the actual register.
+ // Handle this specially.
+
+ if (have_unwindplan_regloc == false
+ && row_register_rewritten_to_return_address_reg == true
+ && IsFrameZero()
+ && row_regnum != LLDB_INVALID_REGNUM)
+ {
+ uint32_t ra_regnum_in_lldb_reg_numbering;
+ if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, row_regnum, eRegisterKindLLDB, ra_regnum_in_lldb_reg_numbering))
+ {
+ lldb_private::UnwindLLDB::RegisterLocation new_regloc;
+ new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+ new_regloc.location.register_number = ra_regnum_in_lldb_reg_numbering;
+ m_registers[lldb_regnum] = new_regloc;
+ regloc = new_regloc;
+ UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0, saved in %d", lldb_regnum, ra_regnum_in_lldb_reg_numbering);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+ }
+
+ // If this architecture stores the return address in a register (it defines a Return Address register)
+ // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
+ // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
+ // is an impossible situation and the instruction emulation code has likely been misled.
+ // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the
+ // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
+ // the stack walk can get past this point.
+
+ // Special note: If the Full UnwindPlan was generated from the compiler, don't second-guess it
+ // when we're at a call site location.
+
+ // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
+ uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM;
+ if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
+ && arch_default_ra_regnum != LLDB_INVALID_REGNUM
+ && pc_regnum != LLDB_INVALID_REGNUM
+ && pc_regnum == lldb_regnum
+ && unwindplan_regloc.IsInOtherRegister()
+ && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+ && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
+ && !m_all_registers_available)
+ {
+ UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
+ m_full_unwind_plan_sp->GetSourceName().GetCString());
+
+ // Throw away the full unwindplan; install the arch default unwindplan
+ InvalidateFullUnwindPlan();
+
+ // Now re-fetch the pc value we're searching for
+ uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+ UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+ if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
+ && arch_default_pc_reg != LLDB_INVALID_REGNUM
+ && active_row
+ && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+ {
+ have_unwindplan_regloc = true;
+ }
+ else
+ {
+ have_unwindplan_regloc = false;
}
}
}
}
-
-
+
+
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
if (have_unwindplan_regloc == false)
{
- // If a volatile register is being requested, we don't want to forward the next frame's register contents
+ // If a volatile register is being requested, we don't want to forward the next frame's register contents
// up the stack -- the register is not retrievable at this frame.
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi)
@@ -1120,14 +1090,9 @@ RegisterContextLLDB::SavedLocationForReg
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
if (reg_info && abi->RegisterIsVolatile (reg_info))
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u did not supply reg location for %d because it is volatile",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
- }
+ UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
+ }
}
if (IsFrameZero ())
@@ -1138,20 +1103,12 @@ RegisterContextLLDB::SavedLocationForReg
new_regloc.location.register_number = lldb_regnum;
m_registers[lldb_regnum] = new_regloc;
regloc = new_regloc;
- return true;
+ UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
else
- {
- if (check_next_frame)
- return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
- }
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
// unwindplan_regloc has valid contents about where to retrieve the register
@@ -1160,33 +1117,20 @@ RegisterContextLLDB::SavedLocationForReg
lldb_private::UnwindLLDB::RegisterLocation new_regloc;
new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
m_registers[lldb_regnum] = new_regloc;
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
if (unwindplan_regloc.IsSame())
{
if (IsFrameZero ())
{
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
else
{
- if (check_next_frame)
- return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
- else
- return false;
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
}
@@ -1196,7 +1140,8 @@ RegisterContextLLDB::SavedLocationForReg
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = m_cfa + offset;
m_registers[lldb_regnum] = regloc;
- return true;
+ UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
if (unwindplan_regloc.IsAtCFAPlusOffset())
@@ -1205,7 +1150,8 @@ RegisterContextLLDB::SavedLocationForReg
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = m_cfa + offset;
m_registers[lldb_regnum] = regloc;
- return true;
+ UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
if (unwindplan_regloc.IsInOtherRegister())
@@ -1214,24 +1160,20 @@ RegisterContextLLDB::SavedLocationForReg
uint32_t row_regnum_in_lldb;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
{
- if (log)
- {
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
regloc.location.register_number = row_regnum_in_lldb;
m_registers[lldb_regnum] = regloc;
- return true;
+ UnwindLogMsg ("supplying caller's register %d, saved in register %d", lldb_regnum, row_regnum_in_lldb);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
{
- DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
- unwindplan_regloc.GetDWARFExpressionLength(),
+ DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
+ unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
@@ -1246,38 +1188,81 @@ RegisterContextLLDB::SavedLocationForReg
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = val;
m_registers[lldb_regnum] = regloc;
- return true;
+ UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsDWARFExpression)", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
else
{
- regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
- regloc.location.target_memory_location = val;
- m_registers[lldb_regnum] = regloc;
- return true;
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+ regloc.location.target_memory_location = val;
+ m_registers[lldb_regnum] = regloc;
+ UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsAtDWARFExpression)", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
}
- if (log)
- {
- log->Printf("%*sFrame %u tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
- return false;
+ UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
- if (log)
+ UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+
+ // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
+
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+}
+
+// If the Full unwindplan has been determined to be incorrect, this method will
+// replace it with the architecture's default unwindplna, if one is defined.
+// It will also find the FuncUnwinders object for this function and replace the
+// Full unwind method for the function there so we don't use the errant Full unwindplan
+// again in the future of this debug session.
+// We're most likely doing this because the Full unwindplan was generated by assembly
+// instruction profiling and the profiler got something wrong.
+
+void
+RegisterContextLLDB::InvalidateFullUnwindPlan ()
+{
+ UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+ ExecutionContext exe_ctx (m_thread.shared_from_this());
+ Process *process = exe_ctx.GetProcessPtr();
+ ABI *abi = process ? process->GetABI().get() : NULL;
+ if (abi)
{
- log->Printf("%*sFrame %u could not supply caller's reg %d location",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+ UnwindPlanSP arch_default_unwind_plan_sp;
+ arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+ if (arch_default_unwind_plan_sp)
+ {
+ UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+
+ if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+ {
+ FuncUnwindersSP func_unwinders_sp;
+ if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+ {
+ func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+ if (func_unwinders_sp)
+ {
+ func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+ }
+ }
+ m_registers.clear();
+ m_full_unwind_plan_sp = arch_default_unwind_plan_sp;
+ addr_t cfa_regval;
+ if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+ {
+ m_cfa = cfa_regval + active_row->GetCFAOffset ();
+ }
-
- // assert ("UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.");
- return false;
+ UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
+ original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString());
+ }
+ }
+ }
}
-// Retrieve a general purpose register value for THIS from, as saved by the NEXT frame, i.e. the frame that
+// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
// this frame called. e.g.
//
// foo () { }
@@ -1320,8 +1305,20 @@ RegisterContextLLDB::ReadGPRValue (int r
return false;
}
+ bool pc_register = false;
+ uint32_t generic_regnum;
+ if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC)
+ {
+ pc_register = true;
+ }
+ else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
+ && generic_regnum == LLDB_REGNUM_GENERIC_PC)
+ {
+ pc_register = true;
+ }
+
lldb_private::UnwindLLDB::RegisterLocation regloc;
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_register))
{
return false;
}
@@ -1338,33 +1335,22 @@ RegisterContextLLDB::ReadGPRValue (int r
bool
RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (!IsValid())
return false;
const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u looking for register saved location for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
// If this is the 0th frame, hand this over to the live register context
if (IsFrameZero ())
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u passing along to the live register context for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
}
lldb_private::UnwindLLDB::RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
return false;
return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
@@ -1373,33 +1359,22 @@ RegisterContextLLDB::ReadRegister (const
bool
RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value)
{
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (!IsValid())
return false;
const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u looking for register saved location for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
// If this is the 0th frame, hand this over to the live register context
if (IsFrameZero ())
{
- if (log && log->GetVerbose ())
- {
- log->Printf("%*sFrame %u passing along to the live register context for reg %d",
- m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
- lldb_regnum);
- }
+ UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
return m_thread.GetRegisterContext()->WriteRegister (reg_info, value);
}
lldb_private::UnwindLLDB::RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents
- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
return false;
return WriteRegisterValueToRegisterLocation (regloc, reg_info, value);
@@ -1463,7 +1438,7 @@ RegisterContextLLDB::GetStartPC (addr_t&
if (!m_start_pc.IsValid())
{
- return ReadPC (start_pc);
+ return ReadPC (start_pc);
}
start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get());
return true;
@@ -1484,12 +1459,12 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
// occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help
// find the bug.
- if (m_all_registers_available == false
+ if (m_all_registers_available == false
&& (pc == 0 || pc == 1))
{
return false;
}
- else
+ else
{
return true;
}
@@ -1499,3 +1474,57 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
return false;
}
}
+
+
+void
+RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log)
+ {
+ va_list args;
+ va_start (args, fmt);
+
+ char *logmsg;
+ if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+ {
+ if (logmsg)
+ free (logmsg);
+ va_end (args);
+ return;
+ }
+ va_end (args);
+
+ log->Printf ("%*sth%d/fr%u %s",
+ m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+ logmsg);
+ free (logmsg);
+ }
+}
+
+void
+RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log && log->GetVerbose())
+ {
+ va_list args;
+ va_start (args, fmt);
+
+ char *logmsg;
+ if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+ {
+ if (logmsg)
+ free (logmsg);
+ va_end (args);
+ return;
+ }
+ va_end (args);
+
+ log->Printf ("%*sth%d/fr%u %s",
+ m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+ logmsg);
+ free (logmsg);
+ }
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextLLDB.h Thu Jun 6 19:06:43 2013
@@ -25,7 +25,7 @@ class UnwindLLDB;
class RegisterContextLLDB : public lldb_private::RegisterContext
{
public:
- typedef STD_SHARED_PTR(RegisterContextLLDB) SharedPtr;
+ typedef std::shared_ptr<RegisterContextLLDB> SharedPtr;
RegisterContextLLDB (lldb_private::Thread &thread,
const SharedPtr& next_frame,
@@ -46,20 +46,20 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t reg_set);
+ GetRegisterSet (size_t reg_set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
virtual bool
WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
-
+
virtual bool
ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
@@ -96,14 +96,14 @@ private:
friend class UnwindLLDB;
// Indicates whether this frame is frame zero -- the currently
- // executing frame -- or not.
+ // executing frame -- or not.
bool
IsFrameZero () const;
- void
+ void
InitializeZerothFrame ();
- void
+ void
InitializeNonZerothFrame();
SharedPtr
@@ -112,7 +112,7 @@ private:
SharedPtr
GetPrevFrame () const;
- // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.
+ // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.
// There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate
// on this ABI) so we allow one invalid frame to be in the stack. Ideally we'll mark this frame specially at some
// point and indicate to the user that the unwinder had a hiccup. Often when this happens we will miss a frame of
@@ -124,32 +124,30 @@ private:
// Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
// function didn't modify/use.
//
- // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register
+ // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register
// being queried mid-stack. Instead of floating frame 0's contents of that register up the stack (which may
// or may not be the value of that reg when the function was executing), we won't return any value.
//
// If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
// stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
// as the requesting frame's.
- //
- // NB this function takes a "check_next_frame" boolean which indicates whether it should call back to the
- // containing UnwindLLDB object to iterate the search down the stack (true) or if this call should look for
- // a register save for that reg in the current frame only (false). Allows UnwindLLDB to iterate through the
- // RegisterContextLLDB's instead of using recursion to find saved register values.
- bool
- SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, bool check_next_frame);
+ lldb_private::UnwindLLDB::RegisterSearchResult
+ SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc);
bool
- ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+ ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool
- WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+ WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
- // Get the contents of a general purpose (address-size) register for this frame
+ void
+ InvalidateFullUnwindPlan ();
+
+ // Get the contents of a general purpose (address-size) register for this frame
// (usually retrieved from the next frame)
bool
ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
@@ -160,8 +158,14 @@ private:
lldb::UnwindPlanSP
GetFullUnwindPlanForFrame ();
+ void
+ UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+ void
+ UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
lldb_private::Thread& m_thread;
-
+
///
// The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
// i.e. where THIS frame saved them
@@ -182,7 +186,7 @@ private:
int m_current_offset_backed_up_one; // how far into the function we've executed; -1 if unknown
// 0 if no instructions have been executed yet.
// On architectures where the return address on the stack points
- // to the instruction after the CALL, this value will have 1
+ // to the instruction after the CALL, this value will have 1
// subtracted from it. Else a function that ends in a CALL will
// have an offset pointing into the next function's address range.
// m_current_pc has the actual address of the "current" pc.
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp Thu Jun 6 19:06:43 2013
@@ -59,7 +59,7 @@ RegisterContextMacOSXFrameBackchain::Get
}
const RegisterInfo *
-RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
{
return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
}
@@ -73,7 +73,7 @@ RegisterContextMacOSXFrameBackchain::Get
const RegisterSet *
-RegisterContextMacOSXFrameBackchain::GetRegisterSet (uint32_t reg_set)
+RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
{
return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h Thu Jun 6 19:06:43 2013
@@ -42,13 +42,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t reg_set);
+ GetRegisterSet (size_t reg_set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.cpp Thu Jun 6 19:06:43 2013
@@ -61,7 +61,8 @@ RegisterContextMemory::~RegisterContextM
void
RegisterContextMemory::InvalidateAllRegisters ()
{
- SetAllRegisterValid (false);
+ if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+ SetAllRegisterValid (false);
}
void
@@ -79,7 +80,7 @@ RegisterContextMemory::GetRegisterCount
}
const RegisterInfo *
-RegisterContextMemory::GetRegisterInfoAtIndex (uint32_t reg)
+RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg)
{
return m_reg_infos.GetRegisterInfoAtIndex (reg);
}
@@ -91,7 +92,7 @@ RegisterContextMemory::GetRegisterSetCou
}
const RegisterSet *
-RegisterContextMemory::GetRegisterSet (uint32_t reg_set)
+RegisterContextMemory::GetRegisterSet (size_t reg_set)
{
return m_reg_infos.GetRegisterSet (reg_set);
}
@@ -164,3 +165,10 @@ RegisterContextMemory::WriteAllRegisterV
}
return false;
}
+
+void
+RegisterContextMemory::SetAllRegisterData (const lldb::DataBufferSP &data_sp)
+{
+ m_reg_data.SetData(data_sp);
+ SetAllRegisterValid (true);
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/RegisterContextMemory.h Thu Jun 6 19:06:43 2013
@@ -46,13 +46,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t reg_set);
+ GetRegisterSet (size_t reg_set);
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
@@ -60,7 +60,7 @@ public:
//------------------------------------------------------------------
// If all of the thread register are in a contiguous buffer in
- // memory, then the default ReadRegister/WriteRegiter and
+ // memory, then the default ReadRegister/WriteRegister and
// ReadAllRegisterValues/WriteAllRegisterValues will work. If thread
// registers are not contiguous, clients will want to subclass this
// class and modify the read/write functions as needed.
@@ -80,6 +80,8 @@ public:
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ void
+ SetAllRegisterData (const lldb::DataBufferSP &data_sp);
protected:
void
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.cpp Thu Jun 6 19:06:43 2013
@@ -16,6 +16,8 @@
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -32,7 +34,7 @@ StopInfoMachException::GetDescription ()
{
if (m_description.empty() && m_value != 0)
{
- ExecutionContext exe_ctx (m_thread.shared_from_this());
+ ExecutionContext exe_ctx (m_thread_wp.lock());
Target *target = exe_ctx.GetTargetPtr();
const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
@@ -47,7 +49,14 @@ StopInfoMachException::GetDescription ()
exc_desc = "EXC_BAD_ACCESS";
subcode_label = "address";
switch (cpu)
- {
+ {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ switch (m_exc_code)
+ {
+ case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break;
+ }
+ break;
case llvm::Triple::arm:
switch (m_exc_code)
{
@@ -184,6 +193,8 @@ StopInfoMachException::GetDescription ()
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
+ // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT
+ case 0: code_desc = "EXC_ARM_BREAKPOINT"; break;
}
break;
@@ -208,6 +219,12 @@ StopInfoMachException::GetDescription ()
case 10:
exc_desc = "EXC_CRASH";
break;
+ case 11:
+ exc_desc = "EXC_RESOURCE";
+ break;
+ case 12:
+ exc_desc = "EXC_GUARD";
+ break;
}
StreamString strm;
@@ -215,14 +232,14 @@ StopInfoMachException::GetDescription ()
if (exc_desc)
strm.PutCString(exc_desc);
else
- strm.Printf("EXC_??? (%llu)", m_value);
+ strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
if (m_exc_data_count >= 1)
{
if (code_desc)
strm.Printf(" (%s=%s", code_label, code_desc);
else
- strm.Printf(" (%s=%llu", code_label, m_exc_code);
+ strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
}
if (m_exc_data_count >= 2)
@@ -230,7 +247,7 @@ StopInfoMachException::GetDescription ()
if (subcode_desc)
strm.Printf(", %s=%s", subcode_label, subcode_desc);
else
- strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode);
+ strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
}
if (m_exc_data_count > 0)
@@ -242,6 +259,9 @@ StopInfoMachException::GetDescription ()
}
+
+
+
StopInfoSP
StopInfoMachException::CreateStopReasonWithMachException
(
@@ -250,11 +270,14 @@ StopInfoMachException::CreateStopReasonW
uint32_t exc_data_count,
uint64_t exc_code,
uint64_t exc_sub_code,
- uint64_t exc_sub_sub_code
+ uint64_t exc_sub_sub_code,
+ bool pc_already_adjusted,
+ bool adjust_pc_if_needed
)
{
if (exc_type != 0)
{
+ uint32_t pc_decrement = 0;
ExecutionContext exe_ctx (thread.shared_from_this());
Target *target = exe_ctx.GetTargetPtr();
const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
@@ -294,12 +317,45 @@ StopInfoMachException::CreateStopReasonW
case 5: // EXC_SOFTWARE
if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
+ {
+ if (exc_sub_code == 5)
+ {
+ // On MacOSX, a SIGTRAP can signify that a process has called
+ // exec, so we should check with our dynamic loader to verify.
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
+ if (dynamic_loader && dynamic_loader->ProcessDidExec())
+ {
+ // The program was re-exec'ed
+ return StopInfo::CreateStopReasonWithExec (thread);
+ }
+// if (!process_did_exec)
+// {
+// // We have a SIGTRAP, make sure we didn't exec by checking
+// // for the PC being at "_dyld_start"...
+// lldb::StackFrameSP frame_sp (thread.GetStackFrameAtIndex(0));
+// if (frame_sp)
+// {
+// const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+// if (symbol)
+// {
+// if (symbol->GetName() == ConstString("_dyld_start"))
+// process_did_exec = true;
+// }
+// }
+// }
+ }
+ }
return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
+ }
break;
case 6: // EXC_BREAKPOINT
{
- bool is_software_breakpoint = false;
+ bool is_actual_breakpoint = false;
+ bool is_trace_if_actual_breakpoint_missing = false;
switch (cpu)
{
case llvm::Triple::x86:
@@ -323,19 +379,26 @@ StopInfoMachException::CreateStopReasonW
return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
}
}
- else if (exc_code == 2) // EXC_I386_BPT
+ else if (exc_code == 2 || // EXC_I386_BPT
+ exc_code == 3) // EXC_I386_BPTFLT
{
- is_software_breakpoint = true;
+ // KDP returns EXC_I386_BPTFLT for trace breakpoints
+ if (exc_code == 3)
+ is_trace_if_actual_breakpoint_missing = true;
+
+ is_actual_breakpoint = true;
+ if (!pc_already_adjusted)
+ pc_decrement = 1;
}
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
- is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
+ is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
break;
case llvm::Triple::arm:
- if (exc_code == 0x102)
+ if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
// data break address from our watchpoint list.
@@ -351,26 +414,43 @@ StopInfoMachException::CreateStopReasonW
return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
}
// EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
- return StopInfo::CreateStopReasonToTrace(thread);
+ if (thread.GetTemporaryResumeState() == eStateStepping)
+ return StopInfo::CreateStopReasonToTrace(thread);
+ }
+ else if (exc_code == 1) // EXC_ARM_BREAKPOINT
+ {
+ is_actual_breakpoint = true;
+ is_trace_if_actual_breakpoint_missing = true;
+ }
+ else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel is currently returning this so accept it as indicating a breakpoint until the kernel is fixed
+ {
+ is_actual_breakpoint = true;
+ is_trace_if_actual_breakpoint_missing = true;
}
- else
- is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
break;
default:
break;
}
- if (is_software_breakpoint)
+ if (is_actual_breakpoint)
{
- addr_t pc = thread.GetRegisterContext()->GetPC();
+ RegisterContextSP reg_ctx_sp (thread.GetRegisterContext());
+ addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
+
ProcessSP process_sp (thread.CalculateProcess());
lldb::BreakpointSiteSP bp_site_sp;
if (process_sp)
bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp)
+ if (bp_site_sp && bp_site_sp->IsEnabled())
{
+ // Update the PC if we were asked to do so, but only do
+ // so if we find a breakpoint that we know about cause
+ // this could be a trap instruction in the code
+ if (pc_decrement > 0 && adjust_pc_if_needed)
+ reg_ctx_sp->SetPC (pc);
+
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
// we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
@@ -379,7 +459,9 @@ StopInfoMachException::CreateStopReasonW
else
return StopInfoSP();
}
- else if (cpu == llvm::Triple::arm)
+
+ // Don't call this a trace if we weren't single stepping this thread.
+ if (is_trace_if_actual_breakpoint_missing && thread.GetTemporaryResumeState() == eStateStepping)
{
return StopInfo::CreateStopReasonToTrace (thread);
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/StopInfoMachException.h Thu Jun 6 19:06:43 2013
@@ -61,8 +61,10 @@ public:
uint32_t exc_data_count,
uint64_t exc_code,
uint64_t exc_sub_code,
- uint64_t exc_sub_sub_code);
-
+ uint64_t exc_sub_sub_code,
+ bool pc_already_adjusted = true,
+ bool adjust_pc_if_needed = false);
+
protected:
uint32_t m_exc_data_count;
uint64_t m_exc_code;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.cpp Thu Jun 6 19:06:43 2013
@@ -13,48 +13,67 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Unwind.h"
+#include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
using namespace lldb;
using namespace lldb_private;
-ThreadMemory::ThreadMemory (const ProcessSP &process_sp,
- tid_t tid,
- const ValueObjectSP &thread_info_valobj_sp) :
- Thread (process_sp, tid),
- m_thread_info_valobj_sp (thread_info_valobj_sp)
+ThreadMemory::ThreadMemory (Process &process,
+ tid_t tid,
+ const ValueObjectSP &thread_info_valobj_sp) :
+ Thread (process, tid),
+ m_backing_thread_sp (),
+ m_thread_info_valobj_sp (thread_info_valobj_sp),
+ m_name(),
+ m_queue()
{
}
+ThreadMemory::ThreadMemory (Process &process,
+ lldb::tid_t tid,
+ const char *name,
+ const char *queue,
+ lldb::addr_t register_data_addr) :
+ Thread (process, tid),
+ m_backing_thread_sp (),
+ m_thread_info_valobj_sp (),
+ m_name(),
+ m_queue(),
+ m_register_data_addr (register_data_addr)
+{
+ if (name)
+ m_name = name;
+ if (queue)
+ m_queue = queue;
+}
+
+
ThreadMemory::~ThreadMemory()
{
DestroyThread();
}
-bool
+void
ThreadMemory::WillResume (StateType resume_state)
{
- ClearStackFrames();
- // Call the Thread::WillResume first. If we stop at a signal, the stop info
- // class for signal will set the resume signal that we need below. The signal
- // stuff obeys the Process::UnixSignal defaults.
- Thread::WillResume(resume_state);
- return true;
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->WillResume(resume_state);
+}
+
+void
+ThreadMemory::ClearStackFrames ()
+{
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->ClearStackFrames();
+ Thread::ClearStackFrames();
}
RegisterContextSP
ThreadMemory::GetRegisterContext ()
{
if (!m_reg_context_sp)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- OperatingSystem *os = process_sp->GetOperatingSystem ();
- if (os)
- m_reg_context_sp = os->CreateRegisterContextForThread (this);
- }
- }
+ m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr));
return m_reg_context_sp;
}
@@ -71,51 +90,51 @@ ThreadMemory::CreateRegisterContextForFr
{
reg_ctx_sp = GetRegisterContext ();
}
- else if (m_unwinder_ap.get())
+ else
{
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
}
return reg_ctx_sp;
}
-lldb::StopInfoSP
-ThreadMemory::GetPrivateStopReason ()
+bool
+ThreadMemory::CalculateStopInfo ()
{
- ProcessSP process_sp (GetProcess());
-
- if (process_sp)
+ if (m_backing_thread_sp)
{
- const uint32_t process_stop_id = process_sp->GetStopID();
- if (m_thread_stop_reason_stop_id != process_stop_id ||
- (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+ lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo());
+ if (backing_stop_info_sp)
+ {
+ backing_stop_info_sp->SetThread (shared_from_this());
+ SetStopInfo (backing_stop_info_sp);
+ return true;
+ }
+ }
+ else
+ {
+ ProcessSP process_sp (GetProcess());
+
+ if (process_sp)
{
- // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
- // for this thread, then m_actual_stop_info_sp will not ever contain
- // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
- // check will never be able to tell us if we have the correct stop info
- // for this thread and we will continually send qThreadStopInfo packets
- // down to the remote GDB server, so we need to keep our own notion
- // of the stop ID that m_actual_stop_info_sp is valid for (even if it
- // contains nothing). We use m_thread_stop_reason_stop_id for this below.
- m_thread_stop_reason_stop_id = process_stop_id;
- m_actual_stop_info_sp.reset();
-
OperatingSystem *os = process_sp->GetOperatingSystem ();
if (os)
- m_actual_stop_info_sp = os->CreateThreadStopReason (this);
+ {
+ SetStopInfo (os->CreateThreadStopReason (this));
+ return true;
+ }
}
}
- return m_actual_stop_info_sp;
-
+ return false;
}
void
ThreadMemory::RefreshStateAfterStop()
{
- RegisterContextSP reg_ctx_sp(GetRegisterContext());
- if (reg_ctx_sp)
- {
- const bool force = true;
- reg_ctx_sp->InvalidateIfNeeded (force);
- }
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->RefreshStateAfterStop();
+
+ if (m_reg_context_sp)
+ m_reg_context_sp->InvalidateAllRegisters();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/ThreadMemory.h Thu Jun 6 19:06:43 2013
@@ -17,43 +17,131 @@ class ThreadMemory :
{
public:
- ThreadMemory (const lldb::ProcessSP &process_sp,
+ ThreadMemory (lldb_private::Process &process,
lldb::tid_t tid,
const lldb::ValueObjectSP &thread_info_valobj_sp);
- virtual
+ ThreadMemory (lldb_private::Process &process,
+ lldb::tid_t tid,
+ const char *name,
+ const char *queue,
+ lldb::addr_t register_data_addr);
+
+ virtual
~ThreadMemory();
//------------------------------------------------------------------
// lldb_private::Thread methods
//------------------------------------------------------------------
- virtual void
- RefreshStateAfterStop();
-
virtual lldb::RegisterContextSP
GetRegisterContext ();
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
- virtual lldb::StopInfoSP
- GetPrivateStopReason ();
-
virtual bool
+ CalculateStopInfo ();
+
+ virtual const char *
+ GetInfo ()
+ {
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetInfo();
+ return NULL;
+ }
+
+ virtual const char *
+ GetName ()
+ {
+ if (!m_name.empty())
+ return m_name.c_str();
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetName();
+ return NULL;
+ }
+
+ virtual const char *
+ GetQueueName ()
+ {
+ if (!m_queue.empty())
+ return m_queue.c_str();
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetQueueName();
+ return NULL;
+ }
+
+ virtual void
WillResume (lldb::StateType resume_state);
+ virtual void
+ DidResume ()
+ {
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->DidResume();
+ }
+
+ virtual lldb::user_id_t
+ GetProtocolID () const
+ {
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->GetProtocolID();
+ return Thread::GetProtocolID();
+ }
+
+ virtual void
+ RefreshStateAfterStop();
+
lldb::ValueObjectSP &
GetValueObject ()
{
return m_thread_info_valobj_sp;
}
+
+ virtual void
+ ClearStackFrames ();
+
+ virtual void
+ ClearBackingThread ()
+ {
+ m_backing_thread_sp.reset();
+ }
+
+ virtual bool
+ SetBackingThread (const lldb::ThreadSP &thread_sp)
+ {
+ //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());
+ m_backing_thread_sp = thread_sp;
+ return (bool)thread_sp;
+ }
+
+ virtual lldb::ThreadSP
+ GetBackingThread () const
+ {
+ return m_backing_thread_sp;
+ }
protected:
+
+ virtual bool
+ IsOperatingSystemPluginThread () const
+ {
+ return true;
+ }
+
+
//------------------------------------------------------------------
// For ThreadMemory and subclasses
//------------------------------------------------------------------
+ // If this memory thread is actually represented by a thread from the
+ // lldb_private::Process subclass, then fill in the thread here and
+ // all APIs will be routed through this thread object. If m_backing_thread_sp
+ // is empty, then this thread is simply in memory with no representation
+ // through the process plug-in.
+ lldb::ThreadSP m_backing_thread_sp;
lldb::ValueObjectSP m_thread_info_valobj_sp;
-
+ std::string m_name;
+ std::string m_queue;
+ lldb::addr_t m_register_data_addr;
private:
//------------------------------------------------------------------
// For ThreadMemory only
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.cpp Thu Jun 6 19:06:43 2013
@@ -53,7 +53,7 @@ UnwindLLDB::DoGetFrameCount()
{
TimeValue now(TimeValue::Now());
uint64_t delta_t = now - time_value;
- printf ("%u frames in %llu.%09llu ms (%g frames/sec)\n",
+ printf ("%u frames in %" PRIu64 ".%09llu ms (%g frames/sec)\n",
FRAME_COUNT,
delta_t / TimeValue::NanoSecPerSec,
delta_t % TimeValue::NanoSecPerSec,
@@ -108,7 +108,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
if (m_unwind_complete)
return false;
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
CursorSP cursor_sp(new Cursor ());
// Frame zero is a little different
@@ -121,6 +121,22 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
cursor_sp->sctx,
cur_idx,
*this));
+
+ // We want to detect an unwind that cycles erronously and stop backtracing.
+ // Don't want this maximum unwind limit to be too low -- if you have a backtrace
+ // with an "infinitely recursing" bug, it will crash when the stack blows out
+ // and the first 35,000 frames are uninteresting - it's the top most 5 frames that
+ // you actually care about. So you can't just cap the unwind at 10,000 or something.
+ // Realistically anything over around 200,000 is going to blow out the stack space.
+ // If we're still unwinding at that point, we're probably never going to finish.
+ if (cur_idx > 300000)
+ {
+ if (log)
+ log->Printf ("%*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping.",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ goto unwind_done;
+ }
+
if (reg_ctx_sp.get() == NULL)
goto unwind_done;
@@ -175,7 +191,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
{
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->StackUsesFrames())
+ 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.
@@ -262,15 +278,44 @@ UnwindLLDB::GetRegisterContextForFrameNu
}
bool
-UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num)
+UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_reg)
{
int64_t frame_num = starting_frame_num;
if (frame_num >= m_frames.size())
return false;
+
+ // Never interrogate more than one level while looking for the saved pc value. If the value
+ // isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
+ if (pc_reg)
+ {
+ UnwindLLDB::RegisterSearchResult result;
+ result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+ if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+ return true;
+ else
+ return false;
+ }
while (frame_num >= 0)
{
- if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc, false))
+ UnwindLLDB::RegisterSearchResult result;
+ result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+
+ // If we have unwind instructions saying that register N is saved in register M in the middle of
+ // the stack (and N can equal M here, meaning the register was not used in this function), then
+ // change the register number we're looking for to M and keep looking for a concrete location
+ // down the stack, or an actual value from a live RegisterContext at frame 0.
+ if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound
+ && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInRegister
+ && frame_num > 0)
+ {
+ result = UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+ lldb_regnum = regloc.location.register_number;
+ }
+
+ if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
return true;
+ if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile)
+ return false;
frame_num--;
}
return false;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindLLDB.h Thu Jun 6 19:06:43 2013
@@ -30,6 +30,13 @@ public:
virtual
~UnwindLLDB() { }
+ enum RegisterSearchResult
+ {
+ eRegisterFound = 0,
+ eRegisterNotFound,
+ eRegisterIsVolatile
+ };
+
protected:
friend class lldb_private::RegisterContextLLDB;
@@ -70,7 +77,7 @@ protected:
lldb::RegisterContextSP
DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
- typedef STD_SHARED_PTR(RegisterContextLLDB) RegisterContextLLDBSP;
+ typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP;
// Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame 1's RegisterContextLLDB)
// The RegisterContext for frame_num must already exist or this returns an empty shared pointer.
@@ -80,7 +87,7 @@ protected:
// Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that
// has a saved location for this reg.
bool
- SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num);
+ SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_register);
private:
@@ -97,7 +104,7 @@ private:
DISALLOW_COPY_AND_ASSIGN (Cursor);
};
- typedef STD_SHARED_PTR(Cursor) CursorSP;
+ typedef std::shared_ptr<Cursor> CursorSP;
std::vector<CursorSP> m_frames;
bool m_unwind_complete; // If this is true, we've enumerated all the frames in the stack, and m_frames.size() is the
// number of frames, etc. Otherwise we've only gone as far as directly asked, and m_frames.size()
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp Thu Jun 6 19:06:43 2013
@@ -12,6 +12,9 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ArchSpec.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -173,7 +176,7 @@ UnwindMacOSXFrameBackchain::GetStackFram
// printf(" ------------------ ------------------ \n");
// for (i=0; i<m_cursors.size(); ++i)
// {
-// printf("[%3u] 0x%16.16llx 0x%16.16llx\n", i, m_cursors[i].pc, m_cursors[i].fp);
+// printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
// }
return m_cursors.size();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Jun 6 19:06:43 2013
@@ -92,7 +92,7 @@ GDBRemoteCommunication::History::Dump (l
const Entry &entry = m_packets[idx];
if (entry.type == ePacketTypeInvalid || entry.packet.empty())
break;
- strm.Printf ("history[%u] tid=0x%4.4llx <%4u> %s packet: %s\n",
+ strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
entry.packet_idx,
entry.tid,
entry.bytes_transmitted,
@@ -116,7 +116,7 @@ GDBRemoteCommunication::History::Dump (l
const Entry &entry = m_packets[idx];
if (entry.type == ePacketTypeInvalid || entry.packet.empty())
break;
- log->Printf ("history[%u] tid=0x%4.4llx <%4u> %s packet: %s",
+ log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
entry.packet_idx,
entry.tid,
entry.bytes_transmitted,
@@ -175,7 +175,7 @@ GDBRemoteCommunication::CalculcateChecks
size_t
GDBRemoteCommunication::SendAck ()
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
char ch = '+';
const size_t bytes_written = Write (&ch, 1, status, NULL);
@@ -188,7 +188,7 @@ GDBRemoteCommunication::SendAck ()
size_t
GDBRemoteCommunication::SendNack ()
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
char ch = '-';
const size_t bytes_written = Write (&ch, 1, status, NULL);
@@ -217,7 +217,7 @@ GDBRemoteCommunication::SendPacketNoLock
packet.PutChar('#');
packet.PutHex8(CalculcateChecksum (payload, payload_length));
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
if (log)
@@ -227,7 +227,7 @@ GDBRemoteCommunication::SendPacketNoLock
// logs all of the packet will set a boolean so that we don't dump this more
// than once
if (!m_history.DidDumpToLog ())
- m_history.Dump (log.get());
+ m_history.Dump (log);
log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
}
@@ -289,7 +289,7 @@ GDBRemoteCommunication::WaitForPacketWit
uint8_t buffer[8192];
Error error;
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
// Check for a packet from our cache first without trying any reading...
if (CheckForPacket (NULL, 0, packet))
@@ -302,12 +302,12 @@ GDBRemoteCommunication::WaitForPacketWit
size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
if (log)
- log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
+ log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
__PRETTY_FUNCTION__,
timeout_usec,
Communication::ConnectionStatusAsCString (status),
error.AsCString(),
- bytes_read);
+ (uint64_t)bytes_read);
if (bytes_read > 0)
{
@@ -344,7 +344,7 @@ GDBRemoteCommunication::CheckForPacket (
// Put the packet data into the buffer in a thread safe fashion
Mutex::Locker locker(m_bytes_mutex);
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
if (src && src_len > 0)
{
@@ -461,7 +461,7 @@ GDBRemoteCommunication::CheckForPacket (
// logs all of the packet will set a boolean so that we don't dump this more
// than once
if (!m_history.DidDumpToLog ())
- m_history.Dump (log.get());
+ m_history.Dump (log);
log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Thu Jun 6 19:06:43 2013
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <sstream>
+
// Other libraries and framework includes
#include "llvm/ADT/Triple.h"
#include "lldb/Interpreter/Args.h"
@@ -47,9 +49,11 @@ GDBRemoteCommunicationClient::GDBRemoteC
m_supports_vCont_s (eLazyBoolCalculate),
m_supports_vCont_S (eLazyBoolCalculate),
m_qHostInfo_is_valid (eLazyBoolCalculate),
+ m_qProcessInfo_is_valid (eLazyBoolCalculate),
m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
m_supports_memory_region_info (eLazyBoolCalculate),
m_supports_watchpoint_support_info (eLazyBoolCalculate),
+ m_supports_detach_stay_stopped (eLazyBoolCalculate),
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
@@ -71,7 +75,9 @@ GDBRemoteCommunicationClient::GDBRemoteC
m_async_packet (),
m_async_response (),
m_async_signal (-1),
+ m_thread_id_to_used_usec_map (),
m_host_arch(),
+ m_process_arch(),
m_os_version_major (UINT32_MAX),
m_os_version_minor (UINT32_MAX),
m_os_version_update (UINT32_MAX)
@@ -188,6 +194,7 @@ GDBRemoteCommunicationClient::ResetDisco
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
+ m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
m_supports_memory_region_info = eLazyBoolCalculate;
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
@@ -204,6 +211,7 @@ GDBRemoteCommunicationClient::ResetDisco
m_supports_z3 = true;
m_supports_z4 = true;
m_host_arch.Clear();
+ m_process_arch.Clear();
}
@@ -305,7 +313,7 @@ GDBRemoteCommunicationClient::SendPacket
)
{
Mutex::Locker locker;
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
size_t response_len = 0;
if (GetSequenceMutex (locker))
{
@@ -418,6 +426,99 @@ GDBRemoteCommunicationClient::SendPacket
return response_len;
}
+static const char *end_delimiter = "--end--;";
+static const int end_delimiter_len = 8;
+
+std::string
+GDBRemoteCommunicationClient::HarmonizeThreadIdsForProfileData
+( ProcessGDBRemote *process,
+ StringExtractorGDBRemote& profileDataExtractor
+)
+{
+ std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+ std::stringstream final_output;
+ std::string name, value;
+
+ // Going to assuming thread_used_usec comes first, else bail out.
+ while (profileDataExtractor.GetNameColonValue(name, value))
+ {
+ if (name.compare("thread_used_id") == 0)
+ {
+ StringExtractor threadIDHexExtractor(value.c_str());
+ uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+
+ bool has_used_usec = false;
+ uint32_t curr_used_usec = 0;
+ std::string usec_name, usec_value;
+ uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+ if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
+ {
+ if (usec_name.compare("thread_used_usec") == 0)
+ {
+ has_used_usec = true;
+ curr_used_usec = strtoull(usec_value.c_str(), NULL, 0);
+ }
+ else
+ {
+ // We didn't find what we want, it is probably
+ // an older version. Bail out.
+ profileDataExtractor.SetFilePos(input_file_pos);
+ }
+ }
+
+ if (has_used_usec)
+ {
+ uint32_t prev_used_usec = 0;
+ std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
+ if (iterator != m_thread_id_to_used_usec_map.end())
+ {
+ prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
+ }
+
+ uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+ // A good first time record is one that runs for at least 0.25 sec
+ bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
+ bool good_subsequent_time = (prev_used_usec > 0) &&
+ ((real_used_usec > 0) || (process->HasAssignedIndexIDToThread(thread_id)));
+
+ if (good_first_time || good_subsequent_time)
+ {
+ // We try to avoid doing too many index id reservation,
+ // resulting in fast increase of index ids.
+
+ final_output << name << ":";
+ int32_t index_id = process->AssignIndexIDToThread(thread_id);
+ final_output << index_id << ";";
+
+ final_output << usec_name << ":" << usec_value << ";";
+ }
+ else
+ {
+ // Skip past 'thread_used_name'.
+ std::string local_name, local_value;
+ profileDataExtractor.GetNameColonValue(local_name, local_value);
+ }
+
+ // Store current time as previous time so that they can be compared later.
+ new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+ }
+ else
+ {
+ // Bail out and use old string.
+ final_output << name << ":" << value << ";";
+ }
+ }
+ else
+ {
+ final_output << name << ":" << value << ";";
+ }
+ }
+ final_output << end_delimiter;
+ m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
+
+ return final_output.str();
+}
+
StateType
GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
(
@@ -428,7 +529,7 @@ GDBRemoteCommunicationClient::SendContin
)
{
m_curr_tid = LLDB_INVALID_THREAD_ID;
- LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
@@ -441,11 +542,11 @@ GDBRemoteCommunicationClient::SendContin
// may change if we are interrupted and we continue after an async packet...
std::string continue_packet(payload, packet_length);
- bool got_stdout = false;
+ bool got_async_packet = false;
while (state == eStateRunning)
{
- if (!got_stdout)
+ if (!got_async_packet)
{
if (log)
log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
@@ -455,7 +556,7 @@ GDBRemoteCommunicationClient::SendContin
m_private_is_running.SetValue (true, eBroadcastAlways);
}
- got_stdout = false;
+ got_async_packet = false;
if (log)
log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str());
@@ -578,7 +679,7 @@ GDBRemoteCommunicationClient::SendContin
}
else if (m_async_packet_predicate.GetValue())
{
- LogSP packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+ Log * packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
// We are supposed to send an asynchronous packet while
// we are running.
@@ -638,7 +739,7 @@ GDBRemoteCommunicationClient::SendContin
case 'O':
// STDOUT
{
- got_stdout = true;
+ got_async_packet = true;
std::string inferior_stdout;
inferior_stdout.reserve(response.GetBytesLeft () / 2);
char ch;
@@ -648,6 +749,36 @@ GDBRemoteCommunicationClient::SendContin
}
break;
+ case 'A':
+ // Async miscellaneous reply. Right now, only profile data is coming through this channel.
+ {
+ got_async_packet = true;
+ std::string input = response.GetStringRef().substr(1); // '1' to move beyond 'A'
+ if (m_partial_profile_data.length() > 0)
+ {
+ m_partial_profile_data.append(input);
+ input = m_partial_profile_data;
+ m_partial_profile_data.clear();
+ }
+
+ size_t found, pos = 0, len = input.length();
+ while ((found = input.find(end_delimiter, pos)) != std::string::npos)
+ {
+ StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
+ const std::string& profile_data = HarmonizeThreadIdsForProfileData(process, profileDataExtractor);
+ process->BroadcastAsyncProfileData (profile_data.c_str(), profile_data.length());
+
+ pos = found + end_delimiter_len;
+ }
+
+ if (pos < len)
+ {
+ // Last incomplete chunk.
+ m_partial_profile_data = input.substr(pos);
+ }
+ }
+ break;
+
case 'E':
// ERROR
state = eStateInvalid;
@@ -708,7 +839,7 @@ GDBRemoteCommunicationClient::SendInterr
)
{
timed_out = false;
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
if (IsRunning())
{
@@ -954,6 +1085,14 @@ GDBRemoteCommunicationClient::GetSystemA
return ArchSpec();
}
+const lldb_private::ArchSpec &
+GDBRemoteCommunicationClient::GetProcessArchitecture ()
+{
+ if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
+ GetCurrentProcessInfo ();
+ return m_process_arch;
+}
+
bool
GDBRemoteCommunicationClient::GetHostInfo (bool force)
@@ -1189,7 +1328,7 @@ GDBRemoteCommunicationClient::SendAttach
if (pid != LLDB_INVALID_PROCESS_ID)
{
char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%llx", pid);
+ const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid);
assert (packet_len < sizeof(packet));
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
@@ -1216,7 +1355,8 @@ GDBRemoteCommunicationClient::AllocateMe
{
m_supports_alloc_dealloc_memory = eLazyBoolYes;
char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size,
+ const int packet_len = ::snprintf (packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s",
+ (uint64_t)size,
permissions & lldb::ePermissionsReadable ? "r" : "",
permissions & lldb::ePermissionsWritable ? "w" : "",
permissions & lldb::ePermissionsExecutable ? "x" : "");
@@ -1242,7 +1382,7 @@ GDBRemoteCommunicationClient::Deallocate
{
m_supports_alloc_dealloc_memory = eLazyBoolYes;
char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr);
+ const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1258,10 +1398,48 @@ GDBRemoteCommunicationClient::Deallocate
return false;
}
-bool
-GDBRemoteCommunicationClient::Detach ()
+Error
+GDBRemoteCommunicationClient::Detach (bool keep_stopped)
{
- return SendPacket ("D", 1) > 0;
+ Error error;
+
+ if (keep_stopped)
+ {
+ if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
+ {
+ char packet[64];
+ const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
+ assert (packet_len < sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ {
+ m_supports_detach_stay_stopped = eLazyBoolYes;
+ }
+ else
+ {
+ m_supports_detach_stay_stopped = eLazyBoolNo;
+ }
+ }
+
+ if (m_supports_detach_stay_stopped == eLazyBoolNo)
+ {
+ error.SetErrorString("Stays stopped not supported by this target.");
+ return error;
+ }
+ else
+ {
+ size_t num_sent = SendPacket ("D1", 2);
+ if (num_sent == 0)
+ error.SetErrorString ("Sending extended disconnect packet failed.");
+ }
+ }
+ else
+ {
+ size_t num_sent = SendPacket ("D", 1);
+ if (num_sent == 0)
+ error.SetErrorString ("Sending disconnect packet failed.");
+ }
+ return error;
}
Error
@@ -1275,7 +1453,7 @@ GDBRemoteCommunicationClient::GetMemoryR
{
m_supports_memory_region_info = eLazyBoolYes;
char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%llx", (uint64_t)addr);
+ const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1608,7 +1786,7 @@ GDBRemoteCommunicationClient::GetProcess
if (m_supports_qProcessInfoPID)
{
char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%llu", pid);
+ const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
@@ -1624,6 +1802,100 @@ GDBRemoteCommunicationClient::GetProcess
return false;
}
+bool
+GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
+{
+ if (m_qProcessInfo_is_valid == eLazyBoolYes)
+ return true;
+ if (m_qProcessInfo_is_valid == eLazyBoolNo)
+ return false;
+
+ GetHostInfo ();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse ("qProcessInfo", response, false))
+ {
+ if (response.IsNormalResponse())
+ {
+ std::string name;
+ std::string value;
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+ std::string arch_name;
+ std::string os_name;
+ std::string vendor_name;
+ std::string triple;
+ uint32_t pointer_byte_size = 0;
+ StringExtractor extractor;
+ ByteOrder byte_order = eByteOrderInvalid;
+ uint32_t num_keys_decoded = 0;
+ while (response.GetNameColonValue(name, value))
+ {
+ if (name.compare("cputype") == 0)
+ {
+ cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
+ if (cpu != LLDB_INVALID_CPUTYPE)
+ ++num_keys_decoded;
+ }
+ else if (name.compare("cpusubtype") == 0)
+ {
+ sub = Args::StringToUInt32 (value.c_str(), 0, 16);
+ if (sub != 0)
+ ++num_keys_decoded;
+ }
+ else if (name.compare("ostype") == 0)
+ {
+ os_name.swap (value);
+ ++num_keys_decoded;
+ }
+ else if (name.compare("vendor") == 0)
+ {
+ vendor_name.swap(value);
+ ++num_keys_decoded;
+ }
+ else if (name.compare("endian") == 0)
+ {
+ ++num_keys_decoded;
+ if (value.compare("little") == 0)
+ byte_order = eByteOrderLittle;
+ else if (value.compare("big") == 0)
+ byte_order = eByteOrderBig;
+ else if (value.compare("pdp") == 0)
+ byte_order = eByteOrderPDP;
+ else
+ --num_keys_decoded;
+ }
+ else if (name.compare("ptrsize") == 0)
+ {
+ pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16);
+ if (pointer_byte_size != 0)
+ ++num_keys_decoded;
+ }
+ }
+ if (num_keys_decoded > 0)
+ m_qProcessInfo_is_valid = eLazyBoolYes;
+ if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
+ {
+ m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+ if (pointer_byte_size)
+ {
+ assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
+ }
+ m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
+ m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
+ return true;
+ }
+ }
+ }
+ else
+ {
+ m_qProcessInfo_is_valid = eLazyBoolNo;
+ }
+
+ return false;
+}
+
+
uint32_t
GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos)
@@ -1678,9 +1950,9 @@ GDBRemoteCommunicationClient::FindProces
}
if (match_info.GetProcessInfo().ProcessIDIsValid())
- packet.Printf("pid:%llu;",match_info.GetProcessInfo().GetProcessID());
+ packet.Printf("pid:%" PRIu64 ";",match_info.GetProcessInfo().GetProcessID());
if (match_info.GetProcessInfo().ParentProcessIDIsValid())
- packet.Printf("parent_pid:%llu;",match_info.GetProcessInfo().GetParentProcessID());
+ packet.Printf("parent_pid:%" PRIu64 ";",match_info.GetProcessInfo().GetParentProcessID());
if (match_info.GetProcessInfo().UserIDIsValid())
packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
if (match_info.GetProcessInfo().GroupIDIsValid())
@@ -1803,7 +2075,7 @@ GDBRemoteCommunicationClient::TestPacket
end_time = TimeValue::Now();
total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %llu.%9.9llu sec for %f packets/sec.\n",
+ printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n",
num_packets,
send_size,
recv_size,
@@ -1827,7 +2099,7 @@ GDBRemoteCommunicationClient::TestPacket
end_time = TimeValue::Now();
total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- printf ("%u 'qC' packets packets in 0x%llu%9.9llu sec for %f packets/sec.\n",
+ printf ("%u 'qC' packets packets in 0x%" PRIu64 "%9.9" PRIu64 " sec for %f packets/sec.\n",
num_packets,
total_time_nsec / TimeValue::NanoSecPerSec,
total_time_nsec % TimeValue::NanoSecPerSec,
@@ -1861,21 +2133,37 @@ GDBRemoteCommunicationClient::SendSpeedT
}
uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
+ pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+ StreamString stream;
+ stream.PutCString("qLaunchGDBServer:port:0;");
+ std::string hostname;
+ if (Host::GetHostname (hostname))
+ {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ }
+ else
+ {
+ // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+ stream.Printf("host:*;");
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
std::string name;
std::string value;
uint16_t port = 0;
- //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value))
{
- if (name.size() == 4 && name.compare("port") == 0)
+ if (name.compare("port") == 0)
port = Args::StringToUInt32(value.c_str(), 0, 0);
-// if (name.size() == 3 && name.compare("pid") == 0)
-// pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("pid") == 0)
+ pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
}
return port;
}
@@ -1883,17 +2171,34 @@ GDBRemoteCommunicationClient::LaunchGDBs
}
bool
-GDBRemoteCommunicationClient::SetCurrentThread (int tid)
+GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
+{
+ StreamString stream;
+ stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ pid = LLDB_INVALID_PROCESS_ID;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ return true;
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
{
if (m_curr_tid == tid)
return true;
-
+
char packet[32];
int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
+ if (tid == UINT64_MAX)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg-1");
else
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid);
assert (packet_len + 1 < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
@@ -1908,18 +2213,18 @@ GDBRemoteCommunicationClient::SetCurrent
}
bool
-GDBRemoteCommunicationClient::SetCurrentThreadForRun (int tid)
+GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
{
if (m_curr_tid_run == tid)
return true;
-
+
char packet[32];
int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
+ if (tid == UINT64_MAX)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hc-1");
else
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
-
+ packet_len = ::snprintf (packet, sizeof(packet), "Hc%" PRIx64, tid);
+
assert (packet_len + 1 < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
@@ -1942,12 +2247,12 @@ GDBRemoteCommunicationClient::GetStopRep
}
bool
-GDBRemoteCommunicationClient::GetThreadStopInfo (uint32_t tid, StringExtractorGDBRemote &response)
+GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtractorGDBRemote &response)
{
if (m_supports_qThreadStopInfo)
{
char packet[256];
- int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", tid);
+ int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
assert (packet_len < sizeof(packet));
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
@@ -1977,13 +2282,12 @@ GDBRemoteCommunicationClient::SendGDBSto
case eWatchpointWrite: if (!m_supports_z2) return UINT8_MAX; break;
case eWatchpointRead: if (!m_supports_z3) return UINT8_MAX; break;
case eWatchpointReadWrite: if (!m_supports_z4) return UINT8_MAX; break;
- default: return UINT8_MAX;
}
char packet[64];
const int packet_len = ::snprintf (packet,
sizeof(packet),
- "%c%i,%llx,%x",
+ "%c%i,%" PRIx64 ",%x",
insert ? 'Z' : 'z',
type,
addr,
@@ -2007,7 +2311,6 @@ GDBRemoteCommunicationClient::SendGDBSto
case eWatchpointWrite: m_supports_z2 = false; break;
case eWatchpointRead: m_supports_z3 = false; break;
case eWatchpointReadWrite: m_supports_z4 = false; break;
- default: break;
}
}
@@ -2037,7 +2340,7 @@ GDBRemoteCommunicationClient::GetCurrent
{
do
{
- tid_t tid = response.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
if (tid != LLDB_INVALID_THREAD_ID)
{
@@ -2053,7 +2356,7 @@ GDBRemoteCommunicationClient::GetCurrent
#if defined (LLDB_CONFIGURATION_DEBUG)
// assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex");
#else
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
if (log)
log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'");
#endif
@@ -2145,19 +2448,44 @@ GDBRemoteCommunicationClient::MakeDirect
}
+static uint64_t
+ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
+ uint64_t fail_result,
+ Error &error)
+{
+ response.SetFilePos(0);
+ if (response.GetChar() != 'F')
+ return fail_result;
+ int32_t result = response.GetS32 (-2);
+ if (result == -2)
+ return fail_result;
+ if (response.GetChar() == ',')
+ {
+ int result_errno = response.GetS32 (-2);
+ if (result_errno != -2)
+ error.SetError(result_errno, eErrorTypePOSIX);
+ else
+ error.SetError(-1, eErrorTypeGeneric);
+ }
+ else
+ error.Clear();
+ return result;
+}
lldb::user_id_t
GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode)
+ mode_t mode,
+ Error &error)
{
lldb_private::StreamString stream;
stream.PutCString("vFile:open:");
- std::string path;
- if (file_spec.GetPath(path) == 0)
+ std::string path (file_spec.GetPath());
+ if (path.empty())
return UINT64_MAX;
stream.PutCStringAsRawHex8(path.c_str());
stream.PutChar(',');
- stream.PutHex32(flags);
+ const uint32_t posix_open_flags = File::ConvertOpenOptionsForPOSIXOpen(flags);
+ stream.PutHex32(posix_open_flags);
stream.PutChar(',');
stream.PutHex32(mode);
const char* packet = stream.GetData();
@@ -2165,28 +2493,23 @@ GDBRemoteCommunicationClient::OpenFile (
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- if (response.GetChar() != 'F')
- return UINT64_MAX;
- uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
- return retcode;
+ return ParseHostIOPacketResponse (response, UINT64_MAX, error);
}
return UINT64_MAX;
}
bool
-GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd)
+GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
+ Error &error)
{
lldb_private::StreamString stream;
- stream.PutCString("vFile:close:");
- stream.PutHex64(fd);
+ stream.Printf("vFile:close:%i", (int)fd);
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- if (response.GetChar() != 'F')
- return UINT64_MAX;
- return true;
+ return ParseHostIOPacketResponse (response, -1, error) == 0;
}
return UINT64_MAX;
}
@@ -2197,10 +2520,8 @@ GDBRemoteCommunicationClient::GetFileSiz
{
lldb_private::StreamString stream;
stream.PutCString("vFile:size:");
- std::string path;
- file_spec.GetPath(path);
+ std::string path (file_spec.GetPath());
stream.PutCStringAsRawHex8(path.c_str());
- stream.PutChar(',');
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
@@ -2215,66 +2536,122 @@ GDBRemoteCommunicationClient::GetFileSiz
}
uint32_t
-GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len)
+GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
{
lldb_private::StreamString stream;
- stream.PutCString("vFile:pread:");
- stream.PutHex64(fd);
- stream.PutChar(',');
- stream.PutHex32(len);
- stream.PutChar(',');
- stream.PutHex32(offset);
+ stream.PutCString("vFile:mode:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
if (response.GetChar() != 'F')
- return UINT32_MAX;
+ {
+ error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
+ return 0;
+ }
+ const uint32_t mode = response.GetS32(-1);
+ if (mode == -1)
+ {
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ }
+ }
+ else
+ error.Clear();
+ return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return 0;
uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
if (retcode == UINT32_MAX)
return retcode;
const char next = (response.Peek() ? *response.Peek() : 0);
if (next == ',')
- return UINT32_MAX;
+ return 0;
if (next == ';')
{
response.GetChar(); // skip the semicolon
std::string buffer;
- response.GetEscapedBinaryData(buffer);
- size_t data_to_write = len;
- if (buffer.size() < len)
- data_to_write = buffer.size();
- memcpy(data_ptr, &buffer[0], data_to_write);
+ if (response.GetEscapedBinaryData(buffer))
+ {
+ const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
+ if (data_to_write > 0)
+ memcpy(dst, &buffer[0], data_to_write);
+ return data_to_write;
+ }
}
- return retcode;
}
- return UINT32_MAX;
+ return 0;
}
-uint32_t
-GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len)
+uint64_t
+GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
{
lldb_private::StreamGDBRemote stream;
- stream.PutCString("vFile:pwrite:");
- stream.PutHex64(fd);
- stream.PutChar(',');
- stream.PutHex32(offset);
- stream.PutChar(',');
- stream.PutEscapedBytes(data, len);
+ stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+ stream.PutEscapedBytes(src, src_len);
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
if (response.GetChar() != 'F')
- return UINT32_MAX;
- uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
- return retcode;
+ {
+ error.SetErrorStringWithFormat("write file failed");
+ return 0;
+ }
+ uint64_t bytes_written = response.GetU64(UINT64_MAX);
+ if (bytes_written == UINT64_MAX)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ return 0;
+ }
+ return bytes_written;
}
- return UINT32_MAX;
+ else
+ {
+ error.SetErrorString ("failed to send vFile:pwrite packet");
+ }
+ return 0;
}
// Extension of host I/O packets to get whether a file exists.
@@ -2283,8 +2660,7 @@ GDBRemoteCommunicationClient::GetFileExi
{
lldb_private::StreamString stream;
stream.PutCString("vFile:exists:");
- std::string path;
- file_spec.GetPath(path);
+ std::string path (file_spec.GetPath());
stream.PutCStringAsRawHex8(path.c_str());
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
@@ -2308,8 +2684,7 @@ GDBRemoteCommunicationClient::CalculateM
{
lldb_private::StreamString stream;
stream.PutCString("vFile:MD5:");
- std::string path;
- file_spec.GetPath(path);
+ std::string path (file_spec.GetPath());
stream.PutCStringAsRawHex8(path.c_str());
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Thu Jun 6 19:06:43 2013
@@ -89,7 +89,10 @@ public:
GetLaunchSuccess (std::string &error_str);
uint16_t
- LaunchGDBserverAndGetPort ();
+ LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+
+ bool
+ KillSpawnedProcess (lldb::pid_t pid);
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'A' packet that delivers program
@@ -199,8 +202,8 @@ public:
bool
DeallocateMemory (lldb::addr_t addr);
- bool
- Detach ();
+ lldb_private::Error
+ Detach (bool keep_stopped);
lldb_private::Error
GetMemoryRegionInfo (lldb::addr_t addr,
@@ -217,7 +220,10 @@ public:
const lldb_private::ArchSpec &
GetHostArchitecture ();
-
+
+ const lldb_private::ArchSpec &
+ GetProcessArchitecture ();
+
bool
GetVContSupported (char flavor);
@@ -294,7 +300,7 @@ public:
GetStopReply (StringExtractorGDBRemote &response);
bool
- GetThreadStopInfo (uint32_t tid,
+ GetThreadStopInfo (lldb::tid_t tid,
StringExtractorGDBRemote &response);
bool
@@ -307,7 +313,6 @@ public:
case eWatchpointWrite: return m_supports_z2;
case eWatchpointRead: return m_supports_z3;
case eWatchpointReadWrite: return m_supports_z4;
- default: break;
}
return false;
}
@@ -330,10 +335,10 @@ public:
uint32_t recv_size);
bool
- SetCurrentThread (int tid);
+ SetCurrentThread (uint64_t tid);
bool
- SetCurrentThreadForRun (int tid);
+ SetCurrentThreadForRun (uint64_t tid);
lldb_private::LazyBool
SupportsAllocDeallocMemory () // const
@@ -356,21 +361,33 @@ public:
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode);
+ mode_t mode,
+ lldb_private::Error &error);
virtual bool
- CloseFile (lldb::user_id_t fd);
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
virtual lldb::user_id_t
GetFileSize (const lldb_private::FileSpec& file_spec);
-
- virtual uint32_t
- ReadFile (lldb::user_id_t fd, uint64_t offset,
- void *data_ptr, size_t len);
virtual uint32_t
- WriteFile (lldb::user_id_t fd, uint64_t offset,
- void* data, size_t len);
+ GetFilePermissions(const lldb_private::FileSpec& file_spec,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
virtual uint32_t
MakeDirectory (const std::string &path,
@@ -392,8 +409,15 @@ public:
uint64_t &high,
uint64_t &low);
+ std::string
+ HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
+ StringExtractorGDBRemote &inputStringExtractor);
+
protected:
+ bool
+ GetCurrentProcessInfo ();
+
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteCommunicationClient can see and modify these
//------------------------------------------------------------------
@@ -407,9 +431,11 @@ protected:
lldb_private::LazyBool m_supports_vCont_s;
lldb_private::LazyBool m_supports_vCont_S;
lldb_private::LazyBool m_qHostInfo_is_valid;
+ lldb_private::LazyBool m_qProcessInfo_is_valid;
lldb_private::LazyBool m_supports_alloc_dealloc_memory;
lldb_private::LazyBool m_supports_memory_region_info;
lldb_private::LazyBool m_supports_watchpoint_support_info;
+ lldb_private::LazyBool m_supports_detach_stay_stopped;
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
@@ -441,8 +467,11 @@ protected:
StringExtractorGDBRemote m_async_response;
int m_async_signal; // We were asked to deliver a signal to the inferior process.
bool m_interrupt_sent;
+ std::string m_partial_profile_data;
+ std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
lldb_private::ArchSpec m_host_arch;
+ lldb_private::ArchSpec m_process_arch;
uint32_t m_os_version_major;
uint32_t m_os_version_minor;
uint32_t m_os_version_update;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Thu Jun 6 19:06:43 2013
@@ -21,6 +21,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Host/File.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -41,6 +42,8 @@ GDBRemoteCommunicationServer::GDBRemoteC
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
+ m_spawned_pids (),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_proc_infos (),
m_proc_infos_index (0),
m_lo_port_num (0),
@@ -62,7 +65,6 @@ GDBRemoteCommunicationServer::GDBRemoteC
hi_port_num = ::atoi(hi_port_c_str);
if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
{
- printf("SetPortRange(%u, %u) called\n", lo_port_num, hi_port_num);
SetPortRange(lo_port_num, hi_port_num);
}
}
@@ -80,7 +82,7 @@ GDBRemoteCommunicationServer::~GDBRemote
//{
// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
//
-// LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
// if (log)
// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
//
@@ -145,6 +147,9 @@ GDBRemoteCommunicationServer::GetPacketA
case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
return Handle_qLaunchGDBServer (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+ return Handle_qKillSpawnedProcess (packet);
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
return Handle_qLaunchSuccess (packet);
@@ -204,7 +209,10 @@ GDBRemoteCommunicationServer::GetPacketA
case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
return Handle_vFile_Size (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+ return Handle_vFile_Mode (packet);
+
case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
return Handle_vFile_Exists (packet);
@@ -333,7 +341,7 @@ GDBRemoteCommunicationServer::Handle_qHo
static void
CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
{
- response.Printf ("pid:%llu;ppid:%llu;uid:%i;gid:%i;euid:%i;egid:%i;",
+ response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
proc_info.GetProcessID(),
proc_info.GetParentProcessID(),
proc_info.GetUserID(),
@@ -699,7 +707,7 @@ GDBRemoteCommunicationServer::Handle_qC
{
lldb::pid_t pid = m_process_launch_info.GetProcessID();
StreamString response;
- response.Printf("QC%llx", pid);
+ response.Printf("QC%" PRIx64, pid);
if (m_is_platform)
{
// If we launch a process and this GDB server is acting as a platform,
@@ -719,6 +727,24 @@ GDBRemoteCommunicationServer::Handle_qC
}
bool
+GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
+{
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ return m_spawned_pids.erase(pid) > 0;
+}
+bool
+GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal, // Zero for no signal
+ int status) // Exit value of process if signal is zero
+{
+ GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+ server->DebugserverProcessReaped (pid);
+ return true;
+}
+
+bool
GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
// Spawn a local debugserver as a platform so we can then attach or launch
@@ -730,6 +756,7 @@ GDBRemoteCommunicationServer::Handle_qLa
ConnectionFileDescriptor file_conn;
char connect_url[PATH_MAX];
Error error;
+ std::string hostname;
char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
if (::mktemp (unix_socket_name) == NULL)
{
@@ -737,47 +764,87 @@ GDBRemoteCommunicationServer::Handle_qLa
}
else
{
+ packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
+ }
+ if (port == UINT16_MAX)
+ port = GetAndUpdateNextPort();
+
::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
- AcceptPortFromInferior,
- connect_url,
- &error);
+ lldb::thread_t accept_thread = NULL;
+
+ if (port == 0)
+ {
+ accept_thread = Host::ThreadCreate (unix_socket_name,
+ AcceptPortFromInferior,
+ connect_url,
+ &error);
+ }
if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
{
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
- char host_and_port[256];
- const int host_and_port_len = ::snprintf (host_and_port,
- sizeof(host_and_port),
- "localhost:%u",
- GetAndUpdateNextPort());
- assert (host_and_port_len < sizeof(host_and_port));
- printf("Launching debugserver with: %s...\n", host_and_port);
- error = StartDebugserverProcess (host_and_port,
+ StreamString host_and_port;
+ if (hostname.empty())
+ hostname = "localhost";
+ host_and_port.Printf("%s:%u", hostname.c_str(), port);
+ const char *host_and_port_cstr = host_and_port.GetString().c_str();
+ printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+ error = StartDebugserverProcess (host_and_port_cstr,
unix_socket_name,
debugserver_launch_info);
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(debugserver_pid);
+ }
+ Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
+ }
+
if (error.Success())
{
bool success = false;
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+ if (accept_thread)
{
- if (accept_thread_result)
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
{
- uint16_t port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%llu;port:%u;", debugserver_pid, port);
- assert (response_len < sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
+ if (accept_thread_result)
+ {
+ port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+ }
}
}
+ else
+ {
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+
+ }
::unlink (unix_socket_name);
if (!success)
@@ -790,7 +857,60 @@ GDBRemoteCommunicationServer::Handle_qLa
}
}
}
- return SendErrorResponse (13);
+ return SendErrorResponse (9);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ if (m_is_platform)
+ {
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return SendErrorResponse (10);
+ }
+ kill (pid, SIGTERM);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+ }
+ return SendErrorResponse (10);
}
bool
@@ -814,7 +934,7 @@ GDBRemoteCommunicationServer::Handle_QEn
m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
return SendOKResponse ();
}
- return SendErrorResponse (9);
+ return SendErrorResponse (11);
}
bool
@@ -829,7 +949,7 @@ GDBRemoteCommunicationServer::Handle_QLa
m_process_launch_info.SetArchitecture(arch_spec);
return SendOKResponse();
}
- return SendErrorResponse(9);
+ return SendErrorResponse(12);
}
bool
@@ -867,7 +987,7 @@ GDBRemoteCommunicationServer::Handle_QSe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (10);
+ return SendErrorResponse (13);
}
bool
@@ -884,7 +1004,7 @@ GDBRemoteCommunicationServer::Handle_QSe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (11);
+ return SendErrorResponse (14);
}
bool
@@ -901,7 +1021,7 @@ GDBRemoteCommunicationServer::Handle_QSe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (12);
+ return SendErrorResponse (15);
}
bool
@@ -943,15 +1063,14 @@ GDBRemoteCommunicationServer::Handle_vFi
if (packet.GetChar() != ',')
return false;
mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
- lldb::user_id_t retcode = Host::OpenFile(FileSpec(path.c_str(), false), flags, mode);
+ Error error;
+ int fd = ::open (path.c_str(), flags, mode);
+ const int save_errno = fd == -1 ? errno : 0;
StreamString response;
response.PutChar('F');
- response.PutHex64(retcode);
- if (retcode == UINT64_MAX)
- {
- response.PutChar(',');
- response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
- }
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
SendPacketNoLock(response.GetData(), response.GetSize());
return true;
}
@@ -960,16 +1079,24 @@ bool
GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:close:"));
- lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
- uint32_t retcode = Host::CloseFile(fd);
- StreamString response;
- response.PutChar('F');
- response.PutHex32(retcode);
- if (retcode == UINT32_MAX)
+ int fd = packet.GetS32(-1);
+ Error error;
+ int err = -1;
+ int save_errno = 0;
+ if (fd >= 0)
{
- response.PutChar(',');
- response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ err = close(fd);
+ save_errno = err == -1 ? errno : 0;
}
+ else
+ {
+ save_errno = EINVAL;
+ }
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", err);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
SendPacketNoLock(response.GetData(), response.GetSize());
return true;
}
@@ -979,35 +1106,30 @@ GDBRemoteCommunicationServer::Handle_vFi
{
StreamGDBRemote response;
packet.SetFilePos(::strlen("vFile:pread:"));
- lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
+ int fd = packet.GetS32(-1);
if (packet.GetChar() != ',')
return false;
- uint32_t count = packet.GetHexMaxU32(false, UINT32_MAX);
+ uint64_t count = packet.GetU64(UINT64_MAX);
if (packet.GetChar() != ',')
return false;
- uint32_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
- if (count == UINT32_MAX) // protect yourself against allocating a 4GB buffer
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX)
{
- response.PutChar('F');
- response.PutHex32(UINT32_MAX);
- response.PutChar(',');
- response.PutHex32(UINT32_MAX); // TODO: replace with Host::GetSyswideErrorCode()
+ response.Printf("F-1:%i", EINVAL);
SendPacketNoLock(response.GetData(), response.GetSize());
return true;
}
std::string buffer(count, 0);
- uint32_t retcode = Host::ReadFile(fd, offset, &buffer[0], count);
+ const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
response.PutChar('F');
- response.PutHex32(retcode);
- if (retcode == UINT32_MAX)
- {
- response.PutChar(',');
- response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
- }
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
else
{
response.PutChar(';');
- response.PutEscapedBytes(&buffer[0], retcode);
+ response.PutEscapedBytes(&buffer[0], bytes_read);
}
SendPacketNoLock(response.GetData(), response.GetSize());
return true;
@@ -1017,23 +1139,30 @@ bool
GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:pwrite:"));
- lldb::user_id_t fd = packet.GetHexMaxU64(false, UINT64_MAX);
+
+ StreamGDBRemote response;
+ response.PutChar('F');
+
+ int fd = packet.GetU32(UINT32_MAX);
if (packet.GetChar() != ',')
return false;
- uint32_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
+ off_t offset = packet.GetU64(UINT32_MAX);
if (packet.GetChar() != ',')
return false;
std::string buffer;
- packet.GetEscapedBinaryData(buffer);
- uint32_t retcode = Host::WriteFile(fd, offset, &buffer[0], buffer.size());
- StreamString response;
- response.PutChar('F');
- response.PutHex32(retcode);
- if (retcode == UINT32_MAX)
+ if (packet.GetEscapedBinaryData(buffer))
{
- response.PutChar(',');
- response.PutHex32(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
}
+ else
+ {
+ response.Printf ("-1,%i", EINVAL);
+ }
+
SendPacketNoLock(response.GetData(), response.GetSize());
return true;
}
@@ -1043,10 +1172,8 @@ GDBRemoteCommunicationServer::Handle_vFi
{
packet.SetFilePos(::strlen("vFile:size:"));
std::string path;
- packet.GetHexByteStringTerminatedBy(path,',');
- if (path.size() == 0)
- return false;
- if (packet.GetChar() != ',')
+ packet.GetHexByteString(path);
+ if (path.empty())
return false;
lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
StreamString response;
@@ -1062,12 +1189,30 @@ GDBRemoteCommunicationServer::Handle_vFi
}
bool
+GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:mode:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ Error error;
+ const uint32_t mode = File::GetPermissions(path.c_str(), error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:exists:"));
std::string path;
packet.GetHexByteString(path);
- if (path.size() == 0)
+ if (path.empty())
return false;
bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
StreamString response;
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h Thu Jun 6 19:06:43 2013
@@ -13,8 +13,10 @@
// C Includes
// C++ Includes
#include <vector>
+#include <set>
// Other libraries and framework includes
// Project includes
+#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "GDBRemoteCommunication.h"
@@ -83,6 +85,8 @@ protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
+ std::set<lldb::pid_t> m_spawned_pids;
+ lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
uint16_t m_lo_port_num;
@@ -90,6 +94,7 @@ protected:
//PortToPIDMap m_port_to_pid_map;
uint16_t m_next_port;
bool m_use_port_range;
+
size_t
SendUnimplementedResponse (const char *packet);
@@ -111,6 +116,9 @@ protected:
bool
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
bool
Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
@@ -174,6 +182,9 @@ protected:
bool
Handle_vFile_Size (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Mode (StringExtractorGDBRemote &packet);
bool
Handle_vFile_Exists (StringExtractorGDBRemote &packet);
@@ -188,6 +199,16 @@ protected:
Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
private:
+ bool
+ DebugserverProcessReaped (lldb::pid_t pid);
+
+ static bool
+ ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status);
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Thu Jun 6 19:06:43 2013
@@ -85,7 +85,7 @@ GDBRemoteRegisterContext::GetRegisterCou
}
const RegisterInfo *
-GDBRemoteRegisterContext::GetRegisterInfoAtIndex (uint32_t reg)
+GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg)
{
return m_reg_info.GetRegisterInfoAtIndex (reg);
}
@@ -99,7 +99,7 @@ GDBRemoteRegisterContext::GetRegisterSet
const RegisterSet *
-GDBRemoteRegisterContext::GetRegisterSet (uint32_t reg_set)
+GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set)
{
return m_reg_info.GetRegisterSet (reg_set);
}
@@ -134,13 +134,13 @@ GDBRemoteRegisterContext::PrivateSetRegi
bool success = bytes_copied == reg_byte_size;
if (success)
{
- m_reg_valid[reg] = true;
+ SetRegisterIsValid(reg, true);
}
else if (bytes_copied > 0)
{
// Only set register is valid to false if we copied some bytes, else
// leave it as it was.
- m_reg_valid[reg] = false;
+ SetRegisterIsValid(reg, false);
}
return success;
}
@@ -155,7 +155,7 @@ GDBRemoteRegisterContext::GetPrimordialR
int packet_len = 0;
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (gdb_comm.GetThreadSuffixSupported())
- packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4llx;", reg, m_thread.GetID());
+ packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, m_thread.GetProtocolID());
else
packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
assert (packet_len < (sizeof(packet) - 1));
@@ -180,14 +180,14 @@ GDBRemoteRegisterContext::ReadRegisterBy
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- if (!m_reg_valid[reg])
+ if (!GetRegisterIsValid(reg))
{
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read register."))
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+ if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
{
char packet[64];
StringExtractorGDBRemote response;
@@ -196,7 +196,7 @@ GDBRemoteRegisterContext::ReadRegisterBy
{
// Get all registers in one packet
if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4llx;", m_thread.GetID());
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
else
packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < (sizeof(packet) - 1));
@@ -207,51 +207,54 @@ GDBRemoteRegisterContext::ReadRegisterBy
SetAllRegisterValid (true);
}
}
- else if (!reg_info->value_regs)
- {
- // Get each register individually
- GetPrimordialRegister(reg_info, gdb_comm);
- }
- else
+ else if (reg_info->value_regs)
{
// Process this composite register request by delegating to the constituent
// primordial registers.
-
+
// Index of the primordial register.
- uint32_t prim_reg_idx;
bool success = true;
- for (uint32_t idx = 0;
- (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
- ++idx)
+ for (uint32_t idx = 0; success; ++idx)
{
+ const uint32_t prim_reg = reg_info->value_regs[idx];
+ if (prim_reg == LLDB_INVALID_REGNUM)
+ break;
// We have a valid primordial regsiter as our constituent.
// Grab the corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
- if (!GetPrimordialRegister(prim_reg_info, gdb_comm))
- {
+ const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+ if (prim_reg_info == NULL)
success = false;
- // Some failure occurred. Let's break out of the for loop.
- break;
+ else
+ {
+ // Read the containing register if it hasn't already been read
+ if (!GetRegisterIsValid(prim_reg))
+ success = GetPrimordialRegister(prim_reg_info, gdb_comm);
}
}
+
if (success)
{
// If we reach this point, all primordial register requests have succeeded.
// Validate this composite register.
- m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = true;
+ SetRegisterIsValid (reg_info, true);
}
}
+ else
+ {
+ // Get each register individually
+ GetPrimordialRegister(reg_info, gdb_comm);
+ }
}
}
else
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
#if LLDB_CONFIGURATION_DEBUG
StreamString strm;
gdb_comm.DumpHistory(strm);
Host::SetCrashDescription (strm.GetData());
assert (!"Didn't get sequence mutex for read register.");
#else
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
if (log)
{
if (log->GetVerbose())
@@ -269,7 +272,7 @@ GDBRemoteRegisterContext::ReadRegisterBy
}
// Make sure we got a valid register value after reading it
- if (!m_reg_valid[reg])
+ if (!GetRegisterIsValid(reg))
return false;
}
@@ -311,10 +314,10 @@ GDBRemoteRegisterContext::SetPrimordialR
lldb::endian::InlHostByteOrder());
if (gdb_comm.GetThreadSuffixSupported())
- packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+ packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
// Invalidate just this register
- m_reg_valid[reg] = false;
+ SetRegisterIsValid(reg, false);
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
@@ -337,7 +340,7 @@ GDBRemoteRegisterContext::SyncThreadStat
StreamString packet;
StringExtractorGDBRemote response;
- packet.Printf ("QSyncThreadState:%4.4llx;", m_thread.GetID());
+ packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID());
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
@@ -383,10 +386,11 @@ GDBRemoteRegisterContext::WriteRegisterB
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+ if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
{
StreamString packet;
StringExtractorGDBRemote response;
+
if (m_read_all_at_once)
{
// Set all registers in one packet
@@ -397,7 +401,7 @@ GDBRemoteRegisterContext::WriteRegisterB
lldb::endian::InlHostByteOrder());
if (thread_suffix_supported)
- packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+ packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
// Invalidate all register values
InvalidateIfNeeded (true);
@@ -414,59 +418,57 @@ GDBRemoteRegisterContext::WriteRegisterB
}
}
}
- else if (!reg_info->value_regs)
- {
- // Set each register individually
- return SetPrimordialRegister(reg_info, gdb_comm);
- }
else
{
- // Process this composite register request by delegating to the constituent
- // primordial registers.
-
- // Invalidate this composite register first.
- m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = false;
-
- // Index of the primordial register.
- uint32_t prim_reg_idx;
- // For loop index.
- uint32_t idx;
+ bool success = true;
- // Invalidate the invalidate_regs, if present.
- if (reg_info->invalidate_regs)
+ if (reg_info->value_regs)
{
- for (idx = 0;
- (prim_reg_idx = reg_info->invalidate_regs[idx]) != LLDB_INVALID_REGNUM;
- ++idx)
+ // This register is part of another register. In this case we read the actual
+ // register data for any "value_regs", and once all that data is read, we will
+ // have enough data in our register context bytes for the value of this register
+
+ // Invalidate this composite register first.
+
+ for (uint32_t idx = 0; success; ++idx)
{
- // Grab the invalidate register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
- m_reg_valid[prim_reg_info->kinds[eRegisterKindLLDB]] = false;
+ const uint32_t reg = reg_info->value_regs[idx];
+ if (reg == LLDB_INVALID_REGNUM)
+ break;
+ // We have a valid primordial regsiter as our constituent.
+ // Grab the corresponding register info.
+ const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+ if (value_reg_info == NULL)
+ success = false;
+ else
+ success = SetPrimordialRegister(value_reg_info, gdb_comm);
}
}
+ else
+ {
+ // This is an actual register, write it
+ success = SetPrimordialRegister(reg_info, gdb_comm);
+ }
- bool success = true;
- for (idx = 0;
- (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
- ++idx)
+ // Check if writing this register will invalidate any other register values?
+ // If so, invalidate them
+ if (reg_info->invalidate_regs)
{
- // We have a valid primordial regsiter as our constituent.
- // Grab the corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
- if (!SetPrimordialRegister(prim_reg_info, gdb_comm))
+ for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
+ reg != LLDB_INVALID_REGNUM;
+ reg = reg_info->invalidate_regs[++idx])
{
- success = false;
- // Some failure occurred. Let's break out of the for loop.
- break;
+ SetRegisterIsValid(reg, false);
}
}
+
return success;
}
}
}
else
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
if (log)
{
if (log->GetVerbose())
@@ -506,11 +508,11 @@ GDBRemoteRegisterContext::ReadAllRegiste
char packet[32];
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+ if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
{
int packet_len = 0;
if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4llx", m_thread.GetID());
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
else
packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < (sizeof(packet) - 1));
@@ -527,7 +529,7 @@ GDBRemoteRegisterContext::ReadAllRegiste
if (thread_suffix_supported)
{
char thread_id_cstr[64];
- ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4llx;", m_thread.GetID());
+ ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
response_str.append (thread_id_cstr);
}
data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
@@ -538,7 +540,7 @@ GDBRemoteRegisterContext::ReadAllRegiste
}
else
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
if (log)
{
if (log->GetVerbose())
@@ -577,7 +579,7 @@ GDBRemoteRegisterContext::WriteAllRegist
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetID()))
+ if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
{
// The data_sp contains the entire G response packet including the
// G, and if the thread suffix is supported, it has the thread suffix
@@ -633,7 +635,7 @@ GDBRemoteRegisterContext::WriteAllRegist
const char *restore_src = (const char *)restore_data.PeekData(reg_byte_offset, reg_byte_size);
if (restore_src)
{
- if (m_reg_valid[reg])
+ if (GetRegisterIsValid(reg))
{
const char *current_src = (const char *)m_reg_data.PeekData(reg_byte_offset, reg_byte_size);
if (current_src)
@@ -650,9 +652,9 @@ GDBRemoteRegisterContext::WriteAllRegist
lldb::endian::InlHostByteOrder());
if (thread_suffix_supported)
- packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+ packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
- m_reg_valid[reg] = false;
+ SetRegisterIsValid(reg, false);
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
@@ -671,7 +673,7 @@ GDBRemoteRegisterContext::WriteAllRegist
}
else
{
- LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
if (log)
{
if (log->GetVerbose())
@@ -855,7 +857,7 @@ GDBRemoteDynamicRegisterInfo::HardcodeAR
static ConstString gpr_reg_set ("General Purpose Registers");
static ConstString sfp_reg_set ("Software Floating Point Registers");
static ConstString vfp_reg_set ("Floating Point Registers");
- uint32_t i;
+ size_t i;
if (from_scratch)
{
// Calculate the offsets of the registers
@@ -903,121 +905,67 @@ GDBRemoteDynamicRegisterInfo::HardcodeAR
else
{
// Add composite registers to our primordial registers, then.
- const uint32_t num_composites = llvm::array_lengthof(g_composites);
- const uint32_t num_primordials = GetNumRegisters();
- RegisterInfo *g_comp_register_infos = g_register_infos + (num_registers - num_composites);
- for (i=0; i<num_composites; ++i)
+ const size_t num_composites = llvm::array_lengthof(g_composites);
+ const size_t num_dynamic_regs = GetNumRegisters();
+ const size_t num_common_regs = num_registers - num_composites;
+ RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
+
+ // First we need to validate that all registers that we already have match the non composite regs.
+ // If so, then we can add the registers, else we need to bail
+ bool match = true;
+ if (num_dynamic_regs == num_common_regs)
{
- ConstString name;
- ConstString alt_name;
- const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
- const char *reg_name = g_register_infos[first_primordial_reg].name;
- if (reg_name && reg_name[0])
- {
- for (uint32_t j = 0; j < num_primordials; ++j)
- {
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
- // Find a matching primordial register info entry.
- if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
- {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite register entry.
- g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
- name.SetCString(g_comp_register_infos[i].name);
- AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
+ for (i=0; match && i<num_dynamic_regs; ++i)
+ {
+ // Make sure all register names match
+ if (m_regs[i].name && g_register_infos[i].name)
+ {
+ if (strcmp(m_regs[i].name, g_register_infos[i].name))
+ {
+ match = false;
+ break;
}
}
+
+ // Make sure all register byte sizes match
+ if (m_regs[i].byte_size != g_register_infos[i].byte_size)
+ {
+ match = false;
+ break;
+ }
}
}
- }
-}
-
-void
-GDBRemoteDynamicRegisterInfo::Addx86_64ConvenienceRegisters()
-{
- // For eax, ebx, ecx, edx, esi, edi, ebp, esp register mapping.
- static const char* g_mapped_names[] = {
- "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp",
- "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp",
- "rax", "rbx", "rcx", "rdx",
- "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp"
- };
-
- // These value regs are to be populated with the corresponding primordial register index.
- // For example,
- static uint32_t g_eax_regs[] = { 0, LLDB_INVALID_REGNUM }; // 0 is to be replaced with rax's index.
- static uint32_t g_ebx_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_ecx_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_edx_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_edi_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_esi_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_ebp_regs[] = { 0, LLDB_INVALID_REGNUM };
- static uint32_t g_esp_regs[] = { 0, LLDB_INVALID_REGNUM };
-
- static RegisterInfo g_conv_register_infos[] =
- {
-// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
-// ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
- { "eax" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs, NULL},
- { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs, NULL},
- { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs, NULL},
- { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs, NULL},
- { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs, NULL},
- { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs, NULL},
- { "ebp" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs, NULL},
- { "esp" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs, NULL},
- { "ax" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs, NULL},
- { "bx" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs, NULL},
- { "cx" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs, NULL},
- { "dx" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs, NULL},
- { "di" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs, NULL},
- { "si" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs, NULL},
- { "bp" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs, NULL},
- { "sp" , NULL, 2, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs, NULL},
- { "ah" , NULL, 1, 1, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs, NULL},
- { "bh" , NULL, 1, 1, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs, NULL},
- { "ch" , NULL, 1, 1, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs, NULL},
- { "dh" , NULL, 1, 1, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs, NULL},
- { "al" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_eax_regs, NULL},
- { "bl" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebx_regs, NULL},
- { "cl" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ecx_regs, NULL},
- { "dl" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edx_regs, NULL},
- { "dil" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_edi_regs, NULL},
- { "sil" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esi_regs, NULL},
- { "bpl" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_ebp_regs, NULL},
- { "spl" , NULL, 1, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }, g_esp_regs, NULL}
- };
-
- static const uint32_t num_conv_regs = llvm::array_lengthof(g_mapped_names);
- static ConstString gpr_reg_set ("General Purpose Registers");
-
- // Add convenience registers to our primordial registers.
- const uint32_t num_primordials = GetNumRegisters();
- uint32_t reg_kind = num_primordials;
- for (uint32_t i=0; i<num_conv_regs; ++i)
- {
- ConstString name;
- ConstString alt_name;
- const char *prim_reg_name = g_mapped_names[i];
- if (prim_reg_name && prim_reg_name[0])
- {
- for (uint32_t j = 0; j < num_primordials; ++j)
- {
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
- // Find a matching primordial register info entry.
- if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, prim_reg_name) == 0)
- {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite register entry.
- g_conv_register_infos[i].byte_offset = reg_info->byte_offset + g_conv_register_infos[i].byte_offset;
- // Update the value_regs and the kinds fields in order to delegate to the primordial register.
- g_conv_register_infos[i].value_regs[0] = j;
- g_conv_register_infos[i].kinds[eRegisterKindLLDB] = ++reg_kind;
- name.SetCString(g_conv_register_infos[i].name);
- AddRegister(g_conv_register_infos[i], name, alt_name, gpr_reg_set);
+ else
+ {
+ // Wrong number of registers.
+ match = false;
+ }
+ // If "match" is true, then we can add extra registers.
+ if (match)
+ {
+ for (i=0; i<num_composites; ++i)
+ {
+ ConstString name;
+ ConstString alt_name;
+ const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
+ const char *reg_name = g_register_infos[first_primordial_reg].name;
+ if (reg_name && reg_name[0])
+ {
+ for (uint32_t j = 0; j < num_dynamic_regs; ++j)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
+ // Find a matching primordial register info entry.
+ if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
+ {
+ // The name matches the existing primordial entry.
+ // Find and assign the offset, and then add this composite register entry.
+ g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
+ name.SetCString(g_comp_register_infos[i].name);
+ AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
+ }
+ }
}
}
}
}
}
-
Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h Thu Jun 6 19:06:43 2013
@@ -46,19 +46,34 @@ public:
}
void
- AddRegister (lldb_private::RegisterInfo ®_info,
+ AddRegister (lldb_private::RegisterInfo reg_info,
lldb_private::ConstString ®_name,
lldb_private::ConstString ®_alt_name,
lldb_private::ConstString &set_name)
{
- const uint32_t reg_num = m_regs.size();
+ const uint32_t reg_num = (uint32_t)m_regs.size();
m_reg_names.push_back (reg_name);
m_reg_alt_names.push_back (reg_alt_name);
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]);
+ m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = m_value_regs_map[reg_num].data();
+ }
+ 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_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
+ }
m_regs.push_back (reg_info);
- uint32_t set = GetRegisterSetIndexByName (set_name, true);
+ uint32_t set = GetRegisterSetIndexByName (set_name);
assert (set < m_sets.size());
assert (set < m_set_reg_nums.size());
assert (set < m_set_names.size());
@@ -114,20 +129,20 @@ public:
}
uint32_t
- GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create)
+ GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
{
name_collection::iterator pos, end = m_set_names.end();
for (pos = m_set_names.begin(); pos != end; ++pos)
{
if (*pos == set_name)
- return std::distance (m_set_names.begin(), pos);
+ return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
}
m_set_names.push_back(set_name);
m_set_reg_nums.resize(m_set_reg_nums.size()+1);
lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
m_sets.push_back (new_set);
- return m_sets.size() - 1;
+ return static_cast<uint32_t>(m_sets.size() - 1);
}
uint32_t
@@ -137,7 +152,7 @@ public:
for (pos = m_regs.begin(); pos != end; ++pos)
{
if (pos->kinds[kind] == num)
- return std::distance (m_regs.begin(), pos);
+ return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
}
return LLDB_INVALID_REGNUM;
@@ -156,9 +171,6 @@ public:
void
HardcodeARMRegisters(bool from_scratch);
- void
- Addx86_64ConvenienceRegisters();
-
protected:
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteRegisterContext can see and modify these
@@ -168,6 +180,7 @@ 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;
reg_collection m_regs;
set_collection m_sets;
@@ -175,6 +188,8 @@ protected:
name_collection m_reg_names;
name_collection m_reg_alt_names;
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
};
@@ -202,13 +217,13 @@ public:
GetRegisterCount ();
virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t reg);
+ GetRegisterInfoAtIndex (size_t reg);
virtual size_t
GetRegisterSetCount ();
virtual const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t reg_set);
+ GetRegisterSet (size_t reg_set);
virtual bool
ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
@@ -243,6 +258,34 @@ protected:
void
SetAllRegisterValid (bool b);
+ bool
+ GetRegisterIsValid (uint32_t reg) const
+ {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+ assert (reg < m_reg_valid.size());
+#endif
+ if (reg < m_reg_valid.size())
+ return m_reg_valid[reg];
+ return false;
+ }
+
+ void
+ SetRegisterIsValid (const lldb_private::RegisterInfo *reg_info, bool valid)
+ {
+ if (reg_info)
+ return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid);
+ }
+
+ void
+ SetRegisterIsValid (uint32_t reg, bool valid)
+ {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+ assert (reg < m_reg_valid.size());
+#endif
+ if (reg < m_reg_valid.size())
+ m_reg_valid[reg] = valid;
+ }
+
void
SyncThreadState(lldb_private::Process *process); // Assumes the sequence mutex has already been acquired.
More information about the llvm-branch-commits
mailing list