pci: don't do sanity check for missing pci bus, the check can misfire.
[minix.git] / commands / mdb / sym.c
blobaca50467435969ee1d8edd99a26d95a68b5654b2
1 /*
2 * sym.c for mdb
3 */
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"
14 struct symtab_s
16 struct nlist *start;
17 struct nlist *end;
18 int text;
19 int data;
20 unsigned nsym;
23 PRIVATE struct symtab_s symtab;
24 PRIVATE int type_of_exec;
26 FORWARD _PROTOTYPE( int check_exec, (struct exec *hdr) );
27 FORWARD _PROTOTYPE( void sortsyms , (struct nlist *array , struct nlist *top ));
28 FORWARD _PROTOTYPE( int symeq , (char *t , struct nlist *sp ));
29 FORWARD _PROTOTYPE( int symprefix , (char *t , struct nlist *sp ));
30 FORWARD _PROTOTYPE( struct nlist *findsname, (char *name, int is_text, int allflag) );
31 FORWARD _PROTOTYPE( void outsym, (struct nlist *sp, off_t off) );
32 FORWARD _PROTOTYPE( struct nlist *findsval, (off_t value, int where) );
34 PUBLIC void syminit( filename )
35 char *filename;
37 int fd;
38 struct exec header;
39 register struct symtab_s *tp;
41 tp = &symtab;
42 if ( (fd = open( filename, O_RDONLY)) < 0) {
43 fprintf(stderr, "Couldn't open %s.\n", filename);
44 perror(filename);
45 exit(1);
48 if( read( fd, (char *) &header, sizeof header ) != sizeof header )
50 fprintf(stderr, "Couldn't read %d bytes from %s.\n", sizeof(header), filename);
51 close( fd );
52 exit(1);
54 type_of_exec = check_exec(&header);
56 #if EXTRA_SYMBOLS
57 if ( type_of_exec == GNU_SYMBOLS) {
58 close(fd);
59 gnu_init(filename);
60 return;
62 #endif
64 /* For MINIX EXEC */
65 if ( lseek( fd, A_SYMPOS( header ), 0 ) != A_SYMPOS( header ) )
67 do_error( "mdb - reading header" );
68 close( fd );
69 exit(1);
71 if ( (int) header.a_syms < 0 ||
72 (unsigned) header.a_syms != header.a_syms ||
73 (tp->start = (struct nlist *) malloc( (unsigned) header.a_syms ))
74 == (struct nlist *) NULL &&
75 header.a_syms != 0 )
77 Printf("mdb: no room for symbol table" );
78 close( fd );
79 return;
81 if ( read( fd, (char *) tp->start, (int) header.a_syms ) < 0 )
83 do_error( "mdb - reading symbol table" );
84 close( fd );
85 return;
87 close( fd );
88 tp->nsym = (unsigned) header.a_syms / sizeof (struct nlist);
89 tp->end = tp->start + tp->nsym;
90 tp->text = 0x07;
91 tp->data = 0x0F;
93 /* sort on value only, name search not used much and storage a problem */
94 Printf("Sorting %d MINIX symbols ....", tp->nsym );
95 sortsyms( tp->start, tp->end );
96 Printf("\n");
99 /* Check exec file
100 * return type of exec
101 * or exit
103 PRIVATE int check_exec(hdr)
104 struct exec *hdr;
106 long magic;
108 /* Check MAGIC number */
109 if (hdr->a_magic[0] != A_MAGIC0 || hdr->a_magic[1] != A_MAGIC1) {
110 Printf("mdb: invalid magic number in exec header - %02x %02x\n",
111 hdr->a_magic[0],
112 hdr->a_magic[1]);
113 exit(1);
116 /* Check CPU */
117 #if (CHIP == INTEL)
118 #if (_WORD_SIZE == 4)
119 if (hdr->a_cpu != A_I80386)
120 #else
121 if (hdr->a_cpu != A_I8086)
122 #endif
123 #endif
124 #if (CHIP == M68000)
125 if (hdr->a_cpu != A_M68K)
126 #endif
128 Printf("mdb: invalid cpu in exec header - %04x\n",
129 hdr->a_cpu);
130 exit(1);
133 is_separate = FALSE;
134 #ifdef MINIX_PC
135 if (hdr->a_flags & A_SEP)
136 is_separate = TRUE;
137 #endif
139 #if GNU_SUPPORT
140 if (hdr->a_flags & A_NSYM)
141 return GNU_SYMBOLS;
142 #endif
145 * A_EXEC is not being set by current cc
146 * It was set in Minix 1.5.0
148 #if 0
149 /* Check flags - separate I & D or not */
150 if (hdr->a_flags & A_EXEC)
151 is_separate = FALSE;
152 else {
153 Printf("mdb: object file not exec %04x\n",
154 hdr->a_flags);
155 exit(1);
157 #endif
158 return MINIX_SYMBOLS;
162 PUBLIC long symbolvalue( name, is_text )
163 char *name;
164 int is_text;
166 register struct nlist *sp;
168 #if EXTRA_SYMBOLS
169 if ( type_of_exec == GNU_SYMBOLS )
170 return gnu_symbolvalue( name, is_text );
171 #endif
173 /* For MINIX EXEC */
174 sp = findsname(name, is_text, 0);
175 if (sp != NULL)
176 return sp->n_value;
177 else
178 return 0L;
181 PRIVATE struct nlist *findsname( name, is_text, allflag )
182 char *name;
183 int is_text;
184 int allflag;
186 char *s;
187 unsigned char sclass;
188 int schar;
189 char *send;
190 register struct nlist *sp;
191 register struct symtab_s *tp;
193 tp = &symtab;
194 if ( allflag )
196 /* find and print all matching symbols */
197 for ( sp = tp->start; sp < tp->end; ++sp )
199 if ( symprefix( name, sp ) )
201 sp = sp;
202 for ( s = sp->n_name, send = s + sizeof sp->n_name;
203 *s != 0 && s < send; ++s )
204 outbyte( *s );
205 for ( ; s <= send; ++s )
206 outspace();
207 switch( sp->n_sclass & N_SECT )
209 case N_ABS: schar = 'a'; break;
210 case N_TEXT: schar = 't'; break;
211 case N_DATA: schar = 'd'; break;
212 case N_BSS: schar = 'b'; break;
213 default: schar = '?'; break;
215 if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
216 schar += 'A' - 'a';
217 outbyte( schar );
218 outspace();
219 #if (_WORD_SIZE == 2)
220 outh16( (u16_t) sp->n_value );
221 #else
222 outh32( sp->n_value );
223 #endif
224 outbyte('\n');
228 else
230 /* find symbol by dumb linear search */
231 for ( sp = tp->start; sp < tp->end; ++sp )
233 sclass = sp->n_sclass & N_SECT;
234 if ( (is_text && sclass == N_TEXT ||
235 !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
236 symeq( name, sp ) )
237 return sp;
240 return NULL;
243 PRIVATE struct nlist *findsval( value, where )
244 off_t value;
245 int where;
247 int left;
248 int middle;
249 int right;
250 unsigned char sclass;
251 register struct nlist *sp;
252 register struct symtab_s *tp;
254 tp = &symtab;
256 /* find last symbol with value <= desired one by binary search */
257 for ( left = 0, right = tp->nsym - 1; left <= right; )
259 middle = (left + right) / 2;
260 sp = tp->start + middle;
261 if ( value < sp->n_value )
262 right = middle - 1;
263 else
264 left = middle + 1;
266 if ( right >= 0 )
267 /* otherwise tp->start + right may wrap around to > tp->start !! */
268 for ( sp = tp->start + right; sp >= tp->start; --sp )
270 if ( (sp->n_sclass & N_CLASS) != C_EXT ) continue;
271 sclass = sp->n_sclass & N_SECT;
272 if ( (where == CSEG && sclass == N_TEXT ||
273 where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
274 return sp;
276 return NULL;
280 PUBLIC void printhex(v)
281 off_t v;
283 if ( v >= 65536L )
284 outh32( v );
285 else if ( v >= 256 )
286 outh16( (u16_t) v );
287 else
288 outh8( (u8_t) v );
292 PRIVATE void outsym( sp, off )
293 struct nlist *sp;
294 off_t off;
296 register char *s;
297 char *send;
299 for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
300 outbyte( *s );
301 if ( (off -= sp->n_value) != 0 )
303 outbyte( '+' );
304 printhex(off);
308 /* shell sort symbols on value */
310 PRIVATE void sortsyms( array, top )
311 struct nlist *array;
312 struct nlist *top;
314 int gap;
315 int i;
316 int j;
317 register struct nlist *left;
318 register struct nlist *right;
319 struct nlist swaptemp;
320 int size;
322 size = top - array;
323 /* choose gaps according to Knuth V3 p95 */
324 for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
328 for ( j = gap; j < size; ++j )
329 for ( i = j - gap; i >= 0; i -= gap )
331 left = array + i;
332 right = array + (i + gap);
333 if ( (off_t) left->n_value <=
334 right->n_value )
335 break;
336 swaptemp = *left;
337 *left = *right;
338 *right = swaptemp;
341 while ( (gap /= 3) != 0 );
344 PUBLIC void symbolic( value, separator )
345 off_t value;
346 int separator;
348 register struct nlist *sp;
349 long off;
351 #if EXTRA_SYMBOLS
352 if ( type_of_exec == GNU_SYMBOLS ) {
353 gnu_symbolic( value, separator );
354 return;
356 #endif
358 /* For MINIX EXEC */
360 if (value < st_addr || value > end_addr) {
361 outstr("0x");
362 printhex(value);
363 outbyte(separator);
364 return;
367 if ( (sp = findsval( value, CSEG )) != NULL )
369 outsym( sp, value );
371 else if ( (sp = findsval( value, DSEG )) != NULL )
373 outsym( sp, value );
375 else
377 outstr("_start");
378 off = value - st_addr;
379 if ( off != 0 )
381 outbyte( '+' );
382 printhex(off);
385 outbyte( separator );
389 PRIVATE int symeq( t, sp )
390 register char *t;
391 struct nlist *sp;
393 return strncmp( t, sp->n_name, sizeof sp->n_name ) == 0;
396 PRIVATE int symprefix( t, sp )
397 register char *t;
398 struct nlist *sp;
400 register char *s;
401 char *send;
403 for ( ; *t == '_'; ++t )
405 for ( s = sp->n_name, send = s + sizeof sp->n_name;
406 s < send && *s == '_'; ++s )
408 return strncmp( s, t, (size_t)(send - s) ) == 0;
413 /* list all symbols - test for selection criteria */
415 PUBLIC void listsym(cmd)
416 char *cmd;
418 register struct symtab_s *tp;
419 register struct nlist *sp;
420 char *s;
421 char *send;
422 char schar;
423 char tchar;
425 /* set selection */
426 cmd = skip(cmd+1);
427 if( *cmd == '\n' || *cmd == ';' )
428 tchar = '*';
429 else
430 tchar = *cmd;
432 #if EXTRA_SYMBOLS
433 if ( type_of_exec == GNU_SYMBOLS ) {
434 gnu_listsym(tchar);
435 return;
437 #endif
439 /* For MINIX EXEC */
441 tp = &symtab;
442 for ( sp = tp->start; sp < tp->end; ++sp )
444 switch( sp->n_sclass & N_SECT )
446 case N_ABS: schar = 'a'; break;
447 case N_TEXT: schar = 't'; break;
448 case N_DATA: schar = 'd'; break;
449 case N_BSS: schar = 'b'; break;
450 default: schar = '?'; break;
453 if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
454 schar += 'A' - 'a';
456 /* check for selection */
457 if ( tchar != '*' && schar != tchar)
458 continue;
460 /* print symbol type and value */
461 for ( s = sp->n_name, send = s + sizeof sp->n_name;
462 *s != 0 && s < send; ++s ) outbyte( *s );
463 for ( ; s <= send; ++s ) outspace();
464 outbyte( schar );
465 outspace();
466 #if (_WORD_SIZE == 2)
467 outh16( (u16_t) sp->n_value );
468 #else
469 outh32( sp->n_value );
470 #endif
471 outbyte('\n');
476 PUBLIC int text_symbol(value)
477 off_t value;
479 struct nlist *sp;
481 #if EXTRA_SYMBOLS
482 if ( type_of_exec == GNU_SYMBOLS )
483 return gnu_text_symbol(value);
484 #endif
486 if ((sp = findsval(value, CSEG)) != NULL && sp->n_value == value)
488 outsym(sp, value);
489 return TRUE;
491 else
492 return FALSE;
495 PUBLIC int finds_data(off,data_seg)
496 off_t off;
497 int data_seg;
499 struct nlist *sp;
501 #if EXTRA_SYMBOLS
502 if ( type_of_exec == GNU_SYMBOLS )
503 return gnu_finds_data(off,data_seg);
504 #endif
506 if ((sp = findsval(off, data_seg)) != NULL)
508 outsym(sp, off);
509 return TRUE;
511 else
512 return FALSE;
515 PUBLIC int finds_pc(pc)
516 off_t pc;
518 struct nlist *sp;
520 #if EXTRA_SYMBOLS
521 if ( type_of_exec == GNU_SYMBOLS )
522 return gnu_finds_pc(pc);
523 #endif
525 if ((sp = findsval(pc, CSEG)) != NULL)
527 outsym(sp, pc);
528 return TRUE;
530 else
531 return FALSE;