Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* ECOFF object file format. |
4c63da97 AM |
2 | Copyright (C) 1993, 94, 95, 96, 97, 98, 99, 2000 |
3 | Free Software Foundation, Inc. | |
252b5132 RH |
4 | Contributed by Cygnus Support. |
5 | This file was put together by Ian Lance Taylor <ian@cygnus.com>. | |
6 | ||
7 | This file is part of GAS. | |
8 | ||
9 | GAS is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2, or (at your option) | |
12 | any later version. | |
13 | ||
14 | GAS is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GAS; see the file COPYING. If not, write to the Free | |
21 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
22 | 02111-1307, USA. */ | |
23 | ||
24 | #define OBJ_HEADER "obj-ecoff.h" | |
25 | #include "as.h" | |
26 | #include "coff/internal.h" | |
27 | #include "bfd/libcoff.h" | |
28 | #include "bfd/libecoff.h" | |
29 | ||
30 | /* Almost all of the ECOFF support is actually in ecoff.c in the main | |
31 | gas directory. This file mostly just arranges to call that one at | |
32 | the right times. */ | |
33 | ||
34 | static int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *)); | |
35 | static void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *)); | |
36 | static void ecoff_pop_insert PARAMS ((void)); | |
37 | ||
38 | /* These are the pseudo-ops we support in this file. Only those | |
39 | relating to debugging information are supported here. | |
40 | ||
41 | The following pseudo-ops from the Kane and Heinrich MIPS book | |
42 | should be defined here, but are currently unsupported: .aent, | |
43 | .bgnb, .endb, .verstamp, .vreg. | |
44 | ||
45 | The following pseudo-ops from the Kane and Heinrich MIPS book are | |
46 | MIPS CPU specific, and should be defined by tc-mips.c: .alias, | |
47 | .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, | |
48 | .rdata, .sdata, .set. | |
49 | ||
50 | The following pseudo-ops from the Kane and Heinrich MIPS book are | |
51 | not MIPS CPU specific, but are also not ECOFF specific. I have | |
52 | only listed the ones which are not already in read.c. It's not | |
53 | completely clear where these should be defined, but tc-mips.c is | |
54 | probably the most reasonable place: .asciiz, .asm0, .endr, .err, | |
55 | .half, .lab, .repeat, .struct, .weakext. */ | |
56 | ||
57 | const pseudo_typeS obj_pseudo_table[] = | |
58 | { | |
59 | /* COFF style debugging information. .ln is not used; .loc is used | |
60 | instead. */ | |
61 | { "def", ecoff_directive_def, 0 }, | |
62 | { "dim", ecoff_directive_dim, 0 }, | |
63 | { "endef", ecoff_directive_endef, 0 }, | |
64 | { "file", ecoff_directive_file, 0 }, | |
65 | { "scl", ecoff_directive_scl, 0 }, | |
66 | { "size", ecoff_directive_size, 0 }, | |
67 | { "esize", ecoff_directive_size, 0 }, | |
68 | { "tag", ecoff_directive_tag, 0 }, | |
69 | { "type", ecoff_directive_type, 0 }, | |
70 | { "etype", ecoff_directive_type, 0 }, | |
71 | { "val", ecoff_directive_val, 0 }, | |
72 | ||
73 | /* ECOFF specific debugging information. */ | |
74 | { "begin", ecoff_directive_begin, 0 }, | |
75 | { "bend", ecoff_directive_bend, 0 }, | |
76 | { "end", ecoff_directive_end, 0 }, | |
77 | { "ent", ecoff_directive_ent, 0 }, | |
78 | { "fmask", ecoff_directive_fmask, 0 }, | |
79 | { "frame", ecoff_directive_frame, 0 }, | |
80 | { "loc", ecoff_directive_loc, 0 }, | |
81 | { "mask", ecoff_directive_mask, 0 }, | |
82 | ||
83 | /* Other ECOFF directives. */ | |
84 | { "extern", ecoff_directive_extern, 0 }, | |
85 | ||
86 | #ifndef TC_MIPS | |
87 | /* For TC_MIPS, tc-mips.c adds this. */ | |
88 | { "weakext", ecoff_directive_weakext, 0 }, | |
89 | #endif | |
90 | ||
91 | /* These are used on Irix. I don't know how to implement them. */ | |
92 | { "bgnb", s_ignore, 0 }, | |
93 | { "endb", s_ignore, 0 }, | |
94 | { "verstamp", s_ignore, 0 }, | |
95 | ||
96 | /* Sentinel. */ | |
97 | { NULL } | |
98 | }; | |
99 | ||
100 | /* Swap out the symbols and debugging information for BFD. */ | |
101 | ||
102 | void | |
103 | ecoff_frob_file () | |
104 | { | |
105 | const struct ecoff_debug_swap * const debug_swap | |
106 | = &ecoff_backend (stdoutput)->debug_swap; | |
107 | bfd_vma addr; | |
108 | asection *sec; | |
109 | HDRR *hdr; | |
110 | char *buf; | |
111 | char *set; | |
112 | ||
113 | /* Set the section VMA values. We force the .sdata and .sbss | |
114 | sections to the end to ensure that their VMA addresses are close | |
115 | together so that the GP register can address both of them. We | |
116 | put the .bss section after the .sbss section. | |
117 | ||
118 | Also, for the Alpha, we must sort the sections, to make sure they | |
119 | appear in the output file in the correct order. (Actually, maybe | |
120 | this is a job for BFD. But the VMAs computed would be out of | |
121 | whack if we computed them given our initial, random ordering. | |
122 | It's possible that that wouldn't break things; I could do some | |
123 | experimenting sometime and find out. | |
124 | ||
125 | This output ordering of sections is magic, on the Alpha, at | |
126 | least. The .lita section must come before .lit8 and .lit4, | |
127 | otherwise the OSF/1 linker may silently trash the .lit{4,8} | |
128 | section contents. Also, .text must preceed .rdata. These differ | |
129 | from the order described in some parts of the DEC OSF/1 Assembly | |
130 | Language Programmer's Guide, but that order doesn't seem to work | |
131 | with their linker. | |
132 | ||
133 | I don't know if section ordering on the MIPS is important. */ | |
134 | ||
135 | static const char *const names[] = { | |
136 | /* text segment */ | |
137 | ".text", ".rdata", ".init", ".fini", | |
138 | /* data segment */ | |
139 | ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got", | |
140 | /* bss segment */ | |
141 | ".sbss", ".bss", | |
142 | }; | |
143 | #define n_names (sizeof (names) / sizeof (names[0])) | |
144 | ||
145 | addr = 0; | |
146 | { | |
147 | /* Sections that match names, order to be straightened out later. */ | |
148 | asection *secs[n_names]; | |
149 | /* Linked list of sections with non-matching names. Random ordering. */ | |
150 | asection *other_sections = 0; | |
151 | /* Pointer to next section, since we're destroying the original | |
152 | ordering. */ | |
153 | asection *next; | |
154 | ||
155 | int i; | |
156 | ||
157 | for (i = 0; i < n_names; i++) | |
158 | secs[i] = 0; | |
159 | for (sec = stdoutput->sections; sec != (asection *) NULL; sec = next) | |
160 | { | |
161 | next = sec->next; | |
162 | for (i = 0; i < n_names; i++) | |
163 | if (!strcmp (sec->name, names[i])) | |
164 | { | |
165 | secs[i] = sec; | |
166 | break; | |
167 | } | |
168 | if (i == n_names) | |
169 | { | |
170 | bfd_set_section_vma (stdoutput, sec, addr); | |
171 | addr += bfd_section_size (stdoutput, sec); | |
172 | sec->next = other_sections; | |
173 | other_sections = sec; | |
174 | } | |
175 | } | |
176 | for (i = 0; i < n_names; i++) | |
177 | if (secs[i]) | |
178 | { | |
179 | sec = secs[i]; | |
180 | bfd_set_section_vma (stdoutput, sec, addr); | |
181 | addr += bfd_section_size (stdoutput, sec); | |
182 | } | |
183 | for (i = n_names - 1; i >= 0; i--) | |
184 | if (secs[i]) | |
185 | { | |
186 | sec = secs[i]; | |
187 | sec->next = other_sections; | |
188 | other_sections = sec; | |
189 | } | |
190 | stdoutput->sections = other_sections; | |
191 | } | |
192 | ||
193 | /* Build the ECOFF debugging information. */ | |
194 | assert (ecoff_data (stdoutput) != 0); | |
195 | hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header; | |
196 | ecoff_build_debug (hdr, &buf, debug_swap); | |
197 | ||
198 | /* Finish up the ecoff_tdata structure. */ | |
199 | set = buf; | |
200 | #define SET(ptr, count, type, size) \ | |
201 | if (hdr->count == 0) \ | |
202 | ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ | |
203 | else \ | |
204 | { \ | |
205 | ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ | |
206 | set += hdr->count * size; \ | |
207 | } | |
208 | ||
209 | SET (line, cbLine, unsigned char *, sizeof (unsigned char)); | |
210 | SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size); | |
211 | SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size); | |
212 | SET (external_sym, isymMax, PTR, debug_swap->external_sym_size); | |
213 | SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size); | |
214 | SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); | |
215 | SET (ss, issMax, char *, sizeof (char)); | |
216 | SET (ssext, issExtMax, char *, sizeof (char)); | |
217 | SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size); | |
218 | SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size); | |
219 | SET (external_ext, iextMax, PTR, debug_swap->external_ext_size); | |
220 | ||
221 | #undef SET | |
222 | ||
223 | /* Fill in the register masks. */ | |
224 | { | |
225 | unsigned long gprmask = 0; | |
226 | unsigned long fprmask = 0; | |
227 | unsigned long *cprmask = NULL; | |
228 | ||
229 | #ifdef TC_MIPS | |
230 | /* Fill in the MIPS register masks. It's probably not worth | |
231 | setting up a generic interface for this. */ | |
232 | gprmask = mips_gprmask; | |
233 | cprmask = mips_cprmask; | |
234 | #endif | |
235 | ||
236 | #ifdef TC_ALPHA | |
237 | alpha_frob_ecoff_data (); | |
238 | ||
239 | if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value)) | |
240 | as_fatal (_("Can't set GP value")); | |
241 | ||
242 | gprmask = alpha_gprmask; | |
243 | fprmask = alpha_fprmask; | |
244 | #endif | |
245 | ||
246 | if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) | |
247 | as_fatal (_("Can't set register masks")); | |
248 | } | |
249 | } | |
250 | ||
251 | /* This is called by the ECOFF code to set the external information | |
252 | for a symbol. We just pass it on to BFD, which expects the swapped | |
253 | information to be stored in the native field of the symbol. */ | |
254 | ||
255 | void | |
256 | obj_ecoff_set_ext (sym, ext) | |
257 | symbolS *sym; | |
258 | EXTR *ext; | |
259 | { | |
260 | const struct ecoff_debug_swap * const debug_swap | |
261 | = &ecoff_backend (stdoutput)->debug_swap; | |
262 | ecoff_symbol_type *esym; | |
263 | ||
fed9b18a ILT |
264 | know (bfd_asymbol_flavour (symbol_get_bfdsym (sym)) |
265 | == bfd_target_ecoff_flavour); | |
266 | esym = ecoffsymbol (symbol_get_bfdsym (sym)); | |
252b5132 RH |
267 | esym->local = false; |
268 | esym->native = xmalloc (debug_swap->external_ext_size); | |
269 | (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native); | |
270 | } | |
271 | ||
272 | static int | |
273 | ecoff_sec_sym_ok_for_reloc (sec) | |
274 | asection *sec; | |
275 | { | |
276 | return 1; | |
277 | } | |
278 | ||
279 | static void | |
280 | obj_ecoff_frob_symbol (sym, puntp) | |
281 | symbolS *sym; | |
282 | int *puntp; | |
283 | { | |
284 | ecoff_frob_symbol (sym); | |
285 | } | |
286 | ||
287 | static void | |
288 | ecoff_pop_insert () | |
289 | { | |
290 | pop_insert (obj_pseudo_table); | |
291 | } | |
292 | ||
293 | const struct format_ops ecoff_format_ops = | |
294 | { | |
295 | bfd_target_ecoff_flavour, | |
4c63da97 AM |
296 | 0, /* dfl_leading_underscore */ |
297 | 1, /* emit_section_symbols */ | |
252b5132 RH |
298 | obj_ecoff_frob_symbol, |
299 | ecoff_frob_file, | |
4c63da97 AM |
300 | 0, /* frob_file_after_relocs */ |
301 | 0, /* s_get_size */ | |
302 | 0, /* s_set_size */ | |
303 | 0, /* s_get_align */ | |
304 | 0, /* s_set_align */ | |
305 | 0, /* s_get_other */ | |
306 | 0, /* s_get_desc */ | |
307 | 0, /* copy_symbol_attributes */ | |
252b5132 RH |
308 | ecoff_generate_asm_lineno, |
309 | ecoff_stab, | |
310 | ecoff_sec_sym_ok_for_reloc, | |
311 | ecoff_pop_insert, | |
312 | ecoff_set_ext, | |
313 | ecoff_read_begin_hook, | |
314 | ecoff_symbol_new_hook, | |
315 | }; |