/*
 * Copyright (C) 2015 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>

#include <algorithm>
#include <vector>

#include <private/ScopedPthreadMutexLocker.h>

#include "backtrace.h"
#include "BacktraceData.h"
#include "Config.h"
#include "DebugData.h"
#include "debug_disable.h"
#include "debug_log.h"
#include "malloc_debug.h"
#include "TrackData.h"

TrackData::TrackData(DebugData* debug_data) : OptionData(debug_data) {
}

void TrackData::GetList(std::vector<const Header*>* list) {
  for (const auto& header : headers_) {
    list->push_back(header);
  }

  // Sort by the size of the allocation.
  std::sort(list->begin(), list->end(), [](const Header* a, const Header* b) {
    if (a->size == b->size) return a < b;
    return a->size > b->size;
  });
}

void TrackData::GetListBySizeThenBacktrace(std::vector<const Header*>* list, size_t* total_memory) {
  if (!(debug_->config().options() & BACKTRACE)) {
    return;
  }

  *total_memory = 0;
  for (const auto& header : headers_) {
    list->push_back(header);
    *total_memory += header->real_size();
  }

  // Put all zygote allocations first by size and backtrace.
  // Then all zygote child allocation by size and backtrace.
  std::sort(list->begin(), list->end(), [&](const Header* a, const Header* b) {
    if (a->zygote_child_alloc() && !b->zygote_child_alloc()) {
      return false;
    } else if (!a->zygote_child_alloc() && b->zygote_child_alloc()) {
      return true;
    }
    if (a->real_size() != b->real_size()) return a->real_size() < b->real_size();
    // If the size is the same, compare backtrace elements.
    BacktraceHeader* a_back = debug_->GetAllocBacktrace(a);
    BacktraceHeader* b_back = debug_->GetAllocBacktrace(b);
    for (size_t i = 0; i < a_back->num_frames; i++) {
      if (i > b_back->num_frames) {
        // All frames equal up to this point, but a has more frames available.
        return false;
      }
      if (a_back->frames[i] < b_back->frames[i]) {
        return false;
      } else if (a_back->frames[i] > b_back->frames[i]) {
        return true;
      }
    }
    if (a_back->num_frames < b_back->num_frames) {
      // All frames equal up to this point, but b has more frames available.
      return true;
    }
    return false;
  });

}

void TrackData::Add(const Header* header, bool backtrace_found) {
  pthread_mutex_lock(&mutex_);
  if (backtrace_found) {
    total_backtrace_allocs_++;
  }
  headers_.insert(header);
  pthread_mutex_unlock(&mutex_);
}

void TrackData::Remove(const Header* header, bool backtrace_found) {
  pthread_mutex_lock(&mutex_);
  headers_.erase(header);
  if (backtrace_found) {
    total_backtrace_allocs_--;
  }
  pthread_mutex_unlock(&mutex_);
}

bool TrackData::Contains(const Header* header) {
  pthread_mutex_lock(&mutex_);
  bool found = headers_.count(header);
  pthread_mutex_unlock(&mutex_);
  return found;
}

void TrackData::DisplayLeaks() {
  std::vector<const Header*> list;
  GetList(&list);

  size_t track_count = 0;
  for (const auto& header : list) {
    error_log("+++ %s leaked block of size %zu at %p (leak %zu of %zu)", getprogname(),
              header->real_size(), debug_->GetPointer(header), ++track_count, list.size());
    if (debug_->config().options() & BACKTRACE) {
      BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
      if (back_header->num_frames > 0) {
        error_log("Backtrace at time of allocation:");
        backtrace_log(&back_header->frames[0], back_header->num_frames);
      }
    }
    g_dispatch->free(header->orig_pointer);
  }
}

void TrackData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
                        size_t* total_memory, size_t* backtrace_size) {
  ScopedPthreadMutexLocker scoped(&mutex_);

  if (headers_.size() == 0 || total_backtrace_allocs_ == 0) {
    return;
  }

  *backtrace_size = debug_->config().backtrace_frames();
  *info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size;
  *info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, total_backtrace_allocs_));
  if (*info == nullptr) {
    return;
  }
  *overall_size = *info_size * total_backtrace_allocs_;

  std::vector<const Header*> list;
  GetList(&list);

  uint8_t* data = *info;
  size_t num_allocations = 1;
  for (const auto& header : list) {
    BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
    if (back_header->num_frames > 0) {
      memcpy(data, &header->size, sizeof(size_t));
      memcpy(&data[sizeof(size_t)], &num_allocations, sizeof(size_t));
      memcpy(&data[2 * sizeof(size_t)], &back_header->frames[0],
            back_header->num_frames * sizeof(uintptr_t));

      *total_memory += header->real_size();

      data += *info_size;
    }
  }
}
