/*
 * Copyright (C) 2017 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 <stdint.h>
#include <stdlib.h>
#include <sys/types.h>

#include <string>
#include <vector>

#include <backtrace/BacktraceMap.h>
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Regs.h>

#include "UnwindStackMap.h"

//-------------------------------------------------------------------------
UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}

bool UnwindStackMap::Build() {
  if (pid_ == 0) {
    pid_ = getpid();
    stack_maps_.reset(new unwindstack::LocalMaps);
  } else {
    stack_maps_.reset(new unwindstack::RemoteMaps(pid_));
  }

  // Create the process memory object.
  process_memory_ = unwindstack::Memory::CreateProcessMemory(pid_);

  if (!stack_maps_->Parse()) {
    return false;
  }

  // Iterate through the maps and fill in the backtrace_map_t structure.
  for (const auto& map_info : *stack_maps_) {
    backtrace_map_t map;
    map.start = map_info->start;
    map.end = map_info->end;
    map.offset = map_info->offset;
    // Set to -1 so that it is demand loaded.
    map.load_bias = static_cast<uint64_t>(-1);
    map.flags = map_info->flags;
    map.name = map_info->name;

    maps_.push_back(map);
  }

  return true;
}

void UnwindStackMap::FillIn(uint64_t addr, backtrace_map_t* map) {
  BacktraceMap::FillIn(addr, map);
  if (map->load_bias != static_cast<uint64_t>(-1)) {
    return;
  }

  // Fill in the load_bias.
  unwindstack::MapInfo* map_info = stack_maps_->Find(addr);
  if (map_info == nullptr) {
    return;
  }
  map->load_bias = map_info->GetLoadBias(process_memory_);
}

uint64_t UnwindStackMap::GetLoadBias(size_t index) {
  if (index >= stack_maps_->Total()) {
    return 0;
  }

  unwindstack::MapInfo* map_info = stack_maps_->Get(index);
  if (map_info == nullptr) {
    return 0;
  }
  return map_info->GetLoadBias(process_memory_);
}

std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) {
  *offset = 0;
  unwindstack::Maps* maps = stack_maps();

  // Get the map for this
  unwindstack::MapInfo* map_info = maps->Find(pc);
  if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
    return "";
  }

  if (arch_ == unwindstack::ARCH_UNKNOWN) {
    if (pid_ == getpid()) {
      arch_ = unwindstack::Regs::CurrentArch();
    } else {
      // Create a remote regs, to figure out the architecture.
      std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::RemoteGet(pid_));
      arch_ = regs->Arch();
    }
  }

  unwindstack::Elf* elf = map_info->GetElf(process_memory(), arch_);

  std::string name;
  uint64_t func_offset;
  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
    return "";
  }
  *offset = func_offset;
  return name;
}

std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
  return process_memory_;
}

UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {}

bool UnwindStackOfflineMap::Build() {
  return false;
}

bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps) {
  for (const backtrace_map_t& map : backtrace_maps) {
    maps_.push_back(map);
  }

  std::sort(maps_.begin(), maps_.end(),
            [](const backtrace_map_t& a, const backtrace_map_t& b) { return a.start < b.start; });

  unwindstack::Maps* maps = new unwindstack::Maps;
  stack_maps_.reset(maps);
  for (const backtrace_map_t& map : maps_) {
    maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias);
  }
  return true;
}

bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) {
  if (stack.start >= stack.end) {
    return false;
  }

  // Create the process memory from the stack data.
  if (memory_ == nullptr) {
    memory_ = new unwindstack::MemoryOfflineBuffer(stack.data, stack.start, stack.end);
    process_memory_.reset(memory_);
  } else {
    memory_->Reset(stack.data, stack.start, stack.end);
  }
  return true;
}

//-------------------------------------------------------------------------
// BacktraceMap create function.
//-------------------------------------------------------------------------
BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
  BacktraceMap* map;

  if (uncached) {
    // Force use of the base class to parse the maps when this call is made.
    map = new BacktraceMap(pid);
  } else if (pid == getpid()) {
    map = new UnwindStackMap(0);
  } else {
    map = new UnwindStackMap(pid);
  }
  if (!map->Build()) {
    delete map;
    return nullptr;
  }
  return map;
}

//-------------------------------------------------------------------------
// BacktraceMap create offline function.
//-------------------------------------------------------------------------
BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps) {
  UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid);
  if (!map->Build(maps)) {
    delete map;
    return nullptr;
  }
  return map;
}
