Example #1
0
void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
                             size_t size, Error &error) {
  error.Clear();

  AllocationMap::iterator iter = FindAllocation(process_address, size);

  if (iter == m_allocations.end()) {
    lldb::ProcessSP process_sp = m_process_wp.lock();

    if (process_sp) {
      process_sp->ReadMemory(process_address, bytes, size, error);
      return;
    }

    lldb::TargetSP target_sp = m_target_wp.lock();

    if (target_sp) {
      Address absolute_address(process_address);
      target_sp->ReadMemory(absolute_address, false, bytes, size, error);
      return;
    }

    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't read: no allocation contains the target "
                         "range, and neither the process nor the target exist");
    return;
  }

  Allocation &allocation = iter->second;

  uint64_t offset = process_address - allocation.m_process_start;

  if (offset > allocation.m_size) {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't read: data is not in the allocation");
    return;
  }

  lldb::ProcessSP process_sp;

  switch (allocation.m_policy) {
  default:
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't read: invalid allocation policy");
    return;
  case eAllocationPolicyHostOnly:
    if (!allocation.m_data.GetByteSize()) {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't read: data buffer is empty");
      return;
    }
    if (allocation.m_data.GetByteSize() < offset + size) {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't read: not enough underlying data");
      return;
    }

    ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
    break;
  case eAllocationPolicyMirror:
    process_sp = m_process_wp.lock();
    if (process_sp) {
      process_sp->ReadMemory(process_address, bytes, size, error);
      if (!error.Success())
        return;
    } else {
      if (!allocation.m_data.GetByteSize()) {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't read: data buffer is empty");
        return;
      }
      ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
    }
    break;
  case eAllocationPolicyProcessOnly:
    process_sp = m_process_wp.lock();
    if (process_sp) {
      process_sp->ReadMemory(process_address, bytes, size, error);
      if (!error.Success())
        return;
    }
    break;
  }

  if (lldb_private::Log *log =
          lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
    log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64
                ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
                (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
                (uint64_t)allocation.m_process_start,
                (uint64_t)allocation.m_process_start +
                    (uint64_t)allocation.m_size);
  }
}
Example #2
0
Error
GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
                                                 uint16_t in_port,
                                                 ProcessLaunchInfo &launch_info,
                                                 uint16_t &out_port)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);

    out_port = in_port;
    Error error;
    // If we locate debugserver, keep that located version around
    static FileSpec g_debugserver_file_spec;
    
    char debugserver_path[PATH_MAX];
    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
    
    // Always check to see if we have an environment override for the path
    // to the debugserver to use and use it if we do.
    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
    if (env_debugserver_path)
    {
        debugserver_file_spec.SetFile (env_debugserver_path, false);
        if (log)
            log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
    }
    else
        debugserver_file_spec = g_debugserver_file_spec;
    bool debugserver_exists = debugserver_file_spec.Exists();
    if (!debugserver_exists)
    {
        // The debugserver binary is in the LLDB.framework/Resources
        // directory.
        if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec))
        {
            debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME);
            debugserver_exists = debugserver_file_spec.Exists();
            if (debugserver_exists)
            {
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());

                g_debugserver_file_spec = debugserver_file_spec;
            }
            else
            {
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());

                g_debugserver_file_spec.Clear();
                debugserver_file_spec.Clear();
            }
        }
    }
    
    if (debugserver_exists)
    {
        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));

        Args &debugserver_args = launch_info.GetArguments();
        debugserver_args.Clear();
        char arg_cstr[PATH_MAX];

        // Start args with "debugserver /file/path -r --"
        debugserver_args.AppendArgument(debugserver_path);

#if !defined(__APPLE__)
        // First argument to lldb-server must be mode in which to run.
        debugserver_args.AppendArgument("gdbserver");
