/*
 * 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 "src/profiling/memory/unwinding.h"

#include <cxxabi.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unwindstack/RegsGetLocal.h>

#include "perfetto/ext/base/scoped_file.h"
#include "src/profiling/memory/client.h"
#include "src/profiling/memory/wire_protocol.h"
#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace profiling {
namespace {

TEST(UnwindingTest, StackOverlayMemoryOverlay) {
  base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
  ASSERT_TRUE(proc_mem);
  uint8_t fake_stack[1] = {120};
  std::shared_ptr<FDMemory> mem(
      std::make_shared<FDMemory>(std::move(proc_mem)));
  StackOverlayMemory memory(mem, 0u, fake_stack, 1);
  uint8_t buf[1] = {};
  ASSERT_EQ(memory.Read(0u, buf, 1), 1u);
  ASSERT_EQ(buf[0], 120);
}

TEST(UnwindingTest, StackOverlayMemoryNonOverlay) {
  uint8_t value = 52;

  base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
  ASSERT_TRUE(proc_mem);
  uint8_t fake_stack[1] = {120};
  std::shared_ptr<FDMemory> mem(
      std::make_shared<FDMemory>(std::move(proc_mem)));
  StackOverlayMemory memory(mem, 0u, fake_stack, 1);
  uint8_t buf[1] = {1};
  ASSERT_EQ(memory.Read(reinterpret_cast<uint64_t>(&value), buf, 1), 1u);
  ASSERT_EQ(buf[0], value);
}

TEST(UnwindingTest, FileDescriptorMapsParse) {
  base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
  ASSERT_TRUE(proc_maps);
  FileDescriptorMaps maps(std::move(proc_maps));
  ASSERT_TRUE(maps.Parse());
  unwindstack::MapInfo* map_info =
      maps.Find(reinterpret_cast<uint64_t>(&proc_maps));
  ASSERT_NE(map_info, nullptr);
  ASSERT_EQ(map_info->name, "[stack]");
}

// This is needed because ASAN thinks copying the whole stack is a buffer
// underrun.
void __attribute__((noinline))
UnsafeMemcpy(void* dst, const void* src, size_t n)
    __attribute__((no_sanitize("address", "hwaddress"))) {
  const uint8_t* from = reinterpret_cast<const uint8_t*>(src);
  uint8_t* to = reinterpret_cast<uint8_t*>(dst);
  for (size_t i = 0; i < n; ++i)
    to[i] = from[i];
}

struct RecordMemory {
  std::unique_ptr<uint8_t[]> payload;
  std::unique_ptr<AllocMetadata> metadata;
};

RecordMemory __attribute__((noinline)) GetRecord(WireMessage* msg) {
  std::unique_ptr<AllocMetadata> metadata(new AllocMetadata);
  *metadata = {};

  const char* stackbase = GetThreadStackBase();
  const char* stacktop = reinterpret_cast<char*>(__builtin_frame_address(0));
  unwindstack::AsmGetRegs(metadata->register_data);

  if (stackbase < stacktop) {
    PERFETTO_FATAL("Stacktop >= stackbase.");
    return {nullptr, nullptr};
  }
  size_t stack_size = static_cast<size_t>(stackbase - stacktop);

  metadata->alloc_size = 10;
  metadata->alloc_address = 0x10;
  metadata->stack_pointer = reinterpret_cast<uint64_t>(stacktop);
  metadata->stack_pointer_offset = sizeof(AllocMetadata);
  metadata->arch = unwindstack::Regs::CurrentArch();
  metadata->sequence_number = 1;

  std::unique_ptr<uint8_t[]> payload(new uint8_t[stack_size]);
  UnsafeMemcpy(&payload[0], stacktop, stack_size);

  *msg = {};
  msg->alloc_header = metadata.get();
  msg->payload = reinterpret_cast<char*>(payload.get());
  msg->payload_size = static_cast<size_t>(stack_size);
  return {std::move(payload), std::move(metadata)};
}

// TODO(rsavitski): Investigate TSAN unwinding.
#if defined(THREAD_SANITIZER)
#define MAYBE_DoUnwind DISABLED_DoUnwind
#else
#define MAYBE_DoUnwind DoUnwind
#endif

TEST(UnwindingTest, MAYBE_DoUnwind) {
  base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
  base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
  GlobalCallstackTrie callsites;
  UnwindingMetadata metadata(getpid(), std::move(proc_maps),
                             std::move(proc_mem));
  WireMessage msg;
  auto record = GetRecord(&msg);
  AllocRecord out;
  ASSERT_TRUE(DoUnwind(&msg, &metadata, &out));
  int st;
  std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
      out.frames[0].frame.function_name.c_str(), nullptr, nullptr, &st));
  ASSERT_EQ(st, 0);
  ASSERT_STREQ(demangled.get(),
               "perfetto::profiling::(anonymous "
               "namespace)::GetRecord(perfetto::profiling::WireMessage*)");
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto
