diff options
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionDeclMap.h | 24 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangUserExpression.h | 26 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanCallFunction.h | 11 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 38 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 24 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanCallFunction.cpp | 7 |
6 files changed, 110 insertions, 20 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index c53157a121b..d3e641aee57 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -425,6 +425,12 @@ public: /// A ClangExpressionVariable containing the result of the /// expression, for potential re-use. /// + /// @param[in] stack_frame_top, stack_frame_bottom + /// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame + /// in which the expression ran. A result whose address falls + /// inside this stack frame is dematerialized as a value + /// requiring rematerialization. + /// /// @param[in] error /// An Error to populate with any messages related to /// dematerializing the struct. @@ -435,6 +441,8 @@ public: bool Dematerialize (ExecutionContext &exe_ctx, lldb::ClangExpressionVariableSP &result_sp, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, Error &error); //------------------------------------------------------------------ @@ -817,6 +825,12 @@ private: /// @param[in] exe_ctx /// The execution context to use. /// + /// @param[in] stack_frame_top, stack_frame_bottom + /// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame + /// in which the expression ran. A result whose address falls + /// inside this stack frame is dematerialized as a value + /// requiring rematerialization. + /// /// @param[out] result /// If the struct is being dematerialized, a pointer into which the /// location of the result persistent variable is placed. If not, @@ -832,6 +846,8 @@ private: bool DoMaterialize (bool dematerialize, ExecutionContext &exe_ctx, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, lldb::ClangExpressionVariableSP *result_sp_ptr, Error &err); @@ -858,6 +874,12 @@ private: /// @param[in] addr /// The address at which to materialize the variable. /// + /// @param[in] stack_frame_top, stack_frame_bottom + /// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame + /// in which the expression ran. A result whose address falls + /// inside this stack frame is dematerialized as a value + /// requiring rematerialization. + /// /// @param[in] err /// An Error to populate with any messages related to /// (de)materializing the persistent variable. @@ -870,6 +892,8 @@ private: ExecutionContext &exe_ctx, lldb::ClangExpressionVariableSP &var_sp, lldb::addr_t addr, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, Error &err); //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h index e1e320e8169..174a78d4a0d 100644 --- a/lldb/include/lldb/Expression/ClangUserExpression.h +++ b/lldb/include/lldb/Expression/ClangUserExpression.h @@ -134,10 +134,34 @@ public: GetThreadPlanToExecuteJITExpression (Stream &error_stream, ExecutionContext &exe_ctx); + //------------------------------------------------------------------ + /// Apply the side effects of the function to program state. + /// + /// @param[in] error_stream + /// A stream to print errors to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of variables, etc.) + /// + /// @param[in] result + /// A pointer to direct at the persistent variable in which the + /// expression's result is stored. + /// + /// @param[in] function_stack_pointer + /// A pointer to the base of the function's stack frame. This + /// is used to determine whether the expession result resides in + /// memory that will still be valid, or whether it needs to be + /// treated as homeless for the purpose of future expressions. + /// + /// @return + /// A Process::Execution results value. + //------------------------------------------------------------------ bool FinalizeJITExecution (Stream &error_stream, ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP &result); + lldb::ClangExpressionVariableSP &result, + lldb::addr_t function_stack_pointer = LLDB_INVALID_ADDRESS); //------------------------------------------------------------------ /// Return the string that the parser should parse. Must be a full diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index cb081aad6f3..8ce3fa8e4ab 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -70,6 +70,16 @@ public: return true; } + // Return the stack pointer that the function received + // on entry. Any stack address below this should be + // considered invalid after the function has been + // cleaned up. + lldb::addr_t + GetFunctionStackPointer() + { + return m_function_sp; + } + // Classes that derive from ClangFunction, and implement // their own WillPop methods should call this so that the // thread state gets restored if the plan gets discarded. @@ -97,6 +107,7 @@ private: Address m_function_addr; Address m_start_addr; lldb::addr_t m_arg_addr; + lldb::addr_t m_function_sp; ValueList *m_args; Process &m_process; Thread &m_thread; diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 3540a4d0783..6c7b2a87dff 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -588,7 +588,12 @@ ClangExpressionDeclMap::Materialize m_material_vars->m_process = exe_ctx.process; - bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err); + bool result = DoMaterialize(false /* dematerialize */, + exe_ctx, + LLDB_INVALID_ADDRESS /* top of stack frame */, + LLDB_INVALID_ADDRESS /* bottom of stack frame */, + NULL, /* result SP */ + err); if (result) struct_address = m_material_vars->m_materialized_location; @@ -717,10 +722,12 @@ ClangExpressionDeclMap::Dematerialize ( ExecutionContext &exe_ctx, ClangExpressionVariableSP &result_sp, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, Error &err ) { - return DoMaterialize(true, exe_ctx, &result_sp, err); + return DoMaterialize(true, exe_ctx, stack_frame_top, stack_frame_bottom, &result_sp, err); DidDematerialize(); } @@ -825,6 +832,8 @@ ClangExpressionDeclMap::DoMaterialize ( bool dematerialize, ExecutionContext &exe_ctx, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, lldb::ClangExpressionVariableSP *result_sp_ptr, Error &err ) @@ -948,7 +957,9 @@ ClangExpressionDeclMap::DoMaterialize if (!DoMaterializeOnePersistentVariable (dematerialize, exe_ctx, member_sp, - m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset, + m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset, + stack_frame_top, + stack_frame_bottom, err)) return false; } @@ -1027,6 +1038,8 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable ExecutionContext &exe_ctx, ClangExpressionVariableSP &var_sp, lldb::addr_t addr, + lldb::addr_t stack_frame_top, + lldb::addr_t stack_frame_bottom, Error &err ) { @@ -1103,10 +1116,7 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem); // Read the contents of the spare memory area - - if (log) - log->Printf("Read"); - + var_sp->ValueUpdated (); if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size) { @@ -1114,6 +1124,20 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable return false; } + if (stack_frame_top != LLDB_INVALID_ADDRESS && + stack_frame_bottom != LLDB_INVALID_ADDRESS && + mem >= stack_frame_bottom && + mem <= stack_frame_top) + { + // If the variable is resident in the stack frame created by the expression, + // then it cannot be relied upon to stay around. We treat it as needing + // reallocation. + + var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + var_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference; + } + var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry; } diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index f1dd49f64dd..6eafd7be7fe 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -421,7 +421,8 @@ ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream, bool ClangUserExpression::FinalizeJITExecution (Stream &error_stream, ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP &result) + lldb::ClangExpressionVariableSP &result, + lldb::addr_t function_stack_pointer) { Error expr_error; @@ -444,8 +445,11 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, log->Printf(" Structure contents:\n%s", args.GetData()); } } + + lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize(); + - if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error)) + if (!m_expr_decl_map->Dematerialize(exe_ctx, result, function_stack_pointer, function_stack_bottom, expr_error)) { error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error")); return false; @@ -497,6 +501,8 @@ ClangUserExpression::Execute (Stream &error_stream, if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL)) return eExecutionSetupError; + + lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer(); call_plan_sp->SetPrivate(true); @@ -506,12 +512,12 @@ ClangUserExpression::Execute (Stream &error_stream, log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx, - call_plan_sp, - stop_others, - try_all_threads, - discard_on_error, - single_thread_timeout_usec, - error_stream); + call_plan_sp, + stop_others, + try_all_threads, + discard_on_error, + single_thread_timeout_usec, + error_stream); if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); @@ -531,7 +537,7 @@ ClangUserExpression::Execute (Stream &error_stream, return execution_result; } - if (FinalizeJITExecution (error_stream, exe_ctx, result)) + if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer)) return eExecutionCompleted; else return eExecutionSetupError; diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index a5e1c1a0e79..83b8270813c 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -49,7 +49,8 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, m_args (NULL), m_process (thread.GetProcess()), m_thread (thread), - m_takedown_done (false) + m_takedown_done (false), + m_function_sp(NULL) { SetOkayToDiscard (discard_on_error); @@ -64,7 +65,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, SetBreakpoints(); - lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); + m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); ModuleSP executableModuleSP (target.GetExecutableModule()); @@ -110,7 +111,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); if (!abi->PrepareTrivialCall(thread, - spBelowRedZone, + m_function_sp, FunctionLoadAddr, StartLoadAddr, m_arg_addr, |