mirror of
https://github.com/google/pebble.git
synced 2025-03-22 03:32:20 +00:00
238 lines
5.7 KiB
C
238 lines
5.7 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <util/heap.h>
|
|
#include "util/list.h"
|
|
#include "util/math.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
ListNode list_node;
|
|
size_t bytes;
|
|
void *ptr;
|
|
void *lr;
|
|
} PointerListNode;
|
|
|
|
static PointerListNode *s_pointer_list = NULL;
|
|
|
|
static bool prv_pointer_list_filter(ListNode *node, void *ptr) {
|
|
return ((PointerListNode *)node)->ptr == ptr;
|
|
}
|
|
|
|
static void prv_pointer_list_add(void *ptr, size_t bytes, void *lr) {
|
|
PointerListNode *node = malloc(sizeof(PointerListNode));
|
|
list_init(&node->list_node);
|
|
node->ptr = ptr;
|
|
node->bytes = bytes;
|
|
node->lr = lr;
|
|
s_pointer_list = (PointerListNode *)list_prepend((ListNode *)s_pointer_list, &node->list_node);
|
|
}
|
|
|
|
static void prv_pointer_list_remove(void *ptr) {
|
|
ListNode *node = list_find((ListNode *)s_pointer_list, prv_pointer_list_filter, ptr);
|
|
if (!node && ptr) {
|
|
printf("*** INVALID FREE: %p\n", ptr);
|
|
cl_fail("Pointer has not been alloc'd (maybe a double free?)");
|
|
}
|
|
|
|
list_remove(node, (ListNode **)&s_pointer_list, NULL);
|
|
free(node);
|
|
}
|
|
|
|
static size_t s_max_size_allowed = ~0;
|
|
|
|
static Heap s_heap;
|
|
Heap *task_heap_get_for_current_task(void) {
|
|
return &s_heap;
|
|
}
|
|
|
|
static void *malloc_and_track(size_t bytes, void *lr) {
|
|
if (bytes >= s_max_size_allowed) {
|
|
return NULL;
|
|
}
|
|
void *rt = malloc(bytes);
|
|
prv_pointer_list_add(rt, bytes, lr);
|
|
return rt;
|
|
}
|
|
|
|
static void *calloc_and_track(int n, size_t bytes, void *lr) {
|
|
if ((bytes * n) >= s_max_size_allowed) {
|
|
return NULL;
|
|
}
|
|
|
|
void *rt = calloc(n, bytes);
|
|
prv_pointer_list_add(rt, bytes, lr);
|
|
return rt;
|
|
}
|
|
|
|
void fake_malloc_set_largest_free_block(size_t bytes) {
|
|
s_max_size_allowed = bytes;
|
|
}
|
|
|
|
static void free_and_track(void *ptr) {
|
|
prv_pointer_list_remove(ptr);
|
|
free(ptr);
|
|
}
|
|
|
|
void *realloc_and_track(void *ptr, size_t bytes, void *lr) {
|
|
void *new_ptr = malloc_and_track(bytes, lr);
|
|
if (new_ptr && ptr) {
|
|
ListNode *node = list_find((ListNode *)s_pointer_list, prv_pointer_list_filter, ptr);
|
|
cl_assert(node);
|
|
memcpy(new_ptr, ptr, MIN(((PointerListNode*)node)->bytes, bytes));
|
|
free_and_track(ptr);
|
|
}
|
|
return new_ptr;
|
|
}
|
|
|
|
int fake_pbl_malloc_num_net_allocs(void) {
|
|
return list_count((ListNode *)s_pointer_list);
|
|
}
|
|
|
|
void fake_pbl_malloc_check_net_allocs(void) {
|
|
if (fake_pbl_malloc_num_net_allocs() > 0) {
|
|
ListNode *node = (ListNode *)s_pointer_list;
|
|
while (node) {
|
|
PointerListNode *ptr_node = (PointerListNode *)node;
|
|
printf("Still allocated: %p (%zu bytes, lr %p)\n",
|
|
ptr_node->ptr, ptr_node->bytes, ptr_node->lr);
|
|
node = list_get_next(node);
|
|
}
|
|
}
|
|
cl_assert_equal_i(fake_pbl_malloc_num_net_allocs(), 0);
|
|
}
|
|
|
|
void fake_pbl_malloc_clear_tracking(void) {
|
|
while (s_pointer_list) {
|
|
ListNode *new_head = list_pop_head((ListNode *)s_pointer_list);
|
|
free(s_pointer_list);
|
|
s_pointer_list = (PointerListNode *)new_head;
|
|
}
|
|
s_max_size_allowed = ~0;
|
|
}
|
|
|
|
void *task_malloc(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *task_malloc_check(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *task_realloc(void *ptr, size_t bytes) {
|
|
return realloc_and_track(ptr, bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *task_zalloc(size_t bytes) {
|
|
void *ptr = task_malloc(bytes);
|
|
if (ptr) {
|
|
memset(ptr, 0, bytes);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
void *task_zalloc_check(size_t bytes) {
|
|
void *ptr = task_malloc_check(bytes);
|
|
memset(ptr, 0, bytes);
|
|
return ptr;
|
|
}
|
|
|
|
void *task_calloc(size_t count, size_t size) {
|
|
return calloc_and_track(count, size, __builtin_return_address(0));
|
|
}
|
|
|
|
void *task_calloc_check(size_t count, size_t size) {
|
|
return calloc_and_track(count, size, __builtin_return_address(0));
|
|
}
|
|
|
|
void task_free(void *ptr) {
|
|
free_and_track(ptr);
|
|
}
|
|
|
|
void *applib_zalloc(size_t bytes) {
|
|
return calloc_and_track(1, bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void applib_free(void *ptr) {
|
|
free_and_track(ptr);
|
|
}
|
|
|
|
void *app_malloc(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *app_malloc_check(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void app_free(void *ptr) {
|
|
free_and_track(ptr);
|
|
}
|
|
|
|
void *kernel_malloc(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *kernel_zalloc(size_t bytes) {
|
|
return calloc_and_track(1, bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *kernel_zalloc_check(size_t bytes) {
|
|
return kernel_zalloc(bytes);
|
|
}
|
|
|
|
void *kernel_malloc_check(size_t bytes) {
|
|
return malloc_and_track(bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void *kernel_realloc(void *ptr, size_t bytes) {
|
|
return realloc_and_track(ptr, bytes, __builtin_return_address(0));
|
|
}
|
|
|
|
void kernel_free(void *ptr) {
|
|
free_and_track(ptr);
|
|
}
|
|
|
|
void* kernel_calloc(size_t count, size_t size) {
|
|
return calloc_and_track(count, size, __builtin_return_address(0));
|
|
}
|
|
|
|
char* kernel_strdup(const char* s) {
|
|
char *r = malloc_and_track(strlen(s) + 1, __builtin_return_address(0));
|
|
if (!r) {
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(r, s);
|
|
return r;
|
|
}
|
|
|
|
char* kernel_strdup_check(const char* s) {
|
|
return kernel_strdup(s);
|
|
}
|
|
|
|
char* task_strdup(const char* s) {
|
|
return kernel_strdup(s);
|
|
}
|
|
|
|
void smart_free(void *ptr) {
|
|
free_and_track(ptr);
|
|
}
|