//===-- JITLoaderGDB.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes

#include "llvm/Support/MathExtras.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

#include "JITLoaderGDB.h"

using namespace lldb;
using namespace lldb_private;

//------------------------------------------------------------------
// Debug Interface Structures
//------------------------------------------------------------------
typedef enum {
  JIT_NOACTION = 0,
  JIT_REGISTER_FN,
  JIT_UNREGISTER_FN
} jit_actions_t;

template <typename ptr_t> struct jit_code_entry {
  ptr_t next_entry;   // pointer
  ptr_t prev_entry;   // pointer
  ptr_t symfile_addr; // pointer
  uint64_t symfile_size;
};

template <typename ptr_t> struct jit_descriptor {
  uint32_t version;
  uint32_t action_flag; // Values are jit_action_t
  ptr_t relevant_entry; // pointer
  ptr_t first_entry;    // pointer
};

namespace {

PropertyDefinition g_properties[] = {
    {"enable-jit-breakpoint", OptionValue::eTypeBoolean, true, true, nullptr,
     nullptr, "Enable breakpoint on __jit_debug_register_code."},
    {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};

enum { ePropertyEnableJITBreakpoint };

class PluginProperties : public Properties {
public:
  static ConstString GetSettingName() {
    return JITLoaderGDB::GetPluginNameStatic();
  }

  PluginProperties() {
    m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
    m_collection_sp->Initialize(g_properties);
  }

  bool GetEnableJITBreakpoint() const {
    return m_collection_sp->GetPropertyAtIndexAsBoolean(
        nullptr, ePropertyEnableJITBreakpoint,
        g_properties[ePropertyEnableJITBreakpoint].default_uint_value != 0);
  }
};

typedef std::shared_ptr<PluginProperties> JITLoaderGDBPropertiesSP;

static const JITLoaderGDBPropertiesSP &GetGlobalPluginProperties() {
  static const auto g_settings_sp(std::make_shared<PluginProperties>());
  return g_settings_sp;
}

template <typename ptr_t>
bool ReadJITEntry(const addr_t from_addr, Process *process,
                  jit_code_entry<ptr_t> *entry) {
  lldbassert(from_addr % sizeof(ptr_t) == 0);

  ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore();
  bool i386_target = ArchSpec::kCore_x86_32_first <= core &&
                     core <= ArchSpec::kCore_x86_32_last;
  uint8_t uint64_align_bytes = i386_target ? 4 : 8;
  const size_t data_byte_size =
      llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t);

  Status error;
  DataBufferHeap data(data_byte_size, 0);
  size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(),
                                          data.GetByteSize(), error);
  if (bytes_read != data_byte_size || !error.Success())
    return false;

  DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
                          process->GetByteOrder(), sizeof(ptr_t));
  lldb::offset_t offset = 0;
  entry->next_entry = extractor.GetPointer(&offset);
  entry->prev_entry = extractor.GetPointer(&offset);
  entry->symfile_addr = extractor.GetPointer(&offset);
  offset = llvm::alignTo(offset, uint64_align_bytes);
  entry->symfile_size = extractor.GetU64(&offset);

  return true;
}

} // anonymous namespace end

JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process)
    : JITLoader(process), m_jit_objects(),
      m_jit_break_id(LLDB_INVALID_BREAK_ID),
      m_jit_descriptor_addr(LLDB_INVALID_ADDRESS) {}

JITLoaderGDB::~JITLoaderGDB() {
  if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
    m_process->GetTarget().RemoveBreakpointByID(m_jit_break_id);
}

void JITLoaderGDB::DebuggerInitialize(Debugger &debugger) {
  if (!PluginManager::GetSettingForJITLoaderPlugin(
          debugger, PluginProperties::GetSettingName())) {
    const bool is_global_setting = true;
    PluginManager::CreateSettingForJITLoaderPlugin(
        debugger, GetGlobalPluginProperties()->GetValueProperties(),
        ConstString("Properties for the JIT LoaderGDB plug-in."),
        is_global_setting);
  }
}

void JITLoaderGDB::DidAttach() {
  Target &target = m_process->GetTarget();
  ModuleList &module_list = target.GetImages();
  SetJITBreakpoint(module_list);
}

void JITLoaderGDB::DidLaunch() {
  Target &target = m_process->GetTarget();
  ModuleList &module_list = target.GetImages();
  SetJITBreakpoint(module_list);
}

void JITLoaderGDB::ModulesDidLoad(ModuleList &module_list) {
  if (!DidSetJITBreakpoint() && m_process->IsAlive())
    SetJITBreakpoint(module_list);
}

