/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "JITDebugReader.h"

#include <inttypes.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <sys/user.h>

#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>

#include "dso.h"
#include "environment.h"
#include "read_apk.h"
#include "read_elf.h"
#include "utils.h"

namespace simpleperf {

// If the size of a symfile is larger than EXPECTED_MAX_SYMFILE_SIZE, we don't want to read it
// remotely.
static constexpr size_t MAX_JIT_SYMFILE_SIZE = 1024 * 1024u;

// It takes about 30us-130us on Pixel (depending on the cpu frequency) to check if the descriptors
// have been updated (most time spent in process_vm_preadv). We want to know if the JIT debug info
// changed as soon as possible, while not wasting too much time checking for updates. So use a
// period of 100 ms.
// In system wide profiling, we may need to check JIT debug info changes for many processes, to
// avoid spending all time checking, wait 100 ms between any two checks.
static constexpr size_t kUpdateJITDebugInfoIntervalInMs = 100;

// Match the format of JITDescriptor in art/runtime/jit/debugger_interface.cc.
template <typename ADDRT>
struct JITDescriptor {
  uint32_t version;
  uint32_t action_flag;
  ADDRT relevant_entry_addr;
  ADDRT first_entry_addr;
  uint8_t magic[8];
  uint32_t flags;
  uint32_t sizeof_descriptor;
  uint32_t sizeof_entry;
  uint32_t action_seqlock;  // incremented before and after any modification
  uint64_t action_timestamp;  // CLOCK_MONOTONIC time of last action

  bool Valid() const;

  int AndroidVersion() const {
    return magic[7] - '0';
  }
};

// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
// with JITDescriptor.magic == "Android1".
template <typename ADDRT>
struct JITCodeEntry {
  ADDRT next_addr;
  ADDRT prev_addr;
  ADDRT symfile_addr;
  uint64_t symfile_size;
  uint64_t register_timestamp;  // CLOCK_MONOTONIC time of entry registration

  bool Valid() const {
    return symfile_addr > 0u && symfile_size > 0u;
  }
};

// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
// with JITDescriptor.magic == "Android1".
template <typename ADDRT>
struct __attribute__((packed)) PackedJITCodeEntry {
  ADDRT next_addr;
  ADDRT prev_addr;
  ADDRT symfile_addr;
  uint64_t symfile_size;
  uint64_t register_timestamp;

  bool Valid() const {
    return symfile_addr > 0u && symfile_size > 0u;
  }
};

// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
// with JITDescriptor.magic == "Android2".
template <typename ADDRT>
struct JITCodeEntryV2 {
  ADDRT next_addr;
  ADDRT prev_addr;
  ADDRT symfile_addr;
  uint64_t symfile_size;
  uint64_t register_timestamp;  // CLOCK_MONOTONIC time of entry registration
  uint32_t seqlock;  // even value if valid

  bool Valid() const {
    return (seqlock & 1) == 0;
  }
};

// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
// with JITDescriptor.magic == "Android2".
template <typename ADDRT>
struct __attribute__((packed)) PackedJITCodeEntryV2 {
  ADDRT next_addr;
  ADDRT prev_addr;
  ADDRT symfile_addr;
  uint64_t symfile_size;
  uint64_t register_timestamp;
  uint32_t seqlock;

  bool Valid() const {
    return (seqlock & 1) == 0;
  }
};

// Match the format of JITCodeEntry in art/runtime/jit/debugger_interface.cc
// with JITDescriptor.magic == "Android2".
template <typename ADDRT>
struct __attribute__((packed)) PaddedJITCodeEntryV2 {
  ADDRT next_addr;
  ADDRT prev_addr;
  ADDRT symfile_addr;
  uint64_t symfile_size;
  uint64_t register_timestamp;
  uint32_t seqlock;
  uint32_t pad;

