/*
 * Copyright (C) 2014 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 <unistd.h>

#include <backtrace/BacktraceMap.h>

#include <libunwind.h>

#include "BacktraceLog.h"
#include "UnwindMap.h"

//-------------------------------------------------------------------------
// libunwind has a single shared address space for the current process
// aka local. If multiple maps are created for the current pid, then
// only update the local address space once, and keep a reference count
// of maps using the same map cursor.
//-------------------------------------------------------------------------
UnwindMap::UnwindMap(pid_t pid) : BacktraceMap(pid) {
}

UnwindMap::~UnwindMap() {
  unw_map_cursor_destroy(&map_cursor_);
  unw_map_cursor_clear(&map_cursor_);
}

bool UnwindMap::GenerateMap() {
  // Use the map_cursor information to construct the BacktraceMap data
  // rather than reparsing /proc/self/maps.
  unw_map_cursor_reset(&map_cursor_);

  unw_map_t unw_map;
  while (unw_map_cursor_get_next(&map_cursor_, &unw_map)) {
    backtrace_map_t map;

    map.start = unw_map.start;
    map.end = unw_map.end;
    map.flags = unw_map.flags;
    map.name = unw_map.path;

    // The maps are in descending order, but we want them in ascending order.
    maps_.push_front(map);
  }

  return true;
}

bool UnwindMap::Build() {
  return (unw_map_cursor_create(&map_cursor_, pid_) == 0) && GenerateMap();
}

UnwindMapLocal::UnwindMapLocal() : UnwindMap(getpid()), map_created_(false) {
}

UnwindMapLocal::~UnwindMapLocal() {
  if (map_created_) {
    unw_map_local_destroy();
    unw_map_cursor_clear(&map_cursor_);
  }
}

bool UnwindMapLocal::GenerateMap() {
  // It's possible for the map to be regenerated while this loop is occurring.
  // If that happens, get the map again, but only try at most three times
  // before giving up.
  for (int i = 0; i < 3; i++) {
    maps_.clear();

    unw_map_local_cursor_get(&map_cursor_);

    unw_map_t unw_map;
    int ret;
    while ((ret = unw_map_local_cursor_get_next(&map_cursor_, &unw_map)) > 0) {
      backtrace_map_t map;

      map.start = unw_map.start;
      map.end = unw_map.end;
      map.flags = unw_map.flags;
      map.name = unw_map.path;

      free(unw_map.path);

      // The maps are in descending order, but we want them in ascending order.
      maps_.push_front(map);
    }
    // Check to see if the map changed while getting the data.
    if (ret != -UNW_EINVAL) {
      return true;
    }
  }

  BACK_LOGW("Unable to generate the map.");
  return false;
}

bool UnwindMapLocal::Build() {
  return (map_created_ = (unw_map_local_create() == 0)) && GenerateMap();;
}

void UnwindMapLocal::FillIn(uintptr_t addr, backtrace_map_t* map) {
  BacktraceMap::FillIn(addr, map);
  if (!IsValid(*map)) {
    // Check to see if the underlying map changed and regenerate the map
    // if it did.
    if (unw_map_local_cursor_valid(&map_cursor_) < 0) {
      if (GenerateMap()) {
        BacktraceMap::FillIn(addr, map);
      }
    }
  }
}

//-------------------------------------------------------------------------
// 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 UnwindMapLocal();
  } else {
    map = new UnwindMap(pid);
  }
  if (!map->Build()) {
    delete map;
    return nullptr;
  }
  return map;
}