//------------------------------------------------------------------
// Setup the JIT Breakpoint
//------------------------------------------------------------------
void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) {
  if (!GetGlobalPluginProperties()->GetEnableJITBreakpoint())
    return;

  if (DidSetJITBreakpoint())
    return;

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
  if (log)
    log->Printf("JITLoaderGDB::%s looking for JIT register hook", __FUNCTION__);

  addr_t jit_addr = GetSymbolAddress(
      module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny);
  if (jit_addr == LLDB_INVALID_ADDRESS)
    return;

  m_jit_descriptor_addr = GetSymbolAddress(
      module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData);
  if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) {
    if (log)
      log->Printf("JITLoaderGDB::%s failed to find JIT descriptor address",
                  __FUNCTION__);
    return;
  }

  if (log)
    log->Printf("JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__);

  Breakpoint *bp =
      m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
  bp->SetCallback(JITDebugBreakpointHit, this, true);
  bp->SetBreakpointKind("jit-debug-register");
  m_jit_break_id = bp->GetID();

  ReadJITDescriptor(true);
}

bool JITLoaderGDB::JITDebugBreakpointHit(void *baton,
                                         StoppointCallbackContext *context,
                                         user_id_t break_id,
                                         user_id_t break_loc_id) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
  if (log)
    log->Printf("JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__);
  JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
  return instance->ReadJITDescriptor(false);
}

static void updateSectionLoadAddress(const SectionList &section_list,
                                     Target &target, uint64_t symbolfile_addr,
                                     uint64_t symbolfile_size,
                                     uint64_t &vmaddrheuristic,
                                     uint64_t &min_addr, uint64_t &max_addr) {
  const uint32_t num_sections = section_list.GetSize();
  for (uint32_t i = 0; i < num_sections; ++i) {
    SectionSP section_sp(section_list.GetSectionAtIndex(i));
    if (section_sp) {
      if (section_sp->IsFake()) {
        uint64_t lower = (uint64_t)-1;
        uint64_t upper = 0;
        updateSectionLoadAddress(section_sp->GetChildren(), target,
                                 symbolfile_addr, symbolfile_size,
                                 vmaddrheuristic, lower, upper);
        if (lower < min_addr)
          min_addr = lower;
        if (upper > max_addr)
          max_addr = upper;
        const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
        section_sp->Slide(slide_amount, false);
        section_sp->GetChildren().Slide(-slide_amount, false);
        section_sp->SetByteSize(upper - lower);
      } else {
        vmaddrheuristic += 2 << section_sp->GetLog2Align();
        uint64_t lower;
        if (section_sp->GetFileAddress() > vmaddrheuristic)
          lower = section_sp->GetFileAddress();
        else {
          lower = symbolfile_addr + section_sp->GetFileOffset();
          section_sp->SetFileAddress(symbolfile_addr +
                                     section_sp->GetFileOffset());
        }
        target.SetSectionLoadAddress(section_sp, lower, true);
        uint64_t upper = lower + section_sp->GetByteSize();
        if (lower < min_addr)
          min_addr = lower;
        if (upper > max_addr)
          max_addr = upper;
        // This is an upper bound, but a good enough heuristic
        vmaddrheuristic += section_sp->GetByteSize();
      }
    }
  }
}

bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) {
  if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
    return ReadJITDescriptorImpl<uint64_t>(all_entries);
  else
    return ReadJITDescriptorImpl<uint32_t>(all_entries);
}

template <typename ptr_t>
bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) {
  if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
    return false;

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

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

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

  while (jit_relevant_entry != 0) {
    jit_code_entry<ptr_t> jit_entry;
    if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) {
      if (log)
        log->Printf("JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
                    __FUNCTION__, jit_relevant_entry);
      return false;
    }

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

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

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

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

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

        module_list.AppendIfNeeded(module_sp);

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

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

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

  return false; // Continue Running.
}

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString JITLoaderGDB::GetPluginNameStatic() {
  static ConstString g_name("gdb");
  return g_name;
}

JITLoaderSP JITLoaderGDB::CreateInstance(Process *process, bool force) {
  JITLoaderSP jit_loader_sp;
  ArchSpec arch(process->GetTarget().GetArchitecture());
  if (arch.GetTriple().getVendor() != llvm::Triple::Apple)
    jit_loader_sp.reset(new JITLoaderGDB(process));
  return jit_loader_sp;
}

const char *JITLoaderGDB::GetPluginDescriptionStatic() {
  return "JIT loader plug-in that watches for JIT events using the GDB "
         "interface.";
}

lldb_private::ConstString JITLoaderGDB::GetPluginName() {
  return GetPluginNameStatic();
}

uint32_t JITLoaderGDB::GetPluginVersion() { return 1; }

void JITLoaderGDB::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInitialize);
}

void JITLoaderGDB::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

bool JITLoaderGDB::DidSetJITBreakpoint() const {
  return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
}

addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list,
                                      const ConstString &name,
                                      SymbolType symbol_type) const {
  SymbolContextList target_symbols;
  Target &target = m_process->GetTarget();

  if (!module_list.FindSymbolsWithNameAndType(name, symbol_type,
                                              target_symbols))
    return LLDB_INVALID_ADDRESS;

  SymbolContext sym_ctx;
  target_symbols.GetContextAtIndex(0, sym_ctx);

  const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress();
  if (!jit_descriptor_addr.IsValid())
    return LLDB_INVALID_ADDRESS;

  const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target);
  return jit_addr;
}
