/*
 * 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 "resolver.h"

#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/primitive.h"
#include "dex/signature-inl.h"
#include "hidden_api.h"
#include "veridex.h"

namespace art {

void VeridexResolver::Run() {
  for (ClassAccessor accessor : dex_file_.GetClasses()) {
    std::string name(accessor.GetDescriptor());
    auto existing = type_map_.find(name);
    const uint32_t type_idx = accessor.GetClassIdx().index_;
    if (existing != type_map_.end()) {
      // Class already exists, cache it and move on.
      type_infos_[type_idx] = *existing->second;
      continue;
    }
    type_infos_[type_idx] = VeriClass(Primitive::Type::kPrimNot, 0, &accessor.GetClassDef());
    type_map_[name] = &type_infos_[type_idx];
    for (const ClassAccessor::Field& field : accessor.GetFields()) {
      field_infos_[field.GetIndex()] = field.GetDataPointer();
    }
    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
      method_infos_[method.GetIndex()] = method.GetDataPointer();
    }
  }
}

static bool HasSameNameAndSignature(const DexFile& dex_file,
                                    const dex::MethodId& method_id,
                                    const char* method_name,
                                    const char* type) {
  return strcmp(method_name, dex_file.GetMethodName(method_id)) == 0 &&
      strcmp(type, dex_file.GetMethodSignature(method_id).ToString().c_str()) == 0;
}

static bool HasSameNameAndSignature(const DexFile& dex_file,
                                    const dex::MethodId& method_id,
                                    const char* method_name,
                                    const Signature& signature) {
  return strcmp(method_name, dex_file.GetMethodName(method_id)) == 0 &&
      dex_file.GetMethodSignature(method_id) == signature;
}

static bool HasSameNameAndType(const DexFile& dex_file,
                               const dex::FieldId& field_id,
                               const char* field_name,
                               const char* field_type) {
  return strcmp(field_name, dex_file.GetFieldName(field_id)) == 0 &&
      strcmp(field_type, dex_file.GetFieldTypeDescriptor(field_id)) == 0;
}

VeriClass* VeridexResolver::GetVeriClass(dex::TypeIndex index) {
  CHECK_LT(index.index_, dex_file_.NumTypeIds());
  // Lookup in our local cache.
  VeriClass* cls = &type_infos_[index.index_];
  if (cls->IsUninitialized()) {
    // Class is defined in another dex file. Lookup in the global cache.
    std::string name(dex_file_.StringByTypeIdx(index));
    auto existing = type_map_.find(name);
    if (existing == type_map_.end()) {
      // Class hasn't been defined, so check if it's an array class.
      size_t last_array = name.find_last_of('[');
      if (last_array == std::string::npos) {
        // There is no such class.
        return nullptr;
      } else {
        // Class is an array class. Check if its most enclosed component type (which is not
        // an array class) has been defined.
        std::string klass_name = name.substr(last_array + 1);
        existing = type_map_.find(klass_name);
        if (existing == type_map_.end()) {
          // There is no such class, so there is no such array.
          return nullptr;
        } else {
          // Create the type, and cache it locally and globally.
          type_infos_[index.index_] = VeriClass(
              existing->second->GetKind(), last_array + 1, existing->second->GetClassDef());
          cls = &(type_infos_[index.index_]);
          type_map_[name] = cls;
        }
      }
    } else {
      // Cache the found class.
      cls = existing->second;
      type_infos_[index.index_] = *cls;
    }
  }
  return cls;
}

VeridexResolver* VeridexResolver::GetResolverOf(const VeriClass& kls) const {
  auto resolver_it = dex_resolvers_.lower_bound(reinterpret_cast<uintptr_t>(kls.GetClassDef()));
  --resolver_it;

  // Check the class def pointer is indeed in the mapped dex file range.
  const DexFile& dex_file = resolver_it->second->dex_file_;
  CHECK_LT(reinterpret_cast<uintptr_t>(dex_file.Begin()),
           reinterpret_cast<uintptr_t>(kls.GetClassDef()));
  CHECK_GT(reinterpret_cast<uintptr_t>(dex_file.Begin()) + dex_file.Size(),
           reinterpret_cast<uintptr_t>(kls.GetClassDef()));
  return resolver_it->second;
}

VeriMethod VeridexResolver::LookupMethodIn(const VeriClass& kls,
                                           const char* method_name,
                                           const Signature& method_signature) {
  if (kls.IsPrimitive()) {
    // Primitive classes don't have methods.
    return nullptr;
  }
  if (kls.IsArray()) {
    // Array classes don't have methods, but inherit the ones in j.l.Object.
    return LookupMethodIn(*VeriClass::object_, method_name, method_signature);
  }
  // Get the resolver where `kls` is from.
  VeridexResolver* resolver = GetResolverOf(kls);

  // Look at methods declared in `kls`.
  const DexFile& other_dex_file = resolver->dex_file_;
  ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef());
  for (const ClassAccessor::Method& method : other_dex_accessor.GetMethods()) {
    const dex::MethodId& other_method_id = other_dex_file.GetMethodId(method.GetIndex());
    if (HasSameNameAndSignature(other_dex_file,
                                other_method_id,
                                method_name,
                                method_signature)) {
      return method.GetDataPointer();
    }
  }

  // Look at methods in `kls`'s super class hierarchy.
  if (kls.GetClassDef()->superclass_idx_.IsValid()) {
    VeriClass* super = resolver->GetVeriClass(kls.GetClassDef()->superclass_idx_);
    if (super != nullptr) {
      VeriMethod super_method = resolver->LookupMethodIn(*super, method_name, method_signature);
      if (super_method != nullptr) {
        return super_method;
      }
    }
  }

  // Look at methods in `kls`'s interface hierarchy.
  const dex::TypeList* interfaces = other_dex_file.GetInterfacesList(*kls.GetClassDef());
  if (interfaces != nullptr) {
    for (size_t i = 0; i < interfaces->Size(); i++) {
      dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_;
      VeriClass* itf = resolver->GetVeriClass(idx);
      if (itf != nullptr) {
        VeriMethod itf_method = resolver->LookupMethodIn(*itf, method_name, method_signature);
        if (itf_method != nullptr) {
          return itf_method;
        }
      }
    }
  }
  return nullptr;
}

VeriField VeridexResolver::LookupFieldIn(const VeriClass& kls,
                                         const char* field_name,
                                         const char* field_type) {
  if (kls.IsPrimitive()) {
    // Primitive classes don't have fields.
    return nullptr;
  }
  if (kls.IsArray()) {
    // Array classes don't have fields.
    return nullptr;
  }
  // Get the resolver where `kls` is from.
  VeridexResolver* resolver = GetResolverOf(kls);

  // Look at fields declared in `kls`.
  const DexFile& other_dex_file = resolver->dex_file_;
  ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef());
  for (const ClassAccessor::Field& field : other_dex_accessor.GetFields()) {
    const dex::FieldId& other_field_id = other_dex_file.GetFieldId(field.GetIndex());
    if (HasSameNameAndType(other_dex_file,
                           other_field_id,
                           field_name,
                           field_type)) {
      return field.GetDataPointer();
    }
  }

  // Look at fields in `kls`'s interface hierarchy.
  const dex::TypeList* interfaces = other_dex_file.GetInterfacesList(*kls.GetClassDef());
  if (interfaces != nullptr) {
    for (size_t i = 0; i < interfaces->Size(); i++) {
      dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_;
      VeriClass* itf = resolver->GetVeriClass(idx);
      if (itf != nullptr) {
        VeriField itf_field = resolver->LookupFieldIn(*itf, field_name, field_type);
        if (itf_field != nullptr) {
          return itf_field;
        }
      }
    }
  }

  // Look at fields in `kls`'s super class hierarchy.
  if (kls.GetClassDef()->superclass_idx_.IsValid()) {
    VeriClass* super = resolver->GetVeriClass(kls.GetClassDef()->superclass_idx_);
    if (super != nullptr) {
      VeriField super_field = resolver->LookupFieldIn(*super, field_name, field_type);
      if (super_field != nullptr) {
        return super_field;
      }
    }
  }
  return nullptr;
}

VeriMethod VeridexResolver::LookupDeclaredMethodIn(const VeriClass& kls,
                                                   const char* method_name,
                                                   const char* type) const {
  if (kls.IsPrimitive()) {
    return nullptr;
  }
  if (kls.IsArray()) {
    return nullptr;
  }
  VeridexResolver* resolver = GetResolverOf(kls);
  const DexFile& other_dex_file = resolver->dex_file_;
  ClassAccessor other_dex_accessor(other_dex_file, *kls.GetClassDef());
  for (const ClassAccessor::Method& method : other_dex_accessor.GetMethods()) {
    if (HasSameNameAndSignature(other_dex_file,
                                other_dex_file.GetMethodId(method.GetIndex()),
                                method_name,
                                type)) {
      return method.GetDataPointer();
    }
  }
  return nullptr;
}

VeriMethod VeridexResolver::GetMethod(uint32_t method_index) {
  VeriMethod method_info = method_infos_[method_index];
  if (method_info == nullptr) {
    // Method is defined in another dex file.
    const dex::MethodId& method_id = dex_file_.GetMethodId(method_index);
    VeriClass* kls = GetVeriClass(method_id.class_idx_);
    if (kls == nullptr) {
      return nullptr;
    }
    // Class found, now lookup the method in it.
    method_info = LookupMethodIn(*kls,
                                 dex_file_.GetMethodName(method_id),
                                 dex_file_.GetMethodSignature(method_id));
    method_infos_[method_index] = method_info;
  }
  return method_info;
}

VeriField VeridexResolver::GetField(uint32_t field_index) {
  VeriField field_info = field_infos_[field_index];
  if (field_info == nullptr) {
    // Field is defined in another dex file.
    const dex::FieldId& field_id = dex_file_.GetFieldId(field_index);
    VeriClass* kls = GetVeriClass(field_id.class_idx_);
    if (kls == nullptr) {
      return nullptr;
    }
    // Class found, now lookup the field in it.
    field_info = LookupFieldIn(*kls,
                               dex_file_.GetFieldName(field_id),
                               dex_file_.GetFieldTypeDescriptor(field_id));
    field_infos_[field_index] = field_info;
  }
  return field_info;
}

void VeridexResolver::ResolveAll() {
  for (uint32_t i = 0; i < dex_file_.NumTypeIds(); ++i) {
    if (GetVeriClass(dex::TypeIndex(i)) == nullptr) {
      LOG(WARNING) << "Unresolved " << dex_file_.PrettyType(dex::TypeIndex(i));
    }
  }

  for (uint32_t i = 0; i < dex_file_.NumMethodIds(); ++i) {
    if (GetMethod(i) == nullptr) {
      LOG(WARNING) << "Unresolved: " << dex_file_.PrettyMethod(i);
    }
  }

  for (uint32_t i = 0; i < dex_file_.NumFieldIds(); ++i) {
    if (GetField(i) == nullptr) {
      LOG(WARNING) << "Unresolved: " << dex_file_.PrettyField(i);
    }
  }
}

}  // namespace art
