// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// 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 "starboard/elf_loader/dynamic_section.h"

#include "starboard/common/log.h"

namespace starboard {
namespace elf_loader {

DynamicSection::DynamicSection(Addr base_memory_address,
                               Dyn* dynamic,
                               size_t dynamic_count,
                               Word dynamic_flags)
    : base_memory_address_(base_memory_address),
      soname_(NULL),
      dynamic_(dynamic),
      dynamic_count_(dynamic_count),
      dynamic_flags_(dynamic_flags),
      has_DT_SYMBOLIC_(false),
      symbol_table_(NULL),
      string_table_(NULL),
      preinit_array_(NULL),
      preinit_array_count_(0),
      init_array_(NULL),
      init_array_count_(0),
      fini_array_(NULL),
      fini_array_count_(0),
      init_func_(NULL),
      fini_func_(NULL) {}

bool DynamicSection::InitDynamicSection() {
  SB_LOG(INFO) << "Dynamic section count=" << dynamic_count_;
  for (int i = 0; i < dynamic_count_; i++) {
    Addr dyn_value = dynamic_[i].d_un.d_val;
    uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr;
    SB_LOG(INFO) << "Dynamic tag=" << dynamic_[i].d_tag;
    switch (dynamic_[i].d_tag) {
      case DT_DEBUG:
        // TODO: implement.
        break;
      case DT_INIT:
        SB_LOG(INFO) << "  DT_INIT addr=0x" << std::hex << dyn_addr;
        init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
        break;
      case DT_FINI:
        SB_LOG(INFO) << "  DT_FINI addr=0x" << std::hex << dyn_addr;
        fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
        break;
      case DT_INIT_ARRAY:
        SB_LOG(INFO) << "  DT_INIT_ARRAY addr=0x" << std::hex << dyn_addr;
        init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_INIT_ARRAYSZ:
        init_array_count_ = dyn_value / sizeof(Addr);
        SB_LOG(INFO) << "  DT_INIT_ARRAYSZ value=0x" << std::hex << dyn_value
                     << " count=" << std::dec << init_array_count_;
        break;
      case DT_FINI_ARRAY:
        SB_LOG(INFO) << "  DT_FINI_ARRAY addr=0x" << std::hex << dyn_addr;
        fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_FINI_ARRAYSZ:
        fini_array_count_ = dyn_value / sizeof(Addr);
        SB_LOG(INFO) << "  DT_FINI_ARRAYSZ value=0x" << std::hex << dyn_value
                     << " count=" << fini_array_count_;
        break;
      case DT_PREINIT_ARRAY:
        SB_LOG(INFO) << "  DT_PREINIT_ARRAY addr=0x" << std::hex << dyn_addr;
        preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_PREINIT_ARRAYSZ:
        preinit_array_count_ = dyn_value / sizeof(Addr);
        SB_LOG(INFO) << "  DT_PREINIT_ARRAYSZ addr=" << dyn_addr
                     << " count=" << preinit_array_count_;
        break;
      case DT_SYMBOLIC:
        SB_LOG(INFO) << "  DT_SYMBOLIC";
        has_DT_SYMBOLIC_ = true;
        break;
      case DT_FLAGS:
        if (dyn_value & DF_SYMBOLIC)
          has_DT_SYMBOLIC_ = true;
        break;
      case DT_SONAME:
        soname_ = string_table_ + dyn_value;
        break;
      default:
        break;
    }
  }
  return true;
}

bool DynamicSection::InitDynamicSymbols() {
  for (int i = 0; i < dynamic_count_; i++) {
    Addr dyn_value = dynamic_[i].d_un.d_val;
    uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr;
    switch (dynamic_[i].d_tag) {
      case DT_HASH:
        SB_LOG(INFO) << "  DT_HASH addr=0x" << std::hex << dyn_addr;
        elf_hash_.Init(dyn_addr);
        break;
      case DT_GNU_HASH:
        SB_LOG(INFO) << "  DT_GNU_HASH addr=0x" << std::hex << dyn_addr;
        gnu_hash_.Init(dyn_addr);
        break;
      case DT_STRTAB:
        SB_LOG(INFO) << "  DT_STRTAB addr=0x" << std::hex << dyn_addr;
        string_table_ = reinterpret_cast<const char*>(dyn_addr);
        break;
      case DT_SYMTAB:
        SB_LOG(INFO) << "  DT_SYMTAB addr=0x" << std::hex << dyn_addr;
        symbol_table_ = reinterpret_cast<Sym*>(dyn_addr);
        break;
      default:
        break;
    }
  }
  return true;
}

const Dyn* DynamicSection::GetDynamicTable() {
  return dynamic_;
}

size_t DynamicSection::GetDynamicTableSize() {
  return dynamic_count_;
}

void DynamicSection::CallConstructors() {
  CallFunction(init_func_, "DT_INIT");
  for (size_t n = 0; n < init_array_count_; ++n)
    CallFunction(init_array_[n], "DT_INIT_ARRAY");
}

void DynamicSection::CallDestructors() {
  for (size_t n = fini_array_count_; n > 0; --n) {
    CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
  }
  CallFunction(fini_func_, "DT_FINI");
}

void DynamicSection::CallFunction(linker_function_t func,
                                  const char* func_type) {
  uintptr_t func_address = reinterpret_cast<uintptr_t>(func);

  // On some platforms  the entries in the array can be 0 or -1,
  // and should  be ignored e.g. Android:
  // https://android.googlesource.com/platform/bionic/+/android-4.2_r1/linker/README.TXT
  if (func_address != 0 && func_address != uintptr_t(-1)) {
    func();
  }
}

const Sym* DynamicSection::LookupById(size_t symbol_id) const {
  // TODO: Calculated the symbol_table size and validation check.
  return &symbol_table_[symbol_id];
}

bool DynamicSection::IsWeakById(size_t symbol_id) const {
  // TODO: Calculated the symbol_table size and validation check.
  return ELF_ST_BIND(symbol_table_[symbol_id].st_info) == STB_WEAK;
}

const char* DynamicSection::LookupNameById(size_t symbol_id) const {
  const Sym* sym = LookupById(symbol_id);
  // TODO: Confirm that LookupById actually can return NULL.
  if (!sym)
    return NULL;
  return string_table_ + sym->st_name;
}

const Sym* DynamicSection::LookupByName(const char* symbol_name) const {
  const Sym* sym =
      gnu_hash_.IsValid()
          ? gnu_hash_.LookupByName(symbol_name, symbol_table_, string_table_)
          : elf_hash_.LookupByName(symbol_name, symbol_table_, string_table_);

  // Ignore undefined symbols or those that are not global or weak definitions.
  if (!sym || sym->st_shndx == SHN_UNDEF)
    return NULL;

  uint8_t info = ELF_ST_BIND(sym->st_info);
  if (info != STB_GLOBAL && info != STB_WEAK)
    return NULL;

  return sym;
}

}  // namespace elf_loader
}  // namespace starboard
