예제 #1
0
void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
                                      Scalar &scalar, size_t size,
                                      Status &error) {
  error.Clear();

  if (size == UINT32_MAX)
    size = scalar.GetByteSize();

  if (size > 0) {
    uint8_t buf[32];
    const size_t mem_size =
        scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
    if (mem_size > 0) {
      return WriteMemory(process_address, buf, mem_size, error);
    } else {
      error.SetErrorToGenericError();
      error.SetErrorString(
          "Couldn't write scalar: failed to get scalar as memory data");
    }
  } else {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't write scalar: its size was zero");
  }
  return;
}
예제 #2
0
uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr,
                                                  const void *src,
                                                  uint32_t src_len,
                                                  Status &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;
  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_packet, reply_packet)) {
    lldb::offset_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;
}
예제 #3
0
bool CommunicationKDP::SendRawRequest(
    uint8_t command_byte,
    const void *src,  // Raw packet payload bytes
    uint32_t src_len, // Raw packet payload length
    DataExtractor &reply_packet, Status &error) {
  PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
                                  m_byte_order);
  // Size is header + address size + uint32_t length
  const uint32_t command_length = 8 + src_len;
  const CommandType command = (CommandType)command_byte;
  MakeRequestPacketHeader(command, request_packet, command_length);
  request_packet.PutRawBytes(src, src_len);

  if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
    lldb::offset_t offset = 8;
    uint32_t kdp_error = reply_packet.GetU32(&offset);
    if (kdp_error && (command_byte != KDP_DUMPINFO))
      error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)",
                                     command_byte, kdp_error);
    else {
      error.Clear();
      return true;
    }
  } else {
    error.SetErrorString("failed to send packet");
  }
  return false;
}
예제 #4
0
addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
                                        Status &error) {
  addr_t allocated_addr = LLDB_INVALID_ADDRESS;

  unsigned prot = 0;
  if (permissions & lldb::ePermissionsReadable)
    prot |= eMmapProtRead;
  if (permissions & lldb::ePermissionsWritable)
    prot |= eMmapProtWrite;
  if (permissions & lldb::ePermissionsExecutable)
    prot |= eMmapProtExec;

  if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
                       eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
    m_addr_to_mmap_size[allocated_addr] = size;
    error.Clear();
  } else {
    allocated_addr = LLDB_INVALID_ADDRESS;
    error.SetErrorStringWithFormat(
        "unable to allocate %zu bytes of memory with permissions %s", size,
        GetPermissionsAsCString(permissions));
  }

  return allocated_addr;
}
예제 #5
0
NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,
                                  socklen_t *addrlen,
                                  bool child_processes_inherit, Status &error) {
  error.Clear();
#if defined(ANDROID_USE_ACCEPT_WORKAROUND)
  // Hack:
  // This enables static linking lldb-server to an API 21 libc, but still
  // having it run on older devices. It is necessary because API 21 libc's
  // implementation of accept() uses the accept4 syscall(), which is not
  // available in older kernels. Using an older libc would fix this issue, but
  // introduce other ones, as the old libraries were quite buggy.
  int fd = syscall(__NR_accept, sockfd, addr, addrlen);
  if (fd >= 0 && !child_processes_inherit) {
    int flags = ::fcntl(fd, F_GETFD);
    if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1)
      return fd;
    SetLastError(error);
    close(fd);
  }
  return fd;
#elif defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
  int flags = 0;
  if (!child_processes_inherit) {
    flags |= SOCK_CLOEXEC;
  }
  NativeSocket fd = ::accept4(sockfd, addr, addrlen, flags);
#else
  NativeSocket fd = ::accept(sockfd, addr, addrlen);
