1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 * 5 * Stub implementations of firmware-provided API functions. 6 */ 7 8 #include <execinfo.h> 9 #include <stdint.h> 10 11 #define _STUB_IMPLEMENTATION_ 12 13 #include <stdarg.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/time.h> 18 19 #include "vboot_api.h" 20 21 #define MAX_STACK_LEVELS 10 22 23 24 /* Keep track of nodes that are currently allocated */ 25 struct alloc_node { 26 struct alloc_node *next; 27 void *ptr; 28 size_t size; 29 void *bt_buffer[MAX_STACK_LEVELS]; 30 int bt_levels; 31 }; 32 33 static struct alloc_node *alloc_head; 34 35 static void print_stacktrace(void) 36 { 37 void *buffer[MAX_STACK_LEVELS]; 38 int levels = backtrace(buffer, MAX_STACK_LEVELS); 39 40 // print to stderr (fd = 2), and remove this function from the trace 41 backtrace_symbols_fd(buffer + 1, levels - 1, 2); 42 } 43 44 void *VbExMalloc(size_t size) 45 { 46 struct alloc_node *node; 47 void *p = malloc(size); 48 49 if (!p) { 50 /* Fatal Error. We must abort. */ 51 abort(); 52 } 53 54 node = malloc(sizeof(*node)); 55 if (!node) 56 abort(); 57 node->next = alloc_head; 58 node->ptr = p; 59 node->size = size; 60 node->bt_levels = backtrace(node->bt_buffer, MAX_STACK_LEVELS); 61 alloc_head = node; 62 63 return p; 64 } 65 66 static struct alloc_node **find_node(void *ptr) 67 { 68 struct alloc_node **nodep; 69 70 for (nodep = &alloc_head; *nodep; nodep = &(*nodep)->next) 71 if ((*nodep)->ptr == ptr) 72 return nodep; 73 74 return NULL; 75 } 76 77 void VbExFree(void *ptr) 78 { 79 struct alloc_node **nodep, *next; 80 81 nodep = find_node(ptr); 82 if (nodep) { 83 next = (*nodep)->next; 84 free(*nodep); 85 *nodep = next; 86 } else { 87 fprintf(stderr, "\n>>>>>> Invalid VbExFree() %p\n", ptr); 88 fflush(stderr); 89 print_stacktrace(); 90 /* 91 * Fall through and do the free() so we get normal error 92 * handling. 93 */ 94 } 95 96 free(ptr); 97 } 98 99 VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, 100 uint32_t firmware_index) 101 { 102 return VBERROR_SUCCESS; 103 } 104 105 int vboot_api_stub_check_memory(void) 106 { 107 struct alloc_node *node, *next; 108 109 if (!alloc_head) 110 return 0; 111 112 /* 113 * Make sure we free all our memory so that valgrind doesn't complain 114 * about leaked memory. 115 */ 116 fprintf(stderr, "\nWarning, some allocations not freed:"); 117 for (node = alloc_head; node; node = next) { 118 next = node->next; 119 fprintf(stderr, "\nptr=%p, size=%zd\n", node->ptr, node->size); 120 fflush(stderr); 121 backtrace_symbols_fd(node->bt_buffer + 1, node->bt_levels - 1, 122 2); 123 free(node); 124 } 125 126 return -1; 127 } 128