#endif

        // If a host and port is supplied then use it
        char host_and_port[128];
        if (hostname)
        {
            snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
            debugserver_args.AppendArgument(host_and_port);
        }
        else
        {
            host_and_port[0] = '\0';
        }

        // use native registers, not the GDB registers
        debugserver_args.AppendArgument("--native-regs");

        if (launch_info.GetLaunchInSeparateProcessGroup())
        {
            debugserver_args.AppendArgument("--setsid");
        }

        llvm::SmallString<PATH_MAX> named_pipe_path;
        Pipe port_pipe;

        bool listen = false;
        if (host_and_port[0])
        {
            // Create a temporary file to get the stdout/stderr and redirect the
            // output of the command into this file. We will later read this file
            // if all goes well and fill the data into "command_output_ptr"

            if (in_port == 0)
            {
                // Binding to port zero, we need to figure out what port it ends up
                // using using a named pipe...
                error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
                if (error.Success())
                {
                    debugserver_args.AppendArgument("--named-pipe");
                    debugserver_args.AppendArgument(named_pipe_path.c_str());
                }
                else
                {
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "named pipe creation failed: %s",
                                __FUNCTION__, error.AsCString());
                    // let's try an unnamed pipe
                    error = port_pipe.CreateNew(true);
                    if (error.Fail())
                    {
                        if (log)
                            log->Printf("GDBRemoteCommunication::%s() "
                                    "unnamed pipe creation failed: %s",
                                    __FUNCTION__, error.AsCString());
                        return error;
                    }
                    int write_fd = port_pipe.GetWriteFileDescriptor();
                    debugserver_args.AppendArgument("--pipe");
                    debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
                    launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
                }
            }
            else
            {
                listen = true;
            }
        }
        else
        {
            // No host and port given, so lets listen on our end and make the debugserver
            // connect to us..
            error = StartListenThread ("127.0.0.1", 0);
            if (error.Fail())
                return error;

            ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
            // Wait for 10 seconds to resolve the bound port
            out_port = connection->GetListeningPort(10);
            if (out_port > 0)
            {
                char port_cstr[32];
                snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
                // Send the host and port down that debugserver and specify an option
                // so that it connects back to the port we are listening to in this process
                debugserver_args.AppendArgument("--reverse-connect");
                debugserver_args.AppendArgument(port_cstr);
            }
            else
            {
                error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
                return error;
            }
        }
        
        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
        if (env_debugserver_log_file)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
            debugserver_args.AppendArgument(arg_cstr);
        }
        
        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
        if (env_debugserver_log_flags)
        {
            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
            debugserver_args.AppendArgument(arg_cstr);
        }

        // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back.
        uint32_t env_var_index = 1;
        bool has_env_var;
        do
        {
            char env_var_name[64];
            snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
            const char *extra_arg = getenv(env_var_name);
            has_env_var = extra_arg != nullptr;

            if (has_env_var)
            {
                debugserver_args.AppendArgument (extra_arg);
                if (log)
                    log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg);
            }
        } while (has_env_var);

        // Close STDIN, STDOUT and STDERR.
        launch_info.AppendCloseFileAction (STDIN_FILENO);
        launch_info.AppendCloseFileAction (STDOUT_FILENO);
        launch_info.AppendCloseFileAction (STDERR_FILENO);

        // Redirect STDIN, STDOUT and STDERR to "/dev/null".
        launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
        launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);
        launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);
        
        error = Host::LaunchProcess(launch_info);
        
        if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
        {
            if (named_pipe_path.size() > 0)
            {
                error = port_pipe.OpenAsReader(named_pipe_path, false);
                if (error.Fail())
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "failed to open named pipe %s for reading: %s",
                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
            }

            if (port_pipe.CanWrite())
                port_pipe.CloseWriteFileDescriptor();
            if (port_pipe.CanRead())
            {
                char port_cstr[256];
                port_cstr[0] = '\0';
                size_t num_bytes = sizeof(port_cstr);
                // Read port from pipe with 10 second timeout.
                error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
                        std::chrono::seconds{10}, num_bytes);
                if (error.Success())
                {
                    assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
                    out_port = StringConvert::ToUInt32(port_cstr, 0);
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "debugserver listens %u port",
                                __FUNCTION__, out_port);
                }
                else
                {
                    if (log)
                        log->Printf("GDBRemoteCommunication::%s() "
                                "failed to read a port value from pipe %s: %s",
                                __FUNCTION__, named_pipe_path.c_str(), error.AsCString());

                }
                port_pipe.Close();
            }

            if (named_pipe_path.size() > 0)
            {
                const auto err = port_pipe.Delete(named_pipe_path);
                if (err.Fail())
                {
                    if (log)
                        log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s",
                                __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
                }
            }

            // Make sure we actually connect with the debugserver...
            JoinListenThread();
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
    }
    return error;
}
Example #3
0
Error
PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
                                  const ArchSpec &exe_arch,
                                  lldb::ModuleSP &exe_module_sp,
                                  const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    FileSpec resolved_exe_file (exe_file);
    
    if (IsHost())
    {
        // If we have "ls" as the exe_file, resolve the executable location based on
        // the current path variables
        if (!resolved_exe_file.Exists())
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            resolved_exe_file.SetFile(exe_path, true);
        }

        if (!resolved_exe_file.Exists())
            resolved_exe_file.ResolveExecutableLocation ();

        if (resolved_exe_file.Exists())
            error.Clear();
        else
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = m_remote_platform_sp->ResolveExecutable (exe_file,
                                                             exe_arch,
                                                             exe_module_sp,
                                                             NULL);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).
            
            if (resolved_exe_file.Exists())
                error.Clear();
            else
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
        }
    }

    if (error.Success())
    {
        ModuleSpec module_spec (resolved_exe_file, exe_arch);
        if (exe_arch.IsValid())
        {
            error = ModuleList::GetSharedModule (module_spec, 
                                                 exe_module_sp, 
                                                 NULL, 
                                                 NULL,
                                                 NULL);
            if (error.Fail())
            {
                // If we failed, it may be because the vendor and os aren't known. If that is the
                // case, try setting them to the host architecture and give it another try.
                llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 
                bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
                bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
                if (!is_vendor_specified || !is_os_specified)
                {
                    const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple();

                    if (!is_vendor_specified)
                        module_triple.setVendorName (host_triple.getVendorName());
                    if (!is_os_specified)
                        module_triple.setOSName (host_triple.getOSName());

                    error = ModuleList::GetSharedModule (module_spec, 
                                                         exe_module_sp, 
                                                         NULL, 
                                                         NULL,
                                                         NULL);
                }
            }
        
            // TODO find out why exe_module_sp might be NULL            
            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
                                                exe_file.GetPath().c_str(),
                                                exe_arch.GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
            {
                error = ModuleList::GetSharedModule (module_spec, 
                                                     exe_module_sp, 
                                                     NULL, 
                                                     NULL,
                                                     NULL);
                // Did we find an executable using one of the 
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }
                
                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName());
            }
            
            if (error.Fail() || !exe_module_sp)
            {
                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                exe_file.GetPath().c_str(),
                                                GetPluginName().GetCString(),
                                                arch_names.GetString().c_str());
            }
        }
    }

    return error;
}
Example #4
0
lldb::ProcessSP
PlatformPOSIX::Attach (ProcessAttachInfo &attach_info,
                       Debugger &debugger,
                       Target *target,
                       Error &error)
{
    lldb::ProcessSP process_sp;
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));

    if (IsHost())
    {
        if (target == NULL)
        {
            TargetSP new_target_sp;

            error = debugger.GetTargetList().CreateTarget (debugger,
                                                           NULL,
                                                           NULL,
                                                           false,
                                                           NULL,
                                                           new_target_sp);
            target = new_target_sp.get();
            if (log)
                log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__);
        }
        else
        {
            error.Clear();
            if (log)
                log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__);
        }

        if (target && error.Success())
        {
            debugger.GetTargetList().SetSelectedTarget(target);
            if (log)
            {
                ModuleSP exe_module_sp = target->GetExecutableModule ();
                log->Printf("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, (void *)target,
                            exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() : "<null>");
            }


            process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL);

            if (process_sp)
            {
                // Set UnixSignals appropriately.
                process_sp->SetUnixSignals (Host::GetUnixSignals ());

                auto listener_sp = attach_info.GetHijackListener();
                if (listener_sp == nullptr)
                {
                    listener_sp.reset(new Listener("lldb.PlatformPOSIX.attach.hijack"));
                    attach_info.SetHijackListener(listener_sp);
                }
                process_sp->HijackProcessEvents(listener_sp.get());
                error = process_sp->Attach (attach_info);
            }
        }
    }
    else
    {
        if (m_remote_platform_sp)
            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
        else
            error.SetErrorString ("the platform is not currently connected");
    }
    return process_sp;
}
void
IRExecutionUnit::GetRunnableInfo(Error &error,
                                 lldb::addr_t &func_addr,
                                 lldb::addr_t &func_end)
{
    lldb::ProcessSP process_sp(GetProcessWP().lock());

    static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive);

    func_addr = LLDB_INVALID_ADDRESS;
    func_end = LLDB_INVALID_ADDRESS;

    if (!process_sp)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
        return;
    }

    if (m_did_jit)
    {
        func_addr = m_function_load_addr;
        func_end = m_function_end_load_addr;

        return;
    };

    Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex);

    m_did_jit = true;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    std::string error_string;

    if (log)
    {
        std::string s;
        llvm::raw_string_ostream oss(s);

        m_module->print(oss, NULL);

        oss.flush();

        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }

    llvm::Triple triple(m_module->getTargetTriple());
    llvm::Function *function = m_module->getFunction (m_name.AsCString());
    llvm::Reloc::Model relocModel;
    llvm::CodeModel::Model codeModel;

    if (triple.isOSBinFormatELF())
    {
        relocModel = llvm::Reloc::Static;
        // This will be small for 32-bit and large for 64-bit.
        codeModel = llvm::CodeModel::JITDefault;
    }
    else
    {
        relocModel = llvm::Reloc::PIC_;
        codeModel = llvm::CodeModel::Small;
    }

    m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);

    llvm::EngineBuilder builder(std::move(m_module_ap));

    builder.setEngineKind(llvm::EngineKind::JIT)
    .setErrorStr(&error_string)
    .setRelocationModel(relocModel)
    .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this)))
    .setCodeModel(codeModel)
    .setOptLevel(llvm::CodeGenOpt::Less);

    llvm::StringRef mArch;
    llvm::StringRef mCPU;
    llvm::SmallVector<std::string, 0> mAttrs;

    for (std::string &feature : m_cpu_features)
        mAttrs.push_back(feature);

    llvm::TargetMachine *target_machine = builder.selectTarget(triple,
                                                               mArch,
                                                               mCPU,
                                                               mAttrs);

    m_execution_engine_ap.reset(builder.create(target_machine));

    if (!m_execution_engine_ap.get())
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return;
    }

    // Make sure we see all sections, including ones that don't have relocations...
    m_execution_engine_ap->setProcessAllSections(true);

    m_execution_engine_ap->DisableLazyCompilation();

    // We don't actually need the function pointer here, this just forces it to get resolved.

    void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);

    if (!error.Success())
    {
        // We got an error through our callback!
        return;
    }

    if (!function)
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
        return;
    }

    if (!fun_ptr)
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
        return;
    }

    m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));

    CommitAllocations(process_sp);
    ReportAllocations(*m_execution_engine_ap);
    WriteData(process_sp);

    if (m_failed_lookups.size())
    {
        StreamString ss;
        
        ss.PutCString("Couldn't lookup symbols:\n");
        
        bool emitNewLine = false;
        
        for (const ConstString &failed_lookup : m_failed_lookups)
        {
            if (emitNewLine)
                ss.PutCString("\n");
            emitNewLine = true;
            ss.PutCString("  ");
            ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString());
        }
        
        m_failed_lookups.clear();
        
        error.SetErrorString(ss.GetData());
        
        return;
    }
    
    m_function_load_addr = LLDB_INVALID_ADDRESS;
    m_function_end_load_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &jitted_function : m_jitted_functions)
    {
        jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);

        if (!jitted_function.m_name.compare(m_name.AsCString()))
        {
            AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
            m_function_end_load_addr = func_range.first + func_range.second;
            m_function_load_addr = jitted_function.m_remote_addr;
        }
    }

    if (log)
    {
        log->Printf("Code can be run in the target.");

        StreamString disassembly_stream;

        Error err = DisassembleFunction(disassembly_stream, process_sp);

        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }

        log->Printf("Sections: ");
        for (AllocationRecord &record : m_records)
        {
            if (record.m_process_address != LLDB_INVALID_ADDRESS)
            {
                record.dump(log);

                DataBufferHeap my_buffer(record.m_size, 0);
                Error err;
                ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);

                if (err.Success())
                {
                    DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
                    my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
                }
            }
        }
    }

    func_addr = m_function_load_addr;
    func_end = m_function_end_load_addr;

    return;
}
Example #6
0
bool
ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
                                      lldb::addr_t  sp  ,
                                      lldb::addr_t  pc  ,
                                      lldb::addr_t  ra  ,
                                      llvm::Type   &prototype,
                                      llvm::ArrayRef<ABI::CallArgument> args) const
{
    // default number of register passed arguments for varg functions
    const int nVArgRegParams = 1;
    Error error;

    // grab the process so we have access to the memory for spilling
    lldb::ProcessSP proc = thread.GetProcess( );

    // push host data onto target
    for ( size_t i = 0; i < args.size( ); i++ )
    {
        const ABI::CallArgument &arg = args[i];
        // skip over target values
        if ( arg.type == ABI::CallArgument::TargetValue )
            continue;
        // round up to 8 byte multiple
        size_t argSize = ( arg.size | 0x7 ) + 1;

        // create space on the stack for this data
        sp -= argSize;

        // write this argument onto the stack of the host process
        proc.get( )->WriteMemory( sp, arg.data_ap.get(), arg.size, error );
        if ( error.Fail( ) )
            return false;

        // update the argument with the target pointer
        //XXX: This is a gross hack for getting around the const
        *const_cast<lldb::addr_t*>(&arg.value) = sp;
    }

#if HEX_ABI_DEBUG
    // print the original stack pointer
    printf( "sp : %04" PRIx64 " \n", sp );
#endif

    // make sure number of parameters matches prototype
    assert( prototype.getFunctionNumParams( ) == args.size( ) );

    // check if this is a variable argument function
    bool isVArg = prototype.isFunctionVarArg();

    // get the register context for modifying all of the registers
    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return false;

    // number of arguments passed by register
    int nRegArgs = nVArgRegParams;
    if (! isVArg )
    {
        // number of arguments is limited by [R0 : R5] space
        nRegArgs = args.size( );
        if ( nRegArgs > 6 )
            nRegArgs = 6;
    }

    // pass arguments that are passed via registers
    for ( int i = 0; i < nRegArgs; i++ )
    {
        // get the parameter as a u32
        uint32_t param = (uint32_t)args[i].value;
        // write argument into register
        if (!reg_ctx->WriteRegisterFromUnsigned( i, param ))
            return false;
    }

    // number of arguments to spill onto stack
    int nSpillArgs = args.size( ) - nRegArgs;
    // make space on the stack for arguments
    sp -= 4 * nSpillArgs;
    // align stack on an 8 byte boundary
    if ( sp & 7 )
        sp -= 4;

    // arguments that are passed on the stack
    for ( size_t i = nRegArgs, offs=0; i < args.size( ); i++ )
    {
        // get the parameter as a u32
        uint32_t param = (uint32_t)args[i].value;
        // write argument to stack
        proc->WriteMemory( sp + offs, (void*)&param, sizeof( param ), error );
        if ( !error.Success( ) )
            return false;
        //
        offs += 4;
    }

    // update registers with current function call state
    reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
    reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
    reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
//  reg_ctx->WriteRegisterFromUnsigned ( FP ??? );

#if HEX_ABI_DEBUG
    // quick and dirty stack dumper for debugging
    for ( int i = -8; i < 8; i++ )
    {
        uint32_t data = 0;
        lldb::addr_t addr = sp + i * 4;
        proc->ReadMemory( addr, (void*)&data, sizeof( data ), error );
        printf( "\n0x%04" PRIx64 " 0x%08x ", addr, data );
        if ( i == 0 ) printf( "<<-- sp" );
    }
    printf( "\n" );
#endif

    return true;
}
bool
ClangUserExpression::Parse (Stream &error_stream, 
                            ExecutionContext &exe_ctx,
                            lldb_private::ExecutionPolicy execution_policy,
                            bool keep_result_in_memory)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    
    Error err;
 
    InstallContext(exe_ctx);
    
    ScanContext(exe_ctx, err);
    
    if (!err.Success())
    {
        error_stream.Printf("warning: %s\n", err.AsCString());
    }
    
    StreamString m_transformed_stream;
    
    ////////////////////////////////////
    // Generate the expression
    //
    
    ApplyObjcCastHack(m_expr_text);
    //ApplyUnicharHack(m_expr_text);

    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));
    
    lldb::LanguageType lang_type;
    
    if (m_cplusplus)
        lang_type = lldb::eLanguageTypeC_plus_plus;
    else if(m_objectivec)
        lang_type = lldb::eLanguageTypeObjC;
    else
        lang_type = lldb::eLanguageTypeC;
    
    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method))
    {
        error_stream.PutCString ("error: couldn't construct expression body");
        return false;
    }
    
    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
    
    ////////////////////////////////////
    // Set up the target and compiler
    //
    
    Target *target = exe_ctx.GetTargetPtr();
    
    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }
    
    //////////////////////////
    // Parse the expression
    //
        
    m_materializer_ap.reset(new Materializer());
        
    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
    
    class OnExit
    {
    public:
        typedef std::function <void (void)> Callback;
        
        OnExit (Callback const &callback) :
            m_callback(callback)
        {
        }
        
        ~OnExit ()
        {
            m_callback();
        }
    private:
        Callback m_callback;
    };
    
    OnExit on_exit([this]() { m_expr_decl_map.reset(); });
    
    if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
        
        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
        
        return false;
    }
    
    Process *process = exe_ctx.GetProcessPtr();
    ExecutionContextScope *exe_scope = process;
    
    if (!exe_scope)
        exe_scope = exe_ctx.GetTargetPtr();
    
    ClangExpressionParser parser(exe_scope, *this);
    
    unsigned num_errors = parser.Parse (error_stream);
    
    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
        
        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
        
        return false;
    }
    
    //////////////////////////////////////////////////////////////////////////////////////////
    // Prepare the output of the parser for execution, evaluating it statically if possible
    //
            
    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
                                                  m_jit_end_addr,
                                                  m_execution_unit_ap,
                                                  exe_ctx,
                                                  m_can_interpret,
                                                  execution_policy);
    
    m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions.
        
    if (jit_error.Success())
    {
        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
lldb_private::Error
NativeRegisterContextLinux_mips64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
{
    Error error;

    if (!reg_info)
    {
        error.SetErrorString ("reg_info NULL");
        return error;
    }

    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
    if (reg == LLDB_INVALID_REGNUM)
    {
        // This is likely an internal register for lldb use only and should not be directly queried.
        error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
        return error;
    }

    if (IsMSA(reg) && !IsMSAAvailable())
    {
        error.SetErrorString ("MSA not available on this processor");
        return error;
    }

    if (IsMSA(reg) || IsFPR(reg))
    {
        uint8_t *src;

        error = ReadCP1();

        if (!error.Success())
        {
            error.SetErrorString ("failed to read co-processor 1 register");
            return error;
        }

        if (IsFPR(reg))
        {
            assert (reg_info->byte_offset < sizeof(UserArea));
            src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
        }
        else
        {
            assert (reg_info->byte_offset < sizeof(UserArea));
            src = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr));
        }
        switch (reg_info->byte_size)
        {
            case 4:
                reg_value.SetUInt32(*(uint32_t *)src);
                break;
            case 8:
                reg_value.SetUInt64(*(uint64_t *)src);
                break;
            case 16:
                reg_value.SetBytes((const void *)src, 16, GetByteOrder());
                break;
            default:
                assert(false && "Unhandled data size.");
                error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
                break;
        }
    }
    else
    {
        error = ReadRegisterRaw(reg, reg_value);
    }

    return error;
}
lldb_private::Error
NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
{
    Error error;

    assert (reg_info && "reg_info is null");

    const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];

    if (reg_index == LLDB_INVALID_REGNUM)
        return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");

    if (IsMSA(reg_index) && !IsMSAAvailable())
    {
        error.SetErrorString ("MSA not available on this processor");
        return error;
    }

    if (IsFPR(reg_index) || IsMSA(reg_index))
    {
        uint8_t *dst;
        uint64_t *src;

        // Initialise the FP and MSA buffers by reading all co-processor 1 registers
        ReadCP1();

        if (IsFPR(reg_index))
        {
            assert (reg_info->byte_offset < sizeof(UserArea));
            dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
        }
        else
        {
            assert (reg_info->byte_offset < sizeof(UserArea));
            dst = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr));
        }
        switch (reg_info->byte_size)
        {
            case 4:
                *(uint32_t *)dst = reg_value.GetAsUInt32();
                break;
            case 8:
                *(uint64_t *)dst = reg_value.GetAsUInt64();
                break;
            case 16:
                src = (uint64_t *)reg_value.GetBytes();
                *(uint64_t *)dst = *src;
                *(uint64_t *)(dst + 8) = *(src + 1);
                break;
            default:
                assert(false && "Unhandled data size.");
                error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
                break;
        }
        error = WriteCP1();
        if (!error.Success())
        {
            error.SetErrorString ("failed to write co-processor 1 register");
            return error;
        }
    }
    else
    {
        error = WriteRegisterRaw(reg_index, reg_value);
    }

    return error;
}
Example #10
0
bool
Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error)
{
    if (info == NULL)
        return false;

    posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions);

    switch (info->GetAction())
    {
        case FileAction::eFileActionNone:
            error.Clear();
            break;

        case FileAction::eFileActionClose:
            if (info->GetFD() == -1)
                error.SetErrorString("invalid fd for posix_spawn_file_actions_addclose(...)");
            else
            {
                error.SetError(::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX);
                if (log && (error.Fail() || log))
                    error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)",
                                   static_cast<void *>(file_actions), info->GetFD());
            }
            break;

        case FileAction::eFileActionDuplicate:
            if (info->GetFD() == -1)
                error.SetErrorString("invalid fd for posix_spawn_file_actions_adddup2(...)");
            else if (info->GetActionArgument() == -1)
                error.SetErrorString("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
            else
            {
                error.SetError(
                    ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()),
                    eErrorTypePOSIX);
                if (log && (error.Fail() || log))
                    error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)",
                                   static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument());
            }
            break;

        case FileAction::eFileActionOpen:
            if (info->GetFD() == -1)
                error.SetErrorString("invalid fd in posix_spawn_file_actions_addopen(...)");
            else
            {
                int oflag = info->GetActionArgument();

                mode_t mode = 0;

                if (oflag & O_CREAT)
                    mode = 0640;

                error.SetError(
                    ::posix_spawn_file_actions_addopen(file_actions, info->GetFD(), info->GetPath(), oflag, mode),
                    eErrorTypePOSIX);
                if (error.Fail() || log)
                    error.PutToLog(log,
                                   "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)",
                                   static_cast<void *>(file_actions), info->GetFD(), info->GetPath(), oflag, mode);
            }
            break;
    }
    return error.Success();
}
Example #11
0
bool
JITLoaderGDB::ReadJITDescriptor(bool all_entries)
{
    if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
        return false;

    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
    Target &target = m_process->GetTarget();
    ModuleList &module_list = target.GetImages();

    jit_descriptor jit_desc;
    const size_t jit_desc_size = sizeof(jit_desc);
    Error error;
    size_t bytes_read = m_process->DoReadMemory(
        m_jit_descriptor_addr, &jit_desc, jit_desc_size, error);
    if (bytes_read != jit_desc_size || !error.Success())
    {
        if (log)
            log->Printf("JITLoaderGDB::%s failed to read JIT descriptor",
                        __FUNCTION__);
        return false;
    }

    jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
    addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
    if (all_entries)
    {
        jit_action = JIT_REGISTER_FN;
        jit_relevant_entry = (addr_t)jit_desc.first_entry;
    }

    while (jit_relevant_entry != 0)
    {
        jit_code_entry jit_entry;
        const size_t jit_entry_size = sizeof(jit_entry);
        bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error);
        if (bytes_read != jit_entry_size || !error.Success())
        {
            if (log)
                log->Printf(
                    "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
                    __FUNCTION__, jit_relevant_entry);
            return false;
        }

        const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
        const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
        ModuleSP module_sp;

        if (jit_action == JIT_REGISTER_FN)
        {
            if (log)
                log->Printf(
                    "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
                    " (%" PRIu64 " bytes)",
                    __FUNCTION__, symbolfile_addr, (uint64_t) symbolfile_size);

            char jit_name[64];
            snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
            module_sp = m_process->ReadModuleFromMemory(
                FileSpec(jit_name, false), symbolfile_addr, symbolfile_size);

            if (module_sp && module_sp->GetObjectFile())
            {
                bool changed;
                m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
                if (module_sp->GetObjectFile()->GetPluginName() == ConstString("mach-o"))
                {
                    ObjectFile *image_object_file = module_sp->GetObjectFile();
                    if (image_object_file)
                    {
                        const SectionList *section_list = image_object_file->GetSectionList ();
                        if (section_list)
                        {
                            uint64_t vmaddrheuristic = 0;
                            uint64_t lower = (uint64_t)-1;
                            uint64_t upper = 0;
                            updateSectionLoadAddress(*section_list, target, symbolfile_addr, symbolfile_size,
                                vmaddrheuristic, lower, upper);
                        }
                    }
                }
                else
                {
                    module_sp->SetLoadAddress(target, 0, true, changed);
                }

                // load the symbol table right away
                module_sp->GetObjectFile()->GetSymtab();

                module_list.AppendIfNeeded(module_sp);

                ModuleList module_list;
                module_list.Append(module_sp);
                target.ModulesDidLoad(module_list);
            }
            else
            {
                if (log)
                    log->Printf("JITLoaderGDB::%s failed to load module for "
                                "JIT entry at 0x%" PRIx64,
                                __FUNCTION__, symbolfile_addr);
            }
        }
        else if (jit_action == JIT_UNREGISTER_FN)
        {
            if (log)
                log->Printf(
                    "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
                    __FUNCTION__, symbolfile_addr);

            JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
            if (it != m_jit_objects.end())
            {
                module_sp = it->second;
                ObjectFile *image_object_file = module_sp->GetObjectFile();
                if (image_object_file)
                {
                    const SectionList *section_list = image_object_file->GetSectionList ();
                    if (section_list)
                    {
                        const uint32_t num_sections = section_list->GetSize();
                        for (uint32_t i = 0; i<num_sections; ++i)
                        {
                            SectionSP section_sp(section_list->GetSectionAtIndex(i));
                            if (section_sp)
                            {
                                target.GetSectionLoadList().SetSectionUnloaded (section_sp);
                            }
                        }
                    }
                }
                module_list.Remove(module_sp);
                m_jit_objects.erase(it);
            }
        }
        else if (jit_action == JIT_NOACTION)
        {
            // Nothing to do
        }
        else
        {
            assert(false && "Unknown jit action");
        }

        if (all_entries)
            jit_relevant_entry = (addr_t)jit_entry.next_entry;
        else
            jit_relevant_entry = 0;
    }

    return false; // Continue Running.
}
Example #12
0
Error
Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
{
    Error error;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));

    posix_spawnattr_t attr;
    error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);

    if (error.Fail() || log)
        error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
    if (error.Fail())
        return error;

    // Make a quick class that will cleanup the posix spawn attributes in case
    // we return in the middle of this function.
    lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);

    sigset_t no_signals;
    sigset_t all_signals;
    sigemptyset (&no_signals);
    sigfillset (&all_signals);
    ::posix_spawnattr_setsigmask(&attr, &no_signals);