#endif
  if (fd == kInvalidSocketValue)
    SetLastError(error);
  return fd;
}
예제 #6
0
bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Status &error) {
  error.Clear();
  if (str.empty())
  {
    error.SetErrorStringWithFormat("Empty breakpoint names are not allowed");
    return false;
  }

  // First character must be a letter or _
  if (!isalpha(str[0]) && str[0] != '_')
  {
    error.SetErrorStringWithFormat("Breakpoint names must start with a "
                                   "character or underscore: %s",
                                   str.str().c_str());
    return false;
  }

  // Cannot contain ., -, or space.
  if (str.find_first_of(".- ") != llvm::StringRef::npos) {
    error.SetErrorStringWithFormat("Breakpoint names cannot contain "
                                   "'.' or '-': \"%s\"",
                                   str.str().c_str());
    return false;
  }

  return true;
}
예제 #7
0
void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
                                       lldb::addr_t address, Status &error) {
  error.Clear();

  Scalar scalar(address);

  WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
}
예제 #8
0
NativeSocket Socket::CreateSocket(const int domain, const int type,
                                  const int protocol,
                                  bool child_processes_inherit, Status &error) {
  error.Clear();
  auto socket_type = type;
#ifdef SOCK_CLOEXEC
  if (!child_processes_inherit)
    socket_type |= SOCK_CLOEXEC;
#endif
  auto sock = ::socket(domain, socket_type, protocol);
  if (sock == kInvalidSocketValue)
    SetLastError(error);

  return sock;
}
예제 #9
0
void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {
  error.Clear();

  AllocationMap::iterator iter = m_allocations.find(process_address);

  if (iter == m_allocations.end()) {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't leak: allocation doesn't exist");
    return;
  }

  Allocation &allocation = iter->second;

  allocation.m_leak = true;
}
예제 #10
0
void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
                                        lldb::addr_t process_address,
                                        Status &error) {
  error.Clear();

  Scalar pointer_scalar;
  ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
                       error);

  if (!error.Success())
    return;

  *address = pointer_scalar.ULongLong();

  return;
}
예제 #11
0
IRMemoryMap::~IRMemoryMap() {
  lldb::ProcessSP process_sp = m_process_wp.lock();

  if (process_sp) {
    AllocationMap::iterator iter;

    Status err;

    while ((iter = m_allocations.begin()) != m_allocations.end()) {
      err.Clear();
      if (iter->second.m_leak)
        m_allocations.erase(iter);
      else
        Free(iter->first, err);
    }
  }
}
예제 #12
0
void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {
  error.Clear();

  AllocationMap::iterator iter = m_allocations.find(process_address);

  if (iter == m_allocations.end()) {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't free: allocation doesn't exist");
    return;
  }

  Allocation &allocation = iter->second;

  switch (allocation.m_policy) {
  default:
  case eAllocationPolicyHostOnly: {
    lldb::ProcessSP process_sp = m_process_wp.lock();
    if (process_sp) {
      if (process_sp->CanJIT() && process_sp->IsAlive())
        process_sp->DeallocateMemory(
            allocation.m_process_alloc); // FindSpace allocated this for real
    }

    break;
  }
  case eAllocationPolicyMirror:
  case eAllocationPolicyProcessOnly: {
    lldb::ProcessSP process_sp = m_process_wp.lock();
    if (process_sp)
      process_sp->DeallocateMemory(allocation.m_process_alloc);
  }
  }

  if (lldb_private::Log *log =
          lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
    log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
                "..0x%" PRIx64 ")",
                (uint64_t)process_address, iter->second.m_process_start,
                iter->second.m_process_start + iter->second.m_size);
  }

  m_allocations.erase(iter);
}
예제 #13
0
void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
                                       lldb::addr_t process_address,
                                       size_t size, Status &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;
}
예제 #14
0
uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu,
                                                    uint32_t flavor, void *dst,
                                                    uint32_t dst_len,
                                                    Status &error) {
  PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size,
                                  m_byte_order);
  const CommandType command = KDP_READREGS;
  // Size is header + 4 byte cpu and 4 byte flavor
  const uint32_t command_length = 8 + 4 + 4;
  MakeRequestPacketHeader(command, request_packet, command_length);
  request_packet.PutHex32(cpu);
  request_packet.PutHex32(flavor);
  DataExtractor reply_packet;
  if (SendRequestAndGetReply(command, request_packet, reply_packet)) {
    lldb::offset_t offset = 8;
    uint32_t kdp_error = reply_packet.GetU32(&offset);
    uint32_t src_len = reply_packet.GetByteSize() - 12;

    if (src_len > 0) {
      const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len);
      const void *src = reply_packet.GetData(&offset, bytes_to_copy);
      if (src) {
        ::memcpy(dst, src, bytes_to_copy);
        error.Clear();
        // Return the number of bytes we could have returned regardless if we
        // copied them or not, just so we know when things don't match up
        return src_len;
      }
    }
    if (kdp_error)
      error.SetErrorStringWithFormat(
          "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu,
          flavor, kdp_error);
    else
      error.SetErrorStringWithFormat(
          "failed to read kdp registers for cpu %u flavor %u", cpu, flavor);
  } else {
    error.SetErrorString("failed to send packet");
  }
  return 0;
}
예제 #15
0
std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol,
                                       bool child_processes_inherit,
                                       Status &error) {
  error.Clear();

  std::unique_ptr<Socket> socket_up;
  switch (protocol) {
  case ProtocolTcp:
    socket_up =
        llvm::make_unique<TCPSocket>(true, child_processes_inherit);
    break;
  case ProtocolUdp:
    socket_up =
        llvm::make_unique<UDPSocket>(true, child_processes_inherit);
    break;
  case ProtocolUnixDomain:
#ifndef LLDB_DISABLE_POSIX
    socket_up =
        llvm::make_unique<DomainSocket>(true, child_processes_inherit);
#else
    error.SetErrorString(
        "Unix domain sockets are not supported on this platform.");
#endif
    break;
  case ProtocolUnixAbstract:
#ifdef __linux__
    socket_up =
        llvm::make_unique<AbstractSocket>(child_processes_inherit);
#else
    error.SetErrorString(
        "Abstract domain sockets are not supported on this platform.");
#endif
    break;
  }

  if (error.Fail())
    socket_up.reset();

  return socket_up;
}
TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) {
  TraceOptions options;
  Status error;

  options.setType(lldb::TraceType::eTraceTypeProcessorTrace);
  options.setMetaDataBufferSize(8192);
  options.setTraceBufferSize(8192);
  options.setThreadID(0x23);

  StructuredData::DictionarySP custom_params =
      std::make_shared<StructuredData::Dictionary>();
  custom_params->AddStringItem("tracetech", "intel-pt");
  custom_params->AddIntegerItem("psb", 0x01);

  options.setTraceParams(custom_params);

  std::future<lldb::user_id_t> result = std::async(std::launch::async, [&] {
    return client.SendStartTracePacket(options, error);
  });

  // Since the line is exceeding 80 characters.
  std::string expected_packet1 =
      R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)";
  std::string expected_packet2 =
      R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
  HandlePacket(server, (expected_packet1 + expected_packet2), "1");
  ASSERT_TRUE(error.Success());
  ASSERT_EQ(result.get(), 1u);

  error.Clear();
  result = std::async(std::launch::async, [&] {
    return client.SendStartTracePacket(options, error);
  });

  HandlePacket(server, (expected_packet1 + expected_packet2), "E23");
  ASSERT_EQ(result.get(), LLDB_INVALID_UID);
  ASSERT_FALSE(error.Success());
}
HostProcess
MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,
                                         Status &error) {
  ProcessLaunchInfo resolved_info(launch_info);

  error.Clear();
  char exe_path[PATH_MAX];

  PlatformSP host_platform_sp(Platform::GetHostPlatform());

  const ArchSpec &arch_spec = resolved_info.GetArchitecture();

  FileSpec exe_spec(resolved_info.GetExecutableFile());

  llvm::sys::fs::file_status stats;
  status(exe_spec.GetPath(), stats);
  if (!is_regular_file(stats)) {
    ModuleSpec module_spec(exe_spec, arch_spec);
    lldb::ModuleSP exe_module_sp;
    error =
        host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL);

    if (error.Fail())
      return HostProcess();

    if (exe_module_sp) {
      exe_spec = exe_module_sp->GetFileSpec();
      status(exe_spec.GetPath(), stats);
    }
  }

  if (exists(stats)) {
    exe_spec.GetPath(exe_path, sizeof(exe_path));
  } else {
    resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
    error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path);
    return HostProcess();
  }

  resolved_info.SetExecutableFile(exe_spec, false);
  assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY));

  HostProcess process =
      m_delegate_launcher->LaunchProcess(resolved_info, error);

  if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    Host::MonitorChildProcessCallback callback =
        launch_info.GetMonitorProcessCallback();

    bool monitor_signals = false;
    if (callback) {
      // If the ProcessLaunchInfo specified a callback, use that.
      monitor_signals = launch_info.GetMonitorSignals();
    } else {
      callback = Process::SetProcessExitStatus;
    }

    process.StartMonitoring(callback, monitor_signals);
    if (log)
      log->PutCString("started monitoring child process.");
  } else {
    // Invalid process ID, something didn't go well
    if (error.Success())
      error.SetErrorString("process launch failed for unknown reasons");
  }
  return process;
}
예제 #18
0
lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
                                 uint32_t permissions, AllocationPolicy policy,
                                 bool zero_memory, Status &error) {
  lldb_private::Log *log(
      lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
  error.Clear();

  lldb::ProcessSP process_sp;
  lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
  lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;

  size_t allocation_size;

  if (size == 0) {
    // FIXME: Malloc(0) should either return an invalid address or assert, in
    // order to cut down on unnecessary allocations.
    allocation_size = alignment;
  } else {
    // Round up the requested size to an aligned value.
    allocation_size = llvm::alignTo(size, alignment);

    // The process page cache does not see the requested alignment. We can't
    // assume its result will be any more than 1-byte aligned. To work around
    // this, request `alignment - 1` additional bytes.
    allocation_size += alignment - 1;
  }

  switch (policy) {
  default:
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't malloc: invalid allocation policy");
    return LLDB_INVALID_ADDRESS;
  case eAllocationPolicyHostOnly:
    allocation_address = FindSpace(allocation_size);
    if (allocation_address == LLDB_INVALID_ADDRESS) {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't malloc: address space is full");
      return LLDB_INVALID_ADDRESS;
    }
    break;
  case eAllocationPolicyMirror:
    process_sp = m_process_wp.lock();
    if (log)
      log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64
                  ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
                  __FUNCTION__, (lldb::addr_t)process_sp.get(),
                  process_sp && process_sp->CanJIT() ? "true" : "false",
                  process_sp && process_sp->IsAlive() ? "true" : "false");
    if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
      if (!zero_memory)
        allocation_address =
            process_sp->AllocateMemory(allocation_size, permissions, error);
      else
        allocation_address =
            process_sp->CallocateMemory(allocation_size, permissions, error);

      if (!error.Success())
        return LLDB_INVALID_ADDRESS;
    } else {
      if (log)
        log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
                    "due to failed condition (see previous expr log message)",
                    __FUNCTION__);
      policy = eAllocationPolicyHostOnly;
      allocation_address = FindSpace(allocation_size);
      if (allocation_address == LLDB_INVALID_ADDRESS) {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't malloc: address space is full");
        return LLDB_INVALID_ADDRESS;
      }
    }
    break;
  case eAllocationPolicyProcessOnly:
    process_sp = m_process_wp.lock();
    if (process_sp) {
      if (process_sp->CanJIT() && process_sp->IsAlive()) {
        if (!zero_memory)
          allocation_address =
              process_sp->AllocateMemory(allocation_size, permissions, error);
        else
          allocation_address =
              process_sp->CallocateMemory(allocation_size, permissions, error);

        if (!error.Success())
          return LLDB_INVALID_ADDRESS;
      } else {
        error.SetErrorToGenericError();
        error.SetErrorString(
            "Couldn't malloc: process doesn't support allocating memory");
        return LLDB_INVALID_ADDRESS;
      }
    } else {
      error.SetErrorToGenericError();
      error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
                           "memory must be in the process");
      return LLDB_INVALID_ADDRESS;
    }
    break;
  }

  lldb::addr_t mask = alignment - 1;
  aligned_address = (allocation_address + mask) & (~mask);

  m_allocations.emplace(
      std::piecewise_construct, std::forward_as_tuple(aligned_address),
      std::forward_as_tuple(allocation_address, aligned_address,
                            allocation_size, permissions, alignment, policy));

  if (zero_memory) {
    Status write_error;
    std::vector<uint8_t> zero_buf(size, 0);
    WriteMemory(aligned_address, zero_buf.data(), size, write_error);
  }

  if (log) {
    const char *policy_string;

    switch (policy) {
    default:
      policy_string = "<invalid policy>";
      break;
    case eAllocationPolicyHostOnly:
      policy_string = "eAllocationPolicyHostOnly";
      break;
    case eAllocationPolicyProcessOnly:
      policy_string = "eAllocationPolicyProcessOnly";
      break;
    case eAllocationPolicyMirror:
      policy_string = "eAllocationPolicyMirror";
      break;
    }

    log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
                ", %s) -> 0x%" PRIx64,
                (uint64_t)allocation_size, (uint64_t)alignment,
                (uint64_t)permissions, policy_string, aligned_address);
  }

  return aligned_address;
}
Status PlatformRemoteDarwinDevice::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();
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);

  Status 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) {
      LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
                m_sdk_directory_infos[connected_sdk_idx].directory);
      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) {
      LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
                m_sdk_directory_infos[m_last_module_sdk_idx].directory);
      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) {
      LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
                m_sdk_directory_infos[current_sdk_idx].directory);
      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;
      }
      LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
                m_sdk_directory_infos[sdk_idx].directory);
      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;

  // See if the file is present in any of the module_search_paths_ptr
  // directories.
  if (!module_sp)
    error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, 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;
}
예제 #20
0
void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
                              const uint8_t *bytes, size_t size,
                              Status &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);
  }
}
예제 #21
0
void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
                             size_t size, Status &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);
  }
}
예제 #22
0
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
                                           Status &error) {
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);

  std::lock_guard<std::mutex> guard(m_condition_mutex);

  size_t condition_hash;
  const char *condition_text = GetConditionText(&condition_hash);

  if (!condition_text) {
    m_user_expression_sp.reset();
    return false;
  }

  error.Clear();

  DiagnosticManager diagnostics;

  if (condition_hash != m_condition_hash || !m_user_expression_sp ||
      !m_user_expression_sp->MatchesContext(exe_ctx)) {
    LanguageType language = eLanguageTypeUnknown;
    // See if we can figure out the language from the frame, otherwise use the
    // default language:
    CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
    if (comp_unit)
      language = comp_unit->GetLanguage();

    m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
        condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
        EvaluateExpressionOptions(), nullptr, error));
    if (error.Fail()) {
      if (log)
        log->Printf("Error getting condition expression: %s.",
                    error.AsCString());
      m_user_expression_sp.reset();
      return true;
    }

    if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
                                     eExecutionPolicyOnlyWhenNeeded, true,
                                     false)) {
      error.SetErrorStringWithFormat(
          "Couldn't parse conditional expression:\n%s",
          diagnostics.GetString().c_str());
      m_user_expression_sp.reset();
      return true;
    }

    m_condition_hash = condition_hash;
  }

  // We need to make sure the user sees any parse errors in their condition, so
  // we'll hook the constructor errors up to the debugger's Async I/O.

  ValueObjectSP result_value_sp;

  EvaluateExpressionOptions options;
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  options.SetTryAllThreads(true);
  options.SetResultIsInternal(
      true); // Don't generate a user variable for condition expressions.

  Status expr_error;

  diagnostics.Clear();

  ExpressionVariableSP result_variable_sp;

  ExpressionResults result_code = m_user_expression_sp->Execute(
      diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);

  bool ret;

  if (result_code == eExpressionCompleted) {
    if (!result_variable_sp) {
      error.SetErrorString("Expression did not return a result");
      return false;
    }

    result_value_sp = result_variable_sp->GetValueObject();

    if (result_value_sp) {
      ret = result_value_sp->IsLogicalTrue(error);
      if (log) {
        if (error.Success()) {
          log->Printf("Condition successfully evaluated, result is %s.\n",
                      ret ? "true" : "false");
        } else {
          error.SetErrorString(
              "Failed to get an integer result from the expression");
          ret = false;
        }
      }
    } else {
      ret = false;
      error.SetErrorString("Failed to get any result from the expression");
    }
  } else {
    ret = false;
    error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
                                   diagnostics.GetString().c_str());
  }

  return ret;
}
예제 #23
0
void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
                                lldb::addr_t process_address, size_t size,
                                Status &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;
  }
}
예제 #24
0
  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    err.Clear();

    ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();

    if (!exe_scope) {
      err.SetErrorString("Couldn't dematerialize a result variable: invalid "
                         "execution context scope");
      return;
    }

    lldb::addr_t address;
    Status read_error;
    const lldb::addr_t load_addr = process_address + m_offset;

    map.ReadPointerFromMemory(&address, load_addr, read_error);

    if (!read_error.Success()) {
      err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
                         "read its address");
      return;
    }

    lldb::TargetSP target_sp = exe_scope->CalculateTarget();

    if (!target_sp) {
      err.SetErrorString("Couldn't dematerialize a result variable: no target");
      return;
    }

    Status type_system_error;
    TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(
        &type_system_error, m_type.GetMinimumLanguage());

    if (!type_system) {
      err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
                                   "couldn't get the corresponding type "
                                   "system: %s",
                                   type_system_error.AsCString());
      return;
    }

    PersistentExpressionState *persistent_state =
        type_system->GetPersistentExpressionState();

    if (!persistent_state) {
      err.SetErrorString("Couldn't dematerialize a result variable: "
                         "corresponding type system doesn't handle persistent "
                         "variables");
      return;
    }

    ConstString name = m_delegate
                           ? m_delegate->GetName()
                           : persistent_state->GetNextPersistentVariableName();

    lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
        exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());

    if (!ret) {
      err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
                                   "failed to make persistent variable %s",
                                   name.AsCString());
      return;
    }

    lldb::ProcessSP process_sp =
        map.GetBestExecutionContextScope()->CalculateProcess();

    if (m_delegate) {
      m_delegate->DidDematerialize(ret);
    }

    bool can_persist =
        (m_is_program_reference && process_sp && process_sp->CanJIT() &&
         !(address >= frame_bottom && address < frame_top));

    if (can_persist && m_keep_in_memory) {
      ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
                                                      address, eAddressTypeLoad,
                                                      map.GetAddressByteSize());
    }

    ret->ValueUpdated();

    const size_t pvar_byte_size = ret->GetByteSize();
    uint8_t *pvar_data = ret->GetValueBytes();

    map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);

    if (!read_error.Success()) {
      err.SetErrorString(
          "Couldn't dematerialize a result variable: couldn't read its memory");
      return;
    }

    if (!can_persist || !m_keep_in_memory) {
      ret->m_flags |= ExpressionVariable::EVNeedsAllocation;

      if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
        Status free_error;
        map.Free(m_temporary_allocation, free_error);
      }
    } else {
      ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
    }

    m_temporary_allocation = LLDB_INVALID_ADDRESS;
    m_temporary_allocation_size = 0;
  }