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