source: trunk/minix/commands/mdb/sym.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 10.3 KB
Line 
1/*
2 * sym.c for mdb
3 */
4
5#include "mdb.h"
6#include <fcntl.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11#include <a.out.h>
12#include "proto.h"
13
14#if GNU_SUPPORT
15#define ZMAGIC 0413
16#define NMAGIC 0410
17#define QMAGIC 0314
18#endif
19
20struct symtab_s
21{
22 struct nlist *start;
23 struct nlist *end;
24 int text;
25 int data;
26 unsigned nsym;
27};
28
29PRIVATE struct symtab_s symtab;
30PRIVATE int type_of_exec;
31
32FORWARD _PROTOTYPE( int check_exec, (struct exec *hdr) );
33FORWARD _PROTOTYPE( void sortsyms , (struct nlist *array , struct nlist *top ));
34FORWARD _PROTOTYPE( int symeq , (char *t , struct nlist *sp ));
35FORWARD _PROTOTYPE( int symprefix , (char *t , struct nlist *sp ));
36FORWARD _PROTOTYPE( struct nlist *findsname, (char *name, int is_text, int allflag) );
37FORWARD _PROTOTYPE( void outsym, (struct nlist *sp, off_t off) );
38FORWARD _PROTOTYPE( struct nlist *findsval, (off_t value, int where) );
39
40PUBLIC void syminit( filename )
41char *filename;
42{
43 int fd;
44 struct exec header;
45 register struct symtab_s *tp;
46
47 tp = &symtab;
48 if ( (fd = open( filename, O_RDONLY)) < 0) {
49 fprintf(stderr, "Couldn't open %s.\n", filename);
50 perror(filename);
51 exit(1);
52 }
53
54 if( read( fd, (char *) &header, sizeof header ) != sizeof header )
55 {
56 fprintf(stderr, "Couldn't read %d bytes from %s.\n", sizeof(header), filename);
57 close( fd );
58 exit(1);
59 }
60 type_of_exec = check_exec(&header);
61
62#if EXTRA_SYMBOLS
63 if ( type_of_exec == GNU_SYMBOLS) {
64 close(fd);
65 gnu_init(filename);
66 return;
67 }
68#endif
69
70 /* For MINIX EXEC */
71 if ( lseek( fd, A_SYMPOS( header ), 0 ) != A_SYMPOS( header ) )
72 {
73 do_error( "mdb - reading header" );
74 close( fd );
75 exit(1);
76 }
77 if ( (int) header.a_syms < 0 ||
78 (unsigned) header.a_syms != header.a_syms ||
79 (tp->start = (struct nlist *) malloc( (unsigned) header.a_syms ))
80 == (struct nlist *) NULL &&
81 header.a_syms != 0 )
82 {
83 Printf("mdb: no room for symbol table" );
84 close( fd );
85 return;
86 }
87 if ( read( fd, (char *) tp->start, (int) header.a_syms ) < 0 )
88 {
89 do_error( "mdb - reading symbol table" );
90 close( fd );
91 return;
92 }
93 close( fd );
94 tp->nsym = (unsigned) header.a_syms / sizeof (struct nlist);
95 tp->end = tp->start + tp->nsym;
96 tp->text = 0x07;
97 tp->data = 0x0F;
98
99 /* sort on value only, name search not used much and storage a problem */
100 Printf("Sorting %d MINIX symbols ....", tp->nsym );
101 sortsyms( tp->start, tp->end );
102 Printf("\n");
103}
104
105/* Check exec file
106 * return type of exec
107 * or exit
108 */
109PRIVATE int check_exec(hdr)
110struct exec *hdr;
111{
112long magic;
113
114 /* Check MAGIC number */
115 if (hdr->a_magic[0] != A_MAGIC0 || hdr->a_magic[1] != A_MAGIC1) {
116#if GNU_SUPPORT
117 memcpy(&magic, hdr, sizeof(long));
118 /* Clear bits */
119 magic &= 0xFFFF;
120
121 if ( magic == ZMAGIC || magic == QMAGIC ) {
122 is_separate = FALSE;
123 return GNU_SYMBOLS;
124 }
125 if ( magic == NMAGIC ) {
126 is_separate = TRUE;
127 return GNU_SYMBOLS;
128 }
129#endif
130 Printf("mdb: invalid magic number in exec header - %02x %02x\n",
131 hdr->a_magic[0],
132 hdr->a_magic[1]);
133 exit(1);
134 }
135
136 /* Check CPU */
137#if (CHIP == INTEL)
138#if (_WORD_SIZE == 4)
139 if (hdr->a_cpu != A_I80386)
140#else
141 if (hdr->a_cpu != A_I8086)
142#endif
143#endif
144#if (CHIP == M68000)
145 if (hdr->a_cpu != A_M68K)
146#endif
147 {
148 Printf("mdb: invalid cpu in exec header - %04x\n",
149 hdr->a_cpu);
150 exit(1);
151 }
152
153 is_separate = FALSE;
154#ifdef MINIX_PC
155 if (hdr->a_flags & A_SEP)
156 is_separate = TRUE;
157#endif
158/*
159 * A_EXEC is not being set by current cc
160 * It was set in Minix 1.5.0
161 */
162#if 0
163 /* Check flags - separate I & D or not */
164 if (hdr->a_flags & A_EXEC)
165 is_separate = FALSE;
166 else {
167 Printf("mdb: object file not exec %04x\n",
168 hdr->a_flags);
169 exit(1);
170 }
171#endif
172 return MINIX_SYMBOLS;
173}
174
175
176PUBLIC long symbolvalue( name, is_text )
177char *name;
178int is_text;
179{
180register struct nlist *sp;
181
182#if EXTRA_SYMBOLS
183 if ( type_of_exec == GNU_SYMBOLS )
184 return gnu_symbolvalue( name, is_text );
185#endif
186
187 /* For MINIX EXEC */
188 sp = findsname(name, is_text, 0);
189 if (sp != NULL)
190 return sp->n_value;
191 else
192 return 0L;
193}
194
195PRIVATE struct nlist *findsname( name, is_text, allflag )
196char *name;
197int is_text;
198int allflag;
199{
200 char *s;
201 unsigned char sclass;
202 int schar;
203 char *send;
204 register struct nlist *sp;
205 register struct symtab_s *tp;
206
207 tp = &symtab;
208 if ( allflag )
209 {
210 /* find and print all matching symbols */
211 for ( sp = tp->start; sp < tp->end; ++sp )
212 {
213 if ( symprefix( name, sp ) )
214 {
215 sp = sp;
216 for ( s = sp->n_name, send = s + sizeof sp->n_name;
217 *s != 0 && s < send; ++s )
218 outbyte( *s );
219 for ( ; s <= send; ++s )
220 outspace();
221 switch( sp->n_sclass & N_SECT )
222 {
223 case N_ABS: schar = 'a'; break;
224 case N_TEXT: schar = 't'; break;
225 case N_DATA: schar = 'd'; break;
226 case N_BSS: schar = 'b'; break;
227 default: schar = '?'; break;
228 }
229 if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
230 schar += 'A' - 'a';
231 outbyte( schar );
232 outspace();
233#if (_WORD_SIZE == 2)
234 outh16( (u16_t) sp->n_value );
235#else
236 outh32( sp->n_value );
237#endif
238 outbyte('\n');
239 }
240 }
241 }
242 else
243 {
244 /* find symbol by dumb linear search */
245 for ( sp = tp->start; sp < tp->end; ++sp )
246 {
247 sclass = sp->n_sclass & N_SECT;
248 if ( (is_text && sclass == N_TEXT ||
249 !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
250 symeq( name, sp ) )
251 return sp;
252 }
253 }
254 return NULL;
255}
256
257PRIVATE struct nlist *findsval( value, where )
258off_t value;
259int where;
260{
261 int left;
262 int middle;
263 int right;
264 unsigned char sclass;
265 register struct nlist *sp;
266 register struct symtab_s *tp;
267
268 tp = &symtab;
269
270 /* find last symbol with value <= desired one by binary search */
271 for ( left = 0, right = tp->nsym - 1; left <= right; )
272 {
273 middle = (left + right) / 2;
274 sp = tp->start + middle;
275 if ( value < sp->n_value )
276 right = middle - 1;
277 else
278 left = middle + 1;
279 }
280 if ( right >= 0 )
281 /* otherwise tp->start + right may wrap around to > tp->start !! */
282 for ( sp = tp->start + right; sp >= tp->start; --sp )
283 {
284 if ( (sp->n_sclass & N_CLASS) != C_EXT ) continue;
285 sclass = sp->n_sclass & N_SECT;
286 if ( (where == CSEG && sclass == N_TEXT ||
287 where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
288 return sp;
289 }
290 return NULL;
291}
292
293
294PUBLIC void printhex(v)
295off_t v;
296{
297 if ( v >= 65536L )
298 outh32( v );
299 else if ( v >= 256 )
300 outh16( (u16_t) v );
301 else
302 outh8( (u8_t) v );
303}
304
305
306PRIVATE void outsym( sp, off )
307struct nlist *sp;
308off_t off;
309{
310 register char *s;
311 char *send;
312
313 for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
314 outbyte( *s );
315 if ( (off -= sp->n_value) != 0 )
316 {
317 outbyte( '+' );
318 printhex(off);
319 }
320}
321
322/* shell sort symbols on value */
323
324PRIVATE void sortsyms( array, top )
325struct nlist *array;
326struct nlist *top;
327{
328 int gap;
329 int i;
330 int j;
331 register struct nlist *left;
332 register struct nlist *right;
333 struct nlist swaptemp;
334 int size;
335
336 size = top - array;
337 /* choose gaps according to Knuth V3 p95 */
338 for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
339 ;
340 do
341 {
342 for ( j = gap; j < size; ++j )
343 for ( i = j - gap; i >= 0; i -= gap )
344 {
345 left = array + i;
346 right = array + (i + gap);
347 if ( (off_t) left->n_value <=
348 right->n_value )
349 break;
350 swaptemp = *left;
351 *left = *right;
352 *right = swaptemp;
353 }
354 }
355 while ( (gap /= 3) != 0 );
356}
357
358PUBLIC void symbolic( value, separator )
359off_t value;
360int separator;
361{
362 register struct nlist *sp;
363 long off;
364
365#if EXTRA_SYMBOLS
366 if ( type_of_exec == GNU_SYMBOLS ) {
367 gnu_symbolic( value, separator );
368 return;
369 }
370#endif
371
372 /* For MINIX EXEC */
373
374 if (value < st_addr || value > end_addr) {
375 outstr("0x");
376 printhex(value);
377 outbyte(separator);
378 return;
379 }
380
381 if ( (sp = findsval( value, CSEG )) != NULL )
382 {
383 outsym( sp, value );
384 }
385 else if ( (sp = findsval( value, DSEG )) != NULL )
386 {
387 outsym( sp, value );
388 }
389 else
390 {
391 outstr("_start");
392 off = value - st_addr;
393 if ( off != 0 )
394 {
395 outbyte( '+' );
396 printhex(off);
397 }
398 }
399 outbyte( separator );
400}
401
402
403PRIVATE int symeq( t, sp )
404register char *t;
405struct nlist *sp;
406{
407 return strncmp( t, sp->n_name, sizeof sp->n_name ) == 0;
408}
409
410PRIVATE int symprefix( t, sp )
411register char *t;
412struct nlist *sp;
413{
414 register char *s;
415 char *send;
416
417 for ( ; *t == '_'; ++t )
418 ;
419 for ( s = sp->n_name, send = s + sizeof sp->n_name;
420 s < send && *s == '_'; ++s )
421 ;
422 return strncmp( s, t, (size_t)(send - s) ) == 0;
423}
424
425
426
427/* list all symbols - test for selection criteria */
428
429PUBLIC void listsym(cmd)
430char *cmd;
431{
432 register struct symtab_s *tp;
433 register struct nlist *sp;
434 char *s;
435 char *send;
436 char schar;
437 char tchar;
438
439 /* set selection */
440 cmd = skip(cmd+1);
441 if( *cmd == '\n' || *cmd == ';' )
442 tchar = '*';
443 else
444 tchar = *cmd;
445
446#if EXTRA_SYMBOLS
447 if ( type_of_exec == GNU_SYMBOLS ) {
448 gnu_listsym(tchar);
449 return;
450 }
451#endif
452
453 /* For MINIX EXEC */
454
455 tp = &symtab;
456 for ( sp = tp->start; sp < tp->end; ++sp )
457 {
458 switch( sp->n_sclass & N_SECT )
459 {
460 case N_ABS: schar = 'a'; break;
461 case N_TEXT: schar = 't'; break;
462 case N_DATA: schar = 'd'; break;
463 case N_BSS: schar = 'b'; break;
464 default: schar = '?'; break;
465 }
466
467 if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
468 schar += 'A' - 'a';
469
470 /* check for selection */
471 if ( tchar != '*' && schar != tchar)
472 continue;
473
474 /* print symbol type and value */
475 for ( s = sp->n_name, send = s + sizeof sp->n_name;
476 *s != 0 && s < send; ++s ) outbyte( *s );
477 for ( ; s <= send; ++s ) outspace();
478 outbyte( schar );
479 outspace();
480#if (_WORD_SIZE == 2)
481 outh16( (u16_t) sp->n_value );
482#else
483 outh32( sp->n_value );
484#endif
485 outbyte('\n');
486 }
487}
488
489
490PUBLIC int text_symbol(value)
491off_t value;
492{
493struct nlist *sp;
494
495#if EXTRA_SYMBOLS
496 if ( type_of_exec == GNU_SYMBOLS )
497 return gnu_text_symbol(value);
498#endif
499
500 if ((sp = findsval(value, CSEG)) != NULL && sp->n_value == value)
501 {
502 outsym(sp, value);
503 return TRUE;
504 }
505 else
506 return FALSE;
507}
508
509PUBLIC int finds_data(off,data_seg)
510off_t off;
511int data_seg;
512{
513struct nlist *sp;
514
515#if EXTRA_SYMBOLS
516 if ( type_of_exec == GNU_SYMBOLS )
517 return gnu_finds_data(off,data_seg);
518#endif
519
520 if ((sp = findsval(off, data_seg)) != NULL)
521 {
522 outsym(sp, off);
523 return TRUE;
524 }
525 else
526 return FALSE;
527}
528
529PUBLIC int finds_pc(pc)
530off_t pc;
531{
532struct nlist *sp;
533
534#if EXTRA_SYMBOLS
535 if ( type_of_exec == GNU_SYMBOLS )
536 return gnu_finds_pc(pc);
537#endif
538
539 if ((sp = findsval(pc, CSEG)) != NULL)
540 {
541 outsym(sp, pc);
542 return TRUE;
543 }
544 else
545 return FALSE;
546}
Note: See TracBrowser for help on using the repository browser.