obj-ecoff.c revision 89857
1290001Sglebius/* ECOFF object file format. 2290001Sglebius Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 3290001Sglebius Free Software Foundation, Inc. 4290001Sglebius Contributed by Cygnus Support. 5290001Sglebius This file was put together by Ian Lance Taylor <ian@cygnus.com>. 6290001Sglebius 7290001Sglebius This file is part of GAS. 8290001Sglebius 9290001Sglebius GAS is free software; you can redistribute it and/or modify 10290001Sglebius it under the terms of the GNU General Public License as published by 11290001Sglebius the Free Software Foundation; either version 2, or (at your option) 12290001Sglebius any later version. 13290001Sglebius 14290001Sglebius GAS is distributed in the hope that it will be useful, 15290001Sglebius but WITHOUT ANY WARRANTY; without even the implied warranty of 16290001Sglebius MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17290001Sglebius GNU General Public License for more details. 18290001Sglebius 19290001Sglebius You should have received a copy of the GNU General Public License 20290001Sglebius along with GAS; see the file COPYING. If not, write to the Free 21290001Sglebius Software Foundation, 59 Temple Place - Suite 330, Boston, MA 22290001Sglebius 02111-1307, USA. */ 23290001Sglebius 24290001Sglebius#define OBJ_HEADER "obj-ecoff.h" 25290001Sglebius#include "as.h" 26290001Sglebius#include "coff/internal.h" 27290001Sglebius#include "bfd/libcoff.h" 28290001Sglebius#include "bfd/libecoff.h" 29290001Sglebius 30290001Sglebius/* Almost all of the ECOFF support is actually in ecoff.c in the main 31290001Sglebius gas directory. This file mostly just arranges to call that one at 32290001Sglebius the right times. */ 33290001Sglebius 34290001Sglebiusstatic int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *)); 35290001Sglebiusstatic void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *)); 36290001Sglebiusstatic void ecoff_pop_insert PARAMS ((void)); 37290001Sglebiusstatic int ecoff_separate_stab_sections PARAMS ((void)); 38290001Sglebius 39290001Sglebius/* These are the pseudo-ops we support in this file. Only those 40290001Sglebius relating to debugging information are supported here. 41290001Sglebius 42290001Sglebius The following pseudo-ops from the Kane and Heinrich MIPS book 43290001Sglebius should be defined here, but are currently unsupported: .aent, 44290001Sglebius .bgnb, .endb, .verstamp, .vreg. 45290001Sglebius 46290001Sglebius The following pseudo-ops from the Kane and Heinrich MIPS book are 47290001Sglebius MIPS CPU specific, and should be defined by tc-mips.c: .alias, 48290001Sglebius .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, 49290001Sglebius .rdata, .sdata, .set. 50290001Sglebius 51290001Sglebius The following pseudo-ops from the Kane and Heinrich MIPS book are 52290001Sglebius not MIPS CPU specific, but are also not ECOFF specific. I have 53290001Sglebius only listed the ones which are not already in read.c. It's not 54290001Sglebius completely clear where these should be defined, but tc-mips.c is 55290001Sglebius probably the most reasonable place: .asciiz, .asm0, .endr, .err, 56290001Sglebius .half, .lab, .repeat, .struct, .weakext. */ 57290001Sglebius 58290001Sglebiusconst pseudo_typeS obj_pseudo_table[] = 59290001Sglebius{ 60290001Sglebius /* COFF style debugging information. .ln is not used; .loc is used 61290001Sglebius instead. */ 62290001Sglebius { "def", ecoff_directive_def, 0 }, 63290001Sglebius { "dim", ecoff_directive_dim, 0 }, 64290001Sglebius { "endef", ecoff_directive_endef, 0 }, 65290001Sglebius { "file", ecoff_directive_file, 0 }, 66290001Sglebius { "scl", ecoff_directive_scl, 0 }, 67290001Sglebius { "size", ecoff_directive_size, 0 }, 68290001Sglebius { "esize", ecoff_directive_size, 0 }, 69290001Sglebius { "tag", ecoff_directive_tag, 0 }, 70290001Sglebius { "type", ecoff_directive_type, 0 }, 71290001Sglebius { "etype", ecoff_directive_type, 0 }, 72290001Sglebius { "val", ecoff_directive_val, 0 }, 73290001Sglebius 74290001Sglebius /* ECOFF specific debugging information. */ 75290001Sglebius { "begin", ecoff_directive_begin, 0 }, 76290001Sglebius { "bend", ecoff_directive_bend, 0 }, 77290001Sglebius { "end", ecoff_directive_end, 0 }, 78290001Sglebius { "ent", ecoff_directive_ent, 0 }, 79290001Sglebius { "fmask", ecoff_directive_fmask, 0 }, 80290001Sglebius { "frame", ecoff_directive_frame, 0 }, 81290001Sglebius { "loc", ecoff_directive_loc, 0 }, 82290001Sglebius { "mask", ecoff_directive_mask, 0 }, 83290001Sglebius 84290001Sglebius /* Other ECOFF directives. */ 85290001Sglebius { "extern", ecoff_directive_extern, 0 }, 86290001Sglebius 87290001Sglebius#ifndef TC_MIPS 88290001Sglebius /* For TC_MIPS, tc-mips.c adds this. */ 89290001Sglebius { "weakext", ecoff_directive_weakext, 0 }, 90290001Sglebius#endif 91290001Sglebius 92290001Sglebius /* These are used on Irix. I don't know how to implement them. */ 93290001Sglebius { "bgnb", s_ignore, 0 }, 94290001Sglebius { "endb", s_ignore, 0 }, 95290001Sglebius { "verstamp", s_ignore, 0 }, 96290001Sglebius 97290001Sglebius /* Sentinel. */ 98290001Sglebius { NULL, s_ignore, 0 } 99290001Sglebius}; 100290001Sglebius 101290001Sglebius/* Swap out the symbols and debugging information for BFD. */ 102290001Sglebius 103290001Sglebiusvoid 104290001Sglebiusecoff_frob_file () 105290001Sglebius{ 106290001Sglebius const struct ecoff_debug_swap * const debug_swap 107290001Sglebius = &ecoff_backend (stdoutput)->debug_swap; 108290001Sglebius bfd_vma addr; 109290001Sglebius asection **sec; 110290001Sglebius HDRR *hdr; 111290001Sglebius char *buf; 112290001Sglebius char *set; 113290001Sglebius 114290001Sglebius /* Set the section VMA values. We force the .sdata and .sbss 115290001Sglebius sections to the end to ensure that their VMA addresses are close 116290001Sglebius together so that the GP register can address both of them. We 117290001Sglebius put the .bss section after the .sbss section. 118290001Sglebius 119290001Sglebius Also, for the Alpha, we must sort the sections, to make sure they 120290001Sglebius appear in the output file in the correct order. (Actually, maybe 121290001Sglebius this is a job for BFD. But the VMAs computed would be out of 122290001Sglebius whack if we computed them given our initial, random ordering. 123290001Sglebius It's possible that that wouldn't break things; I could do some 124290001Sglebius experimenting sometime and find out. 125290001Sglebius 126290001Sglebius This output ordering of sections is magic, on the Alpha, at 127290001Sglebius least. The .lita section must come before .lit8 and .lit4, 128290001Sglebius otherwise the OSF/1 linker may silently trash the .lit{4,8} 129290001Sglebius section contents. Also, .text must preceed .rdata. These differ 130290001Sglebius from the order described in some parts of the DEC OSF/1 Assembly 131290001Sglebius Language Programmer's Guide, but that order doesn't seem to work 132290001Sglebius with their linker. 133290001Sglebius 134290001Sglebius I don't know if section ordering on the MIPS is important. */ 135290001Sglebius 136290001Sglebius static const char *const names[] = { 137290001Sglebius /* text segment */ 138290001Sglebius ".text", ".rdata", ".init", ".fini", 139290001Sglebius /* data segment */ 140290001Sglebius ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got", 141290001Sglebius /* bss segment */ 142290001Sglebius ".sbss", ".bss", 143290001Sglebius }; 144290001Sglebius#define n_names ((int) (sizeof (names) / sizeof (names[0]))) 145290001Sglebius 146290001Sglebius /* Sections that match names, order to be straightened out later. */ 147290001Sglebius asection *secs[n_names]; 148290001Sglebius int i; 149290001Sglebius 150290001Sglebius addr = 0; 151290001Sglebius for (i = 0; i < n_names; i++) 152290001Sglebius secs[i] = 0; 153290001Sglebius 154290001Sglebius for (sec = &stdoutput->sections; *sec != (asection *) NULL; ) 155290001Sglebius { 156290001Sglebius for (i = 0; i < n_names; i++) 157290001Sglebius if (!strcmp ((*sec)->name, names[i])) 158290001Sglebius { 159290001Sglebius secs[i] = *sec; 160290001Sglebius bfd_section_list_remove (stdoutput, sec); 161290001Sglebius break; 162290001Sglebius } 163290001Sglebius if (i == n_names) 164290001Sglebius { 165290001Sglebius bfd_set_section_vma (stdoutput, *sec, addr); 166290001Sglebius addr += bfd_section_size (stdoutput, *sec); 167290001Sglebius sec = &(*sec)->next; 168290001Sglebius } 169290001Sglebius } 170290001Sglebius for (i = 0; i < n_names; i++) 171290001Sglebius if (secs[i]) 172290001Sglebius { 173290001Sglebius bfd_set_section_vma (stdoutput, secs[i], addr); 174290001Sglebius addr += bfd_section_size (stdoutput, secs[i]); 175290001Sglebius } 176290001Sglebius for (i = n_names - 1; i >= 0; i--) 177290001Sglebius if (secs[i]) 178290001Sglebius bfd_section_list_insert (stdoutput, &stdoutput->sections, secs[i]); 179290001Sglebius 180290001Sglebius /* Build the ECOFF debugging information. */ 181290001Sglebius assert (ecoff_data (stdoutput) != 0); 182290001Sglebius hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header; 183290001Sglebius ecoff_build_debug (hdr, &buf, debug_swap); 184290001Sglebius 185290001Sglebius /* Finish up the ecoff_tdata structure. */ 186290001Sglebius set = buf; 187290001Sglebius#define SET(ptr, count, type, size) \ 188290001Sglebius if (hdr->count == 0) \ 189290001Sglebius ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ 190290001Sglebius else \ 191290001Sglebius { \ 192290001Sglebius ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ 193290001Sglebius set += hdr->count * size; \ 194290001Sglebius } 195290001Sglebius 196290001Sglebius SET (line, cbLine, unsigned char *, sizeof (unsigned char)); 197290001Sglebius SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size); 198290001Sglebius SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size); 199290001Sglebius SET (external_sym, isymMax, PTR, debug_swap->external_sym_size); 200290001Sglebius SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size); 201290001Sglebius SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); 202290001Sglebius SET (ss, issMax, char *, sizeof (char)); 203290001Sglebius SET (ssext, issExtMax, char *, sizeof (char)); 204290001Sglebius SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size); 205290001Sglebius SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size); 206290001Sglebius SET (external_ext, iextMax, PTR, debug_swap->external_ext_size); 207290001Sglebius 208290001Sglebius#undef SET 209290001Sglebius 210290001Sglebius /* Fill in the register masks. */ 211290001Sglebius { 212290001Sglebius unsigned long gprmask = 0; 213290001Sglebius unsigned long fprmask = 0; 214290001Sglebius unsigned long *cprmask = NULL; 215290001Sglebius 216290001Sglebius#ifdef TC_MIPS 217290001Sglebius /* Fill in the MIPS register masks. It's probably not worth 218290001Sglebius setting up a generic interface for this. */ 219290001Sglebius gprmask = mips_gprmask; 220290001Sglebius cprmask = mips_cprmask; 221290001Sglebius#endif 222290001Sglebius 223290001Sglebius#ifdef TC_ALPHA 224290001Sglebius alpha_frob_ecoff_data (); 225290001Sglebius 226290001Sglebius if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value)) 227290001Sglebius as_fatal (_("Can't set GP value")); 228290001Sglebius 229290001Sglebius gprmask = alpha_gprmask; 230290001Sglebius fprmask = alpha_fprmask; 231290001Sglebius#endif 232290001Sglebius 233290001Sglebius if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) 234290001Sglebius as_fatal (_("Can't set register masks")); 235290001Sglebius } 236290001Sglebius} 237290001Sglebius 238290001Sglebius/* This is called by the ECOFF code to set the external information 239290001Sglebius for a symbol. We just pass it on to BFD, which expects the swapped 240290001Sglebius information to be stored in the native field of the symbol. */ 241290001Sglebius 242290001Sglebiusvoid 243290001Sglebiusobj_ecoff_set_ext (sym, ext) 244290001Sglebius symbolS *sym; 245290001Sglebius EXTR *ext; 246290001Sglebius{ 247290001Sglebius const struct ecoff_debug_swap * const debug_swap 248290001Sglebius = &ecoff_backend (stdoutput)->debug_swap; 249290001Sglebius ecoff_symbol_type *esym; 250290001Sglebius 251290001Sglebius know (bfd_asymbol_flavour (symbol_get_bfdsym (sym)) 252290001Sglebius == bfd_target_ecoff_flavour); 253290001Sglebius esym = ecoffsymbol (symbol_get_bfdsym (sym)); 254290001Sglebius esym->local = false; 255290001Sglebius esym->native = xmalloc (debug_swap->external_ext_size); 256290001Sglebius (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native); 257290001Sglebius} 258290001Sglebius 259290001Sglebiusstatic int 260290001Sglebiusecoff_sec_sym_ok_for_reloc (sec) 261290001Sglebius asection *sec ATTRIBUTE_UNUSED; 262290001Sglebius{ 263290001Sglebius return 1; 264290001Sglebius} 265290001Sglebius 266290001Sglebiusstatic void 267290001Sglebiusobj_ecoff_frob_symbol (sym, puntp) 268290001Sglebius symbolS *sym; 269290001Sglebius int *puntp ATTRIBUTE_UNUSED; 270290001Sglebius{ 271290001Sglebius ecoff_frob_symbol (sym); 272290001Sglebius} 273290001Sglebius 274290001Sglebiusstatic void 275290001Sglebiusecoff_pop_insert () 276290001Sglebius{ 277290001Sglebius pop_insert (obj_pseudo_table); 278290001Sglebius} 279290001Sglebius 280290001Sglebiusstatic int 281290001Sglebiusecoff_separate_stab_sections () 282290001Sglebius{ 283290001Sglebius return 0; 284290001Sglebius} 285290001Sglebius 286290001Sglebiusconst struct format_ops ecoff_format_ops = 287290001Sglebius{ 288290001Sglebius bfd_target_ecoff_flavour, 289290001Sglebius 0, /* dfl_leading_underscore */ 290290001Sglebius 291290001Sglebius /* FIXME: A comment why emit_section_symbols is different here (1) from 292290001Sglebius the single-format definition (0) would be in order. */ 293290001Sglebius 1, /* emit_section_symbols */ 294290001Sglebius 0, /* begin */ 295290001Sglebius ecoff_new_file, 296290001Sglebius obj_ecoff_frob_symbol, 297290001Sglebius ecoff_frob_file, 298290001Sglebius 0, /* frob_file_before_adjust */ 299290001Sglebius 0, /* frob_file_after_relocs */ 300290001Sglebius 0, /* s_get_size */ 301290001Sglebius 0, /* s_set_size */ 302290001Sglebius 0, /* s_get_align */ 303290001Sglebius 0, /* s_set_align */ 304290001Sglebius 0, /* s_get_other */ 305290001Sglebius 0, /* s_set_other */ 306290001Sglebius 0, /* s_get_desc */ 307290001Sglebius 0, /* s_set_desc */ 308290001Sglebius 0, /* s_get_type */ 309290001Sglebius 0, /* s_set_type */ 310290001Sglebius 0, /* copy_symbol_attributes */ 311290001Sglebius ecoff_generate_asm_lineno, 312290001Sglebius ecoff_stab, 313290001Sglebius ecoff_separate_stab_sections, 314290001Sglebius 0, /* init_stab_section */ 315290001Sglebius ecoff_sec_sym_ok_for_reloc, 316290001Sglebius ecoff_pop_insert, 317290001Sglebius ecoff_set_ext, 318290001Sglebius ecoff_read_begin_hook, 319290001Sglebius ecoff_symbol_new_hook 320290001Sglebius}; 321290001Sglebius