source: trunk/minix/commands/mdb/gnu_sym.c@ 20

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

Minix 3.1.2a

File size: 6.9 KB
Line 
1/*
2 * gnu_sym.c for mdb
3 * copied and modified from sym.c
4 * Support GNU Exec symbol tables
5 */
6
7#include "mdb.h"
8
9#ifdef EXTRA_SYMBOLS
10
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"
19
20#if GNU_SUPPORT
21_PROTOTYPE( PUBLIC unsigned int gnu_load, (char *filename, struct nlist **start) );
22#endif
23
24struct symtab_s
25{
26 struct nlist *start;
27 struct nlist *end;
28 unsigned int nsym;
29};
30
31PRIVATE struct symtab_s symtab;
32
33FORWARD _PROTOTYPE( void gnu_sort , (struct nlist *array , struct nlist *top ));
34FORWARD _PROTOTYPE( int gnu_symeq , (char *t , struct nlist *sp ));
35FORWARD _PROTOTYPE( int gnu_symprefix , (char *t , struct nlist *sp ));
36FORWARD _PROTOTYPE( struct nlist *gnu_sname, (char *name, int is_text, int allflag) );
37FORWARD _PROTOTYPE( struct nlist *gnu_sval, (off_t value, int where) );
38FORWARD _PROTOTYPE( void gnu_sym, (struct nlist *sp, off_t off) );
39
40PUBLIC void gnu_init( filename )
41char *filename;
42{
43 register struct symtab_s *tp;
44
45 tp = &symtab;
46
47 tp->nsym = gnu_load(filename, &tp->start);
48 tp->end = tp->start + tp->nsym;
49
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");
54}
55
56
57
58PUBLIC long gnu_symbolvalue( name, is_text )
59char *name;
60int is_text;
61{
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;
68}
69
70
71PRIVATE struct nlist *gnu_sname( name, is_text, allflag )
72char *name;
73int is_text;
74int allflag;
75{
76 char *s;
77 unsigned char sclass;
78 int schar;
79 char *send;
80 register struct nlist *sp;
81 register struct symtab_s *tp;
82
83 tp = &symtab;
84
85 if ( allflag )
86 {
87 /* find and print all matching symbols */
88 for ( sp = tp->start; sp < tp->end; ++sp )
89 {
90 if ( gnu_symprefix( name, sp ) )
91 {
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 )
99 {
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;
105 }
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');
112 }
113 }
114 }
115 else
116 {
117 /* find symbol by dumb linear search */
118 for ( sp = tp->start; sp < tp->end; ++sp )
119 {
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;
125 }
126 }
127 return NULL;
128}
129
130PRIVATE struct nlist *gnu_sval( value, where )
131off_t value;
132int where;
133{
134 int left;
135 int middle;
136 int right;
137 unsigned char sclass;
138 register struct nlist *sp;
139 register struct symtab_s *tp;
140
141 tp = &symtab;
142
143 /* find last symbol with value <= desired one by binary search */
144 for ( left = 0, right = tp->nsym - 1; left <= right; )
145 {
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;
152 }
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 )
156 {
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;
162 }
163 return NULL;
164}
165
166
167PRIVATE void gnu_sym( sp, off )
168struct nlist *sp;
169off_t off;
170{
171 register char *s;
172 char *send;
173
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 )
177 {
178 outbyte( '+' );
179 printhex(off);
180 }
181}
182
183/* shell sort symbols on value */
184
185PRIVATE void gnu_sort( array, top )
186struct nlist *array;
187struct nlist *top;
188{
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;
196
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 )
200 ;
201 do
202 {
203 for ( j = gap; j < size; ++j )
204 for ( i = j - gap; i >= 0; i -= gap )
205 {
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;
214 }
215 }
216 while ( (gap /= 3) != 0 );
217}
218
219PUBLIC void gnu_symbolic( value, separator )
220off_t value;
221int separator;
222{
223 register struct nlist *sp;
224 long off;
225
226 if (value < st_addr || value > end_addr) {
227 outstr("0x");
228 printhex(value);
229 outbyte(separator);
230 return;
231 }
232
233 if ( (sp = gnu_sval( value, CSEG )) != NULL )
234 {
235 gnu_sym( sp, value );
236 }
237 else if ( (sp = gnu_sval( value, DSEG )) != NULL )
238 {
239 gnu_sym( sp, value );
240 }
241 else
242 {
243 outstr("_start");
244 off = value - st_addr;
245 if ( off != 0 )
246 {
247 outbyte( '+' );
248 printhex(off);
249 }
250 }
251 outbyte( separator );
252}
253
254
255PRIVATE int gnu_symeq( t, sp )
256register char *t;
257struct nlist *sp;
258{
259 return strncmp( t, sp->n_un.n_name, strlen(t) ) == 0;
260}
261
262PRIVATE int gnu_symprefix( t, sp )
263register char *t;
264struct nlist *sp;
265{
266 register char *s;
267 char *send;
268
269 for ( ; *t == '_'; ++t )
270 ;
271 for ( s = sp->n_un.n_name, send = s + strlen(s);
272 s < send && *s == '_'; ++s )
273 ;
274 return strncmp( s, t, send - s ) == 0;
275}
276
277
278
279/* list all symbols - test for selection criteria */
280
281PUBLIC void gnu_listsym( tchar )
282char tchar;
283{
284 register struct symtab_s *tp;
285 register struct nlist *sp;
286 char *s;
287 char *send;
288 char schar;
289
290 outbyte('\n');
291 tp = &symtab;
292 for ( sp = tp->start; sp < tp->end; ++sp )
293 {
294 switch( sp->n_type & N_TYPE )
295 {
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;
301 }
302
303 if ( (sp->n_type & N_EXT) && schar != '?' )
304 schar += 'A' - 'a';
305
306 /* check for selection */
307 if ( tchar != '*' && schar != tchar)
308 continue;
309
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');
318 }
319}
320
321PUBLIC int gnu_text_symbol(value)
322off_t value;
323{
324struct nlist *sp;
325
326 if ((sp = gnu_sval(value, CSEG)) != NULL && sp->n_value == value)
327 {
328 gnu_sym(sp, value);
329 return TRUE;
330 }
331 else
332 return FALSE;
333}
334
335PUBLIC int gnu_finds_data(off,data_seg)
336off_t off;
337int data_seg;
338{
339struct nlist *sp;
340
341 if ((sp = gnu_sval(off, data_seg)) != NULL)
342 {
343 gnu_sym(sp, off);
344 return TRUE;
345 }
346 else
347 return FALSE;
348}
349
350PUBLIC int gnu_finds_pc(pc)
351off_t pc;
352{
353struct nlist *sp;
354
355 if ((sp = gnu_sval(pc, CSEG)) != NULL)
356 {
357 gnu_sym(sp, pc);
358 return TRUE;
359 }
360 else
361 return FALSE;
362}
363
364
365#endif /* EXTRA_SYMBOLS */
Note: See TracBrowser for help on using the repository browser.