-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsymbols.c
More file actions
136 lines (119 loc) · 3.88 KB
/
symbols.c
File metadata and controls
136 lines (119 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/******************************************/
#include "splinter.h"
/******************************************/
#define SYMBOLS_NAME_LENGTH (64 - sizeof(void *) - uint_s - 1)
struct __symbol_t {
struct __symbol_t * next;
uint_t address;
char name[SYMBOLS_NAME_LENGTH + 1];
};
typedef struct __symbol_t symbol_t;
typedef symbol_t * symbol_p;
#define symbol_s sizeof(symbol_t)
uint_t stats_symbols_total;
uint_t stats_symbols_free;
uint_t stats_symbols_used;
uint_t stats_symbols_total_bytes;
uint_t stats_symbols_free_bytes;
uint_t stats_symbols_used_bytes;
uint_t stats_symbols_hash_size;
uint_t stats_symbols_hash_bytes;
static symbol_p __symbols_buffer = NULL;
static symbol_p __symbols_free = NULL;
#define SYMBOLS_HASH_LENGTH 256
static symbol_p __symbols_hashtable[SYMBOLS_HASH_LENGTH];
//
// A naive java.lang.String hash implementation in C
// s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
//
static uint_t __string_hash(char * s) {
char * r;
uint_t h = 0, x = 1, len = strlen(s);
for(r = s + len - 1; r >= s; x *= 31)
h += ((uint_t)(*r--)) * x;
return h;
}
static symbol_p * __symbol_find(char * s) {
symbol_p curr;
symbol_p * prev;
uint_t h = __string_hash(s) & (SYMBOLS_HASH_LENGTH - 1);
DEBUG("symbol [%s] -> hash [%lu]", s, h);
prev = &__symbols_hashtable[h];
for(curr = *prev; curr; curr = *prev) {
if (strcmp(s, curr->name) == 0) break;
prev = &(curr->next);
}
return prev;
}
static symbol_p __symbol_alloc(symbol_p * dst, char * s, uint_t address) {
symbol_p sym;
uint_t len;
DEBUG();
if (dst == NULL || *dst != NULL || s == NULL || __symbols_free == NULL) return NULL;
if ((len = strlen(s)) > SYMBOLS_NAME_LENGTH) {
debug(DEBUG_ERR, "symbol name [%s] too long", s);
return NULL;
}
sym = __symbols_free;
__symbols_free = sym->next;
sym->next = NULL;
*dst = sym;
strcpy(sym->name, s);
sym->address = address;
debug(DEBUG_INF, "[%s] added to hash as [%lx]", s, address);
stats_symbols_free -= 1;
stats_symbols_free_bytes -= symbol_s;
stats_symbols_used += 1;
stats_symbols_used_bytes += symbol_s;
return sym;
}
uint_t splinter_get_symbol(char * s) {
symbol_p * sym;
uint_t address = 0;
DEBUG("looking up [%s]", s);
if (!s || !*s || __symbols_buffer == NULL) return address;
sym = __symbol_find(s);
if (*sym) {
debug(DEBUG_INF, "[%s] found in hash", s);
return (*sym)->address;
}
address = splinter_find_symbol(s);
if (!address) {
debug(DEBUG_ERR, "[%s] not found in hash", s);
return address;
}
__symbol_alloc(sym, s, address);
return address;
}
int symbols_init(uint_t n) {
uint_t i;
debug(DEBUG_INF, "size = %lu", n);
if (!n) return symbols_cleanup();
if (__symbols_buffer) return -1;
__symbols_free = __symbols_buffer = splinter_memory_alloc(n * symbol_s);
if (__symbols_buffer == NULL) {
debug(DEBUG_ERR, "could not alloc symbols buffer");
return -1;
}
for(i = 0; i < n - 1; i++) {
__symbols_buffer[i].next = &__symbols_buffer[i + 1];
}
memset(__symbols_hashtable, 0, SYMBOLS_HASH_LENGTH * sizeof(symbol_p));
stats_symbols_total = stats_symbols_free = n;
stats_symbols_total_bytes = stats_symbols_free_bytes = n * symbol_s;
stats_symbols_used = stats_symbols_used_bytes = 0;
stats_symbols_hash_size = SYMBOLS_HASH_LENGTH;
stats_symbols_hash_bytes = SYMBOLS_HASH_LENGTH * sizeof(symbol_p);
debug(DEBUG_DBG, "symbols buffer = %p - %p", __symbols_buffer, ((byte_p)__symbols_buffer) + n * symbol_s);
return 0;
}
int symbols_cleanup(void) {
if (__symbols_buffer == NULL) return -1;
DEBUG();
__symbols_free = __symbols_buffer = splinter_memory_free(__symbols_buffer);
memset(__symbols_hashtable, 0, SYMBOLS_HASH_LENGTH * sizeof(symbol_p));
stats_symbols_total = stats_symbols_free = stats_symbols_used =
stats_symbols_total_bytes = stats_symbols_free_bytes = stats_symbols_used_bytes = 0;
stats_symbols_hash_size = stats_symbols_hash_bytes = 0;
return 0;
}