#if defined (__linux__)  || defined (__FreeBSD__)
    ::posix_spawnattr_setsigdefault(&attr, &no_signals);
#else
    ::posix_spawnattr_setsigdefault(&attr, &all_signals);
#endif

    short flags = GetPosixspawnFlags(launch_info);

    error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
    if (error.Fail() || log)
        error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
    if (error.Fail())
        return error;

    // posix_spawnattr_setbinpref_np appears to be an Apple extension per:
    // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/
#if defined (__APPLE__) && !defined (__arm__)
    
    // Don't set the binpref if a shell was provided.  After all, that's only going to affect what version of the shell
    // is launched, not what fork of the binary is launched.  We insert "arch --arch <ARCH> as part of the shell invocation
    // to do that job on OSX.
    
    if (launch_info.GetShell() == nullptr)
    {
        // We don't need to do this for ARM, and we really shouldn't now that we
        // have multiple CPU subtypes and no posix_spawnattr call that allows us
        // to set which CPU subtype to launch...
        const ArchSpec &arch_spec = launch_info.GetArchitecture();
        cpu_type_t cpu = arch_spec.GetMachOCPUType();
        cpu_type_t sub = arch_spec.GetMachOCPUSubType();
        if (cpu != 0 &&
            cpu != static_cast<cpu_type_t>(UINT32_MAX) &&
            cpu != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE) &&
            !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try to set the CPU type or we will fail 
        {
            size_t ocount = 0;
            error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
            if (error.Fail() || log)
                error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount);

            if (error.Fail() || ocount != 1)
                return error;
        }
    }

