[Lldb-commits] [lldb] r136928 - in /lldb/trunk: include/lldb/Expression/IRForTarget.h source/Expression/ASTResultSynthesizer.cpp source/Expression/IRForTarget.cpp
Sean Callanan
scallanan at apple.com
Thu Aug 4 14:37:47 PDT 2011
Author: spyffe
Date: Thu Aug 4 16:37:47 2011
New Revision: 136928
URL: http://llvm.org/viewvc/llvm-project?rev=136928&view=rev
Log:
Fixed a problem that caused LLDB to fail to execute
expressions that used function pointers. The problem
was that IRForTarget previously only scanned the IR
for the expression for call instructions; if a function
was used in another context, it was ignored.
Now LLDB scans the Module for functions that are only
declared (not also defined -- so these are externals);
it then constructs function pointers for these
functions and substitutes them wherever the function
is used.
Also made some changes so that "expr main" works just
as well as "expr &main"; they end up being the same
code, but LLDB was generating the result variable in
different ways.
Modified:
lldb/trunk/include/lldb/Expression/IRForTarget.h
lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
lldb/trunk/source/Expression/IRForTarget.cpp
Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Thu Aug 4 16:37:47 2011
@@ -149,11 +149,73 @@
FixFunctionLinkage (llvm::Function &llvm_function);
//------------------------------------------------------------------
+ /// A module-level pass to replace all function pointers with their
+ /// integer equivalents.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_module
+ /// The module currently being processed.
+ ///
+ /// @param[in] llvm_function
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ HasSideEffects (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
/// A function-level pass to check whether the function has side
/// effects.
//------------------------------------------------------------------
//------------------------------------------------------------------
+ /// Get the address of a fuction, and a location to put the complete
+ /// Value of the function if one is available.
+ ///
+ /// @param[in] function
+ /// The function to find the location of.
+ ///
+ /// @param[out] ptr
+ /// The location of the function in the target.
+ ///
+ /// @param[out] name
+ /// The resolved name of the function (matters for intrinsics).
+ ///
+ /// @param[out] value_ptr
+ /// A variable to put the function's completed Value* in, or NULL
+ /// if the Value* shouldn't be stored anywhere.
+ ///
+ /// @return
+ /// The pointer.
+ //------------------------------------------------------------------
+ bool
+ GetFunctionAddress (llvm::Function *function,
+ uint64_t &ptr,
+ lldb_private::ConstString &name,
+ llvm::Constant **&value_ptr);
+
+ //------------------------------------------------------------------
+ /// Build a function pointer given a type and a raw pointer.
+ ///
+ /// @param[in] type
+ /// The type of the function pointer to be built.
+ ///
+ /// @param[in] ptr
+ /// The value of the pointer.
+ ///
+ /// @return
+ /// The pointer.
+ //------------------------------------------------------------------
+ llvm::Constant *
+ BuildFunctionPointer (llvm::Type *type,
+ uint64_t ptr);
+
+ //------------------------------------------------------------------
/// The top-level pass implementation
///
/// @param[in] llvm_function
@@ -164,7 +226,8 @@
/// be determined); false otherwise.
//------------------------------------------------------------------
bool
- HasSideEffects (llvm::Function &llvm_function);
+ ResolveFunctionPointers (llvm::Module &llvm_module,
+ llvm::Function &llvm_function);
//------------------------------------------------------------------
/// A function-level pass to take the generated global value
@@ -382,19 +445,7 @@
MaybeHandleCallArguments (llvm::CallInst *call_inst);
//------------------------------------------------------------------
- /// Handle a single external function call
- ///
- /// @param[in] C
- /// The call instruction.
- ///
- /// @return
- /// True on success; false otherwise
- //------------------------------------------------------------------
- bool
- MaybeHandleCall (llvm::CallInst *C);
-
- //------------------------------------------------------------------
- /// Resolve calls to external functions
+ /// Resolve variable references in calls to external functions
///
/// @param[in] basic_block
/// The basic block currently being processed.
Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Aug 4 16:37:47 2011
@@ -311,7 +311,12 @@
if (is_lvalue)
{
- IdentifierInfo &result_ptr_id = Ctx.Idents.get("$__lldb_expr_result_ptr");
+ IdentifierInfo *result_ptr_id;
+
+ if (expr_type->isFunctionType())
+ result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
+ else
+ result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
QualType ptr_qual_type = Ctx.getPointerType(expr_qual_type);
@@ -319,7 +324,7 @@
DC,
SourceLocation(),
SourceLocation(),
- &result_ptr_id,
+ result_ptr_id,
ptr_qual_type,
NULL,
SC_Static,
Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Aug 4 16:37:47 2011
@@ -169,6 +169,146 @@
return false;
}
+bool
+IRForTarget::GetFunctionAddress (llvm::Function *fun,
+ uint64_t &fun_addr,
+ lldb_private::ConstString &name,
+ Constant **&value_ptr)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ fun_addr = LLDB_INVALID_ADDRESS;
+ name.Clear();
+ value_ptr = NULL;
+
+ if (fun->isIntrinsic())
+ {
+ Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
+
+ switch (intrinsic_id)
+ {
+ default:
+ if (log)
+ log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
+
+ return false;
+ case Intrinsic::memcpy:
+ {
+ static lldb_private::ConstString g_memcpy_str ("memcpy");
+ name = g_memcpy_str;
+ }
+ break;
+ }
+
+ if (log && name)
+ log->Printf("Resolved intrinsic name \"%s\"", name.GetCString());
+ }
+ else
+ {
+ name.SetCStringWithLength (fun->getName().data(), fun->getName().size());
+ }
+
+ // Find the address of the function.
+
+ clang::NamedDecl *fun_decl = DeclForGlobal (fun);
+ Value **fun_value_ptr = NULL;
+
+ if (fun_decl)
+ {
+ if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr))
+ {
+ fun_value_ptr = NULL;
+
+ if (!m_decl_map->GetFunctionAddress (name, fun_addr))
+ {
+ if (log)
+ log->Printf("Function \"%s\" had no address", name.GetCString());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Call to a function '%s' that is not present in the target\n", name.GetCString());
+
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (!m_decl_map->GetFunctionAddress (name, fun_addr))
+ {
+ if (log)
+ log->Printf ("Metadataless function \"%s\" had no address", name.GetCString());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
+
+ return false;
+ }
+ }
+
+ if (log)
+ log->Printf("Found \"%s\" at 0x%llx", name.GetCString(), fun_addr);
+
+ return true;
+}
+
+llvm::Constant *
+IRForTarget::BuildFunctionPointer (llvm::Type *type,
+ uint64_t ptr)
+{
+ IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
+ (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
+ PointerType *fun_ptr_ty = PointerType::getUnqual(type);
+ Constant *fun_addr_int = ConstantInt::get(intptr_ty, ptr, false);
+ return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+}
+
+bool
+IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
+ llvm::Function &llvm_function)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ for (llvm::Module::iterator fi = llvm_module.begin();
+ fi != llvm_module.end();
+ ++fi)
+ {
+ Function *fun = fi;
+
+ bool is_decl = fun->isDeclaration();
+
+ if (log)
+ log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getNameStr().c_str());
+
+ if (!is_decl)
+ continue;
+
+ if (fun->hasNUses(0))
+ continue; // ignore
+
+ uint64_t addr = LLDB_INVALID_ADDRESS;
+ lldb_private::ConstString name;
+ Constant **value_ptr = NULL;
+
+ if (!GetFunctionAddress(fun,
+ addr,
+ name,
+ value_ptr))
+ return false; // GetFunctionAddress reports its own errors
+
+ Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
+
+ if (value_ptr)
+ *value_ptr = value;
+
+ fun->replaceAllUsesWith(value);
+ }
+
+ return true;
+}
+
clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val)
{
@@ -1403,193 +1543,6 @@
}
bool
-IRForTarget::MaybeHandleCall (CallInst *llvm_call_inst)
-{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Function *fun = llvm_call_inst->getCalledFunction();
-
- bool is_bitcast = false;
-
- // If the call is to something other than a plain llvm::Function, resolve which
- // Function is meant or give up.
-
- if (fun == NULL)
- {
- Value *val = llvm_call_inst->getCalledValue();
-
- ConstantExpr *const_expr = dyn_cast<ConstantExpr>(val);
- LoadInst *load_inst = dyn_cast<LoadInst>(val);
-
- if (const_expr && const_expr->getOpcode() == Instruction::BitCast)
- {
- fun = dyn_cast<Function>(const_expr->getOperand(0));
-
- if (!fun)
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTaget]: Called entity is a cast of something not a function\n");
-
- return false;
- }
-
- is_bitcast = true;
- }
- else if (const_expr && const_expr->getOpcode() == Instruction::IntToPtr)
- {
- return true; // already resolved
- }
- else if (load_inst)
- {
- return true; // virtual method call
- }
- else
- {
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Called entity is not a function\n");
-
- return false;
- }
- }
-
- // Determine the name of the called function, which is needed to find the address.
- // Intrinsics are special-cased.
-
- lldb_private::ConstString str;
-
- if (fun->isIntrinsic())
- {
- Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
-
- switch (intrinsic_id)
- {
- default:
- if (log)
- log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
-
- if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
-
- return false;
- case Intrinsic::memcpy:
- {
- static lldb_private::ConstString g_memcpy_str ("memcpy");
- str = g_memcpy_str;
- }
- break;
- }
-
- if (log && str)
- log->Printf("Resolved intrinsic name \"%s\"", str.GetCString());
- }
- else
- {
- str.SetCStringWithLength (fun->getName().data(), fun->getName().size());
- }
-
- // Find the address of the function, and the type if possible.
-
- clang::NamedDecl *fun_decl = DeclForGlobal (fun);
- lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS;
- Value **fun_value_ptr = NULL;
-
- if (fun_decl)
- {
- if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr))
- {
- fun_value_ptr = NULL;
-
- if (!m_decl_map->GetFunctionAddress (str, fun_addr))
- {
- if (log)
- log->Printf("Function \"%s\" had no address", str.GetCString());
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Call to a function '%s' that is not present in the target\n", str.GetCString());
-
- return false;
- }
- }
- }
- else
- {
- if (!m_decl_map->GetFunctionAddress (str, fun_addr))
- {
- if (log)
- log->Printf ("Metadataless function \"%s\" had no address", str.GetCString());
-
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", str.GetCString());
-
- return false;
- }
- }
-
- if (log)
- log->Printf("Found \"%s\" at 0x%llx", str.GetCString(), fun_addr);
-
- // Construct the typed pointer to the function.
-
- Value *fun_addr_ptr = NULL;
-
- if (!fun_value_ptr || !*fun_value_ptr)
- {
- IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
- (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
- FunctionType *fun_ty = fun->getFunctionType();
- PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
- Constant *fun_addr_int = ConstantInt::get(intptr_ty, fun_addr, false);
- fun_addr_ptr = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
-
- if (fun_value_ptr)
- *fun_value_ptr = fun_addr_ptr;
- }
-
- if (fun_value_ptr)
- fun_addr_ptr = *fun_value_ptr;
-
- if (is_bitcast)
- {
- Value *val = llvm_call_inst->getCalledValue();
-
- ConstantExpr *const_expr = dyn_cast<ConstantExpr>(val);
-
- Constant *fun_addr_ptr_cst = dyn_cast<Constant>(fun_addr_ptr);
-
- if (!fun_addr_ptr_cst)
- {
- if (m_error_stream)
- m_error_stream->Printf("Error [IRForTarget]: Non-constant source function '%s' has a constant BitCast\n", str.GetCString());
-
- return false;
- }
-
- Constant *new_bit_cast = ConstantExpr::getBitCast(fun_addr_ptr_cst, const_expr->getType());
-
- llvm_call_inst->setCalledFunction(new_bit_cast);
- }
- else
- {
- llvm_call_inst->setCalledFunction(fun_addr_ptr);
- }
-
- ConstantArray *func_name = (ConstantArray*)ConstantArray::get(m_module->getContext(), str.GetCString());
-
- Value *values[1];
- values[0] = func_name;
- ArrayRef<Value*> value_ref(values, 1);
-
- MDNode *func_metadata = MDNode::get(m_module->getContext(), value_ref);
-
- llvm_call_inst->setMetadata("lldb.call.realName", func_metadata);
-
- if (log)
- log->Printf("Set metadata for %p [%d, \"%s\"]", llvm_call_inst, func_name->isString(), func_name->getAsString().c_str());
-
- return true;
-}
-
-bool
IRForTarget::ResolveCalls(BasicBlock &basic_block)
{
/////////////////////////////////////////////////////////////////////////
@@ -1606,10 +1559,6 @@
CallInst *call = dyn_cast<CallInst>(&inst);
- // MaybeHandleCall handles error reporting; we are silent here
- if (call && !MaybeHandleCall(call))
- return false;
-
// MaybeHandleCallArguments handles error reporting; we are silent here
if (call && !MaybeHandleCallArguments(call))
return false;
@@ -2385,6 +2334,20 @@
return false;
}
+ ///////////////////////////////
+ // Resolve function pointers
+ //
+
+ if (!ResolveFunctionPointers(llvm_module, *function))
+ {
+ if (log)
+ log->Printf("ResolveFunctionPointers() failed");
+
+ // ResolveFunctionPointers() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
//////////////////////////////////
// Run basic-block level passes
//
More information about the lldb-commits
mailing list