4 Read the symbol table of an executable into memory.
6 Created: Mar 6, 1992 by Philip Homburg
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
)
30 return (((u8_t
*)word_p
)[0] << 0) | (((u8_t
*)word_p
)[1] << 8);
33 static u16_t
be16(word_p
)
36 return (((u8_t
*)word_p
)[1] << 0) | (((u8_t
*)word_p
)[0] << 8);
39 static u32_t
le32(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
)
49 return be16(&((u16_t
*)dword_p
)[1]) |
50 ((u32_t
)be16(&((u16_t
*)dword_p
)[0]) << 16);
58 unsigned char n_sclass
;
59 unsigned char n_numaux
;
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 */
75 #define O_C_EXT 0020 /* external symbol */
76 #define O_C_STAT 0030 /* static */
79 int read_nlist(filename
, nlist_table
)
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
;
88 struct exec exec_header
;
90 struct old_nlist
*old_nlist
, *old_nlist_p
;
93 char *str_tab
, *str_base
, *str_null
;
96 exec_fd
= open(filename
, O_RDONLY
);
97 if (exec_fd
== -1) /* No executable present */
102 r
= read(exec_fd
, (char *)&exec_header
, A_MINHDR
);
109 if (BADMAG(exec_header
))
114 switch(exec_header
.a_cpu
& 3)
116 case 0: /* little endian */
120 case 3: /* big endian */
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
)
143 if (exec_header
.a_flags
& A_NSYM
)
149 r
= lseek(exec_fd
, A_SYMPOS(exec_header
)+exec_header
.a_syms
,
155 r
= read(exec_fd
, (char *)&string_siz
, 4);
158 string_siz
= cnv32(&string_siz
)-4;
159 nlist_p
= malloc(exec_header
.a_syms
+ string_siz
+1);
165 r
= lseek(exec_fd
, A_SYMPOS(exec_header
)+exec_header
.a_syms
+4,
174 r
= read(exec_fd
, ((char *)nlist_p
)+exec_header
.a_syms
,
183 r
= lseek(exec_fd
, A_SYMPOS(exec_header
), SEEK_SET
);
191 r
= read(exec_fd
, ((char *)nlist_p
), exec_header
.a_syms
);
192 if (r
!= exec_header
.a_syms
)
199 str_base
= ((char *)nlist_p
) + exec_header
.a_syms
-4;
200 str_null
= (char *)nlist_p
+ exec_header
.a_syms
+ string_siz
;
202 for (nlist_ptr
= nlist_p
; (char *)nlist_ptr
+1 <= str_base
+4;
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
);
211 nlist_ptr
->n_un
.n_name
= str_null
;
213 *nlist_table
= nlist_p
;
214 return nlist_ptr
-nlist_p
;
219 r
= lseek(exec_fd
, A_SYMPOS(exec_header
), SEEK_SET
);
226 n_entries
= exec_header
.a_syms
/sizeof(struct nlist
);
227 nlist_p
= malloc(exec_header
.a_syms
);
234 r
= read(exec_fd
, (char *)nlist_p
, exec_header
.a_syms
);
235 if (r
!= exec_header
.a_syms
)
243 *nlist_table
= nlist_p
;
246 n_entries
= exec_header
.a_syms
/sizeof(struct old_nlist
)+1;
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
)
262 r
= read(exec_fd
, (char *)old_nlist
, exec_header
.a_syms
);
263 if (r
!= exec_header
.a_syms
)
272 old_nlist_end
= (char *)old_nlist
+exec_header
.a_syms
;
273 str_tab
= (char *)&nlist_p
[n_entries
];
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
)
281 nlist_p
[n_entries
].n_type
= N_UNDF
;
284 nlist_p
[n_entries
].n_type
= N_ABS
;
287 nlist_p
[n_entries
].n_type
= N_TEXT
;
290 nlist_p
[n_entries
].n_type
= N_DATA
;
293 nlist_p
[n_entries
].n_type
= N_BSS
;
296 nlist_p
[n_entries
].n_type
= N_COMM
;
301 switch(old_nlist_p
->n_sclass
& O_N_CLASS
)
304 nlist_p
[n_entries
].n_type
|= N_EXT
;
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
);
320 nlist_p
= realloc(nlist_p
, str_tab
-(char *)nlist_p
);
321 *nlist_table
= nlist_p
;
328 * $PchId: read_nlist.c,v 1.5 1996/04/11 07:47:38 philip Exp $