brintos

brintos / llvm-project-archived public Read only

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