  bool Valid() const {
    return (seqlock & 1) == 0;
  }
};

using JITDescriptor32 = JITDescriptor<uint32_t>;
using JITDescriptor64 = JITDescriptor<uint64_t>;

#if defined(__x86_64__)
// Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of i386.
using JITCodeEntry32 = PackedJITCodeEntry<uint32_t>;
using JITCodeEntry32V2 = PackedJITCodeEntryV2<uint32_t>;
#else
using JITCodeEntry32 = JITCodeEntry<uint32_t>;
using JITCodeEntry32V2 = JITCodeEntryV2<uint32_t>;
#endif

using JITCodeEntry64 = JITCodeEntry<uint64_t>;
#if defined(__i386__)
// Make sure simpleperf built for i386 and x86_64 see the correct JITCodeEntry layout of x86_64.
using JITCodeEntry64V2 = PaddedJITCodeEntryV2<uint64_t>;
#else
using JITCodeEntry64V2 = JITCodeEntryV2<uint64_t>;
#endif

template <typename ADDRT>
bool JITDescriptor<ADDRT>::Valid() const {
  const char* magic_str = reinterpret_cast<const char*>(magic);
  if (version != 1 ||
      !(strncmp(magic_str, "Android1", 8) == 0 || strncmp(magic_str, "Android2", 8) == 0)) {
    return false;
  }
  if (sizeof(*this) != sizeof_descriptor) {
    return false;
  }
  if (sizeof(ADDRT) == 4) {
    return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry32)
                                                   : sizeof(JITCodeEntry32V2);
  }
  return sizeof_entry == (AndroidVersion() == 1) ? sizeof(JITCodeEntry64)
                                                 : sizeof(JITCodeEntry64V2);
}

// We want to support both 64-bit and 32-bit simpleperf when profiling either 64-bit or 32-bit
// apps. So using static_asserts to make sure that simpleperf on arm and aarch64 having the same
// view of structures, and simpleperf on i386 and x86_64 having the same view of structures.
static_assert(sizeof(JITDescriptor32) == 48, "");
static_assert(sizeof(JITDescriptor64) == 56, "");

#if defined(__i386__) or defined(__x86_64__)
static_assert(sizeof(JITCodeEntry32) == 28, "");
static_assert(sizeof(JITCodeEntry32V2) == 32, "");
static_assert(sizeof(JITCodeEntry64) == 40, "");
static_assert(sizeof(JITCodeEntry64V2) == 48, "");
#else
static_assert(sizeof(JITCodeEntry32) == 32, "");
static_assert(sizeof(JITCodeEntry32V2) == 40, "");
static_assert(sizeof(JITCodeEntry64) == 40, "");
static_assert(sizeof(JITCodeEntry64V2) == 48, "");
#endif

bool JITDebugReader::RegisterDebugInfoCallback(IOEventLoop* loop,
                                             const debug_info_callback_t& callback) {
  debug_info_callback_ = callback;
  read_event_ = loop->AddPeriodicEvent(SecondToTimeval(kUpdateJITDebugInfoIntervalInMs / 1000.0),
                                       [this]() { return ReadAllProcesses(); });
  return (read_event_ != nullptr && IOEventLoop::DisableEvent(read_event_));
}

bool JITDebugReader::MonitorProcess(pid_t pid) {
  if (processes_.find(pid) == processes_.end()) {
    processes_[pid].pid = pid;
    LOG(DEBUG) << "Start monitoring process " << pid;
    if (processes_.size() == 1u) {
      if (!IOEventLoop::EnableEvent(read_event_)) {
        return false;
      }
    }
  }
  return true;
}

static bool IsArtLib(const std::string& filename) {
  return android::base::EndsWith(filename, "libart.so") ||
      android::base::EndsWith(filename, "libartd.so");
}

