. satisfy some gcc warnings (uninitialized/unused variables)
[minix3.git] / commands / mdb / gnu_sym.c
blob0dd2545211e28901da598fa0306b796da14b5ed1
1 /*
2 * gnu_sym.c for mdb
3 * copied and modified from sym.c
4 * Support GNU Exec symbol tables
5 */
7 #include "mdb.h"
9 #ifdef EXTRA_SYMBOLS
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #if GNU_SUPPORT
16 #include <gnu/a.out.h>
17 #endif
18 #include "proto.h"
20 #if GNU_SUPPORT
21 _PROTOTYPE( PUBLIC unsigned int gnu_load, (char *filename, struct nlist **start) );
22 #endif
24 struct symtab_s
26 struct nlist *start;
27 struct nlist *end;
28 unsigned int nsym;
31 PRIVATE struct symtab_s symtab;
33 FORWARD _PROTOTYPE( void gnu_sort , (struct nlist *array , struct nlist *top ));
34 FORWARD _PROTOTYPE( int gnu_symeq , (char *t , struct nlist *sp ));
35 FORWARD _PROTOTYPE( int gnu_symprefix , (char *t , struct nlist *sp ));
36 FORWARD _PROTOTYPE( struct nlist *gnu_sname, (char *name, int is_text, int allflag) );
37 FORWARD _PROTOTYPE( struct nlist *gnu_sval, (off_t value, int where) );
38 FORWARD _PROTOTYPE( void gnu_sym, (struct nlist *sp, off_t off) );
40 PUBLIC void gnu_init( filename )
41 char *filename;
43 register struct symtab_s *tp;
45 tp = &symtab;
47 tp->nsym = gnu_load(filename, &tp->start);
48 tp->end = tp->start + tp->nsym;
50 /* sort on value only, name search not used much and storage a problem */
51 Printf("Sorting %d GNU symbols ....", tp->nsym );
52 gnu_sort( tp->start, tp->end );
53 Printf("\n");
58 PUBLIC long gnu_symbolvalue( name, is_text )
59 char *name;
60 int is_text;
62 register struct nlist *sp;
63 sp = gnu_sname(name,is_text,0);
64 if (sp != NULL)
65 return sp->n_value;
66 else
67 return 0L;
71 PRIVATE struct nlist *gnu_sname( name, is_text, allflag )
72 char *name;
73 int is_text;
74 int allflag;
76 char *s;
77 unsigned char sclass;
78 int schar;
79 char *send;
80 register struct nlist *sp;
81 register struct symtab_s *tp;
83 tp = &symtab;
85 if ( allflag )
87 /* find and print all matching symbols */
88 for ( sp = tp->start; sp < tp->end; ++sp )
90 if ( gnu_symprefix( name, sp ) )
92 sp = sp;
93 for ( s = sp->n_un.n_name, send = s + strlen(s);
94 *s != 0 && s < send; ++s )
95 outbyte( *s );
96 for ( ; s <= send; ++s )
97 outspace();
98 switch( sp->n_type & N_TYPE )
100 case N_ABS: schar = 'a'; break;
101 case N_TEXT: schar = 't'; break;
102 case N_DATA: schar = 'd'; break;
103 case N_BSS: schar = 'b'; break;
104 default: schar = '?'; break;
106 if ( (sp->n_type & N_EXT) && schar != '?' )
107 schar += 'A' - 'a';
108 outbyte( schar );
109 outspace();
110 outh32( sp->n_value );
111 outbyte('\n');
115 else
117 /* find symbol by dumb linear search */
118 for ( sp = tp->start; sp < tp->end; ++sp )
120 sclass = sp->n_type & N_TYPE;
121 if ( (is_text && sclass == N_TEXT ||
122 !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
123 gnu_symeq( name, sp ) )
124 return sp;
127 return NULL;
130 PRIVATE struct nlist *gnu_sval( value, where )
131 off_t value;
132 int where;
134 int left;
135 int middle;
136 int right;
137 unsigned char sclass;
138 register struct nlist *sp;
139 register struct symtab_s *tp;
141 tp = &symtab;
143 /* find last symbol with value <= desired one by binary search */
144 for ( left = 0, right = tp->nsym - 1; left <= right; )
146 middle = (left + right) / 2;
147 sp = tp->start + middle;
148 if ( value < sp->n_value )
149 right = middle - 1;
150 else
151 left = middle + 1;
153 if ( right >= 0 )
154 /* otherwise tp->start + right may wrap around to > tp->start !! */
155 for ( sp = tp->start + right; sp >= tp->start; --sp )
157 if ( !(sp->n_type & N_EXT) ) continue;
158 sclass = sp->n_type & N_TYPE;
159 if ( (where == CSEG && sclass == N_TEXT ||
160 where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
161 return sp;
163 return NULL;
167 PRIVATE void gnu_sym( sp, off )
168 struct nlist *sp;
169 off_t off;
171 register char *s;
172 char *send;
174 for ( s = sp->n_un.n_name, send = s + strlen(s); *s != 0 && s < send; ++s )
175 outbyte( *s );
176 if ( (off -= sp->n_value) != 0 )
178 outbyte( '+' );
179 printhex(off);
183 /* shell sort symbols on value */
185 PRIVATE void gnu_sort( array, top )
186 struct nlist *array;
187 struct nlist *top;
189 int gap;
190 int i;
191 int j;
192 register struct nlist *left;
193 register struct nlist *right;
194 struct nlist swaptemp;
195 int size;
197 size = top - array;
198 /* choose gaps according to Knuth V3 p95 */
199 for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
203 for ( j = gap; j < size; ++j )
204 for ( i = j - gap; i >= 0; i -= gap )
206 left = array + i;
207 right = array + (i + gap);
208 if ( (off_t) left->n_value <=
209 right->n_value )
210 break;
211 swaptemp = *left;
212 *left = *right;
213 *right = swaptemp;
216 while ( (gap /= 3) != 0 );
219 PUBLIC void gnu_symbolic( value, separator )
220 off_t value;
221 int separator;
223 register struct nlist *sp;
224 long off;
226 if (value < st_addr || value > end_addr) {
227 outstr("0x");
228 printhex(value);
229 outbyte(separator);
230 return;
233 if ( (sp = gnu_sval( value, CSEG )) != NULL )
235 gnu_sym( sp, value );
237 else if ( (sp = gnu_sval( value, DSEG )) != NULL )
239 gnu_sym( sp, value );
241 else
243 outstr("_start");
244 off = value - st_addr;
245 if ( off != 0 )
247 outbyte( '+' );
248 printhex(off);
251 outbyte( separator );
255 PRIVATE int gnu_symeq( t, sp )
256 register char *t;
257 struct nlist *sp;
259 return strncmp( t, sp->n_un.n_name, strlen(t) ) == 0;
262 PRIVATE int gnu_symprefix( t, sp )
263 register char *t;
264 struct nlist *sp;
266 register char *s;
267 char *send;
269 for ( ; *t == '_'; ++t )
271 for ( s = sp->n_un.n_name, send = s + strlen(s);
272 s < send && *s == '_'; ++s )
274 return strncmp( s, t, send - s ) == 0;
279 /* list all symbols - test for selection criteria */
281 PUBLIC void gnu_listsym( tchar )
282 char tchar;
284 register struct symtab_s *tp;
285 register struct nlist *sp;
286 char *s;
287 char *send;
288 char schar;
290 outbyte('\n');
291 tp = &symtab;
292 for ( sp = tp->start; sp < tp->end; ++sp )
294 switch( sp->n_type & N_TYPE )
296 case N_ABS: schar = 'a'; break;
297 case N_TEXT: schar = 't'; break;
298 case N_DATA: schar = 'd'; break;
299 case N_BSS: schar = 'b'; break;
300 default: schar = '?'; break;
303 if ( (sp->n_type & N_EXT) && schar != '?' )
304 schar += 'A' - 'a';
306 /* check for selection */
307 if ( tchar != '*' && schar != tchar)
308 continue;
310 /* print symbol type and value */
311 outh32( sp->n_value );
312 outspace();
313 outbyte( schar );
314 outbyte( '\t' );
315 for ( s = sp->n_un.n_name, send = s + strlen(s);
316 *s != 0 && s < send; ++s ) outbyte( *s );
317 outbyte('\n');
321 PUBLIC int gnu_text_symbol(value)
322 off_t value;
324 struct nlist *sp;
326 if ((sp = gnu_sval(value, CSEG)) != NULL && sp->n_value == value)
328 gnu_sym(sp, value);
329 return TRUE;
331 else
332 return FALSE;
335 PUBLIC int gnu_finds_data(off,data_seg)
336 off_t off;
337 int data_seg;
339 struct nlist *sp;
341 if ((sp = gnu_sval(off, data_seg)) != NULL)
343 gnu_sym(sp, off);
344 return TRUE;
346 else
347 return FALSE;
350 PUBLIC int gnu_finds_pc(pc)
351 off_t pc;
353 struct nlist *sp;
355 if ((sp = gnu_sval(pc, CSEG)) != NULL)
357 gnu_sym(sp, pc);
358 return TRUE;
360 else
361 return FALSE;
365 #endif /* EXTRA_SYMBOLS */