Error
PlatformRemoteGDBServer::ConnectRemote (Args& args)
{
    Error error;
    if (IsConnected())
    {
        error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 
                                        GetHostname());
    }
    else
    {
        if (args.GetArgumentCount() == 1)
        {
            const char *url = args.GetArgumentAtIndex(0);
            m_gdb_client.SetConnection (new ConnectionFileDescriptor());
            const ConnectionStatus status = m_gdb_client.Connect(url, &error);
            if (status == eConnectionStatusSuccess)
            {
                if (m_gdb_client.HandshakeWithServer(&error))
                {
                    m_gdb_client.GetHostInfo();
                    // If a working directory was set prior to connecting, send it down now
                    if (m_working_dir)
                        m_gdb_client.SetWorkingDir(m_working_dir.GetCString());
                }
                else
                {
                    m_gdb_client.Disconnect();
                    if (error.Success())
                        error.SetErrorString("handshake failed");
                }
            }
        }
        else
        {
            error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
        }
    }

    return error;
}
Example #2
0
Error
PlatformiOSSimulator::GetSymbolFile (const FileSpec &platform_file, 
                                     const UUID *uuid_ptr,
                                     FileSpec &local_file)
{
    Error error;
    char platform_file_path[PATH_MAX];
    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
    {
        char resolved_path[PATH_MAX];
    
        const char * sdk_dir = GetSDKsDirectory();
        if (sdk_dir)
        {
            ::snprintf (resolved_path, 
                        sizeof(resolved_path), 
                        "%s/%s", 
                        sdk_dir, 
                        platform_file_path);
            
            // First try in the SDK and see if the file is in there
            local_file.SetFile(resolved_path, true);
            if (local_file.Exists())
                return error;

            // Else fall back to the actual path itself
            local_file.SetFile(platform_file_path, true);
            if (local_file.Exists())
                return error;

        }
        error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 
                                        platform_file_path,
                                        GetPluginName().GetCString());
    }
    else
    {
        error.SetErrorString ("invalid platform file argument");
    }
    return error;
}
Example #3
0
Error
OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
{
    Error error;
    switch (op)
    {
        case eVarSetOperationClear:
            Clear ();
            NotifyValueChanged();
            break;
            
        case eVarSetOperationReplace:
        case eVarSetOperationAssign:
        {
            bool success = false;
            uint64_t value = Args::StringToUInt64 (value_cstr, 0, 0, &success);
            if (success)
            {
                m_value_was_set = true;
                m_current_value = value;
                NotifyValueChanged();
            }
            else
            {
                error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_cstr);
            }
        }
            break;
            
        case eVarSetOperationInsertBefore:
        case eVarSetOperationInsertAfter:
        case eVarSetOperationRemove:
        case eVarSetOperationAppend:
        case eVarSetOperationInvalid:
            error = OptionValue::SetValueFromCString (value_cstr, op);
            break;
    }
    return error;
}
        virtual Error
        SetOptionValue (uint32_t option_idx, const char *option_arg)
        {
            Error error;
            const int short_option = m_getopt_table[option_idx].val;

            switch (short_option)
            {
                case 'c':
                    if (option_arg != NULL)
                        m_condition.assign (option_arg);
                    else
                        m_condition.clear();
                    m_condition_passed = true;
                    break;
                default:
                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }
Example #5
0
ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
                       Error &error) {
  const auto lock_dir_spec = JoinPath(root_dir_spec, kLockDirName);
  error = MakeDirectory(lock_dir_spec);
  if (error.Fail())
    return;

  m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
  m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite |
                                            File::eOpenOptionCanCreate |
                                            File::eOpenOptionCloseOnExec);
  if (!m_file) {
    error.SetErrorToErrno();
    return;
  }

  m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor()));
  error = m_lock->WriteLock(0, 1);
  if (error.Fail())
    error.SetErrorStringWithFormat("Failed to lock file: %s",
                                   error.AsCString());
}
        virtual Error
        SetOptionValue (CommandInterpreter &interpreter,
                        uint32_t option_idx,
                        const char *option_value)
        {
            Error error;
            const int short_option = g_option_table[option_idx].short_option;
            switch (short_option)
            {
                case 's':
                    {
                        OptionValueSP value_sp (OptionValueUInt64::Create (option_value, error));
                        if (value_sp)
                            set_indexes.AppendValue (value_sp);
                    }
                    break;

                case 'a':
                    // When we don't use OptionValue::SetValueFromCString(const char *) to 
                    // set an option value, it won't be marked as being set in the options
                    // so we make a call to let users know the value was set via option
                    dump_all_sets.SetCurrentValue (true);
                    dump_all_sets.SetOptionWasSet ();
                    break;

                case 'A':
                    // When we don't use OptionValue::SetValueFromCString(const char *) to 
                    // set an option value, it won't be marked as being set in the options
                    // so we make a call to let users know the value was set via option
                    alternate_name.SetCurrentValue (true);
                    dump_all_sets.SetOptionWasSet ();
                    break;
                    
                default:
                    error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
                    break;
            }
            return error;
        }
