Home | History | Annotate | Download | only in stub
      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