Home | History | Annotate | Download | only in Utility
      1 //===-- InferiorCallPOSIX.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 "InferiorCallPOSIX.h"
     11 #include "lldb/Core/Address.h"
     12 #include "lldb/Core/StreamFile.h"
     13 #include "lldb/Core/ValueObject.h"
     14 #include "lldb/Symbol/ClangASTContext.h"
     15 #include "lldb/Symbol/SymbolContext.h"
     16 #include "lldb/Target/ExecutionContext.h"
     17 #include "lldb/Target/Process.h"
     18 #include "lldb/Target/Target.h"
     19 #include "lldb/Target/ThreadPlanCallFunction.h"
     20 
     21 #include <sys/mman.h>
     22 
     23 using namespace lldb;
     24 using namespace lldb_private;
     25 
     26 bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
     27                                     addr_t addr, addr_t length, unsigned prot,
     28                                     unsigned flags, addr_t fd, addr_t offset) {
     29     Thread *thread = process->GetThreadList().GetSelectedThread().get();
     30     if (thread == NULL)
     31         return false;
     32 
     33     const bool append = true;
     34     const bool include_symbols = true;
     35     const bool include_inlines = false;
     36     SymbolContextList sc_list;
     37     const uint32_t count
     38       = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
     39                                                         eFunctionNameTypeFull,
     40                                                         include_symbols,
     41                                                         include_inlines,
     42                                                         append,
     43                                                         sc_list);
     44     if (count > 0)
     45     {
     46         SymbolContext sc;
     47         if (sc_list.GetContextAtIndex(0, sc))
     48         {
     49             const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
     50             const bool use_inline_block_range = false;
     51             const bool stop_other_threads = true;
     52             const bool unwind_on_error = true;
     53             const bool ignore_breakpoints = true;
     54             const bool try_all_threads = true;
     55             const uint32_t timeout_usec = 500000;
     56 
     57             addr_t prot_arg, flags_arg = 0;
     58             if (prot == eMmapProtNone)
     59               prot_arg = PROT_NONE;
     60             else {
     61               prot_arg = 0;
     62               if (prot & eMmapProtExec)
     63                 prot_arg |= PROT_EXEC;
     64               if (prot & eMmapProtRead)
     65                 prot_arg |= PROT_READ;
     66               if (prot & eMmapProtWrite)
     67                 prot_arg |= PROT_WRITE;
     68             }
     69 
     70             if (flags & eMmapFlagsPrivate)
     71               flags_arg |= MAP_PRIVATE;
     72             if (flags & eMmapFlagsAnon)
     73               flags_arg |= MAP_ANON;
     74 
     75             AddressRange mmap_range;
     76             if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
     77             {
     78                 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
     79                 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
     80                 ThreadPlanCallFunction *call_function_thread_plan
     81                   = new ThreadPlanCallFunction (*thread,
     82                                                 mmap_range.GetBaseAddress(),
     83                                                 clang_void_ptr_type,
     84                                                 stop_other_threads,
     85                                                 unwind_on_error,
     86                                                 ignore_breakpoints,
     87                                                 &addr,
     88                                                 &length,
     89                                                 &prot_arg,
     90                                                 &flags_arg,
     91                                                 &fd,
     92                                                 &offset);
     93                 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
     94                 if (call_plan_sp)
     95                 {
     96                     StreamFile error_strm;
     97                     // This plan is a utility plan, so set it to discard itself when done.
     98                     call_plan_sp->SetIsMasterPlan (true);
     99                     call_plan_sp->SetOkayToDiscard(true);
    100 
    101                     StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
    102                     if (frame)
    103                     {
    104                         ExecutionContext exe_ctx;
    105                         frame->CalculateExecutionContext (exe_ctx);
    106                         ExecutionResults result = process->RunThreadPlan (exe_ctx,
    107                                                                           call_plan_sp,
    108                                                                           stop_other_threads,
    109                                                                           try_all_threads,
    110                                                                           unwind_on_error,
    111                                                                           ignore_breakpoints,
    112                                                                           timeout_usec,
    113                                                                           error_strm);
    114                         if (result == eExecutionCompleted)
    115                         {
    116 
    117                             allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    118                             if (process->GetAddressByteSize() == 4)
    119                             {
    120                                 if (allocated_addr == UINT32_MAX)
    121                                     return false;
    122                             }
    123                             else if (process->GetAddressByteSize() == 8)
    124                             {
    125                                 if (allocated_addr == UINT64_MAX)
    126                                     return false;
    127                             }
    128                             return true;
    129                         }
    130                     }
    131                 }
    132             }
    133         }
    134     }
    135 
    136     return false;
    137 }
    138 
    139 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
    140                                       addr_t length) {
    141    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    142    if (thread == NULL)
    143        return false;
    144 
    145    const bool append = true;
    146    const bool include_symbols = true;
    147    const bool include_inlines = false;
    148    SymbolContextList sc_list;
    149    const uint32_t count
    150      = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
    151                                                        eFunctionNameTypeFull,
    152                                                        include_symbols,
    153                                                        include_inlines,
    154                                                        append,
    155                                                        sc_list);
    156    if (count > 0)
    157    {
    158        SymbolContext sc;
    159        if (sc_list.GetContextAtIndex(0, sc))
    160        {
    161            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
    162            const bool use_inline_block_range = false;
    163            const bool stop_other_threads = true;
    164            const bool unwind_on_error = true;
    165            const bool ignore_breakpoints = true;
    166            const bool try_all_threads = true;
    167            const uint32_t timeout_usec = 500000;
    168 
    169            AddressRange munmap_range;
    170            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
    171            {
    172                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
    173                                                                             munmap_range.GetBaseAddress(),
    174                                                                             ClangASTType(),
    175                                                                             stop_other_threads,
    176                                                                             unwind_on_error,
    177                                                                             ignore_breakpoints,
    178                                                                             &addr,
    179                                                                             &length));
    180                if (call_plan_sp)
    181                {
    182                    StreamFile error_strm;
    183                    // This plan is a utility plan, so set it to discard itself when done.
    184                    call_plan_sp->SetIsMasterPlan (true);
    185                    call_plan_sp->SetOkayToDiscard(true);
    186 
    187                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
    188                    if (frame)
    189                    {
    190                        ExecutionContext exe_ctx;
    191                        frame->CalculateExecutionContext (exe_ctx);
    192                        ExecutionResults result = process->RunThreadPlan (exe_ctx,
    193                                                                          call_plan_sp,
    194                                                                          stop_other_threads,
    195                                                                          try_all_threads,
    196                                                                          unwind_on_error,
    197                                                                          ignore_breakpoints,
    198                                                                          timeout_usec,
    199                                                                          error_strm);
    200                        if (result == eExecutionCompleted)
    201                        {
    202                            return true;
    203                        }
    204                    }
    205                }
    206            }
    207        }
    208    }
    209 
    210    return false;
    211 }
    212 
    213 bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
    214     Thread *thread = process->GetThreadList().GetSelectedThread().get();
    215     if (thread == NULL || address == NULL)
    216         return false;
    217 
    218     const bool stop_other_threads = true;
    219     const bool unwind_on_error = true;
    220     const bool ignore_breakpoints = true;
    221     const bool try_all_threads = true;
    222     const uint32_t timeout_usec = 500000;
    223 
    224     ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
    225     ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
    226     ThreadPlanCallFunction *call_function_thread_plan
    227         = new ThreadPlanCallFunction (*thread,
    228                                       *address,
    229                                       clang_void_ptr_type,
    230                                       stop_other_threads,
    231                                       unwind_on_error,
    232                                       ignore_breakpoints);
    233     lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
    234     if (call_plan_sp)
    235     {
    236         StreamFile error_strm;
    237         // This plan is a utility plan, so set it to discard itself when done.
    238         call_plan_sp->SetIsMasterPlan (true);
    239         call_plan_sp->SetOkayToDiscard(true);
    240 
    241         StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
    242         if (frame)
    243         {
    244             ExecutionContext exe_ctx;
    245             frame->CalculateExecutionContext (exe_ctx);
    246             ExecutionResults result = process->RunThreadPlan (exe_ctx,
    247                                                               call_plan_sp,
    248                                                               stop_other_threads,
    249                                                               try_all_threads,
    250                                                               unwind_on_error,
    251                                                               ignore_breakpoints,
    252                                                               timeout_usec,
    253                                                               error_strm);
    254             if (result == eExecutionCompleted)
    255             {
    256                 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    257 
    258                 if (process->GetAddressByteSize() == 4)
    259                 {
    260                     if (returned_func == UINT32_MAX)
    261                         return false;
    262                 }
    263                 else if (process->GetAddressByteSize() == 8)
    264                 {
    265                     if (returned_func == UINT64_MAX)
    266                         return false;
    267                 }
    268                 return true;
    269             }
    270         }
    271     }
    272 
    273     return false;
    274 }
    275