bool JITDebugReader::UpdateRecord(const Record* record) {
  if (record->type() == PERF_RECORD_MMAP) {
    auto r = static_cast<const MmapRecord*>(record);
    if (IsArtLib(r->filename)) {
      pids_with_art_lib_.emplace(r->data->pid, false);
    }
  } else if (record->type() == PERF_RECORD_MMAP2) {
    auto r = static_cast<const Mmap2Record*>(record);
    if (IsArtLib(r->filename)) {
      pids_with_art_lib_.emplace(r->data->pid, false);
    }
  } else if (record->type() == PERF_RECORD_FORK) {
    auto r = static_cast<const ForkRecord*>(record);
    if (r->data->pid != r->data->ppid &&
        pids_with_art_lib_.find(r->data->ppid) != pids_with_art_lib_.end()) {
      pids_with_art_lib_.emplace(r->data->pid, false);
    }
  } else if (record->type() == PERF_RECORD_SAMPLE) {
    auto r = static_cast<const SampleRecord*>(record);
    auto it = pids_with_art_lib_.find(r->tid_data.pid);
    if (it != pids_with_art_lib_.end() && !it->second) {
      it->second = true;
      if (!MonitorProcess(r->tid_data.pid)) {
        return false;
      }
      return ReadProcess(r->tid_data.pid);
    }
  }
  return FlushDebugInfo(record->Timestamp());
}

bool JITDebugReader::FlushDebugInfo(uint64_t timestamp) {
  if (sync_with_records_) {
    if (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
      std::vector<JITDebugInfo> debug_info;
      while (!debug_info_q_.empty() && debug_info_q_.top().timestamp < timestamp) {
        debug_info.emplace_back(debug_info_q_.top());
        debug_info_q_.pop();
      }
      return debug_info_callback_(debug_info, false);
    }
  }
  return true;
}

bool JITDebugReader::ReadAllProcesses() {
  if (!IOEventLoop::DisableEvent(read_event_)) {
    return false;
  }
  std::vector<JITDebugInfo> debug_info;
  for (auto it = processes_.begin(); it != processes_.end();) {
    Process& process = it->second;
    ReadProcess(process, &debug_info);
    if (process.died) {
      LOG(DEBUG) << "Stop monitoring process " << process.pid;
      it = processes_.erase(it);
    } else {
      ++it;
    }
  }
  if (!AddDebugInfo(debug_info, true)) {
    return false;
  }
  if (!processes_.empty()) {
    return IOEventLoop::EnableEvent(read_event_);
  }
  return true;
}

bool JITDebugReader::ReadProcess(pid_t pid) {
  auto it = processes_.find(pid);
  if (it != processes_.end()) {
    std::vector<JITDebugInfo> debug_info;
    ReadProcess(it->second, &debug_info);
    return AddDebugInfo(debug_info, false);
  }
  return true;
}

void JITDebugReader::ReadProcess(Process& process, std::vector<JITDebugInfo>* debug_info) {
  if (process.died || (!process.initialized && !InitializeProcess(process))) {
    return;
  }
  // 1. Read descriptors.
  Descriptor jit_descriptor;
  Descriptor dex_descriptor;
  if (!ReadDescriptors(process, &jit_descriptor, &dex_descriptor)) {
    return;
  }
  // 2. Return if descriptors are not changed.
  if (jit_descriptor.action_seqlock == process.last_jit_descriptor.action_seqlock &&
      dex_descriptor.action_seqlock == process.last_dex_descriptor.action_seqlock) {
    return;
  }

  // 3. Read new symfiles.
  auto check_descriptor = [&](Descriptor& descriptor, bool is_jit) {
      Descriptor tmp_jit_descriptor;
      Descriptor tmp_dex_descriptor;
      if (!ReadDescriptors(process, &tmp_jit_descriptor, &tmp_dex_descriptor)) {
        return false;
      }
      if (is_jit) {
        return descriptor.action_seqlock == tmp_jit_descriptor.action_seqlock;
      }
      return descriptor.action_seqlock == tmp_dex_descriptor.action_seqlock;
  };

  auto read_debug_info = [&](Descriptor& new_descriptor, Descriptor& old_descriptor, bool is_jit) {
    bool has_update = new_descriptor.action_seqlock != old_descriptor.action_seqlock &&
                      (new_descriptor.action_seqlock & 1) == 0;
    LOG(DEBUG) << (is_jit ? "JIT" : "Dex") << " symfiles of pid " << process.pid
        << ": old seqlock " << old_descriptor.action_seqlock
        << ", new seqlock " << new_descriptor.action_seqlock;
    if (!has_update) {
      return false;
    }
    std::vector<CodeEntry> new_entries;
    // Adding or removing one code entry will make two increments of action_seqlock. So we should
    // not read more than (seqlock_diff / 2) new entries.
    uint32_t read_entry_limit = (new_descriptor.action_seqlock - old_descriptor.action_seqlock) / 2;
    if (!ReadNewCodeEntries(process, new_descriptor, old_descriptor.action_timestamp,
                            read_entry_limit, &new_entries)) {
      return false;
    }
    // Check if the descriptor was changed while we were reading new entries.
    if (!check_descriptor(new_descriptor, is_jit)) {
      return false;
    }
    LOG(DEBUG) << (is_jit ? "JIT" : "Dex") << " symfiles of pid " << process.pid
               << ": read " << new_entries.size() << " new entries";
    if (new_entries.empty()) {
      return true;
    }
    if (is_jit) {
      ReadJITCodeDebugInfo(process, new_entries, debug_info);
    } else {
      ReadDexFileDebugInfo(process, new_entries, debug_info);
    }
    return true;
  };
  if (read_debug_info(jit_descriptor, process.last_jit_descriptor, true)) {
    process.last_jit_descriptor = jit_descriptor;
  }
  if (read_debug_info(dex_descriptor, process.last_dex_descriptor, false)) {
    process.last_dex_descriptor = dex_descriptor;
  }
}

