1 /* 2 * Copyright (C) 2019 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 <err.h> 18 #include <inttypes.h> 19 #include <stdint.h> 20 #include <stdio.h> 21 #include <unistd.h> 22 23 #include <string> 24 25 #include "Alloc.h" 26 #include "Pointers.h" 27 #include "Utils.h" 28 29 void AllocGetData(const std::string& line, AllocEntry* entry) { 30 int line_pos = 0; 31 char name[128]; 32 // All lines have this format: 33 // TID: ALLOCATION_TYPE POINTER 34 // where 35 // TID is the thread id of the thread doing the operation. 36 // ALLOCATION_TYPE is one of malloc, calloc, memalign, realloc, free, thread_done 37 // POINTER is the hex value of the actual pointer 38 if (sscanf(line.c_str(), "%d: %127s %" SCNx64 " %n", &entry->tid, name, &entry->ptr, &line_pos) != 39 3) { 40 errx(1, "File Error: Failed to process %s", line.c_str()); 41 } 42 const char* line_end = &line[line_pos]; 43 std::string type(name); 44 if (type == "malloc") { 45 // Format: 46 // TID: malloc POINTER SIZE_OF_ALLOCATION 47 if (sscanf(line_end, "%zu", &entry->size) != 1) { 48 errx(1, "File Error: Failed to read malloc data %s", line.c_str()); 49 } 50 entry->type = MALLOC; 51 } else if (type == "free") { 52 // Format: 53 // TID: free POINTER 54 entry->type = FREE; 55 } else if (type == "calloc") { 56 // Format: 57 // TID: calloc POINTER ITEM_COUNT ITEM_SIZE 58 if (sscanf(line_end, "%" SCNd64 " %zu", &entry->u.n_elements, &entry->size) != 2) { 59 errx(1, "File Error: Failed to read calloc data %s", line.c_str()); 60 } 61 entry->type = CALLOC; 62 } else if (type == "realloc") { 63 // Format: 64 // TID: calloc POINTER NEW_SIZE OLD_POINTER 65 if (sscanf(line_end, "%" SCNx64 " %zu", &entry->u.old_ptr, &entry->size) != 2) { 66 errx(1, "File Error: Failed to read realloc data %s", line.c_str()); 67 } 68 entry->type = REALLOC; 69 } else if (type == "memalign") { 70 // Format: 71 // TID: memalign POINTER ALIGNMENT SIZE 72 if (sscanf(line_end, "%" SCNd64 " %zu", &entry->u.align, &entry->size) != 2) { 73 errx(1, "File Error: Failed to read memalign data %s", line.c_str()); 74 } 75 entry->type = MEMALIGN; 76 } else if (type == "thread_done") { 77 entry->type = THREAD_DONE; 78 } else { 79 errx(1, "File Error: Unknown type %s", type.c_str()); 80 } 81 } 82 83 bool AllocDoesFree(const AllocEntry& entry) { 84 switch (entry.type) { 85 case MALLOC: 86 case CALLOC: 87 case MEMALIGN: 88 case THREAD_DONE: 89 return false; 90 91 case FREE: 92 return entry.ptr != 0; 93 94 case REALLOC: 95 return entry.u.old_ptr != 0; 96 } 97 } 98 99 static uint64_t MallocExecute(const AllocEntry& entry, Pointers* pointers) { 100 int pagesize = getpagesize(); 101 uint64_t time_nsecs = Nanotime(); 102 void* memory = malloc(entry.size); 103 MakeAllocationResident(memory, entry.size, pagesize); 104 time_nsecs = Nanotime() - time_nsecs; 105 106 pointers->Add(entry.ptr, memory); 107 108 return time_nsecs; 109 } 110 111 static uint64_t CallocExecute(const AllocEntry& entry, Pointers* pointers) { 112 int pagesize = getpagesize(); 113 uint64_t time_nsecs = Nanotime(); 114 void* memory = calloc(entry.u.n_elements, entry.size); 115 MakeAllocationResident(memory, entry.u.n_elements * entry.size, pagesize); 116 time_nsecs = Nanotime() - time_nsecs; 117 118 pointers->Add(entry.ptr, memory); 119 120 return time_nsecs; 121 } 122 123 static uint64_t ReallocExecute(const AllocEntry& entry, Pointers* pointers) { 124 void* old_memory = nullptr; 125 if (entry.u.old_ptr != 0) { 126 old_memory = pointers->Remove(entry.u.old_ptr); 127 } 128 129 int pagesize = getpagesize(); 130 uint64_t time_nsecs = Nanotime(); 131 void* memory = realloc(old_memory, entry.size); 132 MakeAllocationResident(memory, entry.size, pagesize); 133 time_nsecs = Nanotime() - time_nsecs; 134 135 pointers->Add(entry.ptr, memory); 136 137 return time_nsecs; 138 } 139 140 static uint64_t MemalignExecute(const AllocEntry& entry, Pointers* pointers) { 141 int pagesize = getpagesize(); 142 uint64_t time_nsecs = Nanotime(); 143 void* memory = memalign(entry.u.align, entry.size); 144 MakeAllocationResident(memory, entry.size, pagesize); 145 time_nsecs = Nanotime() - time_nsecs; 146 147 pointers->Add(entry.ptr, memory); 148 149 return time_nsecs; 150 } 151 152 static uint64_t FreeExecute(const AllocEntry& entry, Pointers* pointers) { 153 if (entry.ptr == 0) { 154 return 0; 155 } 156 157 void* memory = pointers->Remove(entry.ptr); 158 uint64_t time_nsecs = Nanotime(); 159 free(memory); 160 return Nanotime() - time_nsecs; 161 } 162 163 uint64_t AllocExecute(const AllocEntry& entry, Pointers* pointers) { 164 switch (entry.type) { 165 case MALLOC: 166 return MallocExecute(entry, pointers); 167 case CALLOC: 168 return CallocExecute(entry, pointers); 169 case REALLOC: 170 return ReallocExecute(entry, pointers); 171 case MEMALIGN: 172 return MemalignExecute(entry, pointers); 173 case FREE: 174 return FreeExecute(entry, pointers); 175 default: 176 return 0; 177 } 178 } 179