1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifdef HAVE_CONFIG_H1 |
15 | #include "config.h" |
16 | #endif |
17 | |
18 | #include <string.h> |
19 | #ifdef HAVE_STRINGS_H1 |
20 | #include <strings.h> |
21 | #endif |
22 | |
23 | #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ |
24 | #include <rtems.h> |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <inttypes.h> |
28 | |
29 | #include <rtems/monitor.h> |
30 | #include "symbols.h" |
31 | |
32 | |
33 | rtems_symbol_table_t * |
34 | rtems_symbol_table_create(void) |
35 | { |
36 | rtems_symbol_table_t *table; |
37 | |
38 | table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t)); |
39 | memset((void *) table, 0, sizeof(*table)); |
40 | |
41 | table->growth_factor = 30; |
42 | |
43 | return table; |
44 | } |
45 | |
46 | void |
47 | rtems_symbol_table_destroy(rtems_symbol_table_t *table) |
48 | { |
49 | rtems_symbol_string_block_t *p, *pnext; |
50 | |
51 | if (table) |
52 | { |
53 | if (table->addresses) |
54 | (void) free(table->addresses); |
55 | table->addresses = 0; |
56 | p = table->string_buffer_head; |
57 | while (p) |
58 | { |
59 | pnext = p->next; |
60 | free(p); |
61 | p = pnext; |
62 | } |
63 | table->string_buffer_head = 0; |
64 | table->string_buffer_current = 0; |
65 | |
66 | free(table); |
67 | } |
68 | } |
69 | |
70 | rtems_symbol_t * |
71 | rtems_symbol_create( |
72 | rtems_symbol_table_t *table, |
73 | const char *name, |
74 | uint32_t value |
75 | ) |
76 | { |
77 | size_t symbol_length; |
78 | size_t newsize; |
79 | rtems_symbol_t *sp; |
80 | |
81 | symbol_length = strlen(name) + 1; |
82 | |
83 | |
84 | if (table->next >= table->size) |
| |
85 | { |
86 | if (table->size == 0) |
| |
87 | newsize = 100; |
88 | else |
89 | newsize = table->size + (table->size / (100 / table->growth_factor)); |
90 | |
91 | table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t)); |
92 | if (table->addresses == 0) |
| |
93 | goto failed; |
94 | table->size = newsize; |
95 | } |
96 | |
97 | sp = &table->addresses[table->next]; |
98 | sp->value = value; |
99 | |
100 | |
101 | |
102 | |
103 | if ((table->string_buffer_head == 0) || |
| |
104 | (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE4080) |
105 | { |
106 | rtems_symbol_string_block_t *p; |
107 | |
108 | p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t)); |
109 | if (p == 0) |
| |
110 | goto failed; |
| 6 | Control jumps to line 133 |
|
111 | p->next = 0; |
112 | if (table->string_buffer_head == 0) |
113 | table->string_buffer_head = p; |
114 | else |
115 | table->string_buffer_current->next = p; |
116 | table->string_buffer_current = p; |
117 | |
118 | table->strings_next = 0; |
119 | } |
120 | |
121 | sp->name = table->string_buffer_current->buffer + table->strings_next; |
122 | (void) strcpy(sp->name, name); |
123 | |
124 | table->strings_next += symbol_length; |
125 | table->sorted = 0; |
126 | table->next++; |
127 | |
128 | return sp; |
129 | |
130 | |
131 | |
132 | failed: |
133 | return 0; |
| 7 | Allocated memory never released. Potential memory leak |
|
134 | } |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | static int |
141 | rtems_symbol_compare(const void *e1, |
142 | const void *e2) |
143 | { |
144 | rtems_symbol_t *s1, *s2; |
145 | s1 = (rtems_symbol_t *) e1; |
146 | s2 = (rtems_symbol_t *) e2; |
147 | |
148 | if (s1->value < s2->value) |
149 | return -1; |
150 | if (s1->value > s2->value) |
151 | return 1; |
152 | return 0; |
153 | } |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | static void |
161 | rtems_symbol_sort(rtems_symbol_table_t *table) |
162 | { |
163 | qsort((void *) table->addresses, (size_t) table->next, |
164 | sizeof(rtems_symbol_t), rtems_symbol_compare); |
165 | table->sorted = 1; |
166 | } |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | rtems_symbol_t * |
176 | rtems_symbol_value_lookup( |
177 | rtems_symbol_table_t *table, |
178 | uint32_t value |
179 | ) |
180 | { |
181 | rtems_symbol_t *sp; |
182 | rtems_symbol_t *base; |
183 | rtems_symbol_t *best = 0; |
184 | uint32_t distance; |
185 | uint32_t best_distance = ~0; |
186 | uint32_t elements; |
187 | |
188 | if (table == 0) |
189 | table = rtems_monitor_symbols; |
190 | |
191 | if ((table == 0) || (table->size == 0)) |
192 | return 0; |
193 | |
194 | if (table->sorted == 0) |
195 | rtems_symbol_sort(table); |
196 | |
197 | base = table->addresses; |
198 | elements = table->next; |
199 | |
200 | while (elements) |
201 | { |
202 | sp = base + (elements / 2); |
203 | if (value < sp->value) |
204 | elements /= 2; |
205 | else if (value > sp->value) |
206 | { |
207 | distance = value - sp->value; |
208 | if (distance < best_distance) |
209 | { |
210 | best_distance = distance; |
211 | best = sp; |
212 | } |
213 | base = sp + 1; |
214 | elements = (elements / 2) - (elements % 2 ? 0 : 1); |
215 | } |
216 | else |
217 | return sp; |
218 | } |
219 | |
220 | if (value == base->value) |
221 | return base; |
222 | |
223 | return best; |
224 | } |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | const rtems_symbol_t * |
238 | rtems_symbol_value_lookup_exact( |
239 | rtems_symbol_table_t *table, |
240 | uint32_t value |
241 | ) |
242 | { |
243 | uint32_t s; |
244 | rtems_symbol_t *sp; |
245 | |
246 | if (table == 0) |
247 | { |
248 | table = rtems_monitor_symbols; |
249 | if (table == 0) |
250 | return NULL((void*)0); |
251 | } |
252 | |
253 | if (table->sorted) |
254 | { |
255 | sp = rtems_symbol_value_lookup(table, value); |
256 | if ( rtems_symbol_value(sp)((sp)->value) == value ) |
257 | return sp; |
258 | else |
259 | return NULL((void*)0); |
260 | } |
261 | |
262 | for (s = 0, sp = table->addresses; s < table->next; s++, sp++) |
263 | { |
264 | if ( sp->value == value ) |
265 | return sp; |
266 | } |
267 | |
268 | return NULL((void*)0); |
269 | |
270 | } |
271 | |
272 | |
273 | |
274 | |
275 | |
276 | |
277 | rtems_symbol_t * |
278 | rtems_symbol_name_lookup( |
279 | rtems_symbol_table_t *table, |
280 | const char *name |
281 | ) |
282 | { |
283 | uint32_t s; |
284 | rtems_symbol_t *sp; |
285 | |
286 | if (table == 0) |
287 | { |
288 | table = rtems_monitor_symbols; |
289 | if (table == 0) |
290 | return NULL((void*)0); |
291 | } |
292 | |
293 | for (s = 0, sp = table->addresses; s < table->next; s++, sp++) |
294 | { |
295 | if ( strcasecmp(sp->name, name) == 0 ) |
296 | return sp; |
297 | } |
298 | |
299 | return NULL((void*)0); |
300 | } |
301 | |
302 | void * |
303 | rtems_monitor_symbol_next( |
304 | void *object_info, |
305 | rtems_monitor_symbol_t *canonical __attribute__((unused)), |
306 | rtems_id *next_id |
307 | ) |
308 | { |
309 | rtems_symbol_table_t *table; |
310 | uint32_t n = rtems_object_id_get_index(*next_id)_Objects_Get_index( *next_id ); |
311 | |
312 | table = *(rtems_symbol_table_t **) object_info; |
313 | if (table == 0) |
314 | goto failed; |
315 | |
316 | if (n >= table->next) |
317 | goto failed; |
318 | |
319 | |
320 | |
321 | if (table->sorted == 0) |
322 | rtems_symbol_sort(table); |
323 | |
324 | _Thread_Disable_dispatch(); |
325 | |
326 | *next_id += 1; |
327 | return (void *) (table->addresses + n); |
328 | |
329 | failed: |
330 | *next_id = RTEMS_OBJECT_ID_FINAL((Objects_Id)~0); |
331 | return 0; |
332 | } |
333 | |
334 | void |
335 | rtems_monitor_symbol_canonical( |
336 | rtems_monitor_symbol_t *canonical_symbol, |
337 | rtems_symbol_t *sp |
338 | ) |
339 | { |
340 | canonical_symbol->value = sp->value; |
341 | canonical_symbol->offset = 0; |
342 | strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1); |
343 | } |
344 | |
345 | |
346 | void |
347 | rtems_monitor_symbol_canonical_by_name( |
348 | rtems_monitor_symbol_t *canonical_symbol, |
349 | const char *name |
350 | ) |
351 | { |
352 | rtems_symbol_t *sp; |
353 | |
354 | sp = rtems_symbol_name_lookup(0, name); |
355 | |
356 | canonical_symbol->value = sp ? sp->value : 0; |
357 | |
358 | strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name) - 1); |
359 | canonical_symbol->offset = 0; |
360 | } |
361 | |
362 | void |
363 | rtems_monitor_symbol_canonical_by_value( |
364 | rtems_monitor_symbol_t *canonical_symbol, |
365 | void *value_void_p |
366 | ) |
367 | { |
368 | uintptr_t value = (uintptr_t) value_void_p; |
369 | rtems_symbol_t *sp; |
370 | |
371 | sp = rtems_symbol_value_lookup(0, value); |
372 | if (sp) |
373 | { |
374 | canonical_symbol->value = sp->value; |
375 | canonical_symbol->offset = value - sp->value; |
376 | strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1); |
377 | } |
378 | else |
379 | { |
380 | canonical_symbol->value = value; |
381 | canonical_symbol->offset = 0; |
382 | canonical_symbol->name[0] = '\0'; |
383 | } |
384 | } |
385 | |
386 | |
387 | uint32_t |
388 | rtems_monitor_symbol_dump( |
389 | rtems_monitor_symbol_t *canonical_symbol, |
390 | bool_Bool verbose |
391 | ) |
392 | { |
393 | uint32_t length = 0; |
394 | |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | if (canonical_symbol->name[0] && (canonical_symbol->value != 0)) |
401 | { |
402 | if (canonical_symbol->offset == 0) |
403 | length += fprintf(stdoutstdout,"%.*s", |
404 | (int) sizeof(canonical_symbol->name), |
405 | canonical_symbol->name); |
406 | else |
407 | length += fprintf(stdoutstdout,"<%.*s+0x%" PRIx32"x" ">", |
408 | (int) sizeof(canonical_symbol->name), |
409 | canonical_symbol->name, |
410 | canonical_symbol->offset); |
411 | if (verbose) |
412 | length += fprintf(stdoutstdout, |
413 | " [0x%" PRIx32"x" "]", canonical_symbol->value); |
414 | } |
415 | else |
416 | length += fprintf(stdoutstdout,"[0x%" PRIx32"x" "]", canonical_symbol->value); |
417 | |
418 | return length; |
419 | } |
420 | |
421 | |
422 | void |
423 | rtems_monitor_symbol_dump_all( |
424 | rtems_symbol_table_t *table, |
425 | bool_Bool verbose __attribute__((unused)) |
426 | ) |
427 | { |
428 | uint32_t s; |
429 | rtems_symbol_t *sp; |
430 | |
431 | if (table == 0) |
432 | { |
433 | table = rtems_monitor_symbols; |
434 | if (table == 0) |
435 | return; |
436 | } |
437 | |
438 | if (table->sorted == 0) |
439 | rtems_symbol_sort(table); |
440 | |
441 | for (s = 0, sp = table->addresses; s < table->next; s++, sp++) |
442 | { |
443 | rtems_monitor_symbol_t canonical_symbol; |
444 | |
445 | rtems_monitor_symbol_canonical(&canonical_symbol, sp); |
446 | rtems_monitor_symbol_dump(&canonical_symbol, true1); |
447 | fprintf(stdoutstdout,"\n"); |
448 | } |
449 | } |
450 | |
451 | |
452 | |
453 | |
454 | |
455 | |
456 | void rtems_monitor_symbol_cmd( |
457 | int argc, |
458 | char **argv, |
459 | const rtems_monitor_command_arg_t *command_arg, |
460 | bool_Bool verbose |
461 | ) |
462 | { |
463 | int arg; |
464 | rtems_symbol_table_t *table; |
465 | |
466 | table = *command_arg->symbol_table; |
467 | if (table == 0) |
468 | { |
469 | table = rtems_monitor_symbols; |
470 | if (table == 0) |
471 | return; |
472 | } |
473 | |
474 | |
475 | |
476 | |
477 | if (argc == 1) |
478 | rtems_monitor_symbol_dump_all(table, verbose); |
479 | else |
480 | { |
481 | rtems_monitor_symbol_t canonical_symbol; |
482 | |
483 | for (arg=1; argv[arg]; arg++) |
484 | { |
485 | rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]); |
486 | rtems_monitor_symbol_dump(&canonical_symbol, verbose); |
487 | fprintf(stdoutstdout,"\n"); |
488 | } |
489 | } |
490 | } |