bool JITDebugReader::InitializeProcess(Process& process) {
  // 1. Read map file to find the location of libart.so.
  std::vector<ThreadMmap> thread_mmaps;
  if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
    process.died = true;
    return false;
  }
  std::string art_lib_path;
  uint64_t min_vaddr_in_memory;
  for (auto& map : thread_mmaps) {
    if ((map.prot & PROT_EXEC) && IsArtLib(map.name)) {
      art_lib_path = map.name;
      min_vaddr_in_memory = map.start_addr;
      break;
    }
  }
  if (art_lib_path.empty()) {
    return false;
  }
  process.is_64bit = art_lib_path.find("lib64") != std::string::npos;

  // 2. Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
  const DescriptorsLocation* location = GetDescriptorsLocation(art_lib_path, process.is_64bit);
  if (location == nullptr) {
    return false;
  }
  process.descriptors_addr = location->relative_addr + min_vaddr_in_memory;
  process.descriptors_size = location->size;
  process.jit_descriptor_offset = location->jit_descriptor_offset;
  process.dex_descriptor_offset = location->dex_descriptor_offset;
  process.initialized = true;
  return true;
}

const JITDebugReader::DescriptorsLocation* JITDebugReader::GetDescriptorsLocation(
    const std::string& art_lib_path, bool is_64bit) {
  auto it = descriptors_location_cache_.find(art_lib_path);
  if (it != descriptors_location_cache_.end()) {
    return it->second.relative_addr == 0u ? nullptr : &it->second;
  }
  DescriptorsLocation& location = descriptors_location_cache_[art_lib_path];

  // Read libart.so to find the addresses of __jit_debug_descriptor and __dex_debug_descriptor.
  uint64_t min_vaddr_in_file;
  uint64_t file_offset;
  ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(art_lib_path, BuildId(),
                                                                &min_vaddr_in_file,
                                                                &file_offset);
  if (status != ElfStatus::NO_ERROR) {
    LOG(ERROR) << "ReadMinExecutableVirtualAddress failed, status = " << status;
    return nullptr;
  }
  // min_vaddr_in_file is the min vaddr of executable segments. It may not be page aligned.
  // And dynamic linker will create map mapping to (segment.p_vaddr & PAGE_MASK).
  uint64_t aligned_segment_vaddr = min_vaddr_in_file & PAGE_MASK;
  const char* jit_str = "__jit_debug_descriptor";
  const char* dex_str = "__dex_debug_descriptor";
  uint64_t jit_addr = 0u;
  uint64_t dex_addr = 0u;

  auto callback = [&](const ElfFileSymbol& symbol) {
    if (symbol.name == jit_str) {
      jit_addr = symbol.vaddr - aligned_segment_vaddr;
    } else if (symbol.name == dex_str) {
      dex_addr = symbol.vaddr - aligned_segment_vaddr;
    }
  };
  if (ParseDynamicSymbolsFromElfFile(art_lib_path, callback) != ElfStatus::NO_ERROR) {
    return nullptr;
  }
  if (jit_addr == 0u || dex_addr == 0u) {
    return nullptr;
  }
  location.relative_addr = std::min(jit_addr, dex_addr);
  location.size = std::max(jit_addr, dex_addr) +
      (is_64bit ? sizeof(JITDescriptor64) : sizeof(JITDescriptor32)) - location.relative_addr;
  if (location.size >= 4096u) {
    PLOG(WARNING) << "The descriptors_size is unexpected large: " << location.size;
  }
  if (descriptors_buf_.size() < location.size) {
    descriptors_buf_.resize(location.size);
  }
  location.jit_descriptor_offset = jit_addr - location.relative_addr;
  location.dex_descriptor_offset = dex_addr - location.relative_addr;
  return &location;
}

