1 //===-- ClangUserExpression.cpp -------------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "ClangUtilityFunction.h"
12 #include "ClangExpressionDeclMap.h"
13 #include "ClangExpressionParser.h"
14 
15 // C Includes
16 #include <stdio.h>
17 #if HAVE_SYS_TYPES_H
18 #include <sys/types.h>
19 #endif
20 
21 // C++ Includes
22 
23 #include "lldb/Core/ConstString.h"
24 #include "lldb/Core/Log.h"
25 #include "lldb/Core/Module.h"
26 #include "lldb/Core/Stream.h"
27 #include "lldb/Core/StreamFile.h"
28 #include "lldb/Expression/ExpressionSourceCode.h"
29 #include "lldb/Expression/IRExecutionUnit.h"
30 #include "lldb/Host/Host.h"
31 #include "lldb/Target/ExecutionContext.h"
32 #include "lldb/Target/Target.h"
33 
34 using namespace lldb_private;
35 
36 //------------------------------------------------------------------
37 /// Constructor
38 ///
39 /// @param[in] text
40 ///     The text of the function.  Must be a full translation unit.
41 ///
42 /// @param[in] name
43 ///     The name of the function, as used in the text.
44 //------------------------------------------------------------------
45 ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
46                                            const char *text, const char *name)
47     : UtilityFunction(exe_scope, text, name) {}
48 
49 ClangUtilityFunction::~ClangUtilityFunction() {}
50 
51 //------------------------------------------------------------------
52 /// Install the utility function into a process
53 ///
54 /// @param[in] diagnostic_manager
55 ///     A diagnostic manager to report errors and warnings to.
56 ///
57 /// @param[in] exe_ctx
58 ///     The execution context to install the utility function to.
59 ///
60 /// @return
61 ///     True on success (no errors); false otherwise.
62 //------------------------------------------------------------------
63 bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
64                                    ExecutionContext &exe_ctx) {
65   if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
66     diagnostic_manager.PutCString(eDiagnosticSeverityWarning,
67                                   "already installed");
68     return false;
69   }
70 
71   ////////////////////////////////////
72   // Set up the target and compiler
73   //
74 
75   Target *target = exe_ctx.GetTargetPtr();
76 
77   if (!target) {
78     diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
79     return false;
80   }
81 
82   Process *process = exe_ctx.GetProcessPtr();
83 
84   if (!process) {
85     diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process");
86     return false;
87   }
88 
89   //////////////////////////
90   // Parse the expression
91   //
92 
93   bool keep_result_in_memory = false;
94 
95   ResetDeclMap(exe_ctx, keep_result_in_memory);
96 
97   if (!DeclMap()->WillParse(exe_ctx, NULL)) {
98     diagnostic_manager.PutCString(
99         eDiagnosticSeverityError,
100         "current process state is unsuitable for expression parsing");
101     return false;
102   }
103 
104   const bool generate_debug_info = true;
105   ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
106                                generate_debug_info);
107 
108   unsigned num_errors = parser.Parse(diagnostic_manager);
109 
110   if (num_errors) {
111     ResetDeclMap();
112 
113     return false;
114   }
115 
116   //////////////////////////////////
117   // JIT the output of the parser
118   //
119 
120   bool can_interpret = false; // should stay that way
121 
122   Error jit_error = parser.PrepareForExecution(
123       m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
124       can_interpret, eExecutionPolicyAlways);
125 
126   if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
127     m_jit_process_wp = process->shared_from_this();
128     if (parser.GetGenerateDebugInfo()) {
129       lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
130 
131       if (jit_module_sp) {
132         ConstString const_func_name(FunctionName());
133         FileSpec jit_file;
134         jit_file.GetFilename() = const_func_name;
135         jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
136         m_jit_module_wp = jit_module_sp;
137         target->GetImages().Append(jit_module_sp);
138       }
139     }
140   }
141 
142 #if 0
143 	// jingham: look here
144     StreamFile logfile ("/tmp/exprs.txt", "a");
145     logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
146                     m_jit_start_addr,
147                     m_function_name.c_str(),
148                     m_function_text.c_str());
149 #endif
150 
151   DeclMap()->DidParse();
152 
153   ResetDeclMap();
154 
155   if (jit_error.Success()) {
156     return true;
157   } else {
158     const char *error_cstr = jit_error.AsCString();
159     if (error_cstr && error_cstr[0]) {
160       diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
161     } else {
162       diagnostic_manager.PutCString(eDiagnosticSeverityError,
163                                     "expression can't be interpreted or run");
164     }
165     return false;
166   }
167 }
168 
169 void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
170     ExecutionContext &exe_ctx, bool keep_result_in_memory) {
171   m_expr_decl_map_up.reset(
172       new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
173 }
174