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
print_stacktrace(void)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
VbExMalloc(size_t size)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
find_node(void * ptr)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
VbExFree(void * ptr)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
VbExHashFirmwareBody(VbCommonParams * cparams,uint32_t firmware_index)99 VbError_t VbExHashFirmwareBody(VbCommonParams *cparams,
100 uint32_t firmware_index)
101 {
102 return VBERROR_SUCCESS;
103 }
104
vboot_api_stub_check_memory(void)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