#endif

    const char *tmp_argv[2];
    char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
    char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
    if (argv == NULL)
    {
        // posix_spawn gets very unhappy if it doesn't have at least the program
        // name in argv[0]. One of the side affects I have noticed is the environment
        // variables don't make it into the child process if "argv == NULL"!!!
        tmp_argv[0] = exe_path;
        tmp_argv[1] = NULL;
        argv = (char * const*)tmp_argv;
    }

#if !defined (__APPLE__)
    // manage the working directory
    char current_dir[PATH_MAX];
    current_dir[0] = '\0';
#endif

    FileSpec working_dir{launch_info.GetWorkingDirectory()};
    if (working_dir)
    {
#if defined (__APPLE__)
        // Set the working directory on this thread only
        if (__pthread_chdir(working_dir.GetCString()) < 0) {
            if (errno == ENOENT) {
                error.SetErrorStringWithFormat("No such file or directory: %s",
                        working_dir.GetCString());
            } else if (errno == ENOTDIR) {
                error.SetErrorStringWithFormat("Path doesn't name a directory: %s",
                        working_dir.GetCString());
            } else {
                error.SetErrorStringWithFormat("An unknown error occurred when changing directory for process execution.");
            }
            return error;
        }
#else
        if (::getcwd(current_dir, sizeof(current_dir)) == NULL)
        {
            error.SetError(errno, eErrorTypePOSIX);
            error.LogIfError(log, "unable to save the current directory");
            return error;
        }

        if (::chdir(working_dir.GetCString()) == -1)
        {
            error.SetError(errno, eErrorTypePOSIX);
            error.LogIfError(log, "unable to change working directory to %s",
                    working_dir.GetCString());
            return error;
        }
#endif
    }

    ::pid_t result_pid = LLDB_INVALID_PROCESS_ID;
    const size_t num_file_actions = launch_info.GetNumFileActions ();
    if (num_file_actions > 0)
    {
        posix_spawn_file_actions_t file_actions;
        error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
        if (error.Fail() || log)
            error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
        if (error.Fail())
            return error;

        // Make a quick class that will cleanup the posix spawn attributes in case
        // we return in the middle of this function.
        lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy);

        for (size_t i=0; i<num_file_actions; ++i)
        {
            const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
            if (launch_file_action)
            {
                if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error))
                    return error;
            }
        }

        error.SetError(::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX);

        if (error.Fail() || log)
        {
            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", result_pid,
                           exe_path, static_cast<void *>(&file_actions), static_cast<void *>(&attr), reinterpret_cast<const void *>(argv),
                           reinterpret_cast<const void *>(envp));
            if (log)
            {
                for (int ii=0; argv[ii]; ++ii)
                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
            }
        }

    }
    else
    {
        error.SetError(::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX);

        if (error.Fail() || log)
        {
            error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
                           result_pid, exe_path, static_cast<void *>(&attr), reinterpret_cast<const void *>(argv),
                           reinterpret_cast<const void *>(envp));
            if (log)
            {
                for (int ii=0; argv[ii]; ++ii)
                    log->Printf("argv[%i] = '%s'", ii, argv[ii]);
            }
        }
    }
    pid = result_pid;

    if (working_dir)
    {
#if defined (__APPLE__)
        // No more thread specific current working directory
        __pthread_fchdir (-1);
#else
        if (::chdir(current_dir) == -1 && error.Success())
        {
            error.SetError(errno, eErrorTypePOSIX);
            error.LogIfError(log, "unable to change current directory back to %s",
                    current_dir);
        }
#endif
    }

    return error;
}
Example #13
0
Error
Host::RunShellCommand(const Args &args,
                      const FileSpec &working_dir,
                      int *status_ptr,
                      int *signo_ptr,
                      std::string *command_output_ptr,
                      uint32_t timeout_sec,
                      bool run_in_default_shell)
{
    Error error;
    ProcessLaunchInfo launch_info;
    launch_info.SetArchitecture(HostInfo::GetArchitecture());
    if (run_in_default_shell)
    {
        // Run the command in a shell
        launch_info.SetShell(HostInfo::GetDefaultShell());
        launch_info.GetArguments().AppendArguments(args);
        const bool localhost = true;
        const bool will_debug = false;
        const bool first_arg_is_full_shell_command = false;
        launch_info.ConvertArgumentsForLaunchingInShell (error,
                                                         localhost,
                                                         will_debug,
                                                         first_arg_is_full_shell_command,
                                                         0);
    }
    else
    {
        // No shell, just run it
        const bool first_arg_is_executable = true;
        launch_info.SetArguments(args, first_arg_is_executable);
    }
    
    if (working_dir)
        launch_info.SetWorkingDirectory(working_dir);
    llvm::SmallString<PATH_MAX> output_file_path;
    
    if (command_output_ptr)
    {
        // Create a temporary file to get the stdout/stderr and redirect the
        // output of the command into this file. We will later read this file
        // if all goes well and fill the data into "command_output_ptr"
        FileSpec tmpdir_file_spec;
        if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
        {
            tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%");
            llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path);
        }
        else
        {
            llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path);
        }
    }

    FileSpec output_file_spec{output_file_path.c_str(), false};

    launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
    if (output_file_spec)
    {
        launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true);
        launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
    }
    else
    {
        launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);
        launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);
    }
    
    // The process monitor callback will delete the 'shell_info_ptr' below...
    std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo());
    
    const bool monitor_signals = false;
    launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals);
    
    error = LaunchProcess (launch_info);
    const lldb::pid_t pid = launch_info.GetProcessID();
    
    if (error.Success() && pid == LLDB_INVALID_PROCESS_ID)
        error.SetErrorString("failed to get process ID");
    
    if (error.Success())
    {
        // The process successfully launched, so we can defer ownership of
        // "shell_info" to the MonitorShellCommand callback function that will
        // get called when the process dies. We release the unique pointer as it
        // doesn't need to delete the ShellInfo anymore.
        ShellInfo *shell_info = shell_info_ap.release();
        TimeValue *timeout_ptr = nullptr;
        TimeValue timeout_time(TimeValue::Now());
        if (timeout_sec > 0) {
            timeout_time.OffsetWithSeconds(timeout_sec);
            timeout_ptr = &timeout_time;
        }
        bool timed_out = false;
        shell_info->process_reaped.WaitForValueEqualTo(true, timeout_ptr, &timed_out);
        if (timed_out)
        {
            error.SetErrorString("timed out waiting for shell command to complete");
            
            // Kill the process since it didn't complete within the timeout specified
            Kill (pid, SIGKILL);
            // Wait for the monitor callback to get the message
            timeout_time = TimeValue::Now();
            timeout_time.OffsetWithSeconds(1);
            timed_out = false;
            shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out);
        }
        else
        {
            if (status_ptr)
                *status_ptr = shell_info->status;
            
            if (signo_ptr)
                *signo_ptr = shell_info->signo;
            
            if (command_output_ptr)
            {
                command_output_ptr->clear();
                uint64_t file_size = output_file_spec.GetByteSize();
                if (file_size > 0)
                {
                    if (file_size > command_output_ptr->max_size())
                    {
                        error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string");
                    }
                    else
                    {
                        std::vector<char> command_output(file_size);
                        output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error);
                        if (error.Success())
                            command_output_ptr->assign(command_output.data(), file_size);
                    }
                }
            }
        }
        shell_info->can_delete.SetValue(true, eBroadcastAlways);
    }

    if (FileSystem::GetFileExists(output_file_spec))
        FileSystem::Unlink(output_file_spec);
    // Handshake with the monitor thread, or just let it know in advance that
    // it can delete "shell_info" in case we timed out and were not able to kill
    // the process...
    return error;
}
Example #14
0
void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
                                lldb::addr_t process_address, size_t size,
                                Error &error) {
  error.Clear();

  if (size > 0) {
    AllocationMap::iterator iter = FindAllocation(process_address, size);

    if (iter == m_allocations.end()) {
      error.SetErrorToGenericError();
      error.SetErrorStringWithFormat(
          "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
          ")",
          process_address, process_address + size);
      return;
    }

    Allocation &allocation = iter->second;

    switch (allocation.m_policy) {
    default:
      error.SetErrorToGenericError();
      error.SetErrorString(
          "Couldn't get memory data: invalid allocation policy");
      return;
    case eAllocationPolicyProcessOnly:
      error.SetErrorToGenericError();
      error.SetErrorString(
          "Couldn't get memory data: memory is only in the target");
      return;
    case eAllocationPolicyMirror: {
      lldb::ProcessSP process_sp = m_process_wp.lock();

      if (!allocation.m_data.GetByteSize()) {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't get memory data: data buffer is empty");
        return;
      }
      if (process_sp) {
        process_sp->ReadMemory(allocation.m_process_start,
                               allocation.m_data.GetBytes(),
                               allocation.m_data.GetByteSize(), error);
        if (!error.Success())
          return;
        uint64_t offset = process_address - allocation.m_process_start;
        extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
                                  GetByteOrder(), GetAddressByteSize());
        return;
      }
    } break;
    case eAllocationPolicyHostOnly:
      if (!allocation.m_data.GetByteSize()) {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't get memory data: data buffer is empty");
        return;
      }
      uint64_t offset = process_address - allocation.m_process_start;
      extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
                                GetByteOrder(), GetAddressByteSize());
      return;
    }
  } else {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't get memory data: its size was zero");
    return;
  }
}
Example #15
0
Error
PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
                                    Process* process,
                                    ModuleSP &module_sp,
                                    const FileSpecList *module_search_paths_ptr,
                                    ModuleSP *old_module_sp_ptr,
                                    bool *did_create_ptr)
{
    // For iOS, the SDK files are all cached locally on the host
    // system. So first we ask for the file in the cached SDK,
    // then we attempt to get a shared module for the right architecture
    // with the right UUID.
    const FileSpec &platform_file = module_spec.GetFileSpec();

    Error error;
    char platform_file_path[PATH_MAX];
    
    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
    {
        ModuleSpec platform_module_spec(module_spec);

        UpdateSDKDirectoryInfosIfNeeded();

        const uint32_t num_sdk_infos = m_sdk_directory_infos.size();

        // If we are connected we migth be able to correctly deduce the SDK directory
        // using the OS build.
        const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
        if (connected_sdk_idx < num_sdk_infos)
        {
            if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    m_last_module_sdk_idx = connected_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Try the last SDK index if it is set as most files from an SDK
        // will tend to be valid in that same SDK.
        if (m_last_module_sdk_idx < num_sdk_infos)
        {
            if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    error.Clear();
                    return error;
                }
            }
        }
        
        // First try for an exact match of major, minor and update:
        // If a particalar SDK version was specified via --version or --build, look for a match on disk.
        const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion();
        const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
        if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx)
        {
            if (GetFileInSDK (platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    m_last_module_sdk_idx = current_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Second try all SDKs that were found.
        for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
        {
            if (m_last_module_sdk_idx == sdk_idx)
            {
                // Skip the last module SDK index if we already searched
                // it above
                continue;
            }
            if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
            {
                //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
                
                error = ResolveExecutable (platform_module_spec, module_sp, NULL);
                if (module_sp)
                {
                    // Remember the index of the last SDK that we found a file
                    // in in case the wrong SDK was selected.
                    m_last_module_sdk_idx = sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }
    }
    // Not the module we are looking for... Nothing to see here...
    module_sp.reset();

    // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
    error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
    if (error.Success())
        return error;

    const bool always_create = false;
    error = ModuleList::GetSharedModule (module_spec,
                                         module_sp,
                                         module_search_paths_ptr,
                                         old_module_sp_ptr,
                                         did_create_ptr,
                                         always_create);

    if (module_sp)
        module_sp->SetPlatformFileSpec(platform_file);

    return error;
}
lldb::ProcessSP
PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
                                 Debugger &debugger,
                                 Target *target,       // Can be NULL, if NULL create a new target, else use existing one
                                 Listener &listener, 
                                 Error &error)
{
    lldb::ProcessSP process_sp;
    if (IsRemote())
    {
        if (IsConnected())
        {
            lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
            ArchSpec remote_arch = GetRemoteSystemArchitecture();
            llvm::Triple &remote_triple = remote_arch.GetTriple();
            uint16_t port = 0;
            if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS)
            {
                // When remote debugging to iOS, we use a USB mux that always talks
                // to localhost, so we will need the remote debugserver to accept connections
                // only from localhost, no matter what our current hostname is
                port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "127.0.0.1");
            }
            else
            {
                // All other hosts should use their actual hostname
                port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL);
            }
            
            if (port == 0)
            {
                error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
            }
            else
            {
                if (target == NULL)
                {
                    TargetSP new_target_sp;
                    
                    error = debugger.GetTargetList().CreateTarget (debugger,
                                                                   NULL,
                                                                   NULL, 
                                                                   false,
                                                                   NULL,
                                                                   new_target_sp);
                    target = new_target_sp.get();
                }
                else
                    error.Clear();
                
                if (target && error.Success())
                {
                    debugger.GetTargetList().SetSelectedTarget(target);
                    
                    // The darwin always currently uses the GDB remote debugger plug-in
                    // so even when debugging locally we are debugging remotely!
                    process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
                    
                    if (process_sp)
                    {
                        char connect_url[256];
                        const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
                        const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
                        int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
                        const int connect_url_len = ::snprintf (connect_url, 
                                                                sizeof(connect_url), 
                                                                "connect://%s:%u", 
                                                                override_hostname ? override_hostname : GetHostname (), 
                                                                port + port_offset);
                        assert (connect_url_len < (int)sizeof(connect_url));
                        error = process_sp->ConnectRemote (NULL, connect_url);
                        if (error.Success())
                            error = process_sp->Attach(attach_info);
                        else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
                        {
                            m_gdb_client.KillSpawnedProcess(debugserver_pid);
                        }
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("not connected to remote gdb server");
        }
    }
    return process_sp;
}
Example #17
0
Error
TargetList::CreateTarget
(
    Debugger &debugger,
    const FileSpec& file,
    const ArchSpec& specified_arch,
    bool get_dependent_files,
    PlatformSP &platform_sp,
    TargetSP &target_sp
)
{
    Timer scoped_timer (__PRETTY_FUNCTION__,
                        "TargetList::CreateTarget (file = '%s/%s', arch = '%s')",
                        file.GetDirectory().AsCString(),
                        file.GetFilename().AsCString(),
                        specified_arch.GetArchitectureName());
    Error error;

    ArchSpec arch(specified_arch);

    if (platform_sp)
    {
        if (arch.IsValid())
        {
            if (!platform_sp->IsCompatibleArchitecture(arch))
                platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
        }
    }
    else if (arch.IsValid())
    {
        platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
    }
    
    if (!platform_sp)
        platform_sp = debugger.GetPlatformList().GetSelectedPlatform();

    if (!arch.IsValid())
        arch = specified_arch;
    

    if (file)
    {
        ModuleSP exe_module_sp;
        FileSpec resolved_file(file);
        if (platform_sp)
        {
            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
            error = platform_sp->ResolveExecutable (file,
                                                    arch,
                                                    exe_module_sp, 
                                                    executable_search_paths.GetSize() ? &executable_search_paths : NULL);
        }

        if (error.Success() && exe_module_sp)
        {
            if (exe_module_sp->GetObjectFile() == NULL)
            {
                if (arch.IsValid())
                {
                    error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
                                                   file.GetDirectory().AsCString(),
                                                   file.GetDirectory() ? "/" : "",
                                                   file.GetFilename().AsCString(),
                                                   arch.GetArchitectureName());
                }
                else
                {
                    error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
                                                   file.GetDirectory().AsCString(),
                                                   file.GetDirectory() ? "/" : "",
                                                   file.GetFilename().AsCString());
                }
                return error;
            }
            target_sp.reset(new Target(debugger, arch, platform_sp));
            target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
        }
    }
    else
    {
        // No file was specified, just create an empty target with any arch
        // if a valid arch was specified
        target_sp.reset(new Target(debugger, arch, platform_sp));
    }

    if (target_sp)
    {
        target_sp->UpdateInstanceName();        

        Mutex::Locker locker(m_target_list_mutex);
        m_selected_target_idx = m_target_list.size();
        m_target_list.push_back(target_sp);
    }

    return error;
}
Example #18
0
Error
ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
{
    Error error;

    // Don't let any JIT happen when doing KDP as we can't allocate
    // memory and we don't want to be mucking with threads that might
    // already be handling exceptions
    SetCanJIT(false);

    if (remote_url == NULL || remote_url[0] == '\0')
    {
        error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url);
        return error;
    }

    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
    if (conn_ap.get())
    {
        // Only try once for now.
        // TODO: check if we should be retrying?
        const uint32_t max_retry_count = 1;
        for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count)
        {
            if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess)
                break;
            usleep (100000);
        }
    }

    if (conn_ap->IsConnected())
    {
        const uint16_t reply_port = conn_ap->GetReadPort ();

        if (reply_port != 0)
        {
            m_comm.SetConnection(conn_ap.release());

            if (m_comm.SendRequestReattach(reply_port))
            {
                if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB..."))
                {
                    m_comm.GetVersion();
                    uint32_t cpu = m_comm.GetCPUType();
                    uint32_t sub = m_comm.GetCPUSubtype();
                    ArchSpec kernel_arch;
                    kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                    m_target.SetArchitecture(kernel_arch);

                    /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet.  */
                    /* An EFI kdp session has neither UUID nor load address. */

                    UUID kernel_uuid = m_comm.GetUUID ();
                    addr_t kernel_load_addr = m_comm.GetLoadAddress ();

                    if (m_comm.RemoteIsEFI ())
                    {
                        m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
                    }
                    else if (m_comm.RemoteIsDarwinKernel ())
                    {
                        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
                        if (kernel_load_addr != LLDB_INVALID_ADDRESS)
                        {
                            m_kernel_load_addr = kernel_load_addr;
                        }
                    }

                    // Set the thread ID
                    UpdateThreadListIfNeeded ();
                    SetID (1);
                    GetThreadList ();
                    SetPrivateState (eStateStopped);
                    StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream());
                    if (async_strm_sp)
                    {
                        const char *cstr;
                        if ((cstr = m_comm.GetKernelVersion ()) != NULL)
                        {
                            async_strm_sp->Printf ("Version: %s\n", cstr);
                            async_strm_sp->Flush();
                        }
//                      if ((cstr = m_comm.GetImagePath ()) != NULL)
//                      {
//                          async_strm_sp->Printf ("Image Path: %s\n", cstr);
//                          async_strm_sp->Flush();
//                      }            
                    }
                }
                else
                {
                    error.SetErrorString("KDP_REATTACH failed");
                }
            }
            else
            {
                error.SetErrorString("KDP_REATTACH failed");
            }
        }
        else
        {
            error.SetErrorString("invalid reply port from UDP connection");
        }
    }
    else
    {
        if (error.Success())
            error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url);
    }
    if (error.Fail())
        m_comm.Disconnect();

    return error;
}
Example #19
0
bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
                                          bool force_lookup) {
  bool success = false;
  const UUID *uuid_ptr = module_spec.GetUUIDPtr();
  const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();

  // It's expensive to check for the DBGShellCommands defaults setting, only do
  // it once per
  // lldb run and cache the result.
  static bool g_have_checked_for_dbgshell_command = false;
  static const char *g_dbgshell_command = NULL;
  if (g_have_checked_for_dbgshell_command == false) {
    g_have_checked_for_dbgshell_command = true;
    CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
        CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
    if (defaults_setting &&
        CFGetTypeID(defaults_setting) == CFStringGetTypeID()) {
      char cstr_buf[PATH_MAX];
      if (CFStringGetCString((CFStringRef)defaults_setting, cstr_buf,
                             sizeof(cstr_buf), kCFStringEncodingUTF8)) {
        g_dbgshell_command =
            strdup(cstr_buf); // this malloc'ed memory will never be freed
      }
    }
    if (defaults_setting) {
      CFRelease(defaults_setting);
    }
  }

  // When g_dbgshell_command is NULL, the user has not enabled the use of an
  // external program
  // to find the symbols, don't run it for them.
  if (force_lookup == false && g_dbgshell_command == NULL) {
    return false;
  }

  if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) {
    static bool g_located_dsym_for_uuid_exe = false;
    static bool g_dsym_for_uuid_exe_exists = false;
    static char g_dsym_for_uuid_exe_path[PATH_MAX];
    if (!g_located_dsym_for_uuid_exe) {
      g_located_dsym_for_uuid_exe = true;
      const char *dsym_for_uuid_exe_path_cstr =
          getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
      FileSpec dsym_for_uuid_exe_spec;
      if (dsym_for_uuid_exe_path_cstr) {
        dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
        g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
      }

      if (!g_dsym_for_uuid_exe_exists) {
        dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
        g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
        if (!g_dsym_for_uuid_exe_exists) {
          long bufsize;
          if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) {
            char buffer[bufsize];
            struct passwd pwd;
            struct passwd *tilde_rc = NULL;
            // we are a library so we need to use the reentrant version of
            // getpwnam()
            if (getpwnam_r("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 &&
                tilde_rc && tilde_rc->pw_dir) {
              std::string dsymforuuid_path(tilde_rc->pw_dir);
              dsymforuuid_path += "/bin/dsymForUUID";
              dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false);
              g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
            }
          }
        }
      }
      if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) {
        dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true);
        g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
      }

      if (g_dsym_for_uuid_exe_exists)
        dsym_for_uuid_exe_spec.GetPath(g_dsym_for_uuid_exe_path,
                                       sizeof(g_dsym_for_uuid_exe_path));
    }
    if (g_dsym_for_uuid_exe_exists) {
      std::string uuid_str;
      char file_path[PATH_MAX];
      file_path[0] = '\0';

      if (uuid_ptr)
        uuid_str = uuid_ptr->GetAsString();

      if (file_spec_ptr)
        file_spec_ptr->GetPath(file_path, sizeof(file_path));

      StreamString command;
      if (!uuid_str.empty())
        command.Printf("%s --ignoreNegativeCache --copyExecutable --databases "
                       "bursar.apple.com,uuidsymmap.apple.com %s",
                       g_dsym_for_uuid_exe_path, uuid_str.c_str());
      else if (file_path[0] != '\0')
        command.Printf("%s --ignoreNegativeCache --copyExecutable --databases "
                       "bursar.apple.com,uuidsymmap.apple.com %s",
                       g_dsym_for_uuid_exe_path, file_path);

      if (!command.GetString().empty()) {
        Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
        int exit_status = -1;
        int signo = -1;
        std::string command_output;
        if (log) {
          if (!uuid_str.empty())
            log->Printf("Calling %s with UUID %s to find dSYM",
                        g_dsym_for_uuid_exe_path, uuid_str.c_str());
          else if (file_path[0] != '\0')
            log->Printf("Calling %s with file %s to find dSYM",
                        g_dsym_for_uuid_exe_path, file_path);
        }
        Error error = Host::RunShellCommand(
            command.GetData(),
            NULL,            // current working directory
            &exit_status,    // Exit status
            &signo,          // Signal int *
            &command_output, // Command output
            30,     // Large timeout to allow for long dsym download times
            false); // Don't run in a shell (we don't need shell expansion)
        if (error.Success() && exit_status == 0 && !command_output.empty()) {
          CFCData data(CFDataCreateWithBytesNoCopy(
              NULL, (const UInt8 *)command_output.data(), command_output.size(),
              kCFAllocatorNull));

          CFCReleaser<CFDictionaryRef> plist(
              (CFDictionaryRef)::CFPropertyListCreateFromXMLData(
                  NULL, data.get(), kCFPropertyListImmutable, NULL));

          if (plist.get() &&
              CFGetTypeID(plist.get()) == CFDictionaryGetTypeID()) {
            if (!uuid_str.empty()) {
              CFCString uuid_cfstr(uuid_str.c_str());
              CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue(
                  plist.get(), uuid_cfstr.get());
              success =
                  GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec);
            } else {
              const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
              if (num_values > 0) {
                std::vector<CFStringRef> keys(num_values, NULL);
                std::vector<CFDictionaryRef> values(num_values, NULL);
                ::CFDictionaryGetKeysAndValues(plist.get(), NULL,
                                               (const void **)&values[0]);
                if (num_values == 1) {
                  return GetModuleSpecInfoFromUUIDDictionary(values[0],
                                                             module_spec);
                } else {
                  for (CFIndex i = 0; i < num_values; ++i) {
                    ModuleSpec curr_module_spec;
                    if (GetModuleSpecInfoFromUUIDDictionary(values[i],
                                                            curr_module_spec)) {
                      if (module_spec.GetArchitecture().IsCompatibleMatch(
                              curr_module_spec.GetArchitecture())) {
                        module_spec = curr_module_spec;
                        return true;
                      }
                    }
                  }
                }
              }
            }
          }
        } else {
          if (log) {
            if (!uuid_str.empty())
              log->Printf("Called %s on %s, no matches",
                          g_dsym_for_uuid_exe_path, uuid_str.c_str());
            else if (file_path[0] != '\0')
              log->Printf("Called %s on %s, no matches",
                          g_dsym_for_uuid_exe_path, file_path);
          }
        }
      }
    }
  }
  return success;
}
Example #20
0
 bool
 DoExecute (Args& command, CommandReturnObject &result)
 {
     const size_t argc = command.GetArgumentCount();
     if (argc == 0)
     {
         if (!m_command_byte.GetOptionValue().OptionWasSet())
         {
             result.AppendError ("the --command option must be set to a valid command byte");
             result.SetStatus (eReturnStatusFailed);
         }
         else
         {
             const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0);
             if (command_byte > 0 && command_byte <= UINT8_MAX)
             {
                 ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
                 if (process)
                 {
                     const StateType state = process->GetState();
                     
                     if (StateIsStoppedState (state, true))
                     {
                         std::vector<uint8_t> payload_bytes;
                         const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue();
                         if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0])
                         {
                             StringExtractor extractor(ascii_hex_bytes_cstr);
                             const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size();
                             if (ascii_hex_bytes_cstr_len & 1)
                             {
                                 result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr);
                                 result.SetStatus (eReturnStatusFailed);
                                 return false;
                             }
                             payload_bytes.resize(ascii_hex_bytes_cstr_len/2);
                             if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size())
                             {
                                 result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr);
                                 result.SetStatus (eReturnStatusFailed);
                                 return false;
                             }
                         }
                         Error error;
                         DataExtractor reply;
                         process->GetCommunication().SendRawRequest (command_byte,
                                                                     payload_bytes.empty() ? NULL : payload_bytes.data(),
                                                                     payload_bytes.size(),
                                                                     reply,
                                                                     error);
                         
                         if (error.Success())
                         {
                             // Copy the binary bytes into a hex ASCII string for the result
                             StreamString packet;
                             packet.PutBytesAsRawHex8(reply.GetDataStart(),
                                                      reply.GetByteSize(),
                                                      lldb::endian::InlHostByteOrder(),
                                                      lldb::endian::InlHostByteOrder());
                             result.AppendMessage(packet.GetString().c_str());
                             result.SetStatus (eReturnStatusSuccessFinishResult);
                             return true;
                         }
                         else
                         {
                             const char *error_cstr = error.AsCString();
                             if (error_cstr && error_cstr[0])
                                 result.AppendError (error_cstr);
                             else
                                 result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError());
                             result.SetStatus (eReturnStatusFailed);
                             return false;
                         }
                     }
                     else
                     {
                         result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state));
                         result.SetStatus (eReturnStatusFailed);
                     }
                 }
                 else
                 {
                     result.AppendError ("invalid process");
                     result.SetStatus (eReturnStatusFailed);
                 }
             }
             else
             {
                 result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte);
                 result.SetStatus (eReturnStatusFailed);
             }
         }
     }
     else
     {
         result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str());
         result.SetStatus (eReturnStatusFailed);
     }
     return false;
 }