Example #7
0
SBError
SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name)
{
    SBError sb_error;
    DebuggerSP debugger_sp(Debugger::FindDebuggerWithInstanceName (ConstString(debugger_instance_name)));
    Error error;
    if (debugger_sp)
    {
        ExecutionContext exe_ctx (debugger_sp->GetCommandInterpreter().GetExecutionContext());
        error = debugger_sp->SetPropertyValue (&exe_ctx,
                                               eVarSetOperationAssign,
                                               var_name,
                                               value);
    }
    else
    {
        error.SetErrorStringWithFormat ("invalid debugger instance name '%s'", debugger_instance_name);
    }
    if (error.Fail())
        sb_error.SetError(error);
    return sb_error;
}
Example #8
0
Error
OptionGroupUUID::SetOptionValue (CommandInterpreter &interpreter,
                                 uint32_t option_idx,
                                 const char *option_arg)
{
    Error error;
    const int short_option = g_option_table[option_idx].short_option;

    switch (short_option)
    {
        case 'u':
            error = m_uuid.SetValueFromString (option_arg);
            if (error.Success())
                m_uuid.SetOptionWasSet();
            break;

        default:
            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
            break;
    }

    return error;
}
Example #9
0
        virtual Error
        SetOptionValue (uint32_t option_idx, const char *option_arg)
        {
            Error error;
            char short_option = (char) m_getopt_table[option_idx].val;

            switch (short_option)
            {
            case 'f':  log_file = option_arg;                                 break;
            case 't':  log_options |= LLDB_LOG_OPTION_THREADSAFE;             break;
            case 'v':  log_options |= LLDB_LOG_OPTION_VERBOSE;                break;
            case 'g':  log_options |= LLDB_LOG_OPTION_DEBUG;                  break;
            case 's':  log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;       break;
            case 'T':  log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;      break;
            case 'p':  log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
            case 'n':  log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;    break;
            default:
                error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
                break;
            }

            return error;
        }
Example #10
0
uint32_t
CommunicationKDP::SendRequestWriteMemory (lldb::addr_t addr,
        const void *src,
        uint32_t src_len,
        Error &error)
{
    PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
    bool use_64 = (GetVersion() >= 11);
    uint32_t command_addr_byte_size = use_64 ? 8 : 4;
    const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM;
    // Size is header + address size + uint32_t length
    const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len;
    const uint32_t request_sequence_id = m_request_sequence_id;
    MakeRequestPacketHeader (command, request_packet, command_length);
    request_packet.PutMaxHex64 (addr, command_addr_byte_size);
    request_packet.PutHex32 (src_len);
    request_packet.PutRawBytes(src, src_len);

    DataExtractor reply_packet;
    if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
    {
        uint32_t offset = 8;
        uint32_t kdp_error = reply_packet.GetU32 (&offset);
        if (kdp_error)
            error.SetErrorStringWithFormat ("kdp write memory failed (error %u)", kdp_error);
        else
        {
            error.Clear();
            return src_len;
        }
    }
    else
    {
        error.SetErrorString ("failed to send packet");
    }
    return 0;
}
Example #11
0
Error
PlatformFreeBSD::ConnectRemote (Args& args)
{
    Error error;
    if (IsHost())
    {
        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
    }
    else
    {
        if (!m_remote_platform_sp)
            m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);

        if (m_remote_platform_sp)
        {
            if (error.Success())
            {
                if (m_remote_platform_sp)
                {
                    error = m_remote_platform_sp->ConnectRemote (args);
                }
                else
                {
                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
                }
            }
        }
        else
            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");

        if (error.Fail())
            m_remote_platform_sp.reset();
    }

    return error;
}
Example #12
0
void
IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
{
    error.Clear();
    
    if (size > 0)
    {
        DataBufferHeap buf(size, 0);
        ReadMemory(buf.GetBytes(), process_address, size, error);
        
        if (!error.Success())
            return;
        
        DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
        
        lldb::offset_t offset = 0;
        
        switch (size)
        {
        default:
            error.SetErrorToGenericError();
            error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
            return;
        case 1: scalar = extractor.GetU8(&offset);  break;
        case 2: scalar = extractor.GetU16(&offset); break;
        case 4: scalar = extractor.GetU32(&offset); break;
        case 8: scalar = extractor.GetU64(&offset); break;
        }
    }
    else
    {
        error.SetErrorToGenericError();
        error.SetErrorString ("Couldn't read scalar: its size was zero");
    }
    return;
}
Example #13
0
lldb_private::Error
OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
                                          uint32_t option_idx,
                                          const char *option_arg)
{
    Error error;
    char short_option = (char) GetDefinitions()[option_idx].short_option;
    switch (short_option)
    {
        case 's':
            m_ssh = true;
            break;
            
        case 'S':
            m_ssh_opts.assign(option_arg);
            break;
            
        default:
            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
            break;
    }
    
    return error;
}
size_t
ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();

    if (core_objfile)
    {
        const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
        if (core_memory_entry)
        {
            const addr_t offset = addr - core_memory_entry->GetRangeBase();
            const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
            size_t bytes_to_read = size;
            if (bytes_to_read > bytes_left)
                bytes_to_read = bytes_left;
            return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
        }
        else
        {
            error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr);
        }
    }
    return 0;
}
Example #15
0
Error
FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
{
    Error error;
    std::wstring path_buffer;
    if (!llvm::ConvertUTF8toWide(file_spec.GetPath(), path_buffer))
    {
        error.SetErrorString(PATH_CONVERSION_ERROR);
        return error;
    }
    if (!recurse)
    {
        BOOL result = ::RemoveDirectoryW(path_buffer.c_str());
        if (!result)
            error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
    }
    else
    {
        // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
        // indicate the end of the list. The first null terminator is there only in the backing
        // store but not the actual vector contents, and so we need to push twice.
        path_buffer.push_back(0);
        path_buffer.push_back(0);

        SHFILEOPSTRUCTW shfos = {0};
        shfos.wFunc = FO_DELETE;
        shfos.pFrom = (LPCWSTR)path_buffer.data();
        shfos.fFlags = FOF_NO_UI;

        int result = ::SHFileOperationW(&shfos);
        // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
        if (result != 0)
            error.SetErrorStringWithFormat("SHFileOperation failed");
    }
    return error;
}
        virtual Error
        SetOptionValue (uint32_t option_idx, const char *option_arg)
        {
            Error error;
            const int short_option = m_getopt_table[option_idx].val;

            switch (short_option)
            {
                case 'b':
                    m_level = lldb::eDescriptionLevelBrief;
                    break;
                case 'f':
                    m_level = lldb::eDescriptionLevelFull;
                    break;
                case 'v':
                    m_level = lldb::eDescriptionLevelVerbose;
                    break;
                default:
                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
                    break;
            }

            return error;
        }
