//===-- AppleObjCRuntimeV1.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "AppleObjCRuntimeV1.h"
#include "AppleObjCDeclVendor.h"
#include "AppleObjCTrampolineHandler.h"

#include "clang/AST/Type.h"

#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

#include <memory>
#include <vector>

using namespace lldb;
using namespace lldb_private;

char AppleObjCRuntimeV1::ID = 0;

AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process)
    : AppleObjCRuntime(process), m_hash_signature(),
      m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {}

// for V1 runtime we just try to return a class name as that is the minimum
// level of support required for the data formatters to work
bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address,
    Value::ValueType &value_type) {
  class_type_or_name.Clear();
  value_type = Value::ValueType::Scalar;
  if (CouldHaveDynamicValue(in_value)) {
    auto class_descriptor(GetClassDescriptor(in_value));
    if (class_descriptor && class_descriptor->IsValid() &&
        class_descriptor->GetClassName()) {
      const addr_t object_ptr = in_value.GetPointerValue();
      address.SetRawAddress(object_ptr);
      class_type_or_name.SetName(class_descriptor->GetClassName());
    }
  }
  return !class_type_or_name.IsEmpty();
}

// Static Functions
lldb_private::LanguageRuntime *
AppleObjCRuntimeV1::CreateInstance(Process *process,
                                   lldb::LanguageType language) {
  // FIXME: This should be a MacOS or iOS process, and we need to look for the
  // OBJC section to make
  // sure we aren't using the V1 runtime.
  if (language == eLanguageTypeObjC) {
    ModuleSP objc_module_sp;

    if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
        ObjCRuntimeVersions::eAppleObjC_V1)
      return new AppleObjCRuntimeV1(process);
    else
      return nullptr;
  } else
    return nullptr;
}

void AppleObjCRuntimeV1::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1",
      CreateInstance,
      /*command_callback = */ nullptr, GetBreakpointExceptionPrecondition);
}

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

lldb_private::ConstString AppleObjCRuntimeV1::GetPluginNameStatic() {
  static ConstString g_name("apple-objc-v1");
  return g_name;
}

// PluginInterface protocol
ConstString AppleObjCRuntimeV1::GetPluginName() {
  return GetPluginNameStatic();
}

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

BreakpointResolverSP
AppleObjCRuntimeV1::CreateExceptionResolver(const BreakpointSP &bkpt,
                                            bool catch_bp, bool throw_bp) {
  BreakpointResolverSP resolver_sp;

  if (throw_bp)
    resolver_sp = std::make_shared<BreakpointResolverName>(
        bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
        eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
        eLazyBoolNo);
  // FIXME: don't do catch yet.
  return resolver_sp;
}

struct BufStruct {
  char contents[2048];
};

llvm::Expected<std::unique_ptr<UtilityFunction>>
AppleObjCRuntimeV1::CreateObjectChecker(std::string name,
                                        ExecutionContext &exe_ctx) {
  std::unique_ptr<BufStruct> buf(new BufStruct);

  int strformatsize =
      snprintf(&buf->contents[0], sizeof(buf->contents),
               "struct __objc_class                                         "
               "           \n"
               "{                                                           "
               "           \n"
               "   struct __objc_class *isa;                                "
               "           \n"
               "   struct __objc_class *super_class;                        "
               "           \n"
               "   const char *name;                                        "
               "           \n"
               "   // rest of struct elided because unused                  "
               "           \n"
               "};                                                          "
               "           \n"
               "                                                            "
               "           \n"
               "struct __objc_object                                        "
               "           \n"
               "{                                                           "
               "           \n"
               "   struct __objc_class *isa;                                "
               "           \n"
               "};                                                          "
               "           \n"
               "                                                            "
               "           \n"
               "extern \"C\" void                                           "
               "           \n"
               "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)       "
               "           \n"
               "{                                                           "
               "           \n"
               "   struct __objc_object *obj = (struct "
               "__objc_object*)$__lldb_arg_obj; \n"
               "   if ($__lldb_arg_obj == (void *)0)                     "
               "                                \n"
               "       return; // nil is ok                              "
               "   (int)strlen(obj->isa->name);                             "
               "           \n"
               "}                                                           "
               "           \n",
               name.c_str());
  assert(strformatsize < (int)sizeof(buf->contents));
  (void)strformatsize;

  return GetTargetRef().CreateUtilityFunction(buf->contents, std::move(name),
                                              eLanguageTypeC, exe_ctx);
}

AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
    ValueObject &isa_pointer) {
  Initialize(isa_pointer.GetValueAsUnsigned(0), isa_pointer.GetProcessSP());
}

AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
    ObjCISA isa, lldb::ProcessSP process_sp) {
  Initialize(isa, process_sp);
}

void AppleObjCRuntimeV1::ClassDescriptorV1::Initialize(
    ObjCISA isa, lldb::ProcessSP process_sp) {
  if (!isa || !process_sp) {
    m_valid = false;
    return;
  }

  m_valid = true;

  Status error;

  m_isa = process_sp->ReadPointerFromMemory(isa, error);

  if (error.Fail()) {
    m_valid = false;
    return;
  }

  uint32_t ptr_size = process_sp->GetAddressByteSize();

  if (!IsPointerValid(m_isa, ptr_size)) {
    m_valid = false;
    return;
  }

  m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size, error);

  if (error.Fail()) {
    m_valid = false;
    return;
  }

  if (!IsPointerValid(m_parent_isa, ptr_size, true)) {
    m_valid = false;
    return;
  }

  lldb::addr_t name_ptr =
      process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size, error);

  if (error.Fail()) {
    m_valid = false;
    return;
  }

  lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));

  size_t count = process_sp->ReadCStringFromMemory(
      name_ptr, (char *)buffer_sp->GetBytes(), 1024, error);

  if (error.Fail()) {
    m_valid = false;
    return;
  }

  if (count)
    m_name = ConstString((char *)buffer_sp->GetBytes());
  else
    m_name = ConstString();

  m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(
      m_isa + 5 * ptr_size, ptr_size, 0, error);

  if (error.Fail()) {
    m_valid = false;
    return;
  }

  m_process_wp = lldb::ProcessWP(process_sp);
}

AppleObjCRuntime::ClassDescriptorSP
AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass() {
  if (!m_valid)
    return AppleObjCRuntime::ClassDescriptorSP();
  ProcessSP process_sp = m_process_wp.lock();
  if (!process_sp)
    return AppleObjCRuntime::ClassDescriptorSP();
  return ObjCLanguageRuntime::ClassDescriptorSP(
      new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa, process_sp));
}

AppleObjCRuntime::ClassDescriptorSP
AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass() const {
  return ClassDescriptorSP();
}

bool AppleObjCRuntimeV1::ClassDescriptorV1::Describe(
    std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
    std::function<bool(const char *, const char *)> const &instance_method_func,
    std::function<bool(const char *, const char *)> const &class_method_func,
    std::function<bool(const char *, const char *, lldb::addr_t,
                       uint64_t)> const &ivar_func) const {
  return false;
}

lldb::addr_t AppleObjCRuntimeV1::GetTaggedPointerObfuscator() {
  return 0;
}

lldb::addr_t AppleObjCRuntimeV1::GetISAHashTablePointer() {
  if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
    ModuleSP objc_module_sp(GetObjCModule());

    if (!objc_module_sp)
      return LLDB_INVALID_ADDRESS;

    static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");

    const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
        g_objc_debug_class_hash, lldb::eSymbolTypeData);
    if (symbol && symbol->ValueIsAddress()) {
      Process *process = GetProcess();
      if (process) {

        lldb::addr_t objc_debug_class_hash_addr =
            symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());

        if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS) {
          Status error;
          lldb::addr_t objc_debug_class_hash_ptr =
              process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
          if (objc_debug_class_hash_ptr != 0 &&
              objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS) {
            m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
          }
        }
      }
    }
  }
  return m_isa_hash_table_ptr;
}

