1 /* MSPDebug - debugging tool for the eZ430
2 * Copyright (C) 2009, 2010 Daniel Beer
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <stdint.h>
24 #include <regex.h>
25 #include <assert.h>
26 #include "btree.h"
27 #include "stab.h"
28 #include "util.h"
29 #include "output.h"
30
31 /************************************************************************
32 * B+Tree definitions
33 */
34
35 struct sym_key {
36 char name[MAX_SYMBOL_LENGTH];
37 };
38
39 static const struct sym_key sym_key_zero = {
40 .name = {0}
41 };
42
sym_key_compare(const void * left,const void * right)43 static int sym_key_compare(const void *left, const void *right)
44 {
45 return strcmp(((const struct sym_key *)left)->name,
46 ((const struct sym_key *)right)->name);
47 }
48
sym_key_init(struct sym_key * key,const char * text)49 static void sym_key_init(struct sym_key *key, const char *text)
50 {
51 int len = strlen(text);
52
53 if (len >= sizeof(key->name))
54 len = sizeof(key->name) - 1;
55
56 memcpy(key->name, text, len);
57 key->name[len] = 0;
58 }
59
60 struct addr_key {
61 address_t addr;
62 char name[MAX_SYMBOL_LENGTH];
63 };
64
65 static const struct addr_key addr_key_zero = {
66 .addr = 0,
67 .name = {0}
68 };
69
addr_key_compare(const void * left,const void * right)70 static int addr_key_compare(const void *left, const void *right)
71 {
72 const struct addr_key *kl = (const struct addr_key *)left;
73 const struct addr_key *kr = (const struct addr_key *)right;
74
75 if (kl->addr < kr->addr)
76 return -1;
77 if (kl->addr > kr->addr)
78 return 1;
79
80 return strcmp(kl->name, kr->name);
81 }
82
addr_key_init(struct addr_key * key,address_t addr,const char * text)83 static void addr_key_init(struct addr_key *key, address_t addr,
84 const char *text)
85 {
86 int len = strlen(text);
87
88 if (len >= sizeof(key->name))
89 len = sizeof(key->name) - 1;
90
91 key->addr = addr;
92 memcpy(key->name, text, len);
93 key->name[len] = 0;
94 }
95
96 static const struct btree_def sym_table_def = {
97 .compare = sym_key_compare,
98 .zero = &sym_key_zero,
99 .branches = 32,
100 .key_size = sizeof(struct sym_key),
101 .data_size = sizeof(address_t)
102 };
103
104 static const struct btree_def addr_table_def = {
105 .compare = addr_key_compare,
106 .zero = &addr_key_zero,
107 .branches = 32,
108 .key_size = sizeof(struct addr_key),
109 .data_size = 0
110 };
111
112 /************************************************************************
113 * Symbol table methods
114 */
115
116 static btree_t stab_sym;
117 static btree_t stab_addr;
118
stab_clear(void)119 void stab_clear(void)
120 {
121 btree_clear(stab_sym);
122 btree_clear(stab_addr);
123 }
124
stab_set(const char * name,int value)125 int stab_set(const char *name, int value)
126 {
127 struct sym_key skey;
128 struct addr_key akey;
129 address_t addr = value;
130 address_t old_addr;
131
132 sym_key_init(&skey, name);
133
134 /* Look for an old address first, and delete the reverse mapping
135 * if it's there.
136 */
137 if (!btree_get(stab_sym, &skey, &old_addr)) {
138 addr_key_init(&akey, old_addr, skey.name);
139 btree_delete(stab_addr, &akey);
140 }
141
142 /* Put the new mapping into both tables */
143 addr_key_init(&akey, addr, name);
144 if (btree_put(stab_addr, &akey, NULL) < 0 ||
145 btree_put(stab_sym, &skey, &addr) < 0) {
146 printc_err("stab: can't set %s = 0x%04x\n", name, addr);
147 return -1;
148 }
149
150 return 0;
151 }
152
stab_nearest(address_t addr,char * ret_name,int max_len,address_t * ret_offset)153 int stab_nearest(address_t addr, char *ret_name, int max_len,
154 address_t *ret_offset)
155 {
156 struct addr_key akey;
157 int i;
158
159 akey.addr = addr;
160 for (i = 0; i < sizeof(akey.name); i++)
161 akey.name[i] = 0xff;
162 akey.name[sizeof(akey.name) - 1] = 0xff;
163
164 if (!btree_select(stab_addr, &akey, BTREE_LE, &akey, NULL)) {
165 strncpy(ret_name, akey.name, max_len);
166 ret_name[max_len - 1] = 0;
167 *ret_offset = addr - akey.addr;
168 return 0;
169 }
170
171 return -1;
172 }
173
stab_get(const char * name,address_t * value)174 int stab_get(const char *name, address_t *value)
175 {
176 struct sym_key skey;
177 address_t addr;
178
179 sym_key_init(&skey, name);
180 if (btree_get(stab_sym, &skey, &addr))
181 return -1;
182
183 *value = addr;
184 return 0;
185 }
186
stab_del(const char * name)187 int stab_del(const char *name)
188 {
189 struct sym_key skey;
190 address_t value;
191 struct addr_key akey;
192
193 sym_key_init(&skey, name);
194 if (btree_get(stab_sym, &skey, &value))
195 return -1;
196
197 addr_key_init(&akey, value, name);
198 btree_delete(stab_sym, &skey);
199 btree_delete(stab_addr, &akey);
200
201 return 0;
202 }
203
stab_enum(stab_callback_t cb,void * user_data)204 int stab_enum(stab_callback_t cb, void *user_data)
205 {
206 int ret;
207 struct addr_key akey;
208
209 ret = btree_select(stab_addr, NULL, BTREE_FIRST,
210 &akey, NULL);
211 while (!ret) {
212 if (cb(user_data, akey.name, akey.addr) < 0)
213 return -1;
214 ret = btree_select(stab_addr, NULL, BTREE_NEXT,
215 &akey, NULL);
216 }
217
218 return 0;
219 }
220
stab_init(void)221 int stab_init(void)
222 {
223 stab_sym = btree_alloc(&sym_table_def);
224 if (!stab_sym) {
225 printc_err("stab: failed to allocate symbol table\n");
226 return -1;
227 }
228
229 stab_addr = btree_alloc(&addr_table_def);
230 if (!stab_addr) {
231 printc_err("stab: failed to allocate address table\n");
232 btree_free(stab_sym);
233 return -1;
234 }
235
236 return 0;
237 }
238
stab_exit(void)239 void stab_exit(void)
240 {
241 btree_free(stab_sym);
242 btree_free(stab_addr);
243 }
244