1//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "ClangFunctionCaller.h" 11 12#include "ASTStructExtractor.h" 13#include "ClangExpressionParser.h" 14 15// C Includes 16// C++ Includes 17// Other libraries and framework includes 18#include "clang/AST/ASTContext.h" 19#include "clang/AST/RecordLayout.h" 20#include "clang/CodeGen/CodeGenAction.h" 21#include "clang/CodeGen/ModuleBuilder.h" 22#include "clang/Frontend/CompilerInstance.h" 23#include "llvm/ADT/StringRef.h" 24#include "llvm/ADT/Triple.h" 25#include "llvm/ExecutionEngine/ExecutionEngine.h" 26#include "llvm/IR/Module.h" 27 28// Project includes 29#include "lldb/Core/DataExtractor.h" 30#include "lldb/Core/Log.h" 31#include "lldb/Core/Module.h" 32#include "lldb/Core/State.h" 33#include "lldb/Core/ValueObject.h" 34#include "lldb/Core/ValueObjectList.h" 35#include "lldb/Expression/IRExecutionUnit.h" 36#include "lldb/Interpreter/CommandReturnObject.h" 37#include "lldb/Symbol/ClangASTContext.h" 38#include "lldb/Symbol/Function.h" 39#include "lldb/Symbol/Type.h" 40#include "lldb/Target/ExecutionContext.h" 41#include "lldb/Target/Process.h" 42#include "lldb/Target/RegisterContext.h" 43#include "lldb/Target/Target.h" 44#include "lldb/Target/Thread.h" 45#include "lldb/Target/ThreadPlan.h" 46#include "lldb/Target/ThreadPlanCallFunction.h" 47 48using namespace lldb_private; 49 50//---------------------------------------------------------------------- 51// ClangFunctionCaller constructor 52//---------------------------------------------------------------------- 53ClangFunctionCaller::ClangFunctionCaller 54( 55 ExecutionContextScope &exe_scope, 56 const CompilerType &return_type, 57 const Address& functionAddress, 58 const ValueList &arg_value_list, 59 const char *name 60) : 61 FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), 62 m_type_system_helper (*this) 63{ 64 m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); 65 // Can't make a ClangFunctionCaller without a process. 66 assert (m_jit_process_wp.lock()); 67} 68 69//---------------------------------------------------------------------- 70// Destructor 71//---------------------------------------------------------------------- 72ClangFunctionCaller::~ClangFunctionCaller() 73{ 74} 75 76unsigned 77ClangFunctionCaller::CompileFunction (Stream &errors) 78{ 79 if (m_compiled) 80 return 0; 81 82 // FIXME: How does clang tell us there's no return value? We need to handle that case. 83 unsigned num_errors = 0; 84 85 std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); 86 87 // Cons up the function we're going to wrap our call in, then compile it... 88 // We declare the function "extern "C"" because the compiler might be in C++ 89 // mode which would mangle the name and then we couldn't find it again... 90 m_wrapper_function_text.clear(); 91 m_wrapper_function_text.append ("extern \"C\" void "); 92 m_wrapper_function_text.append (m_wrapper_function_name); 93 m_wrapper_function_text.append (" (void *input)\n{\n struct "); 94 m_wrapper_function_text.append (m_wrapper_struct_name); 95 m_wrapper_function_text.append (" \n {\n"); 96 m_wrapper_function_text.append (" "); 97 m_wrapper_function_text.append (return_type_str); 98 m_wrapper_function_text.append (" (*fn_ptr) ("); 99 100 // Get the number of arguments. If we have a function type and it is prototyped, 101 // trust that, otherwise use the values we were given. 102 103 // FIXME: This will need to be extended to handle Variadic functions. We'll need 104 // to pull the defined arguments out of the function, then add the types from the 105 // arguments list for the variable arguments. 106 107 uint32_t num_args = UINT32_MAX; 108 bool trust_function = false; 109 // GetArgumentCount returns -1 for an unprototyped function. 110 CompilerType function_clang_type; 111 if (m_function_ptr) 112 { 113 function_clang_type = m_function_ptr->GetCompilerType(); 114 if (function_clang_type) 115 { 116 int num_func_args = function_clang_type.GetFunctionArgumentCount(); 117 if (num_func_args >= 0) 118 { 119 trust_function = true; 120 num_args = num_func_args; 121 } 122 } 123 } 124 125 if (num_args == UINT32_MAX) 126 num_args = m_arg_values.GetSize(); 127 128 std::string args_buffer; // This one stores the definition of all the args in "struct caller". 129 std::string args_list_buffer; // This one stores the argument list called from the structure. 130 for (size_t i = 0; i < num_args; i++) 131 { 132 std::string type_name; 133 134 if (trust_function) 135 { 136 type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); 137 } 138 else 139 { 140 CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); 141 if (clang_qual_type) 142 { 143 type_name = clang_qual_type.GetTypeName().AsCString(""); 144 } 145 else 146 { 147 errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); 148 return 1; 149 } 150 } 151 152 m_wrapper_function_text.append (type_name); 153 if (i < num_args - 1) 154 m_wrapper_function_text.append (", "); 155 156 char arg_buf[32]; 157 args_buffer.append (" "); 158 args_buffer.append (type_name); 159 snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); 160 args_buffer.push_back (' '); 161 args_buffer.append (arg_buf); 162 args_buffer.append (";\n"); 163 164 args_list_buffer.append ("__lldb_fn_data->"); 165 args_list_buffer.append (arg_buf); 166 if (i < num_args - 1) 167 args_list_buffer.append (", "); 168 169 } 170 m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. 171 172 m_wrapper_function_text.append (args_buffer); 173 174 m_wrapper_function_text.append (" "); 175 m_wrapper_function_text.append (return_type_str); 176 m_wrapper_function_text.append (" return_value;"); 177 m_wrapper_function_text.append ("\n };\n struct "); 178 m_wrapper_function_text.append (m_wrapper_struct_name); 179 m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); 180 m_wrapper_function_text.append (m_wrapper_struct_name); 181 m_wrapper_function_text.append (" *) input;\n"); 182 183 m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); 184 m_wrapper_function_text.append (args_list_buffer); 185 m_wrapper_function_text.append (");\n}\n"); 186 187 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 188 if (log) 189 log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); 190 191 // Okay, now compile this expression 192 193 lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); 194 if (jit_process_sp) 195 { 196 const bool generate_debug_info = true; 197 m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); 198 199 num_errors = m_parser->Parse (errors); 200 } 201 else 202 { 203 errors.Printf("no process - unable to inject function"); 204 num_errors = 1; 205 } 206 207 m_compiled = (num_errors == 0); 208 209 if (!m_compiled) 210 return num_errors; 211 212 return num_errors; 213} 214 215clang::ASTConsumer * 216ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) 217{ 218 m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); 219 220 return m_struct_extractor.get(); 221} 222