// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/expr/resolve_base.h"

#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/expr/cast.h"
#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/expr_parser.h"
#include "src/developer/debug/zxdb/expr/find_name.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/expr/resolve_ptr_ref.h"
#include "src/developer/debug/zxdb/expr/resolve_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_utils.h"

namespace zxdb {

namespace {

// When a class has a vtable, the pointer to the vtable is generated as a member of the class' data.
// This member is marked with DW_AT_artificial and named "_vptr.MyClass" by GCC and "_vptr$MyClass"
// by Clang, where "MyClass" is the name of the class. There is no scoping information on the name
// (namespaces, etc.).
const char kVtableMemberPrefix[] = "_vptr";

// The Clang demangler produces this prefix for vtable symbols.
const char kVtableSymbolNamePrefix[] = "vtable for ";

}  // namespace

// The code would be a little simpler if we just tried to dereference the pointer/reference and
// then check for the vtable member. But this will be called a lot when evaluating collections,
// usually won't match, and the dereference will require a slow memory fetch. By checking the
// pointed-to/referenced type first, we avoid this overhead.
void PromotePtrRefToDerived(const fxl::RefPtr<EvalContext>& context, PromoteToDerived what,
                            ExprValue value, EvalCallback cb) {
  // Errors in this function should issue the callback with the original value. Errors mean that
  // promotion has failed, but we can still handle the original base class pointer.
  if (!value.type())
    return cb(std::move(value));

  // Type must be the right match pointer or a reference.
  fxl::RefPtr<Type> input_concrete = context->GetConcreteType(value.type());
  const ModifiedType* mod_type = input_concrete->AsModifiedType();
  if (!mod_type)
    return cb(std::move(value));

  bool tag_match = false;
  switch (what) {
    case PromoteToDerived::kPtrOnly:
      tag_match = (mod_type->tag() == DwarfTag::kPointerType);
      break;
    case PromoteToDerived::kRefOnly:
      tag_match = DwarfTagIsEitherReference(mod_type->tag());
      break;
    case PromoteToDerived::kPtrOrRef:
      tag_match = DwarfTagIsPointerOrReference(mod_type->tag());
      break;
  }
  if (!tag_match)
    return cb(std::move(value));

  // Referenced type must be a collection.
  const Type* type = mod_type->modified().Get()->AsType();
  if (!type)
    return cb(std::move(value));
  fxl::RefPtr<Type> modified_concrete = context->GetConcreteType(type);
  if (!modified_concrete)
    return cb(std::move(value));
  const Collection* modified_collection = modified_concrete->AsCollection();
  if (!modified_collection)
    return cb(std::move(value));

  // Referenced collection must have a vtable pointer.
  fxl::RefPtr<DataMember> vtable_member = GetVtableMember(modified_collection);
  if (!vtable_member)
    return cb(std::move(value));

  // Type is a pointer or reference to a virtual type. Get the vtable pointer value to see where it
  // goes.
  TargetPointer object_loc = 0;
  if (value.PromoteTo64(&object_loc).has_error())
    return cb(std::move(value));

  // Get the value of the vtable member.
  TargetPointer vtable_member_loc = object_loc + vtable_member->member_location();
  ResolvePointer(
      context, vtable_member_loc, RefPtrTo(vtable_member->type().Get()->AsType()),
      [context, original_value = std::move(value), modifier_tag = mod_type->tag(),
       modified_type = RefPtrTo(type), cb = std::move(cb)](ErrOrValue result) mutable {
        if (result.has_error())
          return cb(std::move(original_value));

        TargetPointer vtable = 0;
        if (result.value().PromoteTo64(&vtable).has_error())
          return cb(std::move(original_value));

        fxl::RefPtr<Type> derived_type = DerivedTypeForVtable(context, vtable);
        if (!derived_type)
          return cb(std::move(original_value));

        // Cast to the desired destination type. It should have the same type pattern as the
        // original: [ <C-V qualifier> ] + <pointer or reference> + [ <C-V qualifier> ] We did two
        // GetConcreteType() calls on each side of the ptr/ref and those stripped qualifiers need to
        // be put back.
        //
        // This code isn't perfect and will get confused if there are typedefs. Copying the C-V
        // qualifier will stop at typedefs, but the typedef could expand to something with a
        // qualifier like "const Foo" and this code would miss it. This gets very complicated and
        // the debugger doesn't actually follow qualifiers. This seems good enough for now.
        auto dest_type = AddCVQualifiersToMatch(modified_type.get(), std::move(derived_type));
        dest_type = fxl::MakeRefCounted<ModifiedType>(modifier_tag, std::move(dest_type));
        dest_type = AddCVQualifiersToMatch(original_value.type(), std::move(dest_type));
        CastExprValue(context, CastType::kStatic, original_value, dest_type, ExprValueSource(),
                      [original_value, cb = std::move(cb)](ErrOrValue value) mutable {
                        // Discard casting errors to just use the original value.
                        if (value.has_error())
                          cb(std::move(original_value));
                        else
                          cb(value.value());
                      });
      });
}

fxl::RefPtr<DataMember> GetVtableMember(const Collection* coll) {
  for (const auto& lazy_member : coll->data_members()) {
    const DataMember* member = lazy_member.Get()->AsDataMember();
    if (!member)
      continue;

    if (member->artificial() && StringBeginsWith(member->GetAssignedName(), kVtableMemberPrefix))
      return RefPtrTo(member);
  }
  return fxl::RefPtr<DataMember>();
}

std::string TypeNameForVtableSymbolName(const std::string& sym_name) {
  if (!StringBeginsWith(sym_name, kVtableSymbolNamePrefix))
    return std::string();
  return sym_name.substr(std::size(kVtableSymbolNamePrefix) - 1);  // Trim the prefix w/o the null.
}

fxl::RefPtr<Type> DerivedTypeForVtable(const fxl::RefPtr<EvalContext>& context, TargetPointer ptr) {
  Location loc = context->GetLocationForAddress(ptr);
  if (!loc.symbol())
    return nullptr;

  // Expect vtable symbols to be ELF ones. There won't be DWARF entries since they don't appear in
  // the program.
  const ElfSymbol* elf_symbol = loc.symbol().Get()->AsElfSymbol();
  if (!elf_symbol)
    return nullptr;

  std::string type_name = TypeNameForVtableSymbolName(elf_symbol->GetAssignedName());
  if (type_name.empty())
    return nullptr;  // Not a vtable entry.

  ParsedIdentifier ident;
  if (ExprParser::ParseIdentifier(type_name, &ident).has_error())
    return nullptr;  // Type name not parseable.

  return FindTypeDefinition(context->GetFindNameContext(), std::move(ident));
}

}  // namespace zxdb