Example #17
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 #18
0
Error PlatformFreeBSD::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.GetData());
        } else {
          error.SetErrorStringWithFormat(
              "'%s' is not readable",
              resolved_module_spec.GetFileSpec().GetPath().c_str());
        }
      }
    }
  }

  return error;
}
Example #19
0
Error OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
                                                  VarSetOperationType op) {
  Error error;
  Args args(value.str());
  const size_t argc = args.GetArgumentCount();

  switch (op) {
  case eVarSetOperationClear:
    Clear();
    NotifyValueChanged();
    break;

  case eVarSetOperationReplace:
    if (argc > 1) {
      uint32_t idx =
          StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
      const uint32_t count = m_current_value.GetSize();
      if (idx > count) {
        error.SetErrorStringWithFormat(
            "invalid file list index %u, index must be 0 through %u", idx,
            count);
      } else {
        for (size_t i = 1; i < argc; ++i, ++idx) {
          FileSpec file(args.GetArgumentAtIndex(i), false);
          if (idx < count)
            m_current_value.Replace(idx, file);
          else
            m_current_value.Append(file);
        }
        NotifyValueChanged();
      }
    } else {
      error.SetErrorString("replace operation takes an array index followed by "
                           "one or more values");
    }
    break;

  case eVarSetOperationAssign:
    m_current_value.Clear();
    // Fall through to append case
    LLVM_FALLTHROUGH;
  case eVarSetOperationAppend:
    if (argc > 0) {
      m_value_was_set = true;
      for (size_t i = 0; i < argc; ++i) {
        FileSpec file(args.GetArgumentAtIndex(i), false);
        m_current_value.Append(file);
      }
      NotifyValueChanged();
    } else {
      error.SetErrorString(
          "assign operation takes at least one file path argument");
    }
    break;

  case eVarSetOperationInsertBefore:
  case eVarSetOperationInsertAfter:
    if (argc > 1) {
      uint32_t idx =
          StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
      const uint32_t count = m_current_value.GetSize();
      if (idx > count) {
        error.SetErrorStringWithFormat(
            "invalid insert file list index %u, index must be 0 through %u",
            idx, count);
      } else {
        if (op == eVarSetOperationInsertAfter)
          ++idx;
        for (size_t i = 1; i < argc; ++i, ++idx) {
          FileSpec file(args.GetArgumentAtIndex(i), false);
          m_current_value.Insert(idx, file);
        }
        NotifyValueChanged();
      }
    } else {
      error.SetErrorString("insert operation takes an array index followed by "
                           "one or more values");
    }
    break;

  case eVarSetOperationRemove:
    if (argc > 0) {
      std::vector<int> remove_indexes;
      bool all_indexes_valid = true;
      size_t i;
      for (i = 0; all_indexes_valid && i < argc; ++i) {
        const int idx =
            StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
        if (idx == INT32_MAX)
          all_indexes_valid = false;
        else
          remove_indexes.push_back(idx);
      }

      if (all_indexes_valid) {
        size_t num_remove_indexes = remove_indexes.size();
        if (num_remove_indexes) {
          // Sort and then erase in reverse so indexes are always valid
          std::sort(remove_indexes.begin(), remove_indexes.end());
          for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
            m_current_value.Remove(j);
          }
        }
        NotifyValueChanged();
      } else {
        error.SetErrorStringWithFormat(
            "invalid array index '%s', aborting remove operation",
            args.GetArgumentAtIndex(i));
      }
    } else {
      error.SetErrorString("remove operation takes one or more array index");
    }
    break;

  case eVarSetOperationInvalid:
    error = OptionValue::SetValueFromString(value, op);
    break;
  }
  return error;
}
Example #20
0
Error
Value::GetValueAsData (ExecutionContext *exe_ctx,
                       DataExtractor &data,
                       uint32_t data_offset,
                       Module *module)
{
    data.Clear();

    Error error;
    lldb::addr_t address = LLDB_INVALID_ADDRESS;
    AddressType address_type = eAddressTypeFile;
    Address file_so_addr;
    const CompilerType &ast_type = GetCompilerType();
    switch (m_value_type)
    {
    case eValueTypeVector:
        if (ast_type.IsValid())
            data.SetAddressByteSize (ast_type.GetPointerByteSize());
        else
            data.SetAddressByteSize(sizeof(void *));
        data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order);
        break;

    case eValueTypeScalar:
        {
            data.SetByteOrder (endian::InlHostByteOrder());
            if (ast_type.IsValid())
                data.SetAddressByteSize (ast_type.GetPointerByteSize());
            else
                data.SetAddressByteSize(sizeof(void *));

            uint32_t limit_byte_size = UINT32_MAX;
            
            if (ast_type.IsValid() && ast_type.IsScalarType())
            {
                uint64_t type_encoding_count = 0;
                lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count);
                
                if (type_encoding == eEncodingUint || type_encoding == eEncodingSint)
                    limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
            }
            
            if (m_value.GetData (data, limit_byte_size))
                return error;   // Success;
            
            error.SetErrorStringWithFormat("extracting data from value failed");
            break;
        }
    case eValueTypeLoadAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read load address (no execution context)");
        }
        else 
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process == NULL || !process->IsAlive())
            {
                Target *target = exe_ctx->GetTargetPtr();
                if (target)
                {
                    // Allow expressions to run and evaluate things when the target
                    // has memory sections loaded. This allows you to use "target modules load"
                    // to load your executable and any shared libraries, then execute
                    // commands where you can look at types in data sections.
                    const SectionLoadList &target_sections = target->GetSectionLoadList();
                    if (!target_sections.IsEmpty())
                    {
                        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                        if (target_sections.ResolveLoadAddress(address, file_so_addr))
                        {
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                        }
                        else
                            address = LLDB_INVALID_ADDRESS;
                    }
//                    else
//                    {
//                        ModuleSP exe_module_sp (target->GetExecutableModule());
//                        if (exe_module_sp)
//                        {
//                            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
//                            if (address != LLDB_INVALID_ADDRESS)
//                            {
//                                if (exe_module_sp->ResolveFileAddress(address, file_so_addr))
//                                {
//                                    data.SetByteOrder(target->GetArchitecture().GetByteOrder());
//                                    data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
//                                    address_type = eAddressTypeFile;
//                                }
//                                else
//                                {
//                                    address = LLDB_INVALID_ADDRESS;
//                                }
//                            }
//                        }
//                    }
                }
                else
                {
                    error.SetErrorString ("can't read load address (invalid process)");
                }
            }
            else
            {
                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                address_type = eAddressTypeLoad;
                data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize());
            }
        }
        break;

    case eValueTypeFileAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read file address (no execution context)");
        }
        else if (exe_ctx->GetTargetPtr() == NULL)
        {
            error.SetErrorString ("can't read file address (invalid target)");
        }
        else
        {
            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
            if (address == LLDB_INVALID_ADDRESS)
            {
                error.SetErrorString ("invalid file address");
            }
            else
            {
                if (module == NULL)
                {
                    // The only thing we can currently lock down to a module so that
                    // we can resolve a file address, is a variable.
                    Variable *variable = GetVariable();
                    if (variable)
                    {
                        SymbolContext var_sc;
                        variable->CalculateSymbolContext(&var_sc);
                        module = var_sc.module_sp.get();
                    }
                }
                
                if (module)
                {
                    bool resolved = false;
                    ObjectFile *objfile = module->GetObjectFile();
                    if (objfile)
                    {
                        Address so_addr(address, objfile->GetSectionList());
                        addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr());
                        bool process_launched_and_stopped = exe_ctx->GetProcessPtr()
                            ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */)
                            : false;
                        // Don't use the load address if the process has exited.
                        if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped)
                        {
                            resolved = true;
                            address = load_address;
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize());
                        }
                        else
                        {
                            if (so_addr.IsSectionOffset())
                            {
                                resolved = true;
                                file_so_addr = so_addr;
                                data.SetByteOrder(objfile->GetByteOrder());
                                data.SetAddressByteSize(objfile->GetAddressByteSize());
                            }
                        }
                    }
                    if (!resolved)
                    {
                        Variable *variable = GetVariable();
                        
                        if (module)
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s",
                                                                address, 
                                                                variable->GetName().AsCString(""),
                                                                module->GetFileSpec().GetPath().c_str());
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s",
                                                                address, 
                                                                module->GetFileSpec().GetPath().c_str());
                        }
                        else
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'",
                                                                address, 
                                                                variable->GetName().AsCString(""));
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address);
                        }
                    }
                }
                else
                {
                    // Can't convert a file address to anything valid without more
                    // context (which Module it came from)
                    error.SetErrorString ("can't read memory from file address without more context");
                }
            }
        }
        break;

    case eValueTypeHostAddress:
        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
        address_type = eAddressTypeHost;
        if (exe_ctx)
        {
            Target *target = exe_ctx->GetTargetPtr();
            if (target)
            {
                data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                break;
            }
        }
        // fallback to host settings
        data.SetByteOrder(endian::InlHostByteOrder());
        data.SetAddressByteSize(sizeof(void *));
        break;
    }

    // Bail if we encountered any errors
    if (error.Fail())
        return error;

    if (address == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
        return error;
    }

    // If we got here, we need to read the value from memory
    size_t byte_size = GetValueByteSize (&error, exe_ctx);

    // Bail if we encountered any errors getting the byte size
    if (error.Fail())
        return error;

    // Make sure we have enough room within "data", and if we don't make
    // something large enough that does
    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
    {
        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
        data.SetData(data_sp);
    }

    uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
    if (dst != NULL)
    {
        if (address_type == eAddressTypeHost)
        {
            // The address is an address in this process, so just copy it.
            if (address == 0)
            {
                error.SetErrorStringWithFormat("trying to read from host address of 0.");
                return error;
            }
            memcpy (dst, (uint8_t*)NULL + address, byte_size);
        }
        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
        {
            if (file_so_addr.IsValid())
            {
                // We have a file address that we were able to translate into a
                // section offset address so we might be able to read this from
                // the object files if we don't have a live process. Lets always
                // try and read from the process if we have one though since we
                // want to read the actual value by setting "prefer_file_cache"
                // to false. 
                const bool prefer_file_cache = false;
                if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address);
                }
            }
            else
            {
                // The execution context might have a NULL process, but it
                // might have a valid process in the exe_ctx->target, so use
                // the ExecutionContext::GetProcess accessor to ensure we
                // get the process if there is one.
                Process *process = exe_ctx->GetProcessPtr();

                if (process)
                {
                    const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error);
                    if (bytes_read != byte_size)
                        error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
                                                       (uint64_t)address, 
                                                       (uint32_t)bytes_read, 
                                                       (uint32_t)byte_size);
                }
                else
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address);
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("out of memory");
    }

    return error;
}
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
                                            lldb::addr_t &func_end,
                                            std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
                                            ExecutionContext &exe_ctx,
                                            bool &can_interpret,
                                            ExecutionPolicy execution_policy)
{
	func_addr = LLDB_INVALID_ADDRESS;
	func_end = LLDB_INVALID_ADDRESS;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());

    if (!llvm_module_ap.get())
    {
        err.SetErrorToGenericError();
        err.SetErrorString("IR doesn't contain a module");
        return err;
    }

    // Find the actual name of the function (it's often mangled somehow)

    ConstString function_name;

    if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
    {
        err.SetErrorToGenericError();
        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
        return err;
    }
    else
    {
        if (log)
            log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
    }

    execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
                                                 llvm_module_ap, // handed off here
                                                 function_name,
                                                 exe_ctx.GetTargetSP(),
                                                 m_compiler->getTargetOpts().Features));

    ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL

    if (decl_map)
    {
        Stream *error_stream = NULL;
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
            error_stream = target->GetDebugger().GetErrorFile().get();

        IRForTarget ir_for_target(decl_map,
                                  m_expr.NeedsVariableResolution(),
                                  *execution_unit_sp,
                                  error_stream,
                                  function_name.AsCString());

        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

        Error interpret_error;

        can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);

        Process *process = exe_ctx.GetProcessPtr();

        if (!ir_can_run)
        {
            err.SetErrorString("The expression could not be prepared to run in the target");
            return err;
        }

        if (!can_interpret && execution_policy == eExecutionPolicyNever)
        {
            err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
            return err;
        }

        if (!process && execution_policy == eExecutionPolicyAlways)
        {
            err.SetErrorString("Expression needed to run in the target, but the target can't be run");
            return err;
        }

        if (execution_policy == eExecutionPolicyAlways || !can_interpret)
        {
            if (m_expr.NeedsValidation() && process)
            {
                if (!process->GetDynamicCheckers())
                {
                    DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();

                    StreamString install_errors;

                    if (!dynamic_checkers->Install(install_errors, exe_ctx))
                    {
                        if (install_errors.GetString().empty())
                            err.SetErrorString ("couldn't install checkers, unknown error");
                        else
                            err.SetErrorString (install_errors.GetString().c_str());

                        return err;
                    }

                    process->SetDynamicCheckers(dynamic_checkers);

                    if (log)
                        log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
                }

                IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());

                if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
                {
                    err.SetErrorToGenericError();
                    err.SetErrorString("Couldn't add dynamic checks to the expression");
                    return err;
                }
            }

            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
        }
    }
    else
    {
        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }

    return err;
}
Example #22
0
Error
ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
{
    Error error;
    if (!new_value_sp)
    {
        error.SetErrorString("Empty value object for return value.");
        return error;
    }

    CompilerType clang_type = new_value_sp->GetCompilerType();
    if (!clang_type)
    {
        error.SetErrorString ("Null clang type for return value.");
        return error;
    }

    Thread *thread = frame_sp->GetThread().get();

    bool is_signed;
    uint32_t count;
    bool is_complex;

    RegisterContext *reg_ctx = thread->GetRegisterContext().get();

    bool set_it_simple = false;
    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
    {
        DataExtractor data;
        Error data_error;
        size_t num_bytes = new_value_sp->GetData(data, data_error);
        if (data_error.Fail())
        {
            error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
            return error;
        }

        lldb::offset_t offset = 0;
        if (num_bytes <= 8)
        {
            const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
            if (num_bytes <= 4)
            {
                uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);

                if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
                    set_it_simple = true;
            }
            else
            {
                uint32_t raw_value = data.GetMaxU32(&offset, 4);

                if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
                {
                    const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
                    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);

                    if (reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
                        set_it_simple = true;
                }
            }
        }
        else
        {
            error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
        }
    }
    else if (clang_type.IsFloatingPointType (count, is_complex))
    {
        if (is_complex)
            error.SetErrorString ("We don't support returning complex values at present");
        else
            error.SetErrorString ("We don't support returning float values at present");
    }

    if (!set_it_simple)
        error.SetErrorString ("We only support setting simple integer return types at present.");

    return error;
}
Example #23
0
//----------------------------------------------------------------------
// The file descriptor FD is assumed to already be opened as read only
// and the STAT structure is assumed to a valid pointer and already
// containing valid data from a call to stat().
//
// Memory map FILE_LENGTH bytes in FILE starting FILE_OFFSET bytes into
// the file. If FILE_LENGTH is set to SIZE_MAX, then map as many bytes
// as possible.
//
// RETURNS
//  Number of bytes mapped starting from the requested offset.
//----------------------------------------------------------------------
size_t
DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, 
                                                  off_t offset, 
                                                  size_t length,
                                                  bool writeable,
                                                  bool fd_is_file)
{
    Clear();
    if (fd >= 0)
    {
        struct stat stat;
        if (::fstat(fd, &stat) == 0)
        {
            if (S_ISREG(stat.st_mode) && (stat.st_size > offset))
            {
                const size_t max_bytes_available = stat.st_size - offset;
                if (length == SIZE_MAX)
                {
                    length = max_bytes_available;
                }
                else if (length > max_bytes_available)
                {
                    // Cap the length if too much data was requested
                    length = max_bytes_available;
                }

                if (length > 0)
                {
                    int prot = PROT_READ;
                    if (writeable)
                        prot |= PROT_WRITE;

                    int flags = MAP_PRIVATE;
                    if (fd_is_file)
                        flags |= MAP_FILE;

                    m_mmap_addr = (uint8_t *)::mmap(NULL, length, prot, flags, fd, offset);

                    if (m_mmap_addr == (void*)-1)
                    {
                        Error error;
                        error.SetErrorToErrno ();
                        if (error.GetError() == EINVAL)
                        {
                            // We may still have a shot at memory mapping if we align things correctly
                            size_t page_offset = offset % Host::GetPageSize();
                            if (page_offset != 0)
                            {
                                m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, prot, flags, fd, offset - page_offset);
                                if (m_mmap_addr == (void*)-1)
                                {
                                    // Failed to map file
                                    m_mmap_addr = NULL;
                                }
                                else if (m_mmap_addr != NULL)
                                {
                                    // We recovered and were able to memory map
                                    // after we aligned things to page boundaries

                                    // Save the actual mmap'ed size
                                    m_mmap_size = length + page_offset;
                                    // Our data is at an offset into the the mapped data
                                    m_data = m_mmap_addr + page_offset;
                                    // Our pretend size is the size that was requestd
                                    m_size = length;
                                }
                            }
                        }
                        if (error.GetError() == ENOMEM)
                        {
                           error.SetErrorStringWithFormat("could not allocate %lld bytes of memory to mmap in file", (uint64_t) length);
                        }
                    }
                    else
                    {
                        // We were able to map the requested data in one chunk
                        // where our mmap and actual data are the same.
                        m_mmap_size = length;
                        m_data = m_mmap_addr;
                        m_size = length;
                    }
                }
            }
        }
    }
    return GetByteSize ();
}
Example #24
0
Error
ProcessFreeBSD::DoLaunch (Module *module,
                        ProcessLaunchInfo &launch_info)
{
    Error error;
    assert(m_monitor == NULL);

    FileSpec working_dir = launch_info.GetWorkingDirectory();
    if (working_dir &&
            (!working_dir.ResolvePath() ||
             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
    {
        error.SetErrorStringWithFormat("No such file or directory: %s",
                working_dir.GetCString());
        return error;
    }

    SetPrivateState(eStateLaunching);

    const lldb_private::FileAction *file_action;

    // Default of empty will mean to use existing open file descriptors
    FileSpec stdin_file_spec{};
    FileSpec stdout_file_spec{};
    FileSpec stderr_file_spec{};

    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};

    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);

    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);

    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);

    m_monitor = new ProcessMonitor(this,
                                   module,
                                   launch_info.GetArguments().GetConstArgumentVector(),
                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
                                   stdin_file_spec,
                                   stdout_file_spec,
                                   stderr_file_spec,
                                   working_dir,
                                   launch_info,
                                   error);

    m_module = module;

    if (!error.Success())
        return error;

    int terminal = m_monitor->GetTerminalFD();
    if (terminal >= 0) {
        // The reader thread will close the file descriptor when done, so we pass it a copy.
        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
        if (stdio == -1) {
            error.SetErrorToErrno();
            return error;
        }
        SetSTDIOFileDescriptor(stdio);
    }

    SetID(m_monitor->GetPID());
    return error;
}
Example #25
0
Error
Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
{
    Error error;
    if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments))
    {
        FileSpec expand_tool_spec;
        if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec))
        {
            error.SetErrorString("could not find argdumper tool");
            return error;
        }
        expand_tool_spec.AppendPathComponent("argdumper.exe");
        if (!expand_tool_spec.Exists())
        {
            error.SetErrorString("could not find argdumper tool");
            return error;
        }
        
        std::string quoted_cmd_string;
        launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string);
        std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/');
        StreamString expand_command;
        
        expand_command.Printf("%s %s",
                              expand_tool_spec.GetPath().c_str(),
                              quoted_cmd_string.c_str());
        
        int status;
        std::string output;
        RunShellCommand(expand_command.GetData(), launch_info.GetWorkingDirectory(), &status, nullptr, &output, 10);
        
        if (status != 0)
        {
            error.SetErrorStringWithFormat("argdumper exited with error %d", status);
            return error;
        }
        
        auto data_sp = StructuredData::ParseJSON(output);
        if (!data_sp)
        {
            error.SetErrorString("invalid JSON");
            return error;
        }
        
        auto dict_sp = data_sp->GetAsDictionary();
        if (!data_sp)
        {
            error.SetErrorString("invalid JSON");
            return error;
        }
        
        auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments");
        if (!args_sp)
        {
            error.SetErrorString("invalid JSON");
            return error;
        }
        
        auto args_array_sp = args_sp->GetAsArray();
        if (!args_array_sp)
        {
            error.SetErrorString("invalid JSON");
            return error;
        }
        
        launch_info.GetArguments().Clear();
        
        for (size_t i = 0;
             i < args_array_sp->GetSize();
             i++)
        {
            auto item_sp = args_array_sp->GetItemAtIndex(i);
            if (!item_sp)
                continue;
            auto str_sp = item_sp->GetAsString();
            if (!str_sp)
                continue;
            
            launch_info.GetArguments().AppendArgument(str_sp->GetValue().c_str());
        }
    }
    
    return error;
}
Example #26
0
Error
PlatformKalimba::ResolveExecutable (const FileSpec &exe_file,
                                  const ArchSpec &exe_arch,
                                  lldb::ModuleSP &exe_module_sp,
                                  const FileSpecList *module_search_paths_ptr)
{
    Error error;
    char exe_path[PATH_MAX];
    FileSpec resolved_exe_file (exe_file);

    if (!resolved_exe_file.Exists())
    {
        exe_file.GetPath(exe_path, sizeof(exe_path));
        error.SetErrorStringWithFormat("unable to find executable for '%s'", 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 #27
0
Error
OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
{
    Error error;
    Args args(value);
    const size_t argc = args.GetArgumentCount();

    switch (op)
    {
        case eVarSetOperationClear:
            Clear ();
            break;
            
        case eVarSetOperationReplace:
            // Must be at least one index + 1 pair of paths, and the pair count must be even
            if (argc >= 3 && (((argc - 1) & 1) == 0))
            {
                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
                const uint32_t count = m_path_mappings.GetSize();
                if (idx > count)
                {
                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
                }
                else
                {
                    for (size_t i=1; i<argc; i += 2, ++idx)
                    {
                        ConstString a(args.GetArgumentAtIndex(i));
                        ConstString b(args.GetArgumentAtIndex(i+1));
                        if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
                            m_path_mappings.Append(a, b, m_notify_changes);
                    }
                }
            }
            else
            {
                error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
            }
            break;
            
            
            
        case eVarSetOperationAssign:
            if (argc < 2 || (argc & 1))
            {
                error.SetErrorString("assign operation takes one or more path pairs");
                break;
            }
            m_path_mappings.Clear(m_notify_changes);
            // Fall through to append case
        case eVarSetOperationAppend:
            if (argc < 2 || (argc & 1))
            {
                error.SetErrorString("append operation takes one or more path pairs");
                break;
            }
            else
            {
                for (size_t i=0; i<argc; i += 2)
                {
                    ConstString a(args.GetArgumentAtIndex(i));
                    ConstString b(args.GetArgumentAtIndex(i+1));
                    m_path_mappings.Append(a, b, m_notify_changes);
                    m_value_was_set = true;
                }
            }
            break;
            
        case eVarSetOperationInsertBefore:
        case eVarSetOperationInsertAfter:
            // Must be at least one index + 1 pair of paths, and the pair count must be even
            if (argc >= 3 && (((argc - 1) & 1) == 0))
            {
                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
                const uint32_t count = m_path_mappings.GetSize();
                if (idx > count)
                {
                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
                }
                else
                {
                    if (op == eVarSetOperationInsertAfter)
                        ++idx;
                    for (size_t i=1; i<argc; i += 2, ++idx)
                    {
                        ConstString a(args.GetArgumentAtIndex(i));
                        ConstString b(args.GetArgumentAtIndex(i+1));
                        m_path_mappings.Insert (a, b, idx, m_notify_changes);
                    }
                }
            }
            else
            {
                error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
            }
            break;
            
        case eVarSetOperationRemove:
            if (argc > 0)
            {
                std::vector<int> remove_indexes;
                bool all_indexes_valid = true;
                size_t i;
                for (i=0; all_indexes_valid && i<argc; ++i)
                {
                    const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
                    if (idx == INT32_MAX)
                        all_indexes_valid = false;
                    else
                        remove_indexes.push_back(idx);
                }
                
                if (all_indexes_valid)
                {
                    size_t num_remove_indexes = remove_indexes.size();
                    if (num_remove_indexes)
                    {
                        // Sort and then erase in reverse so indexes are always valid
                        std::sort(remove_indexes.begin(), remove_indexes.end());
                        for (int i=num_remove_indexes-1; i<num_remove_indexes; ++i)
                        {
                            m_path_mappings.Remove (i, m_notify_changes);
                        }
                    }
                }
                else
                {
                    error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
                }
            }
            else
            {
                error.SetErrorString("remove operation takes one or more array index");
            }
            break;

        case eVarSetOperationInvalid:
            error = OptionValue::SetValueFromCString (value, op);
            break;
    }
    return error;

    m_value_was_set = true;
    return Error();
}
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;
}
Error
PlatformRemoteiOS::GetSymbolFile (const FileSpec &platform_file, 
                                  const UUID *uuid_ptr,
                                  FileSpec &local_file)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
    Error error;
    char platform_file_path[PATH_MAX];
    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
    {
        char resolved_path[PATH_MAX];
    
        const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
        if (os_version_dir)
        {
            ::snprintf (resolved_path, 
                        sizeof(resolved_path), 
                        "%s/%s", 
                        os_version_dir, 
                        platform_file_path);
            
            local_file.SetFile(resolved_path, true);
            if (local_file.Exists())
            {
                if (log)
                {
                    log->Printf ("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir);
                }
                return error;
            }

            ::snprintf (resolved_path, 
                        sizeof(resolved_path), 
                        "%s/Symbols.Internal/%s", 
                        os_version_dir, 
                        platform_file_path);

            local_file.SetFile(resolved_path, true);
            if (local_file.Exists())
            {
                if (log)
                {
                    log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir);
                }
                return error;
            }
            ::snprintf (resolved_path, 
                        sizeof(resolved_path), 
                        "%s/Symbols/%s", 
                        os_version_dir, 
                        platform_file_path);

            local_file.SetFile(resolved_path, true);
            if (local_file.Exists())
            {
                if (log)
                {
                    log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir);
                }
                return error;
            }

        }
        local_file = platform_file;
        if (local_file.Exists())
            return error;

        error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 
                                        platform_file_path,
                                        GetPluginName().GetCString());
    }
    else
    {
        error.SetErrorString ("invalid platform file argument");
    }
    return error;
}
Example #30
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;
}