void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
  // TODO: implement HashTableSignature...
  Process *process = GetProcess();

  if (process) {
    // Update the process stop ID that indicates the last time we updated the
    // map, whether it was successful or not.
    m_isa_to_descriptor_stop_id = process->GetStopID();

    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    ProcessSP process_sp = process->shared_from_this();

    ModuleSP objc_module_sp(GetObjCModule());

    if (!objc_module_sp)
      return;

    uint32_t isa_count = 0;

    lldb::addr_t hash_table_ptr = GetISAHashTablePointer();
    if (hash_table_ptr != LLDB_INVALID_ADDRESS) {
      // Read the NXHashTable struct:
      //
      // typedef struct {
      //     const NXHashTablePrototype *prototype;
      //     unsigned   count;
      //     unsigned   nbBuckets;
      //     void       *buckets;
      //     const void *info;
      // } NXHashTable;

      Status error;
      DataBufferHeap buffer(1024, 0);
      if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) ==
          20) {
        const uint32_t addr_size = m_process->GetAddressByteSize();
        const ByteOrder byte_order = m_process->GetByteOrder();
        DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), byte_order,
                           addr_size);
        lldb::offset_t offset = addr_size; // Skip prototype
        const uint32_t count = data.GetU32(&offset);
        const uint32_t num_buckets = data.GetU32(&offset);
        const addr_t buckets_ptr = data.GetAddress(&offset);
        if (m_hash_signature.NeedsUpdate(count, num_buckets, buckets_ptr)) {
          m_hash_signature.UpdateSignature(count, num_buckets, buckets_ptr);

          const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
          buffer.SetByteSize(data_size);

          if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size,
                                  error) == data_size) {
            data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
            offset = 0;
            for (uint32_t bucket_idx = 0; bucket_idx < num_buckets;
                 ++bucket_idx) {
              const uint32_t bucket_isa_count = data.GetU32(&offset);
              const lldb::addr_t bucket_data = data.GetU32(&offset);

              if (bucket_isa_count == 0)
                continue;

              isa_count += bucket_isa_count;

              ObjCISA isa;
              if (bucket_isa_count == 1) {
                // When we only have one entry in the bucket, the bucket data
                // is the "isa"
                isa = bucket_data;
                if (isa) {
                  if (!ISAIsCached(isa)) {
                    ClassDescriptorSP descriptor_sp(
                        new ClassDescriptorV1(isa, process_sp));

                    if (log && log->GetVerbose())
                      LLDB_LOGF(log,
                                "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
                                " from _objc_debug_class_hash to "
                                "isa->descriptor cache",
                                isa);

                    AddClass(isa, descriptor_sp);
                  }
                }
              } else {
                // When we have more than one entry in the bucket, the bucket
                // data is a pointer to an array of "isa" values
                addr_t isa_addr = bucket_data;
                for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count;
                     ++isa_idx, isa_addr += addr_size) {
                  isa = m_process->ReadPointerFromMemory(isa_addr, error);

                  if (isa && isa != LLDB_INVALID_ADDRESS) {
                    if (!ISAIsCached(isa)) {
                      ClassDescriptorSP descriptor_sp(
                          new ClassDescriptorV1(isa, process_sp));

                      if (log && log->GetVerbose())
                        LLDB_LOGF(
                            log,
                            "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
                            " from _objc_debug_class_hash to isa->descriptor "
                            "cache",
                            isa);

                      AddClass(isa, descriptor_sp);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  } else {
    m_isa_to_descriptor_stop_id = UINT32_MAX;
  }
}

DeclVendor *AppleObjCRuntimeV1::GetDeclVendor() {
  return nullptr;
}