bool JITDebugReader::ReadRemoteMem(Process& process, uint64_t remote_addr, uint64_t size,
                                   void* data) {
  iovec local_iov;
  local_iov.iov_base = data;
  local_iov.iov_len = size;
  iovec remote_iov;
  remote_iov.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(remote_addr));
  remote_iov.iov_len = size;
  ssize_t result = process_vm_readv(process.pid, &local_iov, 1, &remote_iov, 1, 0);
  if (static_cast<size_t>(result) != size) {
    PLOG(DEBUG) << "ReadRemoteMem(" << " pid " << process.pid << ", addr " << std::hex
                << remote_addr << ", size " << size << ") failed";
    process.died = true;
    return false;
  }
  return true;
}

bool JITDebugReader::ReadDescriptors(Process& process, Descriptor* jit_descriptor,
                                     Descriptor* dex_descriptor) {
  if (!ReadRemoteMem(process, process.descriptors_addr, process.descriptors_size,
                     descriptors_buf_.data())) {
    return false;
  }
  return LoadDescriptor(process.is_64bit, &descriptors_buf_[process.jit_descriptor_offset],
                        jit_descriptor) &&
      LoadDescriptor(process.is_64bit, &descriptors_buf_[process.dex_descriptor_offset],
                     dex_descriptor);
}

bool JITDebugReader::LoadDescriptor(bool is_64bit, const char* data, Descriptor* descriptor) {
  if (is_64bit) {
    return LoadDescriptorImpl<JITDescriptor64>(data, descriptor);
  }
  return LoadDescriptorImpl<JITDescriptor32>(data, descriptor);
}

template <typename DescriptorT>
bool JITDebugReader::LoadDescriptorImpl(const char* data, Descriptor* descriptor) {
  DescriptorT raw_descriptor;
  MoveFromBinaryFormat(raw_descriptor, data);
  if (!raw_descriptor.Valid()) {
    return false;
  }
  descriptor->action_seqlock = raw_descriptor.action_seqlock;
  descriptor->action_timestamp = raw_descriptor.action_timestamp;
  descriptor->first_entry_addr = raw_descriptor.first_entry_addr;
  descriptor->version = raw_descriptor.AndroidVersion();
  return true;
}