Example #21
0
lldb_private::Error
PlatformPOSIX::GetFile(const lldb_private::FileSpec &source,      // remote file path
                       const lldb_private::FileSpec &destination) // local file path
{
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));

    // Check the args, first.
    std::string src_path (source.GetPath());
    if (src_path.empty())
        return Error("unable to get file path for source");
    std::string dst_path (destination.GetPath());
    if (dst_path.empty())
        return Error("unable to get file path for destination");
    if (IsHost())
    {
        if (FileSpec::Equal(source, destination, true))
            return Error("local scenario->source and destination are the same file path: no operation performed");
        // cp src dst
        StreamString cp_command;
        cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
        int status;
        RunShellCommand(cp_command.GetData(),
                        NULL,
                        &status,
                        NULL,
                        NULL,
                        10);
        if (status != 0)
            return Error("unable to perform copy");
        return Error();
    }
    else if (m_remote_platform_sp)
    {
        if (GetSupportsRSync())
        {
            StreamString command;
            if (GetIgnoresRemoteHostname())
            {
                if (!GetRSyncPrefix())
                    command.Printf("rsync %s %s %s",
                                   GetRSyncOpts(),
                                   src_path.c_str(),
                                   dst_path.c_str());
                else
                    command.Printf("rsync %s %s%s %s",
                                   GetRSyncOpts(),
                                   GetRSyncPrefix(),
                                   src_path.c_str(),
                                   dst_path.c_str());
            }
            else
                command.Printf("rsync %s %s:%s %s",
                               GetRSyncOpts(),
                               m_remote_platform_sp->GetHostname(),
                               src_path.c_str(),
                               dst_path.c_str());
            if (log)
                log->Printf("[GetFile] Running command: %s\n", command.GetData());
            int retcode;
            Host::RunShellCommand(command.GetData(),
                                  NULL,
                                  &retcode,
                                  NULL,
                                  NULL,
                                  60);
            if (retcode == 0)
                return Error();
            // If we are here, rsync has failed - let's try the slow way before giving up
        }
        // open src and dst
        // read/write, read/write, read/write, ...
        // close src
        // close dst
        if (log)
            log->Printf("[GetFile] Using block by block transfer....\n");
        Error error;
        user_id_t fd_src = OpenFile (source,
                                     File::eOpenOptionRead,
                                     lldb::eFilePermissionsFileDefault,
                                     error);

        if (fd_src == UINT64_MAX)
            return Error("unable to open source file");

        uint32_t permissions = 0;
        error = GetFilePermissions(source, permissions);

        if (permissions == 0)
            permissions = lldb::eFilePermissionsFileDefault;

        user_id_t fd_dst = FileCache::GetInstance().OpenFile(
            destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions,
            error);

        if (fd_dst == UINT64_MAX)
        {
            if (error.Success())
                error.SetErrorString("unable to open destination file");
        }

        if (error.Success())
        {
            lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
            uint64_t offset = 0;
            error.Clear();
            while (error.Success())
            {
                const uint64_t n_read = ReadFile (fd_src,
                                                  offset,
                                                  buffer_sp->GetBytes(),
                                                  buffer_sp->GetByteSize(),
                                                  error);
                if (error.Fail())
                    break;
                if (n_read == 0)
                    break;
                if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read)
                {
                    if (!error.Fail())
                        error.SetErrorString("unable to write to destination file");
                    break;
                }
                offset += n_read;
            }
        }
        // Ignore the close error of src.
        if (fd_src != UINT64_MAX)
            CloseFile(fd_src, error);
        // And close the dst file descriptot.
        if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error))
        {
            if (!error.Fail())
                error.SetErrorString("unable to close destination file");

        }
        return error;
    }
    return Platform::GetFile(source,destination);
}
Example #22
0
void
TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
        const char *index_value,
        const char *value,
        const ConstString &instance_name,
        const SettingEntry &entry,
        lldb::VarSetOperationType op,
        Error &err,
        bool pending)
{
    int new_enum = -1;

    if (var_name == GetSettingNameForExpressionPrefix ())
    {
        switch (op)
        {
        default:
            err.SetErrorToGenericError ();
            err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
            return;
        case lldb::eVarSetOperationAssign:
        {
            FileSpec file_spec(value, true);

            if (!file_spec.Exists())
            {
                err.SetErrorToGenericError ();
                err.SetErrorStringWithFormat ("%s does not exist.\n", value);
                return;
            }

            DataBufferSP data_sp (file_spec.ReadFileContents());

            if (!data_sp && data_sp->GetByteSize() == 0)
            {
                err.SetErrorToGenericError ();
                err.SetErrorStringWithFormat ("Couldn't read from %s\n", value);
                return;
            }

            m_expr_prefix_path = value;
            m_expr_prefix_contents.assign(reinterpret_cast<const char *>(data_sp->GetBytes()), data_sp->GetByteSize());
        }
        return;
        case lldb::eVarSetOperationAppend:
            err.SetErrorToGenericError ();
            err.SetErrorString ("Cannot append to a path.\n");
            return;
        case lldb::eVarSetOperationClear:
            m_expr_prefix_path.clear ();
            m_expr_prefix_contents.clear ();
            return;
        }
    }
    else if (var_name == GetSettingNameForExecutionLevel ())
    {
        UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
        if (err.Success())
            m_execution_level = (ExecutionLevel)new_enum;
    }
    else if (var_name == GetSettingNameForExecutionMode ())
    {
        UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
        if (err.Success())
            m_execution_mode = (ExecutionMode)new_enum;
    }
    else if (var_name == GetSettingNameForExecutionOSType ())
    {
        UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
        if (err.Success())
            m_execution_os_type = (ExecutionOSType)new_enum;
    }
}
Example #23
0
Error
PlatformNetBSD::ResolveExecutable (const ModuleSpec &module_spec,
                                   lldb::ModuleSP &exe_module_sp,
                                   const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    ModuleSpec resolved_module_spec(module_spec);

    if (IsHost())
    {
        // If we have "ls" as the module_spec's file, resolve the executable location based on
        // the current path variables
        if (!resolved_module_spec.GetFileSpec().Exists())
        {
            module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
            resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
        }

        if (!resolved_module_spec.GetFileSpec().Exists())
            resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();

        if (resolved_module_spec.GetFileSpec().Exists())
            error.Clear();
        else
        {
            error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).

            // Resolve any executable within a bundle on MacOSX
            Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());

            if (resolved_module_spec.GetFileSpec().Exists())
            {
                error.Clear();
            }
            else
            {
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
            }
        }
    }

    if (error.Success())
    {
        if (resolved_module_spec.GetArchitecture().IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);

            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
                                                resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                resolved_module_spec.GetArchitecture().GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
            {
                error = ModuleList::GetSharedModule (resolved_module_spec,
                                                     exe_module_sp,
                                                     module_search_paths_ptr,
                                                     NULL,
                                                     NULL);
                // Did we find an executable using one of the
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }

                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
            }

            if (error.Fail() || !exe_module_sp)
            {
                if (resolved_module_spec.GetFileSpec().Readable())
                {
                    error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                    resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                    GetPluginName().GetCString(),
                                                    arch_names.GetString().c_str());
                }
                else
                {
                    error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
                }
            }
        }
    }

    return error;
}
Example #24
0
size_t
Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size_t dst_len, Error &error)
{
    error.Clear();

    bool process_is_valid = m_process_sp && m_process_sp->IsAlive();

    size_t bytes_read = 0;
    Address resolved_addr(addr);
    if (!resolved_addr.IsSectionOffset())
    {
        if (process_is_valid)
        {
            m_section_load_list.ResolveLoadAddress (addr.GetOffset(), resolved_addr);
        }
        else
        {
            m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr);
        }
    }

    if (prefer_file_cache)
    {
        bytes_read = ReadMemoryFromFileCache (resolved_addr, dst, dst_len, error);
        if (bytes_read > 0)
            return bytes_read;
    }

    if (process_is_valid)
    {
        lldb::addr_t load_addr = resolved_addr.GetLoadAddress (this);
        if (load_addr == LLDB_INVALID_ADDRESS)
        {
            if (resolved_addr.GetModule() && resolved_addr.GetModule()->GetFileSpec())
                error.SetErrorStringWithFormat("%s[0x%llx] can't be resolved, %s in not currently loaded.\n",
                                               resolved_addr.GetModule()->GetFileSpec().GetFilename().AsCString(),
                                               resolved_addr.GetFileAddress());
            else
                error.SetErrorStringWithFormat("0x%llx can't be resolved.\n", resolved_addr.GetFileAddress());
        }
        else
        {
            bytes_read = m_process_sp->ReadMemory(load_addr, dst, dst_len, error);
            if (bytes_read != dst_len)
            {
                if (error.Success())
                {
                    if (bytes_read == 0)
                        error.SetErrorStringWithFormat("Read memory from 0x%llx failed.\n", load_addr);
                    else
                        error.SetErrorStringWithFormat("Only %zu of %zu bytes were read from memory at 0x%llx.\n", bytes_read, dst_len, load_addr);
                }
            }
            if (bytes_read)
                return bytes_read;
            // If the address is not section offset we have an address that
            // doesn't resolve to any address in any currently loaded shared
            // libaries and we failed to read memory so there isn't anything
            // more we can do. If it is section offset, we might be able to
            // read cached memory from the object file.
            if (!resolved_addr.IsSectionOffset())
                return 0;
        }
    }

    if (!prefer_file_cache)
    {
        // If we didn't already try and read from the object file cache, then
        // try it after failing to read from the process.
        return ReadMemoryFromFileCache (resolved_addr, dst, dst_len, error);
    }
    return 0;
}
Error
IRExecutionUnit::DisassembleFunction (Stream &stream,
                                      lldb::ProcessSP &process_wp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ExecutionContext exe_ctx(process_wp);

    Error ret;

    ret.Clear();

    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &function : m_jitted_functions)
    {
        if (strstr(function.m_name.c_str(), m_name.AsCString()))
        {
            func_local_addr = function.m_local_addr;
            func_remote_addr = function.m_remote_addr;
        }
    }

    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);

    std::pair <lldb::addr_t, lldb::addr_t> func_range;

    func_range = GetRemoteRangeForLocal(func_local_addr);

    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);

    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
        return ret;
    }

    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));

    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);

    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }

    ArchSpec arch(target->GetArchitecture());

    const char *plugin_name = NULL;
    const char *flavor_string = NULL;
    lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);

    if (!disassembler_sp)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }

    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }

    DataExtractor extractor(buffer_sp,
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());

    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log,
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }

    disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);

    InstructionList &instruction_list = disassembler_sp->GetInstructionList();
    instruction_list.Dump(&stream, true, true, &exe_ctx);
    
    // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
    // I'll fix that but for now, just clear the list and it will go away nicely.
    disassembler_sp->GetInstructionList().Clear();
    return ret;
}
Example #26
0
    virtual bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        if (target == NULL)
        {
            result.AppendError ("Invalid target. No current target or watchpoints.");
            result.SetStatus (eReturnStatusSuccessFinishNoResult);
            return true;
        }

        if (target->GetProcessSP() && target->GetProcessSP()->IsAlive())
        {
            uint32_t num_supported_hardware_watchpoints;
            Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints);
            if (error.Success())
                result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n",
                                               num_supported_hardware_watchpoints);
        }

        const WatchpointList &watchpoints = target->GetWatchpointList();
        Mutex::Locker locker;
        target->GetWatchpointList().GetListMutex(locker);

        size_t num_watchpoints = watchpoints.GetSize();

        if (num_watchpoints == 0)
        {
            result.AppendMessage("No watchpoints currently set.");
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
            return true;
        }

        Stream &output_stream = result.GetOutputStream();

        if (command.GetArgumentCount() == 0)
        {
            // No watchpoint selected; show info about all currently set watchpoints.
            result.AppendMessage ("Current watchpoints:");
            for (size_t i = 0; i < num_watchpoints; ++i)
            {
                Watchpoint *wp = watchpoints.GetByIndex(i).get();
                AddWatchpointDescription(&output_stream, wp, m_options.m_level);
            }
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
        }
        else
        {
            // Particular watchpoints selected; enable them.
            std::vector<uint32_t> wp_ids;
            if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(command, wp_ids))
            {
                result.AppendError("Invalid watchpoints specification.");
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            const size_t size = wp_ids.size();
            for (size_t i = 0; i < size; ++i)
            {
                Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
                if (wp)
                    AddWatchpointDescription(&output_stream, wp, m_options.m_level);
                result.SetStatus(eReturnStatusSuccessFinishNoResult);
            }
        }

        return result.Succeeded();
    }
bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
                                                    TypeAndOrName &class_type_or_name, Address &dynamic_address,
                                                    Value::ValueType &value_type)
{
    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name
    // demangled will contain the full class name.
    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
    // start of the value object which holds the dynamic type.
    //

    class_type_or_name.Clear();
    value_type = Value::ValueType::eValueTypeScalar;

    // Only a pointer or reference type can have a different dynamic and static type:
    if (CouldHaveDynamicValue(in_value))
    {
        // First job, pull out the address at 0 offset from the object.
        AddressType address_type;
        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
        if (original_ptr == LLDB_INVALID_ADDRESS)
            return false;

        ExecutionContext exe_ctx(in_value.GetExecutionContextRef());

        Process *process = exe_ctx.GetProcessPtr();

        if (process == nullptr)
            return false;

        Error error;
        const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error);

        if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS)
        {
            return false;
        }

        class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point);

        if (class_type_or_name)
        {
            TypeSP type_sp = class_type_or_name.GetTypeSP();
            // There can only be one type with a given name,
            // so we've just found duplicate definitions, and this
            // one will do as well as any other.
            // We don't consider something to have a dynamic type if
            // it is the same as the static type.  So compare against
            // the value we were handed.
            if (type_sp)
            {
                if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType()))
                {
                    // The dynamic type we found was the same type,
                    // so we don't have a dynamic type here...
                    return false;
                }

                // The offset_to_top is two pointers above the vtable pointer.
                const uint32_t addr_byte_size = process->GetAddressByteSize();
                const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size;
                // Watch for underflow, offset_to_top_location should be less than vtable_address_point
                if (offset_to_top_location >= vtable_address_point)
                    return false;
                const int64_t offset_to_top =
                    process->ReadSignedIntegerFromMemory(offset_to_top_location, addr_byte_size, INT64_MIN, error);

                if (offset_to_top == INT64_MIN)
                    return false;
                // So the dynamic type is a value that starts at offset_to_top
                // above the original address.
                lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
                if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(dynamic_addr, dynamic_address))
                {
                    dynamic_address.SetRawAddress(dynamic_addr);
                }
                return true;
            }
        }
    }

    return class_type_or_name.IsEmpty() == false;
}
Example #28
0
Error
PlatformRemoteiOS::ResolveExecutable (const ModuleSpec &ms,
                                      lldb::ModuleSP &exe_module_sp,
                                      const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    ModuleSpec resolved_module_spec(ms);

    // Resolve any executable within a bundle on MacOSX
    // TODO: verify that this handles shallow bundles, if not then implement one ourselves
    Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());

    if (resolved_module_spec.GetFileSpec().Exists())
    {
        if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp, 
                                                 NULL,
                                                 NULL, 
                                                 NULL);
        
            if (exe_module_sp && exe_module_sp->GetObjectFile())
                return error;
            exe_module_sp.reset();
        }
        // No valid architecture was specified or the exact ARM slice wasn't
        // found so ask the platform for the architectures that we should be
        // using (in the correct order) and see if we can find a match that way
        StreamString arch_names;
        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp, 
                                                 NULL,
                                                 NULL, 
                                                 NULL);
            // Did we find an executable using one of the 
            if (error.Success())
            {
                if (exe_module_sp && exe_module_sp->GetObjectFile())
                    break;
                else
                    error.SetErrorToGenericError();
            }
            
            if (idx > 0)
                arch_names.PutCString (", ");
            arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
        }
        
        if (error.Fail() || !exe_module_sp)
        {
            if (resolved_module_spec.GetFileSpec().Readable())
            {
                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                GetPluginName().GetCString(),
                                                arch_names.GetString().c_str());
            }
            else
            {
                error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s' does not exist",
                                        resolved_module_spec.GetFileSpec().GetPath().c_str());
    }

    return error;
}
Example #29
0
void 
ThreadPlanAssemblyTracer::Log ()
{
    Stream *stream = GetLogStream ();
    
    if (!stream)
        return;
            
    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
    
    lldb::addr_t pc = reg_ctx->GetPC();
    ProcessSP process_sp (m_thread.GetProcess());
    Address pc_addr;
    bool addr_valid = false;
    uint8_t buffer[16] = {0}; // Must be big enough for any single instruction
    addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, pc_addr);
    
    pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress);
    stream->PutCString (" ");
    
    Disassembler *disassembler = GetDisassembler();
    if (disassembler)
    {        
        Error err;
        process_sp->ReadMemory(pc, buffer, sizeof(buffer), err);
        
        if (err.Success())
        {
            DataExtractor extractor(buffer, sizeof(buffer), 
                                    process_sp->GetByteOrder(), 
                                    process_sp->GetAddressByteSize());
            
			bool data_from_file = false;
            if (addr_valid)
                disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file);
            else
                disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file);
            
            InstructionList &instruction_list = disassembler->GetInstructionList();
            const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();

            if (instruction_list.GetSize())
            {
                const bool show_bytes = true;
                const bool show_address = true;
                Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
                const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat();
                instruction->Dump (stream,
                                   max_opcode_byte_size,
                                   show_address,
                                   show_bytes,
                                   NULL,
                                   NULL,
                                   NULL,
                                   disassemble_format,
                                   0);
            }
        }
    }
    
    const ABI *abi = process_sp->GetABI().get();
    TypeFromUser intptr_type = GetIntPointerType();
    
    if (abi && intptr_type.IsValid())
    {
        ValueList value_list;
        const int num_args = 1;
        
        for (int arg_index = 0; arg_index < num_args; ++arg_index)
        {
            Value value;
            value.SetValueType (Value::eValueTypeScalar);
//            value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
            value.SetClangType (intptr_type);
            value_list.PushValue (value);
        }
        
        if (abi->GetArgumentValues (m_thread, value_list))
        {                
            for (int arg_index = 0; arg_index < num_args; ++arg_index)
            {
                stream->Printf("\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong());
                
                if (arg_index + 1 < num_args)
                    stream->PutCString (", ");
            }
        }
    }
    
    
    RegisterValue reg_value;
    for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
         reg_num < num_registers;
         ++reg_num)
    {
        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
        if (reg_ctx->ReadRegister (reg_info, reg_value))
        {
            assert (reg_num < m_register_values.size());
            if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || 
                reg_value != m_register_values[reg_num])
            {
                if (reg_value.GetType() != RegisterValue::eTypeInvalid)
                {
                    stream->PutCString ("\n\t");
                    reg_value.Dump(stream, reg_info, true, false, eFormatDefault);
                }
            }
            m_register_values[reg_num] = reg_value;
        }
    }
    stream->EOL();
    stream->Flush();
}
Example #30
0
void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
                              const uint8_t *bytes, size_t size, Error &error) {
  error.Clear();

  AllocationMap::iterator iter = FindAllocation(process_address, size);

  if (iter == m_allocations.end()) {
    lldb::ProcessSP process_sp = m_process_wp.lock();

    if (process_sp) {
      process_sp->WriteMemory(process_address, bytes, size, error);
      return;
    }

    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't write: no allocation contains the target "
                         "range and the process doesn't exist");
    return;
  }

  Allocation &allocation = iter->second;

  uint64_t offset = process_address - allocation.m_process_start;

  lldb::ProcessSP process_sp;

  switch (allocation.m_policy) {
  default:
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't write: invalid allocation policy");
    return;
  case eAllocationPolicyHostOnly:
    if (!allocation.m_data.GetByteSize()) {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't write: data buffer is empty");
      return;
    }
    ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
    break;
  case eAllocationPolicyMirror:
    if (!allocation.m_data.GetByteSize()) {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't write: data buffer is empty");
      return;
    }
    ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
    process_sp = m_process_wp.lock();
    if (process_sp) {
      process_sp->WriteMemory(process_address, bytes, size, error);
      if (!error.Success())
        return;
    }
    break;
  case eAllocationPolicyProcessOnly:
    process_sp = m_process_wp.lock();
    if (process_sp) {
      process_sp->WriteMemory(process_address, bytes, size, error);
      if (!error.Success())
        return;
    }
    break;
  }

  if (lldb_private::Log *log =
          lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
    log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64
                ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
                (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
                (uint64_t)allocation.m_process_start,
                (uint64_t)allocation.m_process_start +
                    (uint64_t)allocation.m_size);
  }
}