ClangUserExpression.cpp revision 05a5a1bcbed5c0f31fed29153bb2912d71836e91
1//===-- ClangUserExpression.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// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13#  include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <string>
19#include <map>
20
21#include "lldb/Core/ConstString.h"
22#include "lldb/Core/Log.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Core/ValueObjectConstResult.h"
25#include "lldb/Expression/ASTSplitConsumer.h"
26#include "lldb/Expression/ASTResultSynthesizer.h"
27#include "lldb/Expression/ClangExpressionDeclMap.h"
28#include "lldb/Expression/ClangExpressionParser.h"
29#include "lldb/Expression/ClangFunction.h"
30#include "lldb/Expression/ClangUserExpression.h"
31#include "lldb/Host/Host.h"
32#include "lldb/Symbol/VariableList.h"
33#include "lldb/Target/ExecutionContext.h"
34#include "lldb/Target/Process.h"
35#include "lldb/Target/StackFrame.h"
36#include "lldb/Target/Target.h"
37#include "lldb/Target/ThreadPlan.h"
38#include "lldb/Target/ThreadPlanCallUserExpression.h"
39
40using namespace lldb_private;
41
42ClangUserExpression::ClangUserExpression (const char *expr,
43                                          const char *expr_prefix) :
44    m_expr_text(expr),
45    m_expr_prefix(expr_prefix ? expr_prefix : ""),
46    m_transformed_text(),
47    m_jit_addr(LLDB_INVALID_ADDRESS),
48    m_cplusplus(false),
49    m_objectivec(false),
50    m_needs_object_ptr(false),
51    m_const_object(false),
52    m_desired_type(NULL, NULL)
53{
54}
55
56ClangUserExpression::~ClangUserExpression ()
57{
58}
59
60clang::ASTConsumer *
61ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
62{
63    return new ASTResultSynthesizer(passthrough,
64                                    m_desired_type);
65}
66
67void
68ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
69{
70    if (!exe_ctx.frame)
71        return;
72
73    VariableList *vars = exe_ctx.frame->GetVariableList(false);
74
75    if (!vars)
76        return;
77
78    lldb::VariableSP this_var(vars->FindVariable(ConstString("this")));
79    lldb::VariableSP self_var(vars->FindVariable(ConstString("self")));
80
81    if (this_var.get())
82    {
83        Type *this_type = this_var->GetType();
84
85        lldb::clang_type_t pointer_target_type;
86
87        if (ClangASTContext::IsPointerType(this_type->GetClangType(),
88                                           &pointer_target_type))
89        {
90            TypeFromUser target_ast_type(pointer_target_type, this_type->GetClangAST());
91
92            if (target_ast_type.IsDefined())
93                m_cplusplus = true;
94
95            if (target_ast_type.IsConst())
96                m_const_object = true;
97        }
98    }
99    else if (self_var.get())
100    {
101        m_objectivec = true;
102    }
103}
104
105// This is a really nasty hack, meant to fix Objective-C expressions of the form
106// (int)[myArray count].  Right now, because the type information for count is
107// not available, [myArray count] returns id, which can't be directly cast to
108// int without causing a clang error.
109static void
110ApplyObjcCastHack(std::string &expr)
111{
112#define OBJC_CAST_HACK_FROM "(int)["
113#define OBJC_CAST_HACK_TO   "(int)(long long)["
114
115    size_t from_offset;
116
117    while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
118        expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
119
120#undef OBJC_CAST_HACK_TO
121#undef OBJC_CAST_HACK_FROM
122}
123
124// Another hack, meant to allow use of unichar despite it not being available in
125// the type information.  Although we could special-case it in type lookup,
126// hopefully we'll figure out a way to #include the same environment as is
127// present in the original source file rather than try to hack specific type
128// definitions in as needed.
129static void
130ApplyUnicharHack(std::string &expr)
131{
132#define UNICHAR_HACK_FROM "unichar"
133#define UNICHAR_HACK_TO   "unsigned short"
134
135    size_t from_offset;
136
137    while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
138        expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
139
140#undef UNICHAR_HACK_TO
141#undef UNICHAR_HACK_FROM
142}
143
144bool
145ClangUserExpression::Parse (Stream &error_stream,
146                            ExecutionContext &exe_ctx,
147                            TypeFromUser desired_type,
148                            lldb::ClangExpressionVariableSP *const_result)
149{
150    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
151
152    ScanContext(exe_ctx);
153
154    StreamString m_transformed_stream;
155
156    ////////////////////////////////////
157    // Generate the expression
158    //
159
160    ApplyObjcCastHack(m_expr_text);
161    //ApplyUnicharHack(m_expr_text);
162
163    if (m_cplusplus)
164    {
165        m_transformed_stream.Printf("%s                                     \n"
166                                    "typedef unsigned short unichar;        \n"
167                                    "void                                   \n"
168                                    "$__lldb_class::%s(void *$__lldb_arg) %s\n"
169                                    "{                                      \n"
170                                    "    %s;                                \n"
171                                    "}                                      \n",
172                                    m_expr_prefix.c_str(),
173                                    FunctionName(),
174                                    (m_const_object ? "const" : ""),
175                                    m_expr_text.c_str());
176
177        m_needs_object_ptr = true;
178    }
179    else if(m_objectivec)
180    {
181        const char *function_name = FunctionName();
182
183        m_transformed_stream.Printf("%s                                                     \n"
184                                    "@interface $__lldb_objc_class ($__lldb_category)       \n"
185                                    "-(void)%s:(void *)$__lldb_arg;                         \n"
186                                    "@end                                                   \n"
187                                    "@implementation $__lldb_objc_class ($__lldb_category)  \n"
188                                    "-(void)%s:(void *)$__lldb_arg                          \n"
189                                    "{                                                      \n"
190                                    "    %s;                                                \n"
191                                    "}                                                      \n"
192                                    "@end                                                   \n",
193                                    m_expr_prefix.c_str(),
194                                    function_name,
195                                    function_name,
196                                    m_expr_text.c_str());
197
198        m_needs_object_ptr = true;
199    }
200    else
201    {
202        m_transformed_stream.Printf("%s                             \n"
203                                    "typedef unsigned short unichar;\n"
204                                    "void                           \n"
205                                    "%s(void *$__lldb_arg)          \n"
206                                    "{                              \n"
207                                    "    %s;                        \n"
208                                    "}                              \n",
209                                    m_expr_prefix.c_str(),
210                                    FunctionName(),
211                                    m_expr_text.c_str());
212    }
213
214    m_transformed_text = m_transformed_stream.GetData();
215
216
217    if (log)
218        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
219
220    ////////////////////////////////////
221    // Set up the target and compiler
222    //
223
224    Target *target = exe_ctx.target;
225
226    if (!target)
227    {
228        error_stream.PutCString ("error: invalid target\n");
229        return false;
230    }
231
232    ConstString target_triple;
233
234    target->GetTargetTriple (target_triple);
235
236    if (!target_triple)
237        target_triple = Host::GetTargetTriple ();
238
239    if (!target_triple)
240    {
241        error_stream.PutCString ("error: invalid target triple\n");
242        return false;
243    }
244
245    //////////////////////////
246    // Parse the expression
247    //
248
249    m_desired_type = desired_type;
250
251    m_expr_decl_map.reset(new ClangExpressionDeclMap());
252
253    m_expr_decl_map->WillParse(exe_ctx);
254
255    ClangExpressionParser parser(target_triple.GetCString(), *this);
256
257    unsigned num_errors = parser.Parse (error_stream);
258
259    if (num_errors)
260    {
261        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
262
263        m_expr_decl_map->DidParse();
264
265        return false;
266    }
267
268    ///////////////////////////////////////////////
269    // Convert the output of the parser to DWARF
270    //
271
272    m_dwarf_opcodes.reset(new StreamString);
273    m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
274    m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
275
276    m_local_variables.reset(new ClangExpressionVariableList());
277
278    Error dwarf_error = parser.MakeDWARF ();
279
280    if (dwarf_error.Success())
281    {
282        if (log)
283            log->Printf("Code can be interpreted.");
284
285        m_expr_decl_map->DidParse();
286
287        return true;
288    }
289
290    //////////////////////////////////
291    // JIT the output of the parser
292    //
293
294    m_dwarf_opcodes.reset();
295
296    lldb::addr_t jit_end;
297
298    Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx, const_result);
299
300    m_expr_decl_map->DidParse();
301
302    if (jit_error.Success())
303    {
304        return true;
305    }
306    else
307    {
308        error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
309        return false;
310    }
311}
312
313bool
314ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
315                                                    ExecutionContext &exe_ctx,
316                                                    lldb::addr_t &struct_address,
317                                                    lldb::addr_t &object_ptr,
318                                                    lldb::addr_t &cmd_ptr)
319{
320    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
321
322    if (m_jit_addr != LLDB_INVALID_ADDRESS)
323    {
324        Error materialize_error;
325
326        if (m_needs_object_ptr)
327        {
328            ConstString object_name;
329
330            if (m_cplusplus)
331            {
332                object_name.SetCString("this");
333            }
334            else if (m_objectivec)
335            {
336                object_name.SetCString("self");
337            }
338            else
339            {
340                error_stream.Printf("Need object pointer but don't know the language\n");
341                return false;
342            }
343
344            if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
345            {
346                error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
347                return false;
348            }
349
350            if (m_objectivec)
351            {
352                ConstString cmd_name("_cmd");
353
354                if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
355                {
356                    error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
357                    return false;
358                }
359            }
360        }
361
362        if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
363        {
364            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
365            return false;
366        }
367
368        if (log)
369        {
370            log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
371
372            log->Printf("  Function address  : 0x%llx", (uint64_t)m_jit_addr);
373
374            if (m_needs_object_ptr)
375                log->Printf("  Object pointer    : 0x%llx", (uint64_t)object_ptr);
376
377            log->Printf("  Structure address : 0x%llx", (uint64_t)struct_address);
378
379            StreamString args;
380
381            Error dump_error;
382
383            if (struct_address)
384            {
385                if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
386                {
387                    log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
388                }
389                else
390                {
391                    log->Printf("  Structure contents:\n%s", args.GetData());
392                }
393            }
394        }
395    }
396    return true;
397}
398
399ThreadPlan *
400ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
401                                       ExecutionContext &exe_ctx)
402{
403    lldb::addr_t struct_address;
404
405    lldb::addr_t object_ptr = NULL;
406    lldb::addr_t cmd_ptr = NULL;
407
408    PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
409
410    // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
411    // ClangUserExpression resources before the thread plan finishes execution in the target.  But because we are
412    // forcing unwind_on_error to be true here, in practical terms that can't happen.
413
414    return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
415                                                       m_jit_addr,
416                                                       struct_address,
417                                                       error_stream,
418                                                       true,
419                                                       true,
420                                                       (m_needs_object_ptr ? &object_ptr : NULL),
421                                                       (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
422}
423
424bool
425ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
426                                           ExecutionContext &exe_ctx,
427                                           lldb::ClangExpressionVariableSP &result)
428{
429    Error expr_error;
430
431    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
432
433    if (log)
434    {
435        log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
436
437        StreamString args;
438
439        Error dump_error;
440
441        if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
442        {
443            log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
444        }
445        else
446        {
447            log->Printf("  Structure contents:\n%s", args.GetData());
448        }
449    }
450
451    if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
452    {
453        error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
454        return false;
455    }
456    return true;
457}
458
459lldb::ExecutionResults
460ClangUserExpression::Execute (Stream &error_stream,
461                              ExecutionContext &exe_ctx,
462                              bool discard_on_error,
463                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
464                              lldb::ClangExpressionVariableSP &result)
465{
466    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
467
468    if (m_dwarf_opcodes.get())
469    {
470        // TODO execute the JITted opcodes
471
472        error_stream.Printf("We don't currently support executing DWARF expressions");
473
474        return lldb::eExecutionSetupError;
475    }
476    else if (m_jit_addr != LLDB_INVALID_ADDRESS)
477    {
478        lldb::addr_t struct_address;
479
480        lldb::addr_t object_ptr = NULL;
481        lldb::addr_t cmd_ptr = NULL;
482
483        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
484            return lldb::eExecutionSetupError;
485
486        const bool stop_others = true;
487        const bool try_all_threads = true;
488
489        Address wrapper_address (NULL, m_jit_addr);
490        lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
491                                                                          wrapper_address,
492                                                                          struct_address,
493                                                                          stop_others,
494                                                                          discard_on_error,
495                                                                          (m_needs_object_ptr ? &object_ptr : NULL),
496                                                                          ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
497                                                                          shared_ptr_to_me));
498
499        if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
500            return lldb::eExecutionSetupError;
501
502        call_plan_sp->SetPrivate(true);
503
504        uint32_t single_thread_timeout_usec = 10000000;
505
506        if (log)
507            log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
508
509        lldb::ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
510                                                                                  call_plan_sp,
511                                                                                  stop_others,
512                                                                                  try_all_threads,
513                                                                                  discard_on_error,
514                                                                                  single_thread_timeout_usec,
515                                                                                  error_stream);
516
517        if (log)
518            log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
519
520        if (execution_result == lldb::eExecutionInterrupted)
521        {
522            if (discard_on_error)
523                error_stream.Printf ("Expression execution was interrupted.  The process has been returned to the state before execution.");
524            else
525                error_stream.Printf ("Expression execution was interrupted.  The process has been left at the point where it was interrupted.");
526
527            return execution_result;
528        }
529        else if (execution_result != lldb::eExecutionCompleted)
530        {
531            error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
532            return execution_result;
533        }
534
535        if  (FinalizeJITExecution (error_stream, exe_ctx, result))
536            return lldb::eExecutionCompleted;
537        else
538            return lldb::eExecutionSetupError;
539    }
540    else
541    {
542        error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
543        return lldb::eExecutionSetupError;
544    }
545}
546
547StreamString &
548ClangUserExpression::DwarfOpcodeStream ()
549{
550    if (!m_dwarf_opcodes.get())
551        m_dwarf_opcodes.reset(new StreamString());
552
553    return *m_dwarf_opcodes.get();
554}
555
556lldb::ExecutionResults
557ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
558                               bool discard_on_error,
559                               const char *expr_cstr,
560                               const char *expr_prefix,
561                               lldb::ValueObjectSP &result_valobj_sp)
562{
563    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
564
565    Error error;
566    lldb::ExecutionResults execution_results = lldb::eExecutionSetupError;
567
568    if (exe_ctx.process == NULL)
569    {
570        error.SetErrorString ("Must have a process to evaluate expressions.");
571
572        result_valobj_sp.reset (new ValueObjectConstResult (error));
573        return lldb::eExecutionSetupError;
574    }
575
576    if (!exe_ctx.process->GetDynamicCheckers())
577    {
578        if (log)
579            log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
580
581        DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
582
583        StreamString install_errors;
584
585        if (!dynamic_checkers->Install(install_errors, exe_ctx))
586        {
587            if (install_errors.GetString().empty())
588                error.SetErrorString ("couldn't install checkers, unknown error");
589            else
590                error.SetErrorString (install_errors.GetString().c_str());
591
592            result_valobj_sp.reset (new ValueObjectConstResult (error));
593            return lldb::eExecutionSetupError;
594        }
595
596        exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
597
598        if (log)
599            log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
600    }
601
602    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
603
604    StreamString error_stream;
605
606    lldb::ClangExpressionVariableSP const_result;
607
608    if (log)
609        log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
610
611    if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result))
612    {
613        if (error_stream.GetString().empty())
614            error.SetErrorString ("expression failed to parse, unknown error");
615        else
616            error.SetErrorString (error_stream.GetString().c_str());
617    }
618    else
619    {
620        lldb::ClangExpressionVariableSP expr_result;
621
622        if (const_result.get())
623        {
624            if (log)
625                log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
626
627            result_valobj_sp = const_result->GetValueObject();
628        }
629        else
630        {
631            error_stream.GetString().clear();
632
633            if (log)
634                log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
635
636            execution_results = user_expression_sp->Execute (error_stream,
637                                                             exe_ctx,
638                                                             discard_on_error,
639                                                             user_expression_sp,
640                                                             expr_result);
641
642            if (execution_results != lldb::eExecutionCompleted)
643            {
644                if (log)
645                    log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
646
647                if (error_stream.GetString().empty())
648                    error.SetErrorString ("expression failed to execute, unknown error");
649                else
650                    error.SetErrorString (error_stream.GetString().c_str());
651            }
652            else
653            {
654                if (expr_result)
655                {
656                    result_valobj_sp = expr_result->GetValueObject();
657
658                    if (log)
659                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString(exe_ctx.GetBestExecutionContextScope()));
660                }
661                else
662                {
663                    if (log)
664                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
665
666                    error.SetErrorString ("Expression did not return a result");
667                }
668            }
669        }
670    }
671
672    if (result_valobj_sp.get() == NULL)
673        result_valobj_sp.reset (new ValueObjectConstResult (error));
674
675    return execution_results;
676}
677