/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Stub implementations of firmware-provided API functions. */ #include <execinfo.h> #include <stdint.h> #define _STUB_IMPLEMENTATION_ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include "vboot_api.h" #define MAX_STACK_LEVELS 10 /* Keep track of nodes that are currently allocated */ struct alloc_node { struct alloc_node *next; void *ptr; size_t size; void *bt_buffer[MAX_STACK_LEVELS]; int bt_levels; }; static struct alloc_node *alloc_head; static void print_stacktrace(void) { void *buffer[MAX_STACK_LEVELS]; int levels = backtrace(buffer, MAX_STACK_LEVELS); // print to stderr (fd = 2), and remove this function from the trace backtrace_symbols_fd(buffer + 1, levels - 1, 2); } void *VbExMalloc(size_t size) { struct alloc_node *node; void *p = malloc(size); if (!p) { /* Fatal Error. We must abort. */ abort(); } node = malloc(sizeof(*node)); if (!node) abort(); node->next = alloc_head; node->ptr = p; node->size = size; node->bt_levels = backtrace(node->bt_buffer, MAX_STACK_LEVELS); alloc_head = node; return p; } static struct alloc_node **find_node(void *ptr) { struct alloc_node **nodep; for (nodep = &alloc_head; *nodep; nodep = &(*nodep)->next) if ((*nodep)->ptr == ptr) return nodep; return NULL; } void VbExFree(void *ptr) { struct alloc_node **nodep, *next; nodep = find_node(ptr); if (nodep) { next = (*nodep)->next; free(*nodep); *nodep = next; } else { fprintf(stderr, "\n>>>>>> Invalid VbExFree() %p\n", ptr); fflush(stderr); print_stacktrace(); /* * Fall through and do the free() so we get normal error * handling. */ } free(ptr); } VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, uint32_t firmware_index) { return VBERROR_SUCCESS; } int vboot_api_stub_check_memory(void) { struct alloc_node *node, *next; if (!alloc_head) return 0; /* * Make sure we free all our memory so that valgrind doesn't complain * about leaked memory. */ fprintf(stderr, "\nWarning, some allocations not freed:"); for (node = alloc_head; node; node = next) { next = node->next; fprintf(stderr, "\nptr=%p, size=%zd\n", node->ptr, node->size); fflush(stderr); backtrace_symbols_fd(node->bt_buffer + 1, node->bt_levels - 1, 2); free(node); } return -1; }