// Read new code entries with timestamp > last_action_timestamp.
// Since we don't stop the app process while reading code entries, it is possible we are reading
// broken data. So return false once we detect that the data is broken.
bool JITDebugReader::ReadNewCodeEntries(Process& process, const Descriptor& descriptor,
                                        uint64_t last_action_timestamp, uint32_t read_entry_limit,
                                        std::vector<CodeEntry>* new_code_entries) {
  if (descriptor.version == 1) {
    if (process.is_64bit) {
      return ReadNewCodeEntriesImpl<JITCodeEntry64>(
          process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
    }
    return ReadNewCodeEntriesImpl<JITCodeEntry32>(
        process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
  }
  if (descriptor.version == 2) {
    if (process.is_64bit) {
      return ReadNewCodeEntriesImplV2<JITCodeEntry64V2>(
          process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
    }
    return ReadNewCodeEntriesImplV2<JITCodeEntry32V2>(
        process, descriptor, last_action_timestamp, read_entry_limit, new_code_entries);
  }
  return false;
}

template <typename CodeEntryT>
bool JITDebugReader::ReadNewCodeEntriesImpl(Process& process, const Descriptor& descriptor,
                                            uint64_t last_action_timestamp,
                                            uint32_t read_entry_limit,
                                            std::vector<CodeEntry>* new_code_entries) {
  uint64_t current_entry_addr = descriptor.first_entry_addr;
  uint64_t prev_entry_addr = 0u;
  std::unordered_set<uint64_t> entry_addr_set;

  for (size_t i = 0u; i < read_entry_limit && current_entry_addr != 0u; ++i) {
    if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
      // We enter a loop, which means a broken linked list.
      return false;
    }
    CodeEntryT entry;
    if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
      return false;
    }
    if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
      // A broken linked list
      return false;
    }
    if (entry.register_timestamp <= last_action_timestamp) {
      // The linked list has entries with timestamp in decreasing order. So stop searching
      // once we hit an entry with timestamp <= last_action_timestmap.
      break;
    }
    if (entry.symfile_size > 0) {
      CodeEntry code_entry;
      code_entry.addr = current_entry_addr;
      code_entry.symfile_addr = entry.symfile_addr;
      code_entry.symfile_size = entry.symfile_size;
      code_entry.timestamp = entry.register_timestamp;
      new_code_entries->push_back(code_entry);
    }
    entry_addr_set.insert(current_entry_addr);
    prev_entry_addr = current_entry_addr;
    current_entry_addr = entry.next_addr;
  }
  return true;
}

// Temporary work around for patch "JIT mini-debug-info: Append packed entries towards end.", which
// adds new entries at the end of the list and forces simpleperf to read the whole list.
template <typename CodeEntryT>
bool JITDebugReader::ReadNewCodeEntriesImplV2(Process& process, const Descriptor& descriptor,
                                              uint64_t last_action_timestamp,
                                              uint32_t /* read_entry_limit */,
                                              std::vector<CodeEntry>* new_code_entries) {
  uint64_t current_entry_addr = descriptor.first_entry_addr;
  uint64_t prev_entry_addr = 0u;
  std::unordered_set<uint64_t> entry_addr_set;
  const size_t READ_ENTRY_LIMIT = 10000;  // to avoid endless loop

  for (size_t i = 0u; i < READ_ENTRY_LIMIT && current_entry_addr != 0u; ++i) {
    if (entry_addr_set.find(current_entry_addr) != entry_addr_set.end()) {
      // We enter a loop, which means a broken linked list.
      return false;
    }
    CodeEntryT entry;
    if (!ReadRemoteMem(process, current_entry_addr, sizeof(entry), &entry)) {
      return false;
    }
    if (entry.prev_addr != prev_entry_addr || !entry.Valid()) {
      // A broken linked list
      return false;
    }
    if (entry.symfile_size > 0 && entry.register_timestamp > last_action_timestamp) {
      CodeEntry code_entry;
      code_entry.addr = current_entry_addr;
      code_entry.symfile_addr = entry.symfile_addr;
      code_entry.symfile_size = entry.symfile_size;
      code_entry.timestamp = entry.register_timestamp;
      new_code_entries->push_back(code_entry);
    }
    entry_addr_set.insert(current_entry_addr);
    prev_entry_addr = current_entry_addr;
    current_entry_addr = entry.next_addr;
  }
  return true;
}

