/*
 * Copyright (C) 2017 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 <stdint.h>
#include <sys/mman.h>

#include <memory>
#include <vector>

#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>

// This implements the JIT Compilation Interface.
// See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html

namespace unwindstack {

struct JITCodeEntry32Pack {
  uint32_t next;
  uint32_t prev;
  uint32_t symfile_addr;
  uint64_t symfile_size;
} __attribute__((packed));

struct JITCodeEntry32Pad {
  uint32_t next;
  uint32_t prev;
  uint32_t symfile_addr;
  uint32_t pad;
  uint64_t symfile_size;
};

struct JITCodeEntry64 {
  uint64_t next;
  uint64_t prev;
  uint64_t symfile_addr;
  uint64_t symfile_size;
};

struct JITDescriptorHeader {
  uint32_t version;
  uint32_t action_flag;
};

struct JITDescriptor32 {
  JITDescriptorHeader header;
  uint32_t relevant_entry;
  uint32_t first_entry;
};

struct JITDescriptor64 {
  JITDescriptorHeader header;
  uint64_t relevant_entry;
  uint64_t first_entry;
};

JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {}

JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
    : memory_(memory), search_libs_(search_libs) {}

JitDebug::~JitDebug() {
  for (auto* elf : elf_list_) {
    delete elf;
  }
}

uint64_t JitDebug::ReadDescriptor32(uint64_t addr) {
  JITDescriptor32 desc;
  if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
    return 0;
  }

  if (desc.header.version != 1 || desc.first_entry == 0) {
    // Either unknown version, or no jit entries.
    return 0;
  }

  return desc.first_entry;
}

uint64_t JitDebug::ReadDescriptor64(uint64_t addr) {
  JITDescriptor64 desc;
  if (!memory_->ReadFully(addr, &desc, sizeof(desc))) {
    return 0;
  }

  if (desc.header.version != 1 || desc.first_entry == 0) {
    // Either unknown version, or no jit entries.
    return 0;
  }

  return desc.first_entry;
}

uint64_t JitDebug::ReadEntry32Pack(uint64_t* start, uint64_t* size) {
  JITCodeEntry32Pack code;
  if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
    return 0;
  }

  *start = code.symfile_addr;
  *size = code.symfile_size;
  return code.next;
}

uint64_t JitDebug::ReadEntry32Pad(uint64_t* start, uint64_t* size) {
  JITCodeEntry32Pad code;
  if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
    return 0;
  }

  *start = code.symfile_addr;
  *size = code.symfile_size;
  return code.next;
}

uint64_t JitDebug::ReadEntry64(uint64_t* start, uint64_t* size) {
  JITCodeEntry64 code;
  if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) {
    return 0;
  }

  *start = code.symfile_addr;
  *size = code.symfile_size;
  return code.next;
}

void JitDebug::SetArch(ArchEnum arch) {
  switch (arch) {
    case ARCH_X86:
      read_descriptor_func_ = &JitDebug::ReadDescriptor32;
      read_entry_func_ = &JitDebug::ReadEntry32Pack;
      break;

    case ARCH_ARM:
    case ARCH_MIPS:
      read_descriptor_func_ = &JitDebug::ReadDescriptor32;
      read_entry_func_ = &JitDebug::ReadEntry32Pad;
      break;

    case ARCH_ARM64:
    case ARCH_X86_64:
    case ARCH_MIPS64:
      read_descriptor_func_ = &JitDebug::ReadDescriptor64;
      read_entry_func_ = &JitDebug::ReadEntry64;
      break;
    case ARCH_UNKNOWN:
      abort();
  }
}

void JitDebug::Init(Maps* maps) {
  if (initialized_) {
    return;
  }
  // Regardless of what happens below, consider the init finished.
  initialized_ = true;

  const std::string descriptor_name("__jit_debug_descriptor");
  for (MapInfo* info : *maps) {
    if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
      continue;
    }

    if (!search_libs_.empty()) {
      bool found = false;
      const char* lib = basename(info->name.c_str());
      for (std::string& name : search_libs_) {
        if (strcmp(name.c_str(), lib) == 0) {
          found = true;
          break;
        }
      }
      if (!found) {
        continue;
      }
    }

    Elf* elf = info->GetElf(memory_, true);
    uint64_t descriptor_addr;
    if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr)) {
      // Search for the first non-zero entry.
      descriptor_addr += info->start;
      entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
      if (entry_addr_ != 0) {
        break;
      }
    }
  }
}

Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
  // Use a single lock, this object should be used so infrequently that
  // a fine grain lock is unnecessary.
  std::lock_guard<std::mutex> guard(lock_);
  if (!initialized_) {
    Init(maps);
  }

  // Search the existing elf object first.
  for (Elf* elf : elf_list_) {
    if (elf->IsValidPc(pc)) {
      return elf;
    }
  }

  while (entry_addr_ != 0) {
    uint64_t start;
    uint64_t size;
    entry_addr_ = (this->*read_entry_func_)(&start, &size);

    Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0));
    elf->Init(true);
    if (!elf->valid()) {
      // The data is not formatted in a way we understand, do not attempt
      // to process any other entries.
      entry_addr_ = 0;
      delete elf;
      return nullptr;
    }
    elf_list_.push_back(elf);

    if (elf->IsValidPc(pc)) {
      return elf;
    }
  }
  return nullptr;
}

}  // namespace unwindstack
