pci: don't do sanity check for missing pci bus, the check can misfire.
[minix.git] / commands / swifi / read_nlist.c
blob1c50df36fab82a4cdf3f2af2c9c4c75b3ddc871e
1 /*
2 read_nlist.c
4 Read the symbol table of an executable into memory.
6 Created: Mar 6, 1992 by Philip Homburg
7 */
9 #include <sys/types.h>
10 #include <assert.h>
11 #include <a.out.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
18 #include "extra.h"
20 #define USE_OLD_NLIST 1
22 static u16_t le16 _ARGS(( u16_t *word_p ));
23 static u32_t le32 _ARGS(( u32_t *word_p ));
24 static u16_t be16 _ARGS(( u16_t *word_p ));
25 static u32_t be32 _ARGS(( u32_t *word_p ));
27 static u16_t le16(word_p)
28 u16_t *word_p;
30 return (((u8_t *)word_p)[0] << 0) | (((u8_t *)word_p)[1] << 8);
33 static u16_t be16(word_p)
34 u16_t *word_p;
36 return (((u8_t *)word_p)[1] << 0) | (((u8_t *)word_p)[0] << 8);
39 static u32_t le32(dword_p)
40 u32_t *dword_p;
42 return le16(&((u16_t *)dword_p)[0]) |
43 ((u32_t)le16(&((u16_t *)dword_p)[1]) << 16);
46 static u32_t be32(dword_p)
47 u32_t *dword_p;
49 return be16(&((u16_t *)dword_p)[1]) |
50 ((u32_t)be16(&((u16_t *)dword_p)[0]) << 16);
53 #ifndef USE_OLD_NLIST
54 struct old_nlist
56 char n_name[8];
57 long n_value;
58 unsigned char n_sclass;
59 unsigned char n_numaux;
60 unsigned char n_type;
63 /* Low bits of storage class (section). */
64 #define O_N_SECT 07 /* section mask */
65 #define O_N_UNDF 00 /* undefined */
66 #define O_N_ABS 01 /* absolute */
67 #define O_N_TEXT 02 /* text */
68 #define O_N_DATA 03 /* data */
69 #define O_N_BSS 04 /* bss */
70 #define O_N_COMM 05 /* (common) */
72 /* High bits of storage class. */
73 #define O_N_CLASS 0370 /* storage class mask */
74 #define O_C_NULL
75 #define O_C_EXT 0020 /* external symbol */
76 #define O_C_STAT 0030 /* static */
77 #endif
79 int read_nlist(filename, nlist_table)
80 const char *filename;
81 struct nlist **nlist_table;
83 int r, n_entries, save_err;
84 u32_t (*cnv32) _ARGS(( u32_t *addr ));
85 u16_t (*cnv16) _ARGS(( u16_t *addr ));
86 struct nlist *nlist_p, *nlist_ptr;
87 int exec_fd;
88 struct exec exec_header;
89 #ifndef USE_OLD_NLIST
90 struct old_nlist *old_nlist, *old_nlist_p;
91 void *old_nlist_end;
92 #endif
93 char *str_tab, *str_base, *str_null;
94 u32_t string_siz;
96 exec_fd= open(filename, O_RDONLY);
97 if (exec_fd == -1) /* No executable present */
99 return -1;
102 r= read(exec_fd, (char *)&exec_header, A_MINHDR);
103 if (r != A_MINHDR)
105 if (r != -1)
106 errno= ENOEXEC;
107 return -1;
109 if (BADMAG(exec_header))
111 errno= ENOEXEC;
112 return -1;
114 switch(exec_header.a_cpu & 3)
116 case 0: /* little endian */
117 cnv32= le32;
118 cnv16= le16;
119 break;
120 case 3: /* big endian */
121 cnv32= be32;
122 cnv16= be16;
123 break;
124 default:
125 errno= ENOEXEC;
126 return -1;
128 exec_header.a_version= cnv16((u16_t *)&exec_header.a_version);
129 exec_header.a_text= cnv32((u32_t *)&exec_header.a_text);
130 exec_header.a_data= cnv32((u32_t *)&exec_header.a_data);
131 exec_header.a_bss= cnv32((u32_t *)&exec_header.a_bss);
132 exec_header.a_entry= cnv32((u32_t *)&exec_header.a_entry);
133 exec_header.a_total= cnv32((u32_t *)&exec_header.a_total);
134 exec_header.a_syms= cnv32((u32_t *)&exec_header.a_syms);
135 exec_header.a_trsize= cnv32((u32_t *)&exec_header.a_trsize);
136 exec_header.a_drsize= cnv32((u32_t *)&exec_header.a_drsize);
137 exec_header.a_tbase= cnv32((u32_t *)&exec_header.a_tbase);
138 exec_header.a_dbase= cnv32((u32_t *)&exec_header.a_dbase);
140 if (!exec_header.a_syms)
141 return 0;
143 if (exec_header.a_flags & A_NSYM)
145 #if USE_OLD_NLIST
146 errno= EINVAL;
147 return -1;
148 #else
149 r= lseek(exec_fd, A_SYMPOS(exec_header)+exec_header.a_syms,
150 SEEK_SET);
151 if (r == -1)
153 return -1;
155 r= read(exec_fd, (char *)&string_siz, 4);
156 if (r != 4)
157 return -1;
158 string_siz= cnv32(&string_siz)-4;
159 nlist_p= malloc(exec_header.a_syms + string_siz+1);
160 if (!nlist_p)
162 errno= ENOMEM;
163 return -1;
165 r= lseek(exec_fd, A_SYMPOS(exec_header)+exec_header.a_syms+4,
166 SEEK_SET);
167 if (r == -1)
169 save_err= errno;
170 free(nlist_p);
171 errno= save_err;
172 return -1;
174 r= read(exec_fd, ((char *)nlist_p)+exec_header.a_syms,
175 string_siz);
176 if (r != string_siz)
178 save_err= errno;
179 free(nlist_p);
180 errno= save_err;
181 return -1;
183 r= lseek(exec_fd, A_SYMPOS(exec_header), SEEK_SET);
184 if (r == -1)
186 save_err= errno;
187 free(nlist_p);
188 errno= save_err;
189 return -1;
191 r= read(exec_fd, ((char *)nlist_p), exec_header.a_syms);
192 if (r != exec_header.a_syms)
194 save_err= errno;
195 free(nlist_p);
196 errno= save_err;
197 return -1;
199 str_base= ((char *)nlist_p) + exec_header.a_syms -4;
200 str_null= (char *)nlist_p + exec_header.a_syms + string_siz;
201 *str_null= '\0';
202 for (nlist_ptr= nlist_p; (char *)nlist_ptr+1 <= str_base+4;
203 nlist_ptr++)
205 nlist_ptr->n_desc= le16((u16_t *)&nlist_ptr->n_desc);
206 nlist_ptr->n_value= le32(&nlist_ptr->n_value);
207 if (nlist_ptr->n_un.n_strx)
208 nlist_ptr->n_un.n_name= str_base+
209 cnv32((u32_t *)&nlist_ptr->n_un.n_strx);
210 else
211 nlist_ptr->n_un.n_name= str_null;
213 *nlist_table= nlist_p;
214 return nlist_ptr-nlist_p;
215 #endif
217 else
219 r= lseek(exec_fd, A_SYMPOS(exec_header), SEEK_SET);
220 if (r == -1)
222 return -1;
225 #if USE_OLD_NLIST
226 n_entries= exec_header.a_syms/sizeof(struct nlist);
227 nlist_p= malloc(exec_header.a_syms);
228 if (!nlist_p)
230 free(nlist_p);
231 errno= ENOMEM;
232 return -1;
234 r= read(exec_fd, (char *)nlist_p, exec_header.a_syms);
235 if (r != exec_header.a_syms)
237 save_err= errno;
238 free(nlist_p);
239 errno= save_err;
240 return -1;
243 *nlist_table= nlist_p;
244 return n_entries;
245 #else
246 n_entries= exec_header.a_syms/sizeof(struct old_nlist)+1;
247 nlist_p= NULL;
248 old_nlist= NULL;
250 nlist_p= malloc(n_entries * (sizeof(struct nlist)+
251 sizeof(old_nlist->n_name)+1));
252 old_nlist= malloc(exec_header.a_syms);
253 if (!old_nlist || !nlist_p)
255 if (nlist_p)
256 free(nlist_p);
257 if (old_nlist)
258 free(old_nlist);
259 errno= ENOMEM;
260 return -1;
262 r= read(exec_fd, (char *)old_nlist, exec_header.a_syms);
263 if (r != exec_header.a_syms)
265 save_err= errno;
266 free(nlist_p);
267 free(old_nlist);
268 errno= save_err;
269 return -1;
272 old_nlist_end= (char *)old_nlist+exec_header.a_syms;
273 str_tab= (char *)&nlist_p[n_entries];
274 n_entries= 0;
275 for (old_nlist_p= old_nlist;
276 (void *)(old_nlist_p+1)<=old_nlist_end; old_nlist_p++)
278 switch(old_nlist_p->n_sclass & O_N_SECT)
280 case O_N_UNDF:
281 nlist_p[n_entries].n_type= N_UNDF;
282 break;
283 case O_N_ABS:
284 nlist_p[n_entries].n_type= N_ABS;
285 break;
286 case O_N_TEXT:
287 nlist_p[n_entries].n_type= N_TEXT;
288 break;
289 case O_N_DATA:
290 nlist_p[n_entries].n_type= N_DATA;
291 break;
292 case O_N_BSS:
293 nlist_p[n_entries].n_type= N_BSS;
294 break;
295 case O_N_COMM:
296 nlist_p[n_entries].n_type= N_COMM;
297 break;
298 default:
299 continue;
301 switch(old_nlist_p->n_sclass & O_N_CLASS)
303 case O_C_EXT:
304 nlist_p[n_entries].n_type |= N_EXT;
305 case O_C_STAT:
306 break;
307 default:
308 continue;
310 nlist_p[n_entries].n_value=
311 cnv32((u32_t *)&old_nlist_p->n_value);
312 nlist_p[n_entries].n_un.n_name= str_tab;
313 memcpy(str_tab, old_nlist_p->n_name,
314 sizeof(old_nlist_p->n_name));
315 str_tab += sizeof(old_nlist_p->n_name);
316 *str_tab++= '\0';
317 n_entries++;
319 free(old_nlist);
320 nlist_p= realloc(nlist_p, str_tab-(char *)nlist_p);
321 *nlist_table= nlist_p;
322 return n_entries;
323 #endif
328 * $PchId: read_nlist.c,v 1.5 1996/04/11 07:47:38 philip Exp $