void JITDebugReader::ReadJITCodeDebugInfo(Process& process,
                                          const std::vector<CodeEntry>& jit_entries,
                                          std::vector<JITDebugInfo>* debug_info) {
  std::vector<char> data;
  for (auto& jit_entry : jit_entries) {
    if (jit_entry.symfile_size > MAX_JIT_SYMFILE_SIZE) {
      continue;
    }
    if (data.size() < jit_entry.symfile_size) {
      data.resize(jit_entry.symfile_size);
    }
    if (!ReadRemoteMem(process, jit_entry.symfile_addr, jit_entry.symfile_size, data.data())) {
      continue;
    }
    if (!IsValidElfFileMagic(data.data(), jit_entry.symfile_size)) {
      continue;
    }
    std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile(!keep_symfiles_);
    if (tmp_file == nullptr || !android::base::WriteFully(tmp_file->fd, data.data(),
                                                          jit_entry.symfile_size)) {
      continue;
    }
    if (keep_symfiles_) {
      tmp_file->DoNotRemove();
    }
    auto callback = [&](const ElfFileSymbol& symbol) {
      if (symbol.len == 0) {  // Some arm labels can have zero length.
        return;
      }
      LOG(VERBOSE) << "JITSymbol " << symbol.name << " at [" << std::hex << symbol.vaddr
                   << " - " << (symbol.vaddr + symbol.len) << " with size " << symbol.len;
      debug_info->emplace_back(process.pid, jit_entry.timestamp, symbol.vaddr, symbol.len,
                               tmp_file->path);
    };
    ParseSymbolsFromElfFileInMemory(data.data(), jit_entry.symfile_size, callback);
  }
}

void JITDebugReader::ReadDexFileDebugInfo(Process& process,
                                          const std::vector<CodeEntry>& dex_entries,
                                          std::vector<JITDebugInfo>* debug_info) {
  std::vector<ThreadMmap> thread_mmaps;
  if (!GetThreadMmapsInProcess(process.pid, &thread_mmaps)) {
    process.died = true;
    return;
  }
  auto comp = [](const ThreadMmap& map, uint64_t addr) {
    return map.start_addr <= addr;
  };
  for (auto& dex_entry : dex_entries) {
    auto it = std::lower_bound(thread_mmaps.begin(), thread_mmaps.end(),
                               dex_entry.symfile_addr, comp);
    if (it == thread_mmaps.begin()) {
      continue;
    }
    --it;
    if (it->start_addr + it->len < dex_entry.symfile_addr + dex_entry.symfile_size) {
      continue;
    }
    std::string file_path;
    std::string zip_path;
    std::string entry_path;
    std::shared_ptr<ThreadMmap> extracted_dex_file_map;
    if (ParseExtractedInMemoryPath(it->name, &zip_path, &entry_path)) {
      file_path = GetUrlInApk(zip_path, entry_path);
      extracted_dex_file_map = std::make_shared<ThreadMmap>(*it);
    } else {
      if (!IsRegularFile(it->name)) {
        // TODO: read dex file only exist in memory?
        continue;
      }
      file_path = it->name;
    }
    // Offset of dex file in .vdex file or .apk file.
    uint64_t dex_file_offset = dex_entry.symfile_addr - it->start_addr + it->pgoff;
    debug_info->emplace_back(process.pid, dex_entry.timestamp, dex_file_offset, file_path,
                             extracted_dex_file_map);
    LOG(VERBOSE) << "DexFile " << file_path << "+" << std::hex << dex_file_offset
                 << " in map [" << it->start_addr << " - " << (it->start_addr + it->len)
                 << "] with size " << dex_entry.symfile_size;
  }
}

bool JITDebugReader::AddDebugInfo(const std::vector<JITDebugInfo>& debug_info,
                                    bool sync_kernel_records) {
  if (!debug_info.empty()) {
    if (sync_with_records_) {
      for (auto& info : debug_info) {
        debug_info_q_.push(std::move(info));
      }
    } else {
      return debug_info_callback_(debug_info, sync_kernel_records);
    }
  }
  return true;
}

}  // namespace simpleperf
