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