1eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr/*
2eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * Copyright 2017 The Android Open Source Project
3eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr *
4eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * Licensed under the Apache License, Version 2.0 (the "License");
5eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * you may not use this file except in compliance with the License.
6eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * You may obtain a copy of the License at
7eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr *
8eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr *      http://www.apache.org/licenses/LICENSE-2.0
9eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr *
10eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * Unless required by applicable law or agreed to in writing, software
11eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * distributed under the License is distributed on an "AS IS" BASIS,
12eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * See the License for the specific language governing permissions and
14eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr * limitations under the License.
15eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr */
16eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
17eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <stdio.h>
18eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <stdlib.h>
19eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <string.h>
20eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
21eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <map>
22eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
23eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <base/debug/stack_trace.h>
24eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
25eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr#include <libatap/libatap.h>
26eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
27eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid* atap_memcpy(void* dest, const void* src, size_t n) {
28eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  return memcpy(dest, src, n);
29eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
30eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
31eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid* atap_memset(void* dest, const int c, size_t n) {
32eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  return memset(dest, c, n);
33eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
34eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
35eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid atap_abort(void) {
36eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  abort();
37eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
38eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
39eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid atap_print(const char* message) {
40eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  fprintf(stderr, "%s", message);
41eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
42eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
43eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid atap_printv(const char* message, ...) {
44eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  va_list ap;
45eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  const char* m;
46eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
47eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  va_start(ap, message);
48eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  for (m = message; m != NULL; m = va_arg(ap, const char*)) {
49eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    fprintf(stderr, "%s", m);
50eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
51eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  va_end(ap);
52eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
53eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
54eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrsize_t atap_strlen(const char* str) {
55eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  return strlen(str);
56eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
57eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
58eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrtypedef struct {
59eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  size_t size;
60eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  base::debug::StackTrace stack_trace;
61eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr} AtapAllocatedBlock;
62eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
63eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrstatic std::map<void*, AtapAllocatedBlock> allocated_blocks;
64eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
65eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid* atap_malloc(size_t size) {
66eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  void* ptr = malloc(size);
67eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  atap_assert(ptr != nullptr);
68eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  AtapAllocatedBlock block;
69eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  block.size = size;
70eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  allocated_blocks[ptr] = block;
71eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  return ptr;
72eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
73eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
74eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid atap_free(void* ptr) {
75eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  auto block_it = allocated_blocks.find(ptr);
76eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  if (block_it == allocated_blocks.end()) {
77eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    atap_fatal("Tried to free pointer to non-allocated block.\n");
78eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    return;
79eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
80eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  allocated_blocks.erase(block_it);
81eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  free(ptr);
82eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
83eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
84eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrnamespace atap {
85eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
86eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrvoid testing_memory_reset() {
87eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  allocated_blocks.clear();
88eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
89eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
90eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohrbool testing_memory_all_freed() {
91eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  if (allocated_blocks.size() == 0) {
92eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    return true;
93eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
94eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
95eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  size_t sum = 0;
96eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  for (const auto& block_it : allocated_blocks) {
97eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    sum += block_it.second.size;
98eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
99eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  fprintf(stderr,
100eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr          "%zd bytes still allocated in %zd blocks:\n",
101eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr          sum,
102eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr          allocated_blocks.size());
103eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  size_t n = 0;
104eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  for (const auto& block_it : allocated_blocks) {
105eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    fprintf(stderr,
106eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr            "--\nAllocation %zd/%zd of %zd bytes:\n",
107eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr            1 + n++,
108eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr            allocated_blocks.size(),
109eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr            block_it.second.size);
110eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    block_it.second.stack_trace.Print();
111eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
112eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  return false;
113eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
114eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
115eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr// Also check leaks at process exit.
116eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr__attribute__((destructor)) static void ensure_all_memory_freed_at_exit() {
117eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  if (!testing_memory_all_freed()) {
118eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr    atap_fatal("libatap memory leaks at process exit.\n");
119eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr  }
120eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}
121eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr
122eb3a3e3eafd643fb61456dfda4eca3c61d50ff14Jocelyn Bohr}  // namespace atap
123