]>
Commit | Line | Data |
---|---|---|
fecd2382 | 1 | /* coff object file format |
a87b3269 | 2 | Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. |
355afbcd | 3 | |
a39116f1 | 4 | This file is part of GAS. |
355afbcd | 5 | |
a39116f1 RP |
6 | GAS is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
355afbcd | 10 | |
a39116f1 RP |
11 | GAS is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
355afbcd | 15 | |
a39116f1 RP |
16 | You should have received a copy of the GNU General Public License |
17 | along with GAS; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
fecd2382 | 19 | |
fecd2382 RP |
20 | #include "as.h" |
21 | ||
22 | #include "obstack.h" | |
23 | ||
355afbcd KR |
24 | lineno *lineno_rootP; |
25 | ||
26 | const short seg_N_TYPE[] = | |
27 | { /* in: segT out: N_TYPE bits */ | |
28 | C_ABS_SECTION, | |
29 | C_TEXT_SECTION, | |
30 | C_DATA_SECTION, | |
31 | C_BSS_SECTION, | |
32 | C_UNDEF_SECTION, /* SEG_UNKNOWN */ | |
33 | C_UNDEF_SECTION, /* SEG_ABSENT */ | |
34 | C_UNDEF_SECTION, /* SEG_PASS1 */ | |
35 | C_UNDEF_SECTION, /* SEG_GOOF */ | |
36 | C_UNDEF_SECTION, /* SEG_BIG */ | |
37 | C_UNDEF_SECTION, /* SEG_DIFFERENCE */ | |
38 | C_DEBUG_SECTION, /* SEG_DEBUG */ | |
39 | C_NTV_SECTION, /* SEG_NTV */ | |
40 | C_PTV_SECTION, /* SEG_PTV */ | |
41 | C_REGISTER_SECTION, /* SEG_REGISTER */ | |
fecd2382 RP |
42 | }; |
43 | ||
44 | ||
45 | /* Add 4 to the real value to get the index and compensate the negatives */ | |
46 | ||
355afbcd | 47 | const segT N_TYPE_seg[32] = |
fecd2382 | 48 | { |
355afbcd KR |
49 | SEG_PTV, /* C_PTV_SECTION == -4 */ |
50 | SEG_NTV, /* C_NTV_SECTION == -3 */ | |
51 | SEG_DEBUG, /* C_DEBUG_SECTION == -2 */ | |
52 | SEG_ABSOLUTE, /* C_ABS_SECTION == -1 */ | |
53 | SEG_UNKNOWN, /* C_UNDEF_SECTION == 0 */ | |
54 | SEG_TEXT, /* C_TEXT_SECTION == 1 */ | |
55 | SEG_DATA, /* C_DATA_SECTION == 2 */ | |
56 | SEG_BSS, /* C_BSS_SECTION == 3 */ | |
57 | SEG_REGISTER, /* C_REGISTER_SECTION == 4 */ | |
58 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, | |
59 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, | |
60 | SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF | |
61 | }; | |
62 | ||
63 | char *s_get_name PARAMS ((symbolS * s)); | |
64 | static symbolS *tag_find_or_make PARAMS ((char *name)); | |
65 | static symbolS *tag_find PARAMS ((char *name)); | |
57574979 | 66 | #ifdef BFD_HEADERS |
355afbcd | 67 | static void obj_coff_section_header_append PARAMS ((char **where, struct internal_scnhdr * header)); |
57574979 | 68 | #else |
355afbcd | 69 | static void obj_coff_section_header_append PARAMS ((char **where, SCNHDR * header)); |
57574979 | 70 | #endif |
355afbcd KR |
71 | static void obj_coff_def PARAMS ((int what)); |
72 | static void obj_coff_dim PARAMS ((void)); | |
73 | static void obj_coff_endef PARAMS ((void)); | |
74 | static void obj_coff_line PARAMS ((void)); | |
75 | static void obj_coff_ln PARAMS ((void)); | |
76 | static void obj_coff_scl PARAMS ((void)); | |
77 | static void obj_coff_size PARAMS ((void)); | |
78 | static void obj_coff_stab PARAMS ((int what)); | |
79 | static void obj_coff_tag PARAMS ((void)); | |
80 | static void obj_coff_type PARAMS ((void)); | |
81 | static void obj_coff_val PARAMS ((void)); | |
82 | static void tag_init PARAMS ((void)); | |
83 | static void tag_insert PARAMS ((char *name, symbolS * symbolP)); | |
84 | ||
85 | int line_base; | |
fecd2382 RP |
86 | |
87 | static struct hash_control *tag_hash; | |
355afbcd | 88 | static symbolS *def_symbol_in_progress; |
fecd2382 | 89 | |
355afbcd KR |
90 | const pseudo_typeS obj_pseudo_table[] = |
91 | { | |
fecd2382 | 92 | #ifndef IGNORE_DEBUG |
355afbcd KR |
93 | {"def", obj_coff_def, 0}, |
94 | {"dim", obj_coff_dim, 0}, | |
95 | {"endef", obj_coff_endef, 0}, | |
96 | {"line", obj_coff_line, 0}, | |
97 | {"ln", obj_coff_ln, 0}, | |
98 | {"scl", obj_coff_scl, 0}, | |
99 | {"size", obj_coff_size, 0}, | |
100 | {"tag", obj_coff_tag, 0}, | |
101 | {"type", obj_coff_type, 0}, | |
102 | {"val", obj_coff_val, 0}, | |
fecd2382 | 103 | #else |
355afbcd KR |
104 | {"def", s_ignore, 0}, |
105 | {"dim", s_ignore, 0}, | |
106 | {"endef", s_ignore, 0}, | |
107 | {"line", s_ignore, 0}, | |
108 | {"ln", s_ignore, 0}, | |
109 | {"scl", s_ignore, 0}, | |
110 | {"size", s_ignore, 0}, | |
111 | {"tag", s_ignore, 0}, | |
112 | {"type", s_ignore, 0}, | |
113 | {"val", s_ignore, 0}, | |
fecd2382 | 114 | #endif /* ignore debug */ |
355afbcd KR |
115 | |
116 | {"ident", s_ignore, 0}, /* we don't yet handle this. */ | |
117 | ||
118 | ||
119 | /* stabs aka a.out aka b.out directives for debug symbols. | |
a39116f1 RP |
120 | Currently ignored silently. Except for .line at which |
121 | we guess from context. */ | |
355afbcd KR |
122 | {"desc", s_ignore, 0}, /* def */ |
123 | /* { "line", s_ignore, 0 }, *//* source code line number */ | |
124 | {"stabd", obj_coff_stab, 'd'},/* stabs */ | |
125 | {"stabn", obj_coff_stab, 'n'},/* stabs */ | |
126 | {"stabs", obj_coff_stab, 's'},/* stabs */ | |
127 | ||
128 | /* stabs-in-coff (?) debug pseudos (ignored) */ | |
129 | {"optim", s_ignore, 0}, /* For sun386i cc (?) */ | |
130 | /* other stuff */ | |
131 | {"ABORT", s_abort, 0}, | |
132 | ||
133 | {NULL} /* end sentinel */ | |
134 | }; /* obj_pseudo_table */ | |
fecd2382 RP |
135 | |
136 | ||
a39116f1 | 137 | /* obj dependant output values */ |
57574979 SC |
138 | #ifdef BFD_HEADERS |
139 | static struct internal_scnhdr bss_section_header; | |
140 | struct internal_scnhdr data_section_header; | |
141 | struct internal_scnhdr text_section_header; | |
142 | #else | |
fecd2382 | 143 | static SCNHDR bss_section_header; |
57574979 SC |
144 | SCNHDR data_section_header; |
145 | SCNHDR text_section_header; | |
146 | #endif | |
fecd2382 RP |
147 | /* Relocation. */ |
148 | ||
355afbcd KR |
149 | static int |
150 | reloc_compare (p1, p2) | |
6d5460ab | 151 | #ifdef BFD_HEADERS |
355afbcd | 152 | struct internal_reloc *p1, *p2; |
6d5460ab | 153 | #else |
355afbcd | 154 | RELOC *p1, *p2; |
6d5460ab RP |
155 | #endif |
156 | { | |
355afbcd | 157 | return (int) (p1->r_vaddr - p2->r_vaddr); |
6d5460ab RP |
158 | } |
159 | ||
fecd2382 RP |
160 | /* |
161 | * emit_relocations() | |
162 | * | |
163 | * Crawl along a fixS chain. Emit the segment's relocations. | |
164 | */ | |
165 | ||
355afbcd KR |
166 | void |
167 | obj_emit_relocations (where, fixP, segment_address_in_file) | |
168 | char **where; | |
169 | fixS *fixP; /* Fixup chain for this segment. */ | |
170 | relax_addressT segment_address_in_file; | |
fecd2382 | 171 | { |
57574979 | 172 | #ifdef BFD_HEADERS |
355afbcd | 173 | struct internal_reloc *ri_table; |
57574979 | 174 | #else |
355afbcd KR |
175 | RELOC *ri_table; |
176 | #endif | |
177 | #ifdef TC_I960 | |
178 | char *callj_table; | |
57574979 | 179 | #endif |
355afbcd KR |
180 | symbolS *symbolP; |
181 | int i, count; | |
182 | fixS *p; | |
183 | ||
184 | for (count = 0, p = fixP; p; p = p->fx_next) | |
185 | if (p->fx_addsy) | |
186 | count++; | |
187 | if (!count) | |
188 | return; | |
189 | ||
6d5460ab | 190 | #ifdef BFD_HEADERS |
355afbcd | 191 | ri_table = (struct internal_reloc *) calloc (sizeof (*ri_table), count); |
6d5460ab | 192 | #else |
355afbcd | 193 | ri_table = (RELOC *) calloc (sizeof (*ri_table), count); |
6d5460ab | 194 | #endif |
355afbcd KR |
195 | if (!ri_table) |
196 | as_fatal ("obj_emit_relocations: Could not malloc relocation table"); | |
197 | ||
6d5460ab | 198 | #ifdef TC_I960 |
355afbcd KR |
199 | callj_table = (char *) malloc (sizeof (char) * count); |
200 | if (!callj_table) | |
201 | as_fatal ("obj_emit_relocations: Could not malloc callj table"); | |
6d5460ab | 202 | #endif |
355afbcd KR |
203 | |
204 | for (i = 0; fixP; fixP = fixP->fx_next) | |
205 | { | |
206 | if (symbolP = fixP->fx_addsy) | |
207 | { | |
fecd2382 | 208 | #if defined(TC_M68K) |
355afbcd KR |
209 | ri_table[i].r_type = (fixP->fx_pcrel ? |
210 | (fixP->fx_size == 1 ? R_PCRBYTE : | |
211 | fixP->fx_size == 2 ? R_PCRWORD : | |
212 | R_PCRLONG) : | |
213 | (fixP->fx_size == 1 ? R_RELBYTE : | |
214 | fixP->fx_size == 2 ? R_RELWORD : | |
215 | R_RELLONG)); | |
fecd2382 | 216 | #elif defined(TC_I386) |
355afbcd | 217 | /* FIXME-SOON R_OFF8 & R_DIR16 are a vague guess, completly |
6d5460ab | 218 | untested. */ |
355afbcd KR |
219 | ri_table[i].r_type = (fixP->fx_pcrel ? |
220 | (fixP->fx_size == 1 ? R_PCRBYTE : | |
221 | fixP->fx_size == 2 ? R_PCRWORD : | |
222 | R_PCRLONG) : | |
223 | (fixP->fx_size == 1 ? R_OFF8 : | |
224 | fixP->fx_size == 2 ? R_DIR16 : | |
225 | R_DIR32)); | |
fecd2382 | 226 | #elif defined(TC_I960) |
355afbcd KR |
227 | ri_table[i].r_type = (fixP->fx_pcrel |
228 | ? R_IPRMED | |
229 | : R_RELLONG); | |
230 | callj_table[i] = fixP->fx_callj ? 1 : 0; | |
fecd2382 | 231 | #elif defined(TC_A29K) |
355afbcd KR |
232 | ri_table[i].r_type = tc_coff_fix2rtype (fixP); |
233 | ||
fecd2382 | 234 | #else |
6d5460ab | 235 | #error you lose |
fecd2382 | 236 | #endif /* TC_M68K || TC_I386 */ |
355afbcd KR |
237 | ri_table[i].r_vaddr = (fixP->fx_frag->fr_address |
238 | + fixP->fx_where); | |
239 | /* If symbol associated to relocation entry is a bss symbol | |
fecd2382 RP |
240 | or undefined symbol just remember the index of the symbol. |
241 | Otherwise store the index of the symbol describing the | |
242 | section the symbol belong to. This heuristic speeds up ld. | |
243 | */ | |
355afbcd | 244 | /* Local symbols can generate relocation information. In case |
fecd2382 RP |
245 | of structure return for instance. But they have no symbol |
246 | number because they won't be emitted in the final object. | |
247 | In the case where they are in the BSS section, this leads | |
248 | to an incorrect r_symndx. | |
6d5460ab RP |
249 | Under bsd the loader do not care if the symbol reference |
250 | is incorrect. But the SYS V ld complains about this. To | |
251 | avoid this we associate the symbol to the associated | |
252 | section, *even* if it is the BSS section. */ | |
355afbcd | 253 | /* If someone can tell me why the other symbols of the bss |
fecd2382 RP |
254 | section are not associated with the .bss section entry, |
255 | I'd be gratefull. I guess that it has to do with the special | |
256 | nature of the .bss section. Or maybe this is because the | |
257 | bss symbols are declared in the common section and can | |
258 | be resized later. Can it break code some where ? */ | |
355afbcd KR |
259 | ri_table[i].r_symndx = (S_GET_SEGMENT (symbolP) == SEG_TEXT |
260 | ? dot_text_symbol->sy_number | |
261 | : (S_GET_SEGMENT (symbolP) == SEG_DATA | |
262 | ? dot_data_symbol->sy_number | |
263 | : ((SF_GET_LOCAL (symbolP) | |
264 | ? dot_bss_symbol->sy_number | |
265 | : symbolP->sy_number)))); /* bss or undefined */ | |
266 | ||
267 | /* md_ri_to_chars((char *) &ri, ri); *//* Last step : write md f */ | |
268 | ||
269 | i++; | |
270 | } /* if there's a symbol */ | |
271 | } /* for each fixP */ | |
272 | ||
273 | /* | |
6d5460ab RP |
274 | * AIX ld prefer to have the reloc table with r_vaddr sorted. |
275 | * But sorting it should not hurt any other ld. | |
276 | */ | |
355afbcd KR |
277 | qsort (ri_table, count, sizeof (*ri_table), reloc_compare); |
278 | ||
279 | for (i = 0; i < count; i++) | |
280 | { | |
57574979 | 281 | #ifdef BFD_HEADERS |
355afbcd | 282 | *where += bfd_coff_swap_reloc_out (stdoutput, &ri_table[i], *where); |
6d5460ab | 283 | # ifdef TC_A29K |
355afbcd | 284 | /* The 29k has a special kludge for the high 16 bit reloc. |
6d5460ab RP |
285 | Two relocations are emmited, R_IHIHALF, and R_IHCONST. |
286 | The second one doesn't contain a symbol, but uses the | |
287 | value for offset */ | |
355afbcd KR |
288 | if (ri_table[i].r_type == R_IHIHALF) |
289 | { | |
290 | /* now emit the second bit */ | |
291 | ri_table[i].r_type = R_IHCONST; | |
292 | ri_table[i].r_symndx = fixP->fx_addnumber; | |
293 | *where += bfd_coff_swap_reloc_out (stdoutput, &ri_table[i], | |
294 | *where); | |
295 | } | |
296 | # endif /* TC_A29K */ | |
297 | ||
6d5460ab | 298 | #else /* not BFD_HEADERS */ |
355afbcd | 299 | append (where, (char *) &ri_table[i], RELSZ); |
6d5460ab | 300 | #endif /* not BFD_HEADERS */ |
355afbcd | 301 | |
fecd2382 | 302 | #ifdef TC_I960 |
355afbcd KR |
303 | if (callj_table[i]) |
304 | { | |
305 | ri_table[i].r_type = R_OPTCALL; | |
6d5460ab | 306 | # ifdef BFD_HEADERS |
355afbcd KR |
307 | *where += bfd_coff_swap_reloc_out (stdoutput, &ri_table[i], |
308 | *where); | |
6d5460ab | 309 | # else |
355afbcd KR |
310 | append (where, (char *) &ri_table[i], (unsigned long) RELSZ); |
311 | # endif /* BFD_HEADERS */ | |
312 | } /* if it's a callj, do it again for the opcode */ | |
fecd2382 | 313 | #endif /* TC_I960 */ |
355afbcd KR |
314 | } |
315 | ||
316 | free (ri_table); | |
6d5460ab | 317 | #ifdef TC_I960 |
355afbcd | 318 | free (callj_table); |
6d5460ab | 319 | #endif |
355afbcd KR |
320 | |
321 | return; | |
322 | } /* obj_emit_relocations() */ | |
fecd2382 RP |
323 | |
324 | /* Coff file generation & utilities */ | |
325 | ||
57574979 | 326 | #ifdef BFD_HEADERS |
355afbcd KR |
327 | void |
328 | obj_header_append (where, headers) | |
329 | char **where; | |
330 | object_headers *headers; | |
57574979 | 331 | { |
355afbcd KR |
332 | tc_headers_hook (headers); |
333 | *where += bfd_coff_swap_filehdr_out (stdoutput, &(headers->filehdr), *where); | |
57574979 | 334 | #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER |
355afbcd | 335 | *where += bfd_coff_swap_aouthdr_out (stdoutput, &(headers->aouthdr), *where); |
57574979 | 336 | #endif |
355afbcd KR |
337 | obj_coff_section_header_append (where, &text_section_header); |
338 | obj_coff_section_header_append (where, &data_section_header); | |
339 | obj_coff_section_header_append (where, &bss_section_header); | |
340 | ||
57574979 SC |
341 | } |
342 | ||
343 | #else | |
344 | ||
355afbcd KR |
345 | void |
346 | obj_header_append (where, headers) | |
347 | char **where; | |
348 | object_headers *headers; | |
fecd2382 | 349 | { |
355afbcd KR |
350 | tc_headers_hook (headers); |
351 | ||
d1a9e594 | 352 | #ifdef CROSS_COMPILE |
355afbcd KR |
353 | /* Eventually swap bytes for cross compilation for file header */ |
354 | md_number_to_chars (*where, headers->filehdr.f_magic, sizeof (headers->filehdr.f_magic)); | |
355 | *where += sizeof (headers->filehdr.f_magic); | |
356 | md_number_to_chars (*where, headers->filehdr.f_nscns, sizeof (headers->filehdr.f_nscns)); | |
357 | *where += sizeof (headers->filehdr.f_nscns); | |
358 | md_number_to_chars (*where, headers->filehdr.f_timdat, sizeof (headers->filehdr.f_timdat)); | |
359 | *where += sizeof (headers->filehdr.f_timdat); | |
360 | md_number_to_chars (*where, headers->filehdr.f_symptr, sizeof (headers->filehdr.f_symptr)); | |
361 | *where += sizeof (headers->filehdr.f_symptr); | |
362 | md_number_to_chars (*where, headers->filehdr.f_nsyms, sizeof (headers->filehdr.f_nsyms)); | |
363 | *where += sizeof (headers->filehdr.f_nsyms); | |
364 | md_number_to_chars (*where, headers->filehdr.f_opthdr, sizeof (headers->filehdr.f_opthdr)); | |
365 | *where += sizeof (headers->filehdr.f_opthdr); | |
366 | md_number_to_chars (*where, headers->filehdr.f_flags, sizeof (headers->filehdr.f_flags)); | |
367 | *where += sizeof (headers->filehdr.f_flags); | |
368 | ||
fecd2382 | 369 | #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER |
355afbcd KR |
370 | /* Eventually swap bytes for cross compilation for a.out header */ |
371 | md_number_to_chars (*where, headers->aouthdr.magic, sizeof (headers->aouthdr.magic)); | |
372 | *where += sizeof (headers->aouthdr.magic); | |
373 | md_number_to_chars (*where, headers->aouthdr.vstamp, sizeof (headers->aouthdr.vstamp)); | |
374 | *where += sizeof (headers->aouthdr.vstamp); | |
375 | md_number_to_chars (*where, headers->aouthdr.tsize, sizeof (headers->aouthdr.tsize)); | |
376 | *where += sizeof (headers->aouthdr.tsize); | |
377 | md_number_to_chars (*where, headers->aouthdr.dsize, sizeof (headers->aouthdr.dsize)); | |
378 | *where += sizeof (headers->aouthdr.dsize); | |
379 | md_number_to_chars (*where, headers->aouthdr.bsize, sizeof (headers->aouthdr.bsize)); | |
380 | *where += sizeof (headers->aouthdr.bsize); | |
381 | md_number_to_chars (*where, headers->aouthdr.entry, sizeof (headers->aouthdr.entry)); | |
382 | *where += sizeof (headers->aouthdr.entry); | |
383 | md_number_to_chars (*where, headers->aouthdr.text_start, sizeof (headers->aouthdr.text_start)); | |
384 | *where += sizeof (headers->aouthdr.text_start); | |
385 | md_number_to_chars (*where, headers->aouthdr.data_start, sizeof (headers->aouthdr.data_start)); | |
386 | *where += sizeof (headers->aouthdr.data_start); | |
387 | md_number_to_chars (*where, headers->aouthdr.tagentries, sizeof (headers->aouthdr.tagentries)); | |
388 | *where += sizeof (headers->aouthdr.tagentries); | |
fecd2382 | 389 | #endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ |
355afbcd | 390 | |
d1a9e594 | 391 | #else /* CROSS_COMPILE */ |
355afbcd KR |
392 | |
393 | append (where, (char *) &headers->filehdr, sizeof (headers->filehdr)); | |
fecd2382 | 394 | #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER |
355afbcd | 395 | append (where, (char *) &headers->aouthdr, sizeof (headers->aouthdr)); |
fecd2382 | 396 | #endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ |
355afbcd | 397 | |
d1a9e594 | 398 | #endif /* CROSS_COMPILE */ |
355afbcd KR |
399 | |
400 | /* Output the section headers */ | |
401 | obj_coff_section_header_append (where, &text_section_header); | |
402 | obj_coff_section_header_append (where, &data_section_header); | |
403 | obj_coff_section_header_append (where, &bss_section_header); | |
404 | ||
405 | return; | |
406 | } /* obj_header_append() */ | |
407 | ||
57574979 | 408 | #endif |
355afbcd KR |
409 | void |
410 | obj_symbol_to_chars (where, symbolP) | |
411 | char **where; | |
412 | symbolS *symbolP; | |
fecd2382 | 413 | { |
57574979 | 414 | #ifdef BFD_HEADERS |
355afbcd KR |
415 | unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; |
416 | unsigned int i; | |
417 | ||
418 | if (S_GET_SEGMENT (symbolP) == SEG_REGISTER) | |
419 | { | |
420 | S_SET_SEGMENT (symbolP, SEG_ABSOLUTE); | |
421 | } | |
422 | *where += bfd_coff_swap_sym_out (stdoutput, &symbolP->sy_symbol.ost_entry, | |
423 | *where); | |
424 | ||
425 | for (i = 0; i < numaux; i++) | |
426 | { | |
427 | *where += bfd_coff_swap_aux_out (stdoutput, | |
428 | &symbolP->sy_symbol.ost_auxent[i], | |
429 | S_GET_DATA_TYPE (symbolP), | |
430 | S_GET_STORAGE_CLASS (symbolP), | |
431 | *where); | |
432 | } | |
433 | ||
a39116f1 | 434 | #else /* BFD_HEADERS */ |
355afbcd KR |
435 | SYMENT *syment = &symbolP->sy_symbol.ost_entry; |
436 | int i; | |
437 | char numaux = syment->n_numaux; | |
438 | unsigned short type = S_GET_DATA_TYPE (symbolP); | |
439 | ||
d1a9e594 | 440 | #ifdef CROSS_COMPILE |
355afbcd KR |
441 | md_number_to_chars (*where, syment->n_value, sizeof (syment->n_value)); |
442 | *where += sizeof (syment->n_value); | |
443 | md_number_to_chars (*where, syment->n_scnum, sizeof (syment->n_scnum)); | |
444 | *where += sizeof (syment->n_scnum); | |
445 | md_number_to_chars (*where, 0, sizeof (short)); /* pad n_flags */ | |
446 | *where += sizeof (short); | |
447 | md_number_to_chars (*where, syment->n_type, sizeof (syment->n_type)); | |
448 | *where += sizeof (syment->n_type); | |
449 | md_number_to_chars (*where, syment->n_sclass, sizeof (syment->n_sclass)); | |
450 | *where += sizeof (syment->n_sclass); | |
451 | md_number_to_chars (*where, syment->n_numaux, sizeof (syment->n_numaux)); | |
452 | *where += sizeof (syment->n_numaux); | |
d1a9e594 | 453 | #else /* CROSS_COMPILE */ |
355afbcd | 454 | append (where, (char *) syment, sizeof (*syment)); |
d1a9e594 | 455 | #endif /* CROSS_COMPILE */ |
355afbcd KR |
456 | |
457 | /* Should do the following : if (.file entry) MD(..)... else if (static entry) MD(..) */ | |
458 | if (numaux > OBJ_COFF_MAX_AUXENTRIES) | |
459 | { | |
460 | as_bad ("Internal error? too many auxents for symbol"); | |
461 | } /* too many auxents */ | |
462 | ||
463 | for (i = 0; i < numaux; ++i) | |
464 | { | |
d1a9e594 | 465 | #ifdef CROSS_COMPILE |
355afbcd KR |
466 | #if 0 /* This code has never been tested */ |
467 | /* The most common case, x_sym entry. */ | |
468 | if ((SF_GET (symbolP) & (SF_FILE | SF_STATICS)) == 0) | |
469 | { | |
470 | md_number_to_chars (*where, auxP->x_sym.x_tagndx, sizeof (auxP->x_sym.x_tagndx)); | |
471 | *where += sizeof (auxP->x_sym.x_tagndx); | |
472 | if (ISFCN (type)) | |
473 | { | |
474 | md_number_to_chars (*where, auxP->x_sym.x_misc.x_fsize, sizeof (auxP->x_sym.x_misc.x_fsize)); | |
475 | *where += sizeof (auxP->x_sym.x_misc.x_fsize); | |
476 | } | |
477 | else | |
478 | { | |
479 | md_number_to_chars (*where, auxP->x_sym.x_misc.x_lnno, sizeof (auxP->x_sym.x_misc.x_lnno)); | |
480 | *where += sizeof (auxP->x_sym.x_misc.x_lnno); | |
481 | md_number_to_chars (*where, auxP->x_sym.x_misc.x_size, sizeof (auxP->x_sym.x_misc.x_size)); | |
482 | *where += sizeof (auxP->x_sym.x_misc.x_size); | |
483 | } | |
484 | if (ISARY (type)) | |
485 | { | |
486 | register int index; | |
487 | for (index = 0; index < DIMNUM; index++) | |
488 | md_number_to_chars (*where, auxP->x_sym.x_fcnary.x_ary.x_dimen[index], sizeof (auxP->x_sym.x_fcnary.x_ary.x_dimen[index])); | |
489 | *where += sizeof (auxP->x_sym.x_fcnary.x_ary.x_dimen[index]); | |
490 | } | |
491 | else | |
492 | { | |
493 | md_number_to_chars (*where, auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr, sizeof (auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr)); | |
494 | *where += sizeof (auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr); | |
495 | md_number_to_chars (*where, auxP->x_sym.x_fcnary.x_fcn.x_endndx, sizeof (auxP->x_sym.x_fcnary.x_fcn.x_endndx)); | |
496 | *where += sizeof (auxP->x_sym.x_fcnary.x_fcn.x_endndx); | |
497 | } | |
498 | md_number_to_chars (*where, auxP->x_sym.x_tvndx, sizeof (auxP->x_sym.x_tvndx)); | |
499 | *where += sizeof (auxP->x_sym.x_tvndx); | |
500 | } | |
501 | else if (SF_GET_FILE (symbolP)) | |
502 | { /* .file */ | |
503 | ; | |
504 | } | |
505 | else if (SF_GET_STATICS (symbolP)) | |
506 | { /* .text, .data, .bss symbols */ | |
507 | md_number_to_chars (*where, auxP->x_scn.x_scnlen, sizeof (auxP->x_scn.x_scnlen)); | |
508 | *where += sizeof (auxP->x_scn.x_scnlen); | |
509 | md_number_to_chars (*where, auxP->x_scn.x_nreloc, sizeof (auxP->x_scn.x_nreloc)); | |
510 | *where += sizeof (auxP->x_scn.x_nreloc); | |
511 | md_number_to_chars (*where, auxP->x_scn.x_nlinno, sizeof (auxP->x_scn.x_nlinno)); | |
512 | *where += sizeof (auxP->x_scn.x_nlinno); | |
513 | } | |
fecd2382 | 514 | #endif /* 0 */ |
d1a9e594 | 515 | #else /* CROSS_COMPILE */ |
355afbcd | 516 | append (where, (char *) &symbolP->sy_symbol.ost_auxent[i], sizeof (symbolP->sy_symbol.ost_auxent[i])); |
d1a9e594 | 517 | #endif /* CROSS_COMPILE */ |
355afbcd KR |
518 | |
519 | }; /* for each aux in use */ | |
520 | #endif /* BFD_HEADERS */ | |
521 | return; | |
522 | } /* obj_symbol_to_chars() */ | |
fecd2382 | 523 | |
57574979 | 524 | #ifdef BFD_HEADERS |
355afbcd KR |
525 | static void |
526 | obj_coff_section_header_append (where, header) | |
527 | char **where; | |
528 | struct internal_scnhdr *header; | |
57574979 | 529 | { |
355afbcd | 530 | *where += bfd_coff_swap_scnhdr_out (stdoutput, header, *where); |
57574979 | 531 | } |
355afbcd | 532 | |
57574979 | 533 | #else |
355afbcd KR |
534 | static void |
535 | obj_coff_section_header_append (where, header) | |
536 | char **where; | |
537 | SCNHDR *header; | |
fecd2382 | 538 | { |
d1a9e594 | 539 | #ifdef CROSS_COMPILE |
355afbcd KR |
540 | memcpy (*where, header->s_name, sizeof (header->s_name)); |
541 | *where += sizeof (header->s_name); | |
542 | ||
543 | md_number_to_chars (*where, header->s_paddr, sizeof (header->s_paddr)); | |
544 | *where += sizeof (header->s_paddr); | |
545 | ||
546 | md_number_to_chars (*where, header->s_vaddr, sizeof (header->s_vaddr)); | |
547 | *where += sizeof (header->s_vaddr); | |
548 | ||
549 | md_number_to_chars (*where, header->s_size, sizeof (header->s_size)); | |
550 | *where += sizeof (header->s_size); | |
551 | ||
552 | md_number_to_chars (*where, header->s_scnptr, sizeof (header->s_scnptr)); | |
553 | *where += sizeof (header->s_scnptr); | |
554 | ||
555 | md_number_to_chars (*where, header->s_relptr, sizeof (header->s_relptr)); | |
556 | *where += sizeof (header->s_relptr); | |
557 | ||
558 | md_number_to_chars (*where, header->s_lnnoptr, sizeof (header->s_lnnoptr)); | |
559 | *where += sizeof (header->s_lnnoptr); | |
560 | ||
561 | md_number_to_chars (*where, header->s_nreloc, sizeof (header->s_nreloc)); | |
562 | *where += sizeof (header->s_nreloc); | |
563 | ||
564 | md_number_to_chars (*where, header->s_nlnno, sizeof (header->s_nlnno)); | |
565 | *where += sizeof (header->s_nlnno); | |
566 | ||
567 | md_number_to_chars (*where, header->s_flags, sizeof (header->s_flags)); | |
568 | *where += sizeof (header->s_flags); | |
569 | ||
57574979 | 570 | #ifdef TC_I960 |
355afbcd KR |
571 | md_number_to_chars (*where, header->s_align, sizeof (header->s_align)); |
572 | *where += sizeof (header->s_align); | |
57574979 | 573 | #endif /* TC_I960 */ |
355afbcd | 574 | |
d1a9e594 | 575 | #else /* CROSS_COMPILE */ |
355afbcd KR |
576 | |
577 | append (where, (char *) header, sizeof (*header)); | |
578 | ||
d1a9e594 | 579 | #endif /* CROSS_COMPILE */ |
355afbcd KR |
580 | |
581 | return; | |
582 | } /* obj_coff_section_header_append() */ | |
fecd2382 | 583 | |
57574979 | 584 | #endif |
355afbcd KR |
585 | void |
586 | obj_emit_symbols (where, symbol_rootP) | |
587 | char **where; | |
588 | symbolS *symbol_rootP; | |
fecd2382 | 589 | { |
355afbcd KR |
590 | symbolS *symbolP; |
591 | /* | |
a39116f1 RP |
592 | * Emit all symbols left in the symbol chain. |
593 | */ | |
355afbcd KR |
594 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) |
595 | { | |
596 | /* Used to save the offset of the name. It is used to point | |
a39116f1 | 597 | to the string in memory but must be a file offset. */ |
355afbcd KR |
598 | register char *temp; |
599 | ||
600 | tc_coff_symbol_emit_hook (symbolP); | |
601 | ||
602 | temp = S_GET_NAME (symbolP); | |
603 | if (SF_GET_STRING (symbolP)) | |
604 | { | |
605 | S_SET_OFFSET (symbolP, symbolP->sy_name_offset); | |
606 | S_SET_ZEROES (symbolP, 0); | |
607 | } | |
608 | else | |
609 | { | |
610 | memset (symbolP->sy_symbol.ost_entry.n_name, '\0', SYMNMLEN); | |
611 | strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN); | |
a39116f1 | 612 | } |
355afbcd KR |
613 | obj_symbol_to_chars (where, symbolP); |
614 | S_SET_NAME (symbolP, temp); | |
615 | } | |
616 | } /* obj_emit_symbols() */ | |
fecd2382 RP |
617 | |
618 | /* Merge a debug symbol containing debug information into a normal symbol. */ | |
619 | ||
355afbcd KR |
620 | void |
621 | c_symbol_merge (debug, normal) | |
622 | symbolS *debug; | |
623 | symbolS *normal; | |
fecd2382 | 624 | { |
355afbcd KR |
625 | S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); |
626 | S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); | |
627 | ||
628 | if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) | |
629 | { | |
630 | S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); | |
631 | } /* take the most we have */ | |
632 | ||
633 | if (S_GET_NUMBER_AUXILIARY (debug) > 0) | |
634 | { | |
635 | memcpy ((char *) &normal->sy_symbol.ost_auxent[0], (char *) &debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY (debug) * AUXESZ); | |
636 | } /* Move all the auxiliary information */ | |
637 | ||
638 | /* Move the debug flags. */ | |
639 | SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); | |
640 | } /* c_symbol_merge() */ | |
fecd2382 RP |
641 | |
642 | static symbolS *previous_file_symbol = NULL; | |
643 | ||
355afbcd KR |
644 | void |
645 | c_dot_file_symbol (filename) | |
646 | char *filename; | |
fecd2382 | 647 | { |
355afbcd KR |
648 | symbolS *symbolP; |
649 | ||
650 | symbolP = symbol_new (".file", | |
651 | SEG_DEBUG, | |
652 | 0, | |
653 | &zero_address_frag); | |
654 | ||
655 | S_SET_STORAGE_CLASS (symbolP, C_FILE); | |
656 | S_SET_NUMBER_AUXILIARY (symbolP, 1); | |
657 | SA_SET_FILE_FNAME (symbolP, filename); | |
658 | ||
659 | #ifndef NO_LISTING | |
660 | { | |
661 | extern int listing; | |
662 | if (listing) | |
663 | { | |
664 | listing_source_file (filename); | |
665 | } | |
666 | } | |
667 | #endif | |
668 | ||
669 | SF_SET_DEBUG (symbolP); | |
670 | S_SET_VALUE (symbolP, (long) previous_file_symbol); | |
671 | ||
672 | previous_file_symbol = symbolP; | |
673 | ||
674 | /* Make sure that the symbol is first on the symbol chain */ | |
675 | if (symbol_rootP != symbolP) | |
676 | { | |
677 | if (symbolP == symbol_lastP) | |
678 | { | |
679 | symbol_lastP = symbol_lastP->sy_previous; | |
680 | } /* if it was the last thing on the list */ | |
681 | ||
682 | symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); | |
683 | symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); | |
684 | symbol_rootP = symbolP; | |
685 | } /* if not first on the list */ | |
686 | ||
687 | } /* c_dot_file_symbol() */ | |
688 | ||
fecd2382 RP |
689 | /* |
690 | * Build a 'section static' symbol. | |
691 | */ | |
692 | ||
355afbcd KR |
693 | char * |
694 | c_section_symbol (name, value, length, nreloc, nlnno) | |
695 | char *name; | |
696 | long value; | |
697 | long length; | |
698 | unsigned short nreloc; | |
699 | unsigned short nlnno; | |
fecd2382 | 700 | { |
355afbcd KR |
701 | symbolS *symbolP; |
702 | ||
703 | symbolP = symbol_new (name, | |
704 | (name[1] == 't' | |
705 | ? SEG_TEXT | |
706 | : (name[1] == 'd' | |
707 | ? SEG_DATA | |
708 | : SEG_BSS)), | |
709 | value, | |
710 | &zero_address_frag); | |
711 | ||
712 | S_SET_STORAGE_CLASS (symbolP, C_STAT); | |
713 | S_SET_NUMBER_AUXILIARY (symbolP, 1); | |
714 | ||
715 | SA_SET_SCN_SCNLEN (symbolP, length); | |
716 | SA_SET_SCN_NRELOC (symbolP, nreloc); | |
717 | SA_SET_SCN_NLINNO (symbolP, nlnno); | |
718 | ||
719 | SF_SET_STATICS (symbolP); | |
720 | ||
721 | return (char *) symbolP; | |
722 | } /* c_section_symbol() */ | |
723 | ||
724 | void | |
725 | c_section_header (header, | |
726 | name, | |
727 | core_address, | |
728 | size, | |
729 | data_ptr, | |
730 | reloc_ptr, | |
731 | lineno_ptr, | |
732 | reloc_number, | |
733 | lineno_number, | |
734 | alignment) | |
57574979 | 735 | #ifdef BFD_HEADERS |
355afbcd | 736 | struct internal_scnhdr *header; |
57574979 | 737 | #else |
355afbcd | 738 | SCNHDR *header; |
57574979 | 739 | #endif |
355afbcd KR |
740 | char *name; |
741 | long core_address; | |
742 | long size; | |
743 | long data_ptr; | |
744 | long reloc_ptr; | |
745 | long lineno_ptr; | |
746 | long reloc_number; | |
747 | long lineno_number; | |
748 | long alignment; | |
fecd2382 | 749 | { |
355afbcd KR |
750 | strncpy (header->s_name, name, 8); |
751 | header->s_paddr = header->s_vaddr = core_address; | |
752 | header->s_scnptr = ((header->s_size = size) != 0) ? data_ptr : 0; | |
753 | header->s_relptr = reloc_ptr; | |
754 | header->s_lnnoptr = lineno_ptr; | |
755 | header->s_nreloc = reloc_number; | |
756 | header->s_nlnno = lineno_number; | |
757 | ||
fecd2382 RP |
758 | #ifdef OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT |
759 | #ifdef OBJ_COFF_BROKEN_ALIGNMENT | |
355afbcd | 760 | header->s_align = ((name[1] == 'b' || (size > 0)) ? 16 : 0); |
fecd2382 | 761 | #else |
355afbcd KR |
762 | header->s_align = ((alignment == 0) |
763 | ? 0 | |
764 | : (1 << alignment)); | |
fecd2382 RP |
765 | #endif /* OBJ_COFF_BROKEN_ALIGNMENT */ |
766 | #endif /* OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT */ | |
355afbcd KR |
767 | |
768 | header->s_flags = STYP_REG | (name[1] == 't' | |
769 | ? STYP_TEXT | |
770 | : (name[1] == 'd' | |
771 | ? STYP_DATA | |
772 | : (name[1] == 'b' | |
773 | ? STYP_BSS | |
774 | : STYP_INFO))); | |
775 | return; | |
776 | } /* c_section_header() */ | |
fecd2382 RP |
777 | |
778 | /* Line number handling */ | |
779 | ||
780 | int function_lineoff = -1; /* Offset in line#s where the last function | |
781 | started (the odd entry for line #0) */ | |
782 | int text_lineno_number = 0; | |
783 | int our_lineno_number = 0; /* we use this to build pointers from .bf's | |
784 | into the linetable. It should match | |
785 | exactly the values that are later | |
786 | assigned in text_lineno_number by | |
787 | write.c. */ | |
355afbcd | 788 | lineno *lineno_lastP = (lineno *) 0; |
fecd2382 RP |
789 | |
790 | int | |
355afbcd KR |
791 | c_line_new (paddr, line_number, frag) |
792 | long paddr; | |
793 | unsigned short line_number; | |
794 | fragS *frag; | |
fecd2382 | 795 | { |
355afbcd KR |
796 | lineno *new_line = (lineno *) xmalloc (sizeof (lineno)); |
797 | ||
798 | new_line->line.l_addr.l_paddr = paddr; | |
799 | new_line->line.l_lnno = line_number; | |
800 | new_line->frag = (char *) frag; | |
801 | new_line->next = (lineno *) 0; | |
802 | ||
803 | if (lineno_rootP == (lineno *) 0) | |
804 | lineno_rootP = new_line; | |
805 | else | |
806 | lineno_lastP->next = new_line; | |
807 | lineno_lastP = new_line; | |
808 | return LINESZ * our_lineno_number++; | |
fecd2382 RP |
809 | } |
810 | ||
355afbcd KR |
811 | void |
812 | obj_emit_lineno (where, line, file_start) | |
813 | char **where; | |
814 | lineno *line; | |
815 | char *file_start; | |
fecd2382 | 816 | { |
57574979 | 817 | #ifdef BFD_HEADERS |
355afbcd | 818 | struct bfd_internal_lineno *line_entry; |
57574979 | 819 | #else |
355afbcd | 820 | LINENO *line_entry; |
57574979 | 821 | #endif |
355afbcd KR |
822 | for (; line; line = line->next) |
823 | { | |
824 | line_entry = &line->line; | |
825 | ||
826 | /* FIXME-SOMEDAY Resolving the sy_number of function linno's used to be done in | |
a39116f1 RP |
827 | write_object_file() but their symbols need a fileptr to the lnno, so |
828 | I moved this resolution check here. xoxorich. */ | |
355afbcd KR |
829 | |
830 | if (line_entry->l_lnno == 0) | |
831 | { | |
832 | /* There is a good chance that the symbol pointed to | |
fecd2382 RP |
833 | is not the one that will be emitted and that the |
834 | sy_number is not accurate. */ | |
355afbcd KR |
835 | /* char *name; */ |
836 | symbolS *symbolP; | |
837 | ||
838 | symbolP = (symbolS *) line_entry->l_addr.l_symndx; | |
839 | ||
840 | line_entry->l_addr.l_symndx = symbolP->sy_number; | |
841 | symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr = *where - file_start; | |
842 | ||
843 | } /* if this is a function linno */ | |
57574979 | 844 | #ifdef BFD_HEADERS |
355afbcd | 845 | *where += bfd_coff_swap_lineno_out (stdoutput, line_entry, *where); |
57574979 | 846 | #else |
355afbcd | 847 | /* No matter which member of the union we process, they are |
fecd2382 | 848 | both long. */ |
d1a9e594 | 849 | #ifdef CROSS_COMPILE |
355afbcd KR |
850 | md_number_to_chars (*where, line_entry->l_addr.l_paddr, sizeof (line_entry->l_addr.l_paddr)); |
851 | *where += sizeof (line_entry->l_addr.l_paddr); | |
852 | ||
853 | md_number_to_chars (*where, line_entry->l_lnno, sizeof (line_entry->l_lnno)); | |
854 | *where += sizeof (line_entry->l_lnno); | |
855 | ||
a39116f1 | 856 | #ifdef TC_I960 |
355afbcd KR |
857 | **where = '0'; |
858 | ++*where; | |
859 | **where = '0'; | |
860 | ++*where; | |
a39116f1 | 861 | #endif /* TC_I960 */ |
355afbcd | 862 | |
d1a9e594 | 863 | #else /* CROSS_COMPILE */ |
355afbcd | 864 | append (where, (char *) line_entry, LINESZ); |
d1a9e594 | 865 | #endif /* CROSS_COMPILE */ |
a39116f1 | 866 | #endif /* BFD_HEADERS */ |
355afbcd KR |
867 | } /* for each line number */ |
868 | ||
869 | return; | |
870 | } /* obj_emit_lineno() */ | |
fecd2382 | 871 | |
355afbcd KR |
872 | void |
873 | obj_symbol_new_hook (symbolP) | |
874 | symbolS *symbolP; | |
fecd2382 | 875 | { |
355afbcd KR |
876 | char underscore = 0; /* Symbol has leading _ */ |
877 | ||
878 | /* Effective symbol */ | |
879 | /* Store the pointer in the offset. */ | |
880 | S_SET_ZEROES (symbolP, 0L); | |
881 | S_SET_DATA_TYPE (symbolP, T_NULL); | |
882 | S_SET_STORAGE_CLASS (symbolP, 0); | |
883 | S_SET_NUMBER_AUXILIARY (symbolP, 0); | |
884 | /* Additional information */ | |
885 | symbolP->sy_symbol.ost_flags = 0; | |
886 | /* Auxiliary entries */ | |
887 | memset ((char *) &symbolP->sy_symbol.ost_auxent[0], '\0', AUXESZ); | |
888 | ||
a39116f1 | 889 | #ifdef STRIP_UNDERSCORE |
355afbcd | 890 | /* Remove leading underscore at the beginning of the symbol. |
fecd2382 RP |
891 | * This is to be compatible with the standard librairies. |
892 | */ | |
355afbcd KR |
893 | if (*S_GET_NAME (symbolP) == '_') |
894 | { | |
895 | underscore = 1; | |
896 | S_SET_NAME (symbolP, S_GET_NAME (symbolP) + 1); | |
897 | } /* strip underscore */ | |
fecd2382 | 898 | #endif /* STRIP_UNDERSCORE */ |
355afbcd KR |
899 | |
900 | if (S_IS_STRING (symbolP)) | |
901 | SF_SET_STRING (symbolP); | |
902 | if (!underscore && S_IS_LOCAL (symbolP)) | |
903 | SF_SET_LOCAL (symbolP); | |
904 | ||
905 | return; | |
906 | } /* obj_symbol_new_hook() */ | |
fecd2382 | 907 | |
a39116f1 | 908 | /* stack stuff */ |
355afbcd KR |
909 | stack * |
910 | stack_init (chunk_size, element_size) | |
911 | unsigned long chunk_size; | |
912 | unsigned long element_size; | |
fecd2382 | 913 | { |
355afbcd KR |
914 | stack *st; |
915 | ||
916 | if ((st = (stack *) malloc (sizeof (stack))) == (stack *) 0) | |
917 | return (stack *) 0; | |
918 | if ((st->data = malloc (chunk_size)) == (char *) 0) | |
919 | { | |
920 | free (st); | |
921 | return (stack *) 0; | |
922 | } | |
923 | st->pointer = 0; | |
924 | st->size = chunk_size; | |
925 | st->chunk_size = chunk_size; | |
926 | st->element_size = element_size; | |
927 | return st; | |
928 | } /* stack_init() */ | |
929 | ||
930 | void | |
931 | stack_delete (st) | |
932 | stack *st; | |
fecd2382 | 933 | { |
355afbcd KR |
934 | free (st->data); |
935 | free (st); | |
fecd2382 RP |
936 | } |
937 | ||
355afbcd KR |
938 | char * |
939 | stack_push (st, element) | |
940 | stack *st; | |
941 | char *element; | |
fecd2382 | 942 | { |
355afbcd KR |
943 | if (st->pointer + st->element_size >= st->size) |
944 | { | |
945 | st->size += st->chunk_size; | |
946 | if ((st->data = xrealloc (st->data, st->size)) == (char *) 0) | |
947 | return (char *) 0; | |
948 | } | |
949 | memcpy (st->data + st->pointer, element, st->element_size); | |
950 | st->pointer += st->element_size; | |
951 | return st->data + st->pointer; | |
952 | } /* stack_push() */ | |
953 | ||
954 | char * | |
955 | stack_pop (st) | |
956 | stack *st; | |
fecd2382 | 957 | { |
355afbcd KR |
958 | if ((st->pointer -= st->element_size) < 0) |
959 | { | |
960 | st->pointer = 0; | |
961 | return (char *) 0; | |
962 | } | |
963 | return st->data + st->pointer; | |
fecd2382 RP |
964 | } |
965 | ||
355afbcd KR |
966 | char * |
967 | stack_top (st) | |
968 | stack *st; | |
fecd2382 | 969 | { |
355afbcd | 970 | return st->data + st->pointer - st->element_size; |
fecd2382 RP |
971 | } |
972 | ||
973 | ||
974 | /* | |
975 | * Handle .ln directives. | |
976 | */ | |
977 | ||
355afbcd KR |
978 | static void |
979 | obj_coff_ln () | |
980 | { | |
981 | int l; | |
982 | if (def_symbol_in_progress != NULL) | |
983 | { | |
984 | as_warn (".ln pseudo-op inside .def/.endef: ignored."); | |
985 | demand_empty_rest_of_line (); | |
986 | return; | |
987 | } /* wrong context */ | |
988 | ||
989 | c_line_new (obstack_next_free (&frags) - frag_now->fr_literal, | |
990 | l = get_absolute_expression (), | |
991 | frag_now); | |
992 | ||
993 | #ifndef NO_LISTING | |
994 | { | |
995 | extern int listing; | |
996 | ||
997 | if (listing) | |
998 | { | |
999 | listing_source_line (l + line_base - 1); | |
1000 | } | |
1001 | } | |
1002 | #endif | |
1003 | ||
1004 | demand_empty_rest_of_line (); | |
1005 | return; | |
1006 | } /* obj_coff_ln() */ | |
fecd2382 RP |
1007 | |
1008 | /* | |
1009 | * def() | |
1010 | * | |
1011 | * Handle .def directives. | |
1012 | * | |
1013 | * One might ask : why can't we symbol_new if the symbol does not | |
1014 | * already exist and fill it with debug information. Because of | |
1015 | * the C_EFCN special symbol. It would clobber the value of the | |
1016 | * function symbol before we have a chance to notice that it is | |
1017 | * a C_EFCN. And a second reason is that the code is more clear this | |
1018 | * way. (at least I think it is :-). | |
1019 | * | |
1020 | */ | |
1021 | ||
1022 | #define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') | |
1023 | #define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ | |
a39116f1 RP |
1024 | *input_line_pointer == '\t') \ |
1025 | input_line_pointer++; | |
fecd2382 | 1026 | |
355afbcd KR |
1027 | static void |
1028 | obj_coff_def (what) | |
1029 | int what; | |
fecd2382 | 1030 | { |
355afbcd KR |
1031 | char name_end; /* Char after the end of name */ |
1032 | char *symbol_name; /* Name of the debug symbol */ | |
1033 | char *symbol_name_copy; /* Temporary copy of the name */ | |
1034 | unsigned int symbol_name_length; | |
1035 | /*$char* directiveP;$ *//* Name of the pseudo opcode */ | |
1036 | /*$char directive[MAX_DIRECTIVE];$ *//* Backup of the directive */ | |
1037 | /*$char end = 0;$ *//* If 1, stop parsing */ | |
1038 | ||
1039 | if (def_symbol_in_progress != NULL) | |
1040 | { | |
1041 | as_warn (".def pseudo-op used inside of .def/.endef: ignored."); | |
1042 | demand_empty_rest_of_line (); | |
1043 | return; | |
1044 | } /* if not inside .def/.endef */ | |
1045 | ||
1046 | SKIP_WHITESPACES (); | |
1047 | ||
1048 | def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress)); | |
1049 | memset (def_symbol_in_progress, '\0', sizeof (*def_symbol_in_progress)); | |
1050 | ||
1051 | symbol_name = input_line_pointer; | |
1052 | name_end = get_symbol_end (); | |
1053 | symbol_name_length = strlen (symbol_name); | |
1054 | symbol_name_copy = xmalloc (symbol_name_length + 1); | |
1055 | strcpy (symbol_name_copy, symbol_name); | |
1056 | ||
1057 | /* Initialize the new symbol */ | |
a39116f1 | 1058 | #ifdef STRIP_UNDERSCORE |
355afbcd KR |
1059 | S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_' |
1060 | ? symbol_name_copy + 1 | |
1061 | : symbol_name_copy)); | |
fecd2382 | 1062 | #else /* STRIP_UNDERSCORE */ |
355afbcd | 1063 | S_SET_NAME (def_symbol_in_progress, symbol_name_copy); |
fecd2382 | 1064 | #endif /* STRIP_UNDERSCORE */ |
355afbcd KR |
1065 | /* free(symbol_name_copy); */ |
1066 | def_symbol_in_progress->sy_name_offset = ~0; | |
1067 | def_symbol_in_progress->sy_number = ~0; | |
1068 | def_symbol_in_progress->sy_frag = &zero_address_frag; | |
1069 | ||
1070 | if (S_IS_STRING (def_symbol_in_progress)) | |
1071 | { | |
1072 | SF_SET_STRING (def_symbol_in_progress); | |
1073 | } /* "long" name */ | |
1074 | ||
1075 | *input_line_pointer = name_end; | |
1076 | ||
1077 | demand_empty_rest_of_line (); | |
1078 | return; | |
1079 | } /* obj_coff_def() */ | |
fecd2382 RP |
1080 | |
1081 | unsigned int dim_index; | |
355afbcd KR |
1082 | static void |
1083 | obj_coff_endef () | |
1084 | { | |
1085 | symbolS *symbolP; | |
1086 | /* DIM BUG FIX [email protected] */ | |
1087 | dim_index = 0; | |
1088 | if (def_symbol_in_progress == NULL) | |
1089 | { | |
1090 | as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); | |
1091 | demand_empty_rest_of_line (); | |
1092 | return; | |
1093 | } /* if not inside .def/.endef */ | |
1094 | ||
1095 | /* Set the section number according to storage class. */ | |
1096 | switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) | |
1097 | { | |
1098 | case C_STRTAG: | |
1099 | case C_ENTAG: | |
1100 | case C_UNTAG: | |
1101 | SF_SET_TAG (def_symbol_in_progress); | |
1102 | /* intentional fallthrough */ | |
1103 | case C_FILE: | |
1104 | case C_TPDEF: | |
1105 | SF_SET_DEBUG (def_symbol_in_progress); | |
1106 | S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG); | |
1107 | break; | |
1108 | ||
1109 | case C_EFCN: | |
1110 | SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ | |
1111 | /* intentional fallthrough */ | |
1112 | case C_BLOCK: | |
1113 | SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ | |
1114 | /* intentional fallthrough */ | |
1115 | case C_FCN: | |
1116 | S_SET_SEGMENT (def_symbol_in_progress, SEG_TEXT); | |
1117 | ||
1118 | if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b' | |
1119 | && def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][2] == 'f') | |
1120 | { | |
1121 | if (function_lineoff < 0) | |
1122 | { | |
1123 | as_warn ("`.bf' symbol without preceding function"); | |
1124 | } | |
1125 | SA_GET_SYM_LNNOPTR (def_symbol_in_progress) = function_lineoff; | |
1126 | /* Will need relocating */ | |
1127 | SF_SET_PROCESS (def_symbol_in_progress); | |
1128 | function_lineoff = -1; | |
1129 | } | |
1130 | break; | |
1131 | ||
fecd2382 | 1132 | #ifdef C_AUTOARG |
355afbcd | 1133 | case C_AUTOARG: |
fecd2382 | 1134 | #endif /* C_AUTOARG */ |
355afbcd KR |
1135 | case C_AUTO: |
1136 | case C_REG: | |
1137 | case C_MOS: | |
1138 | case C_MOE: | |
1139 | case C_MOU: | |
1140 | case C_ARG: | |
1141 | case C_REGPARM: | |
1142 | case C_FIELD: | |
1143 | case C_EOS: | |
1144 | SF_SET_DEBUG (def_symbol_in_progress); | |
1145 | S_SET_SEGMENT (def_symbol_in_progress, SEG_ABSOLUTE); | |
1146 | break; | |
1147 | ||
1148 | case C_EXT: | |
1149 | case C_STAT: | |
1150 | case C_LABEL: | |
1151 | /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ | |
1152 | break; | |
1153 | ||
1154 | case C_USTATIC: | |
1155 | case C_EXTDEF: | |
1156 | case C_ULABEL: | |
1157 | as_warn ("unexpected storage class %d", S_GET_STORAGE_CLASS (def_symbol_in_progress)); | |
1158 | break; | |
1159 | } /* switch on storage class */ | |
1160 | ||
1161 | /* Now that we have built a debug symbol, try to | |
fecd2382 RP |
1162 | find if we should merge with an existing symbol |
1163 | or not. If a symbol is C_EFCN or SEG_ABSOLUTE or | |
1164 | untagged SEG_DEBUG it never merges. */ | |
355afbcd KR |
1165 | |
1166 | /* Two cases for functions. Either debug followed | |
fecd2382 RP |
1167 | by definition or definition followed by debug. |
1168 | For definition first, we will merge the debug | |
1169 | symbol into the definition. For debug first, the | |
1170 | lineno entry MUST point to the definition | |
1171 | function or else it will point off into space | |
1172 | when obj_crawl_symbol_chain() merges the debug | |
1173 | symbol into the real symbol. Therefor, let's | |
1174 | presume the debug symbol is a real function | |
1175 | reference. */ | |
355afbcd KR |
1176 | |
1177 | /* FIXME-SOON If for some reason the definition | |
fecd2382 RP |
1178 | label/symbol is never seen, this will probably |
1179 | leave an undefined symbol at link time. */ | |
355afbcd KR |
1180 | |
1181 | if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN | |
1182 | || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG | |
1183 | && !SF_GET_TAG (def_symbol_in_progress)) | |
1184 | || S_GET_SEGMENT (def_symbol_in_progress) == SEG_ABSOLUTE | |
1185 | || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL) | |
1186 | { | |
1187 | ||
1188 | symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); | |
1189 | ||
1190 | } | |
1191 | else | |
1192 | { | |
1193 | /* This symbol already exists, merge the | |
fecd2382 RP |
1194 | newly created symbol into the old one. |
1195 | This is not mandatory. The linker can | |
1196 | handle duplicate symbols correctly. But I | |
1197 | guess that it save a *lot* of space if | |
1198 | the assembly file defines a lot of | |
1199 | symbols. [loic] */ | |
355afbcd KR |
1200 | |
1201 | /* The debug entry (def_symbol_in_progress) | |
fecd2382 | 1202 | is merged into the previous definition. */ |
355afbcd KR |
1203 | |
1204 | c_symbol_merge (def_symbol_in_progress, symbolP); | |
1205 | /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ | |
1206 | def_symbol_in_progress = symbolP; | |
1207 | ||
1208 | if (SF_GET_FUNCTION (def_symbol_in_progress) | |
1209 | || SF_GET_TAG (def_symbol_in_progress)) | |
1210 | { | |
1211 | /* For functions, and tags, the symbol *must* be where the debug symbol | |
fecd2382 | 1212 | appears. Move the existing symbol to the current place. */ |
355afbcd KR |
1213 | /* If it already is at the end of the symbol list, do nothing */ |
1214 | if (def_symbol_in_progress != symbol_lastP) | |
1215 | { | |
1216 | symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); | |
1217 | symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); | |
1218 | } /* if not already in place */ | |
1219 | } /* if function */ | |
1220 | } /* normal or mergable */ | |
1221 | ||
1222 | if (SF_GET_TAG (def_symbol_in_progress) | |
1223 | && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL) | |
1224 | { | |
1225 | tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); | |
1226 | } /* If symbol is a {structure,union} tag, associate symbol to its name. */ | |
1227 | ||
1228 | if (SF_GET_FUNCTION (def_symbol_in_progress)) | |
1229 | { | |
1230 | know (sizeof (def_symbol_in_progress) <= sizeof (long)); | |
1231 | function_lineoff = c_line_new ((long) def_symbol_in_progress, 0, &zero_address_frag); | |
1232 | SF_SET_PROCESS (def_symbol_in_progress); | |
1233 | ||
1234 | if (symbolP == NULL) | |
1235 | { | |
1236 | /* That is, if this is the first | |
fecd2382 | 1237 | time we've seen the function... */ |
355afbcd KR |
1238 | symbol_table_insert (def_symbol_in_progress); |
1239 | } /* definition follows debug */ | |
1240 | } /* Create the line number entry pointing to the function being defined */ | |
1241 | ||
1242 | def_symbol_in_progress = NULL; | |
1243 | demand_empty_rest_of_line (); | |
1244 | return; | |
1245 | } /* obj_coff_endef() */ | |
1246 | ||
1247 | static void | |
1248 | obj_coff_dim () | |
1249 | { | |
1250 | register int dim_index; | |
1251 | ||
1252 | if (def_symbol_in_progress == NULL) | |
1253 | { | |
1254 | as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); | |
1255 | demand_empty_rest_of_line (); | |
1256 | return; | |
1257 | } /* if not inside .def/.endef */ | |
1258 | ||
1259 | S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); | |
1260 | ||
1261 | for (dim_index = 0; dim_index < DIMNUM; dim_index++) | |
1262 | { | |
1263 | SKIP_WHITESPACES (); | |
1264 | SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, get_absolute_expression ()); | |
1265 | ||
1266 | switch (*input_line_pointer) | |
1267 | { | |
1268 | ||
1269 | case ',': | |
1270 | input_line_pointer++; | |
1271 | break; | |
1272 | ||
1273 | default: | |
1274 | as_warn ("badly formed .dim directive ignored"); | |
1275 | /* intentional fallthrough */ | |
1276 | case '\n': | |
1277 | case ';': | |
1278 | dim_index = DIMNUM; | |
1279 | break; | |
1280 | } /* switch on following character */ | |
1281 | } /* for each dimension */ | |
1282 | ||
1283 | demand_empty_rest_of_line (); | |
1284 | return; | |
1285 | } /* obj_coff_dim() */ | |
1286 | ||
1287 | static void | |
1288 | obj_coff_line () | |
1289 | { | |
1290 | int this_base; | |
1291 | ||
1292 | if (def_symbol_in_progress == NULL) | |
1293 | { | |
1294 | obj_coff_ln (); | |
1295 | return; | |
1296 | } /* if it looks like a stabs style line */ | |
1297 | ||
1298 | this_base = get_absolute_expression (); | |
1299 | if (this_base > line_base) | |
1300 | { | |
1301 | line_base = this_base; | |
1302 | } | |
1303 | ||
1304 | ||
1305 | S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); | |
1306 | SA_SET_SYM_LNNO (def_symbol_in_progress, line_base); | |
1307 | ||
1308 | demand_empty_rest_of_line (); | |
1309 | return; | |
1310 | } /* obj_coff_line() */ | |
1311 | ||
1312 | static void | |
1313 | obj_coff_size () | |
1314 | { | |
1315 | if (def_symbol_in_progress == NULL) | |
1316 | { | |
1317 | as_warn (".size pseudo-op used outside of .def/.endef ignored."); | |
1318 | demand_empty_rest_of_line (); | |
1319 | return; | |
1320 | } /* if not inside .def/.endef */ | |
1321 | ||
1322 | S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); | |
1323 | SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); | |
1324 | demand_empty_rest_of_line (); | |
1325 | return; | |
1326 | } /* obj_coff_size() */ | |
1327 | ||
1328 | static void | |
1329 | obj_coff_scl () | |
1330 | { | |
1331 | if (def_symbol_in_progress == NULL) | |
1332 | { | |
1333 | as_warn (".scl pseudo-op used outside of .def/.endef ignored."); | |
1334 | demand_empty_rest_of_line (); | |
1335 | return; | |
1336 | } /* if not inside .def/.endef */ | |
1337 | ||
1338 | S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); | |
1339 | demand_empty_rest_of_line (); | |
1340 | return; | |
1341 | } /* obj_coff_scl() */ | |
1342 | ||
1343 | static void | |
1344 | obj_coff_tag () | |
a39116f1 | 1345 | { |
355afbcd KR |
1346 | char *symbol_name; |
1347 | char name_end; | |
1348 | ||
1349 | if (def_symbol_in_progress == NULL) | |
1350 | { | |
1351 | as_warn (".tag pseudo-op used outside of .def/.endef ignored."); | |
1352 | demand_empty_rest_of_line (); | |
1353 | return; | |
1354 | } /* if not inside .def/.endef */ | |
1355 | ||
1356 | S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); | |
1357 | symbol_name = input_line_pointer; | |
1358 | name_end = get_symbol_end (); | |
1359 | ||
1360 | /* Assume that the symbol referred to by .tag is always defined. */ | |
1361 | /* This was a bad assumption. I've added find_or_make. xoxorich. */ | |
1362 | SA_SET_SYM_TAGNDX (def_symbol_in_progress, (long) tag_find_or_make (symbol_name)); | |
1363 | if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) | |
1364 | { | |
1365 | as_warn ("tag not found for .tag %s", symbol_name); | |
1366 | } /* not defined */ | |
1367 | ||
1368 | SF_SET_TAGGED (def_symbol_in_progress); | |
1369 | *input_line_pointer = name_end; | |
1370 | ||
1371 | demand_empty_rest_of_line (); | |
1372 | return; | |
1373 | } /* obj_coff_tag() */ | |
1374 | ||
1375 | static void | |
1376 | obj_coff_type () | |
1377 | { | |
1378 | if (def_symbol_in_progress == NULL) | |
1379 | { | |
1380 | as_warn (".type pseudo-op used outside of .def/.endef ignored."); | |
1381 | demand_empty_rest_of_line (); | |
1382 | return; | |
1383 | } /* if not inside .def/.endef */ | |
1384 | ||
1385 | S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); | |
1386 | ||
1387 | if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && | |
1388 | S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) | |
1389 | { | |
1390 | SF_SET_FUNCTION (def_symbol_in_progress); | |
1391 | } /* is a function */ | |
1392 | ||
1393 | demand_empty_rest_of_line (); | |
1394 | return; | |
1395 | } /* obj_coff_type() */ | |
1396 | ||
1397 | static void | |
1398 | obj_coff_val () | |
1399 | { | |
1400 | if (def_symbol_in_progress == NULL) | |
1401 | { | |
1402 | as_warn (".val pseudo-op used outside of .def/.endef ignored."); | |
1403 | demand_empty_rest_of_line (); | |
1404 | return; | |
1405 | } /* if not inside .def/.endef */ | |
1406 | ||
1407 | if (is_name_beginner (*input_line_pointer)) | |
1408 | { | |
1409 | char *symbol_name = input_line_pointer; | |
1410 | char name_end = get_symbol_end (); | |
1411 | ||
1412 | if (!strcmp (symbol_name, ".")) | |
1413 | { | |
1414 | def_symbol_in_progress->sy_frag = frag_now; | |
1415 | S_SET_VALUE (def_symbol_in_progress, obstack_next_free (&frags) - frag_now->fr_literal); | |
1416 | /* If the .val is != from the .def (e.g. statics) */ | |
1417 | } | |
1418 | else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) | |
1419 | { | |
1420 | def_symbol_in_progress->sy_forward = symbol_find_or_make (symbol_name); | |
1421 | ||
1422 | /* If the segment is undefined when the forward | |
fecd2382 RP |
1423 | reference is solved, then copy the segment id |
1424 | from the forward symbol. */ | |
355afbcd KR |
1425 | SF_SET_GET_SEGMENT (def_symbol_in_progress); |
1426 | } | |
1427 | /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ | |
1428 | *input_line_pointer = name_end; | |
1429 | } | |
1430 | else | |
1431 | { | |
1432 | S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); | |
1433 | } /* if symbol based */ | |
1434 | ||
1435 | demand_empty_rest_of_line (); | |
1436 | return; | |
1437 | } /* obj_coff_val() */ | |
fecd2382 RP |
1438 | |
1439 | /* | |
1440 | * Maintain a list of the tagnames of the structres. | |
1441 | */ | |
1442 | ||
355afbcd KR |
1443 | static void |
1444 | tag_init () | |
fecd2382 | 1445 | { |
355afbcd KR |
1446 | tag_hash = hash_new (); |
1447 | return; | |
1448 | } /* tag_init() */ | |
1449 | ||
1450 | static void | |
1451 | tag_insert (name, symbolP) | |
1452 | char *name; | |
1453 | symbolS *symbolP; | |
fecd2382 | 1454 | { |
355afbcd KR |
1455 | register char *error_string; |
1456 | ||
1457 | if (*(error_string = hash_jam (tag_hash, name, (char *) symbolP))) | |
1458 | { | |
1459 | as_fatal ("Inserting \"%s\" into structure table failed: %s", | |
1460 | name, error_string); | |
1461 | } | |
1462 | return; | |
1463 | } /* tag_insert() */ | |
1464 | ||
1465 | static symbolS * | |
1466 | tag_find_or_make (name) | |
1467 | char *name; | |
1468 | { | |
1469 | symbolS *symbolP; | |
1470 | ||
1471 | if ((symbolP = tag_find (name)) == NULL) | |
1472 | { | |
1473 | symbolP = symbol_new (name, | |
1474 | SEG_UNKNOWN, | |
1475 | 0, | |
1476 | &zero_address_frag); | |
1477 | ||
1478 | tag_insert (S_GET_NAME (symbolP), symbolP); | |
1479 | symbol_table_insert (symbolP); | |
1480 | } /* not found */ | |
1481 | ||
1482 | return (symbolP); | |
1483 | } /* tag_find_or_make() */ | |
1484 | ||
1485 | static symbolS * | |
1486 | tag_find (name) | |
1487 | char *name; | |
fecd2382 | 1488 | { |
a39116f1 | 1489 | #ifdef STRIP_UNDERSCORE |
355afbcd KR |
1490 | if (*name == '_') |
1491 | name++; | |
fecd2382 | 1492 | #endif /* STRIP_UNDERSCORE */ |
355afbcd KR |
1493 | return ((symbolS *) hash_find (tag_hash, name)); |
1494 | } /* tag_find() */ | |
fecd2382 | 1495 | |
355afbcd KR |
1496 | void |
1497 | obj_read_begin_hook () | |
1498 | { | |
1499 | /* These had better be the same. Usually 18 bytes. */ | |
57574979 | 1500 | #ifndef BFD_HEADERS |
355afbcd KR |
1501 | know (sizeof (SYMENT) == sizeof (AUXENT)); |
1502 | know (SYMESZ == AUXESZ); | |
57574979 | 1503 | #endif |
355afbcd KR |
1504 | tag_init (); |
1505 | ||
1506 | return; | |
1507 | } /* obj_read_begin_hook() */ | |
fecd2382 | 1508 | |
355afbcd KR |
1509 | void |
1510 | obj_crawl_symbol_chain (headers) | |
1511 | object_headers *headers; | |
fecd2382 | 1512 | { |
355afbcd KR |
1513 | int symbol_number = 0; |
1514 | lineno *lineP; | |
1515 | symbolS *last_functionP = NULL; | |
1516 | symbolS *last_tagP; | |
1517 | symbolS *symbolP; | |
1518 | symbolS *symbol_externP = NULL; | |
1519 | symbolS *symbol_extern_lastP = NULL; | |
1520 | ||
1521 | /* Initialize the stack used to keep track of the matching .bb .be */ | |
1522 | stack *block_stack = stack_init (512, sizeof (symbolS *)); | |
1523 | ||
1524 | /* JF deal with forward references first... */ | |
1525 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) | |
1526 | { | |
1527 | ||
1528 | if (symbolP->sy_forward) | |
1529 | { | |
1530 | S_SET_VALUE (symbolP, (S_GET_VALUE (symbolP) | |
1531 | + S_GET_VALUE (symbolP->sy_forward) | |
1532 | + symbolP->sy_forward->sy_frag->fr_address)); | |
1533 | ||
1534 | if ( | |
1535 | #ifndef TE_I386AIX | |
1536 | SF_GET_GET_SEGMENT (symbolP) | |
1537 | #else | |
1538 | SF_GET_GET_SEGMENT (symbolP) | |
1539 | && S_GET_SEGMENT (symbolP) == SEG_UNKNOWN | |
1540 | #endif /* TE_I386AIX */ | |
1541 | ) | |
1542 | { | |
1543 | S_SET_SEGMENT (symbolP, S_GET_SEGMENT (symbolP->sy_forward)); | |
1544 | } /* forward segment also */ | |
1545 | ||
1546 | symbolP->sy_forward = 0; | |
1547 | } /* if it has a forward reference */ | |
1548 | } /* walk the symbol chain */ | |
1549 | ||
1550 | tc_crawl_symbol_chain (headers); | |
1551 | ||
1552 | /* The symbol list should be ordered according to the following sequence | |
1553 | * order : | |
1554 | * . .file symbol | |
1555 | * . debug entries for functions | |
1556 | * . fake symbols for .text .data and .bss | |
1557 | * . defined symbols | |
1558 | * . undefined symbols | |
1559 | * But this is not mandatory. The only important point is to put the | |
1560 | * undefined symbols at the end of the list. | |
1561 | */ | |
1562 | ||
1563 | if (symbol_rootP == NULL | |
1564 | || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) | |
1565 | { | |
1566 | know (!previous_file_symbol); | |
1567 | c_dot_file_symbol ("fake"); | |
1568 | } /* Is there a .file symbol ? If not insert one at the beginning. */ | |
1569 | ||
1570 | /* | |
1571 | * Build up static symbols for .text, .data and .bss | |
1572 | */ | |
1573 | dot_text_symbol = (symbolS *) | |
1574 | c_section_symbol (".text", | |
1575 | 0, | |
1576 | H_GET_TEXT_SIZE (headers), | |
1577 | 0 /*text_relocation_number */ , | |
1578 | 0 /*text_lineno_number */ ); | |
1579 | #ifdef TE_I386AIX | |
1580 | symbol_remove (dot_text_symbol, &symbol_rootP, &symbol_lastP); | |
1581 | symbol_append (dot_text_symbol, previous_file_symbol, | |
1582 | &symbol_rootP, &symbol_lastP); | |
1583 | #endif /* TE_I386AIX */ | |
1584 | ||
1585 | dot_data_symbol = (symbolS *) | |
1586 | c_section_symbol (".data", | |
1587 | H_GET_TEXT_SIZE (headers), | |
1588 | H_GET_DATA_SIZE (headers), | |
1589 | 0 /*data_relocation_number */ , | |
1590 | 0); /* There are no data lineno entries */ | |
1591 | #ifdef TE_I386AIX | |
1592 | symbol_remove (dot_data_symbol, &symbol_rootP, &symbol_lastP); | |
1593 | symbol_append (dot_data_symbol, dot_text_symbol, | |
1594 | &symbol_rootP, &symbol_lastP); | |
1595 | #endif /* TE_I386AIX */ | |
1596 | ||
1597 | dot_bss_symbol = (symbolS *) | |
1598 | c_section_symbol (".bss", | |
1599 | H_GET_TEXT_SIZE (headers) + H_GET_DATA_SIZE (headers), | |
1600 | H_GET_BSS_SIZE (headers), | |
1601 | 0, /* No relocation for a bss section. */ | |
1602 | 0); /* There are no bss lineno entries */ | |
1603 | #ifdef TE_I386AIX | |
1604 | symbol_remove (dot_bss_symbol, &symbol_rootP, &symbol_lastP); | |
1605 | symbol_append (dot_bss_symbol, dot_data_symbol, | |
1606 | &symbol_rootP, &symbol_lastP); | |
1607 | #endif /* TE_I386AIX */ | |
1608 | ||
fecd2382 | 1609 | #if defined(DEBUG) |
355afbcd | 1610 | verify_symbol_chain (symbol_rootP, symbol_lastP); |
fecd2382 | 1611 | #endif /* DEBUG */ |
355afbcd KR |
1612 | |
1613 | /* Three traversals of symbol chains here. The | |
1614 | first traversal yanks externals into a temporary | |
1615 | chain, removing the externals from the global | |
1616 | chain, numbers symbols, and does some other guck. | |
1617 | The second traversal is on the temporary chain of | |
1618 | externals and just appends them to the global | |
1619 | chain again, numbering them as we go. The third | |
1620 | traversal patches pointers to symbols (using sym | |
1621 | indexes). The last traversal was once done as | |
1622 | part of the first pass, but that fails when a | |
1623 | reference preceeds a definition as the definition | |
1624 | has no number at the time we process the | |
1625 | reference. */ | |
1626 | ||
1627 | /* Note that symbolP will be NULL at the end of a loop | |
1628 | if an external was at the beginning of the list (it | |
1629 | gets moved off the list). Hence the weird check in | |
1630 | the loop control. | |
1631 | */ | |
1632 | for (symbolP = symbol_rootP; | |
1633 | symbolP; | |
1634 | symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP) | |
1635 | { | |
1636 | if (!SF_GET_DEBUG (symbolP)) | |
1637 | { | |
1638 | /* Debug symbols do not need all this rubbish */ | |
1639 | symbolS *real_symbolP; | |
1640 | ||
1641 | /* L* and C_EFCN symbols never merge. */ | |
1642 | if (!SF_GET_LOCAL (symbolP) | |
1643 | && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP)) | |
1644 | && real_symbolP != symbolP) | |
1645 | { | |
1646 | /* FIXME-SOON: where do dups come from? Maybe tag references before definitions? xoxorich. */ | |
1647 | /* Move the debug data from the debug symbol to the | |
1648 | real symbol. Do NOT do the oposite (i.e. move from | |
1649 | real symbol to debug symbol and remove real symbol from the | |
1650 | list.) Because some pointers refer to the real symbol | |
1651 | whereas no pointers refer to the debug symbol. */ | |
1652 | c_symbol_merge (symbolP, real_symbolP); | |
1653 | /* Replace the current symbol by the real one */ | |
1654 | /* The symbols will never be the last or the first | |
1655 | because : 1st symbol is .file and 3 last symbols are | |
1656 | .text, .data, .bss */ | |
1657 | symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP); | |
1658 | symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP); | |
1659 | symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); | |
1660 | symbolP = real_symbolP; | |
1661 | } /* if not local but dup'd */ | |
1662 | ||
1663 | if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_DATA)) | |
1664 | { | |
1665 | S_SET_SEGMENT (symbolP, SEG_TEXT); | |
1666 | } /* push data into text */ | |
1667 | ||
1668 | S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); | |
1669 | ||
1670 | if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) | |
1671 | { | |
1672 | S_SET_EXTERNAL (symbolP); | |
1673 | } | |
1674 | else if (S_GET_STORAGE_CLASS (symbolP) == C_NULL) | |
1675 | { | |
1676 | if (S_GET_SEGMENT (symbolP) == SEG_TEXT) | |
1677 | { | |
1678 | S_SET_STORAGE_CLASS (symbolP, C_LABEL); | |
1679 | } | |
1680 | else | |
1681 | { | |
1682 | S_SET_STORAGE_CLASS (symbolP, C_STAT); | |
1683 | } | |
1684 | } /* no storage class yet */ | |
1685 | ||
1686 | /* Mainly to speed up if not -g */ | |
1687 | if (SF_GET_PROCESS (symbolP)) | |
1688 | { | |
1689 | /* Handle the nested blocks auxiliary info. */ | |
1690 | if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK) | |
1691 | { | |
1692 | if (!strcmp (S_GET_NAME (symbolP), ".bb")) | |
1693 | stack_push (block_stack, (char *) &symbolP); | |
1694 | else | |
1695 | { /* .eb */ | |
1696 | register symbolS *begin_symbolP; | |
1697 | begin_symbolP = *(symbolS **) stack_pop (block_stack); | |
1698 | if (begin_symbolP == (symbolS *) 0) | |
1699 | as_warn ("mismatched .eb"); | |
1700 | else | |
1701 | SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2); | |
1702 | } | |
1703 | } | |
1704 | /* If we are able to identify the type of a function, and we | |
1705 | are out of a function (last_functionP == 0) then, the | |
1706 | function symbol will be associated with an auxiliary | |
1707 | entry. */ | |
1708 | if (last_functionP == (symbolS *) 0 && | |
1709 | SF_GET_FUNCTION (symbolP)) | |
1710 | { | |
1711 | last_functionP = symbolP; | |
1712 | ||
1713 | if (S_GET_NUMBER_AUXILIARY (symbolP) < 1) | |
1714 | { | |
1715 | S_SET_NUMBER_AUXILIARY (symbolP, 1); | |
1716 | } /* make it at least 1 */ | |
1717 | ||
1718 | /* Clobber possible stale .dim information. */ | |
1719 | memset (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen, | |
1720 | '\0', sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen)); | |
1721 | } | |
1722 | /* The C_FCN doesn't need any additional information. | |
1723 | I don't even know if this is needed for sdb. But the | |
1724 | standard assembler generates it, so... | |
fecd2382 | 1725 | */ |
355afbcd KR |
1726 | if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN) |
1727 | { | |
1728 | if (last_functionP == (symbolS *) 0) | |
1729 | as_fatal ("C_EFCN symbol out of scope"); | |
1730 | SA_SET_SYM_FSIZE (last_functionP, | |
1731 | (long) (S_GET_VALUE (symbolP) - | |
1732 | S_GET_VALUE (last_functionP))); | |
1733 | SA_SET_SYM_ENDNDX (last_functionP, symbol_number); | |
1734 | last_functionP = (symbolS *) 0; | |
fecd2382 | 1735 | } |
355afbcd KR |
1736 | } |
1737 | } | |
1738 | else if (SF_GET_TAG (symbolP)) | |
1739 | { | |
1740 | /* First descriptor of a structure must point to | |
1741 | the first slot after the structure description. */ | |
1742 | last_tagP = symbolP; | |
1743 | ||
1744 | } | |
1745 | else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS) | |
1746 | { | |
1747 | /* +2 take in account the current symbol */ | |
1748 | SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2); | |
1749 | } | |
1750 | else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE) | |
1751 | { | |
1752 | if (S_GET_VALUE (symbolP)) | |
1753 | { | |
1754 | S_SET_VALUE ((symbolS *) S_GET_VALUE (symbolP), symbol_number); | |
1755 | S_SET_VALUE (symbolP, 0); | |
1756 | } /* no one points at the first .file symbol */ | |
1757 | } /* if debug or tag or eos or file */ | |
1758 | ||
1759 | /* We must put the external symbols apart. The loader | |
1760 | does not bomb if we do not. But the references in | |
1761 | the endndx field for a .bb symbol are not corrected | |
1762 | if an external symbol is removed between .bb and .be. | |
1763 | I.e in the following case : | |
1764 | [20] .bb endndx = 22 | |
1765 | [21] foo external | |
1766 | [22] .be | |
1767 | ld will move the symbol 21 to the end of the list but | |
1768 | endndx will still be 22 instead of 21. */ | |
1769 | ||
1770 | ||
1771 | if (SF_GET_LOCAL (symbolP)) | |
1772 | { | |
1773 | /* remove C_EFCN and LOCAL (L...) symbols */ | |
1774 | /* next pointer remains valid */ | |
1775 | symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); | |
1776 | ||
1777 | } | |
1778 | else if ( | |
1779 | #ifdef TE_I386AIX | |
1780 | S_GET_STORAGE_CLASS (symbolP) == C_EXT && !SF_GET_FUNCTION (symbolP) | |
1781 | #else /* not TE_I386AIX */ | |
1782 | !S_IS_DEFINED (symbolP) && !S_IS_DEBUG (symbolP) && !SF_GET_STATICS (symbolP) | |
1783 | #endif /* not TE_I386AIX */ | |
1784 | ) | |
1785 | { | |
1786 | /* if external, Remove from the list */ | |
1787 | symbolS *hold = symbol_previous (symbolP); | |
1788 | ||
1789 | symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); | |
1790 | symbol_clear_list_pointers (symbolP); | |
1791 | symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP); | |
1792 | symbolP = hold; | |
1793 | } | |
1794 | else | |
1795 | { | |
1796 | if (SF_GET_STRING (symbolP)) | |
1797 | { | |
1798 | symbolP->sy_name_offset = string_byte_count; | |
1799 | string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; | |
1800 | } | |
1801 | else | |
1802 | { | |
1803 | symbolP->sy_name_offset = 0; | |
1804 | } /* fix "long" names */ | |
1805 | ||
1806 | symbolP->sy_number = symbol_number; | |
1807 | symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); | |
1808 | } /* if local symbol */ | |
1809 | } /* traverse the symbol list */ | |
1810 | ||
1811 | for (symbolP = symbol_externP; symbol_externP;) | |
1812 | { | |
1813 | symbolS *tmp = symbol_externP; | |
1814 | ||
1815 | /* append */ | |
1816 | symbol_remove (tmp, &symbol_externP, &symbol_extern_lastP); | |
1817 | symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP); | |
1818 | ||
1819 | /* and process */ | |
1820 | if (SF_GET_STRING (tmp)) | |
1821 | { | |
1822 | tmp->sy_name_offset = string_byte_count; | |
1823 | string_byte_count += strlen (S_GET_NAME (tmp)) + 1; | |
1824 | } | |
1825 | else | |
1826 | { | |
1827 | tmp->sy_name_offset = 0; | |
1828 | } /* fix "long" names */ | |
1829 | ||
1830 | tmp->sy_number = symbol_number; | |
1831 | symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp); | |
1832 | } /* append the entire extern chain */ | |
1833 | ||
1834 | /* When a tag reference preceeds the tag definition, | |
1835 | the definition will not have a number at the time | |
1836 | we process the reference during the first | |
1837 | traversal. Thus, a second traversal. */ | |
1838 | ||
1839 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) | |
1840 | { | |
1841 | if (SF_GET_TAGGED (symbolP)) | |
1842 | { | |
1843 | SA_SET_SYM_TAGNDX (symbolP, ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number); | |
1844 | } /* If the symbol has a tagndx entry, resolve it */ | |
1845 | } /* second traversal */ | |
1846 | ||
1847 | know (symbol_externP == NULL); | |
1848 | know (symbol_extern_lastP == NULL); | |
1849 | ||
1850 | /* FIXME-SOMEDAY I'm counting line no's here so we know what to put in the section | |
1851 | headers, and I'm resolving the addresses since I'm not sure how to | |
1852 | do it later. I am NOT resolving the linno's representing functions. | |
1853 | Their symbols need a fileptr pointing to this linno when emitted. | |
1854 | Thus, I resolve them on emit. xoxorich. */ | |
1855 | ||
1856 | for (lineP = lineno_rootP; lineP; lineP = lineP->next) | |
1857 | { | |
1858 | if (lineP->line.l_lnno > 0) | |
1859 | { | |
1860 | lineP->line.l_addr.l_paddr += ((fragS *) lineP->frag)->fr_address; | |
1861 | } | |
1862 | else | |
1863 | { | |
1864 | ; | |
1865 | } | |
1866 | text_lineno_number++; | |
1867 | } /* for each line number */ | |
1868 | ||
1869 | H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); | |
1870 | ||
1871 | return; | |
1872 | } /* obj_crawl_symbol_chain() */ | |
fecd2382 RP |
1873 | |
1874 | /* | |
1875 | * Find strings by crawling along symbol table chain. | |
1876 | */ | |
1877 | ||
355afbcd KR |
1878 | void |
1879 | obj_emit_strings (where) | |
1880 | char **where; | |
fecd2382 | 1881 | { |
355afbcd KR |
1882 | symbolS *symbolP; |
1883 | ||
d1a9e594 | 1884 | #ifdef CROSS_COMPILE |
355afbcd KR |
1885 | /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ |
1886 | md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); | |
1887 | *where += sizeof (string_byte_count); | |
d1a9e594 | 1888 | #else /* CROSS_COMPILE */ |
355afbcd | 1889 | append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); |
d1a9e594 | 1890 | #endif /* CROSS_COMPILE */ |
355afbcd KR |
1891 | |
1892 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) | |
1893 | { | |
1894 | if (SF_GET_STRING (symbolP)) | |
1895 | { | |
1896 | append (where, S_GET_NAME (symbolP), (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); | |
1897 | } /* if it has a string */ | |
1898 | } /* walk the symbol chain */ | |
1899 | ||
1900 | return; | |
1901 | } /* obj_emit_strings() */ | |
1902 | ||
1903 | void | |
1904 | obj_pre_write_hook (headers) | |
1905 | object_headers *headers; | |
fecd2382 | 1906 | { |
355afbcd KR |
1907 | register int text_relocation_number = 0; |
1908 | register int data_relocation_number = 0; | |
1909 | register fixS *fixP; | |
1910 | ||
1911 | /* FIXME-SOMEDAY this should be done at | |
fecd2382 RP |
1912 | fixup_segment time but I'm going to wait until I |
1913 | do multiple segments. xoxorich. */ | |
355afbcd KR |
1914 | /* Count the number of relocation entries for text and data */ |
1915 | for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) | |
1916 | { | |
1917 | if (fixP->fx_addsy) | |
1918 | { | |
1919 | ++text_relocation_number; | |
fecd2382 | 1920 | #ifdef TC_I960 |
355afbcd KR |
1921 | /* two relocs per callj under coff. */ |
1922 | if (fixP->fx_callj) | |
1923 | { | |
1924 | ++text_relocation_number; | |
1925 | } /* if callj and not already fixed. */ | |
fecd2382 | 1926 | #endif /* TC_I960 */ |
57574979 | 1927 | #ifdef TC_A29K |
355afbcd KR |
1928 | /* Count 2 for a constH */ |
1929 | if (fixP->fx_r_type == RELOC_CONSTH) | |
1930 | { | |
1931 | ++text_relocation_number; | |
1932 | } | |
57574979 | 1933 | #endif |
355afbcd KR |
1934 | |
1935 | } /* if not yet fixed */ | |
1936 | } /* for each fix */ | |
1937 | ||
1938 | SA_SET_SCN_NRELOC (dot_text_symbol, text_relocation_number); | |
1939 | /* Assign the number of line number entries for the text section */ | |
1940 | SA_SET_SCN_NLINNO (dot_text_symbol, text_lineno_number); | |
1941 | /* Assign the size of the section */ | |
1942 | SA_SET_SCN_SCNLEN (dot_text_symbol, H_GET_TEXT_SIZE (headers)); | |
1943 | ||
1944 | for (fixP = data_fix_root; fixP; fixP = fixP->fx_next) | |
1945 | { | |
1946 | if (fixP->fx_addsy) | |
1947 | { | |
1948 | ++data_relocation_number; | |
1949 | } /* if still relocatable */ | |
57574979 | 1950 | #ifdef TC_A29K |
355afbcd KR |
1951 | /* Count 2 for a constH */ |
1952 | if (fixP->fx_r_type == RELOC_CONSTH) | |
1953 | { | |
1954 | ++data_relocation_number; | |
1955 | } | |
57574979 | 1956 | #endif |
355afbcd KR |
1957 | |
1958 | } /* for each fix */ | |
1959 | ||
1960 | ||
1961 | SA_SET_SCN_NRELOC (dot_data_symbol, data_relocation_number); | |
1962 | /* Assign the size of the section */ | |
1963 | SA_SET_SCN_SCNLEN (dot_data_symbol, H_GET_DATA_SIZE (headers)); | |
1964 | ||
1965 | /* Assign the size of the section */ | |
1966 | SA_SET_SCN_SCNLEN (dot_bss_symbol, H_GET_BSS_SIZE (headers)); | |
1967 | ||
1968 | /* pre write hook can add relocs (for 960 and 29k coff) so */ | |
1969 | headers->relocation_size = text_relocation_number * RELSZ + | |
1970 | data_relocation_number * RELSZ; | |
1971 | ||
1972 | ||
1973 | ||
1974 | /* Fill in extra coff fields */ | |
1975 | ||
1976 | /* Initialize general line number information. */ | |
1977 | H_SET_LINENO_SIZE (headers, text_lineno_number * LINESZ); | |
1978 | ||
1979 | /* filehdr */ | |
1980 | H_SET_FILE_MAGIC_NUMBER (headers, FILE_HEADER_MAGIC); | |
1981 | H_SET_NUMBER_OF_SECTIONS (headers, 3); /* text+data+bss */ | |
57574979 | 1982 | #ifndef OBJ_COFF_OMIT_TIMESTAMP |
355afbcd | 1983 | H_SET_TIME_STAMP (headers, (long) time ((long *) 0)); |
57574979 | 1984 | #else /* OBJ_COFF_OMIT_TIMESTAMP */ |
355afbcd | 1985 | H_SET_TIME_STAMP (headers, 0); |
57574979 | 1986 | #endif /* OBJ_COFF_OMIT_TIMESTAMP */ |
355afbcd | 1987 | H_SET_SYMBOL_TABLE_POINTER (headers, H_GET_SYMBOL_TABLE_FILE_OFFSET (headers)); |
57574979 | 1988 | #if 0 |
355afbcd KR |
1989 | printf ("FILHSZ %x\n", FILHSZ); |
1990 | printf ("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ); | |
1991 | printf ("section headers %x\n", H_GET_NUMBER_OF_SECTIONS (headers) * SCNHSZ); | |
1992 | printf ("get text size %x\n", H_GET_TEXT_SIZE (headers)); | |
1993 | printf ("get data size %x\n", H_GET_DATA_SIZE (headers)); | |
1994 | printf ("get relocation size %x\n", H_GET_RELOCATION_SIZE (headers)); | |
1995 | printf ("get lineno size %x\n", H_GET_LINENO_SIZE (headers)); | |
57574979 | 1996 | #endif |
355afbcd KR |
1997 | /* symbol table size allready set */ |
1998 | H_SET_SIZEOF_OPTIONAL_HEADER (headers, OBJ_COFF_AOUTHDRSZ); | |
1999 | ||
2000 | /* do not added the F_RELFLG for the standard COFF. | |
6d5460ab RP |
2001 | * The AIX linker complain on file with relocation info striped flag. |
2002 | */ | |
2003 | #ifdef KEEP_RELOC_INFO | |
355afbcd KR |
2004 | H_SET_FLAGS (headers, (text_lineno_number == 0 ? F_LNNO : 0) |
2005 | | BYTE_ORDERING); | |
6d5460ab | 2006 | #else |
355afbcd KR |
2007 | H_SET_FLAGS (headers, (text_lineno_number == 0 ? F_LNNO : 0) |
2008 | | ((text_relocation_number + data_relocation_number) ? 0 : F_RELFLG) | |
2009 | | BYTE_ORDERING); | |
2010 | #endif | |
2011 | /* aouthdr */ | |
2012 | /* magic number allready set */ | |
2013 | H_SET_VERSION_STAMP (headers, 0); | |
2014 | /* Text, data, bss size; entry point; text_start and data_start are already set */ | |
2015 | ||
2016 | /* Build section headers */ | |
2017 | ||
2018 | c_section_header (&text_section_header, | |
2019 | ".text", | |
2020 | 0, | |
2021 | H_GET_TEXT_SIZE (headers), | |
2022 | H_GET_TEXT_FILE_OFFSET (headers), | |
2023 | (SA_GET_SCN_NRELOC (dot_text_symbol) | |
2024 | ? H_GET_RELOCATION_FILE_OFFSET (headers) | |
2025 | : 0), | |
2026 | (text_lineno_number | |
2027 | ? H_GET_LINENO_FILE_OFFSET (headers) | |
2028 | : 0), | |
2029 | SA_GET_SCN_NRELOC (dot_text_symbol), | |
2030 | text_lineno_number, | |
2031 | section_alignment[(int) SEG_TEXT]); | |
2032 | ||
2033 | c_section_header (&data_section_header, | |
2034 | ".data", | |
2035 | H_GET_TEXT_SIZE (headers), | |
2036 | H_GET_DATA_SIZE (headers), | |
2037 | (H_GET_DATA_SIZE (headers) | |
2038 | ? H_GET_DATA_FILE_OFFSET (headers) | |
2039 | : 0), | |
2040 | (SA_GET_SCN_NRELOC (dot_data_symbol) | |
2041 | ? (H_GET_RELOCATION_FILE_OFFSET (headers) | |
2042 | + text_section_header.s_nreloc * RELSZ) | |
2043 | : 0), | |
2044 | 0, /* No line number information */ | |
2045 | SA_GET_SCN_NRELOC (dot_data_symbol), | |
2046 | 0, /* No line number information */ | |
2047 | section_alignment[(int) SEG_DATA]); | |
2048 | ||
2049 | c_section_header (&bss_section_header, | |
2050 | ".bss", | |
2051 | H_GET_TEXT_SIZE (headers) + H_GET_DATA_SIZE (headers), | |
2052 | H_GET_BSS_SIZE (headers), | |
2053 | 0, /* No file offset */ | |
2054 | 0, /* No relocation information */ | |
2055 | 0, /* No line number information */ | |
2056 | 0, /* No relocation information */ | |
2057 | 0, /* No line number information */ | |
2058 | section_alignment[(int) SEG_BSS]); | |
2059 | ||
2060 | return; | |
2061 | } /* obj_pre_write_hook() */ | |
fecd2382 RP |
2062 | |
2063 | /* This is a copy from aout. All I do is neglect to actually build the symbol. */ | |
2064 | ||
355afbcd KR |
2065 | static void |
2066 | obj_coff_stab (what) | |
2067 | int what; | |
fecd2382 | 2068 | { |
355afbcd KR |
2069 | char *string; |
2070 | expressionS e; | |
2071 | int goof = 0; /* TRUE if we have aborted. */ | |
2072 | int length; | |
2073 | int saved_type = 0; | |
2074 | long longint; | |
2075 | symbolS *symbolP = 0; | |
2076 | ||
2077 | if (what == 's') | |
2078 | { | |
2079 | string = demand_copy_C_string (&length); | |
2080 | SKIP_WHITESPACE (); | |
2081 | ||
2082 | if (*input_line_pointer == ',') | |
2083 | { | |
2084 | input_line_pointer++; | |
2085 | } | |
2086 | else | |
2087 | { | |
2088 | as_bad ("I need a comma after symbol's name"); | |
2089 | goof = 1; | |
2090 | } /* better be a comma */ | |
2091 | } /* skip the string */ | |
2092 | ||
2093 | /* | |
fecd2382 RP |
2094 | * Input_line_pointer->after ','. String->symbol name. |
2095 | */ | |
355afbcd KR |
2096 | if (!goof) |
2097 | { | |
2098 | if (get_absolute_expression_and_terminator (&longint) != ',') | |
2099 | { | |
2100 | as_bad ("I want a comma after the n_type expression"); | |
2101 | goof = 1; | |
2102 | input_line_pointer--; /* Backup over a non-',' char. */ | |
2103 | } /* on error */ | |
2104 | } /* no error */ | |
2105 | ||
2106 | if (!goof) | |
2107 | { | |
2108 | if (get_absolute_expression_and_terminator (&longint) != ',') | |
2109 | { | |
2110 | as_bad ("I want a comma after the n_other expression"); | |
2111 | goof = 1; | |
2112 | input_line_pointer--; /* Backup over a non-',' char. */ | |
2113 | } /* on error */ | |
2114 | } /* no error */ | |
2115 | ||
2116 | if (!goof) | |
2117 | { | |
2118 | get_absolute_expression (); | |
2119 | ||
2120 | if (what == 's' || what == 'n') | |
2121 | { | |
2122 | if (*input_line_pointer != ',') | |
2123 | { | |
2124 | as_bad ("I want a comma after the n_desc expression"); | |
2125 | goof = 1; | |
2126 | } | |
2127 | else | |
2128 | { | |
2129 | input_line_pointer++; | |
2130 | } /* on goof */ | |
2131 | } /* not stabd */ | |
2132 | } /* no error */ | |
2133 | ||
2134 | expression (&e); | |
2135 | ||
2136 | if (goof) | |
2137 | { | |
2138 | ignore_rest_of_line (); | |
2139 | } | |
2140 | else | |
2141 | { | |
2142 | demand_empty_rest_of_line (); | |
2143 | } /* on error */ | |
2144 | } /* obj_coff_stab() */ | |
fecd2382 RP |
2145 | |
2146 | #ifdef DEBUG | |
a39116f1 | 2147 | /* for debugging */ |
355afbcd KR |
2148 | char * |
2149 | s_get_name (s) | |
2150 | symbolS *s; | |
fecd2382 | 2151 | { |
355afbcd KR |
2152 | return ((s == NULL) ? "(NULL)" : S_GET_NAME (s)); |
2153 | } /* s_get_name() */ | |
2154 | ||
2155 | void | |
2156 | symbol_dump () | |
2157 | { | |
2158 | symbolS *symbolP; | |
2159 | ||
2160 | for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) | |
2161 | { | |
2162 | printf ("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n", | |
2163 | symbolP->sy_number, | |
2164 | (unsigned long) symbolP, | |
2165 | S_GET_NAME (symbolP), | |
2166 | (long) S_GET_DATA_TYPE (symbolP), | |
2167 | S_GET_STORAGE_CLASS (symbolP), | |
2168 | (int) S_GET_SEGMENT (symbolP)); | |
2169 | } /* traverse symbols */ | |
2170 | ||
2171 | return; | |
2172 | } /* symbol_dump() */ | |
2173 | ||
fecd2382 RP |
2174 | #endif /* DEBUG */ |
2175 | ||
57574979 | 2176 | |
fecd2382 RP |
2177 | /* |
2178 | * Local Variables: | |
2179 | * comment-column: 0 | |
2180 | * fill-column: 131 | |
2181 | * End: | |
2182 | */ | |
2183 | ||
2184 | /* end of obj-coff.c */ |