diff options
author | Ken Raeburn <raeburn@cygnus> | 1995-05-10 23:08:40 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@cygnus> | 1995-05-10 23:08:40 +0000 |
commit | e7757ad0bc0d57143b4b313c56ce42abe63560cd (patch) | |
tree | 647c9947e4749bf15d53bc0c5b81fb75efdb9079 /gas/config | |
parent | 5c36767ef41ecf7aa5e174a8449112f46a87a7a0 (diff) | |
download | gdb-e7757ad0bc0d57143b4b313c56ce42abe63560cd.zip gdb-e7757ad0bc0d57143b4b313c56ce42abe63560cd.tar.gz gdb-e7757ad0bc0d57143b4b313c56ce42abe63560cd.tar.bz2 |
First cut at handling multiple emulation modes for some MIPS targets.
Mostly works, not entirely.
Details in ChangeLog.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/e-mipsecoff.c | 25 | ||||
-rw-r--r-- | gas/config/e-mipself.c | 25 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 414 | ||||
-rw-r--r-- | gas/config/obj-multi.c | 4 | ||||
-rw-r--r-- | gas/config/te-multi.h | 22 |
5 files changed, 342 insertions, 148 deletions
diff --git a/gas/config/e-mipsecoff.c b/gas/config/e-mipsecoff.c new file mode 100644 index 0000000..e766ee1 --- /dev/null +++ b/gas/config/e-mipsecoff.c @@ -0,0 +1,25 @@ +#include "as.h" +#include "emul.h" + +static const char * +mipsecoff_bfd_name () +{ + abort (); +} + +#define emul_bfd_name mipsecoff_bfd_name +#define emul_format &ecoff_format_ops + +#define emul_name "mipsbecoff" +#define emul_struct_name mipsbecoff +#define emul_default_endian 1 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipslecoff" +#define emul_struct_name mipslecoff +#define emul_default_endian 0 +#include "emul-target.h" diff --git a/gas/config/e-mipself.c b/gas/config/e-mipself.c new file mode 100644 index 0000000..a2ba055 --- /dev/null +++ b/gas/config/e-mipself.c @@ -0,0 +1,25 @@ +#include "as.h" +#include "emul.h" + +static const char * +mipself_bfd_name () +{ + abort (); +} + +#define emul_bfd_name mipself_bfd_name +#define emul_format &elf_format_ops + +#define emul_name "mipsbelf" +#define emul_struct_name mipsbelf +#define emul_default_endian 1 +#include "emul-target.h" + +#undef emul_name +#undef emul_struct_name +#undef emul_default_endian + +#define emul_name "mipslelf" +#define emul_struct_name mipslelf +#define emul_default_endian 0 +#include "emul-target.h" diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 33429e5..a349e55 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -17,11 +17,16 @@ License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define OBJ_HEADER "obj-elf.h" #include "as.h" #include "subsegs.h" #include "obstack.h" -#ifdef ECOFF_DEBUGGING +#ifndef ECOFF_DEBUGGING +#define ECOFF_DEBUGGING 0 +#endif + +#if ECOFF_DEBUGGING #include "ecoff.h" #endif @@ -29,7 +34,7 @@ #include "elf/mips.h" #endif -#ifdef ECOFF_DEBUGGING +#if ECOFF_DEBUGGING static boolean elf_get_extr PARAMS ((asymbol *, EXTR *)); static void elf_set_index PARAMS ((asymbol *, bfd_size_type)); #endif @@ -45,7 +50,7 @@ static void obj_elf_common PARAMS ((int)); static void obj_elf_data PARAMS ((int)); static void obj_elf_text PARAMS ((int)); -const pseudo_typeS obj_pseudo_table[] = +static const pseudo_typeS elf_pseudo_table[] = { {"comm", obj_elf_common, 0}, {"ident", obj_elf_ident, 0}, @@ -69,7 +74,12 @@ const pseudo_typeS obj_pseudo_table[] = {"data", obj_elf_data, 0}, {"text", obj_elf_text, 0}, -#ifdef ECOFF_DEBUGGING + /* End sentinel. */ + {NULL}, +}; + +static const pseudo_typeS ecoff_debug_pseudo_table[] = +{ /* COFF style debugging information for ECOFF. .ln is not used; .loc is used instead. */ { "def", ecoff_directive_def, 0 }, @@ -104,7 +114,6 @@ const pseudo_typeS obj_pseudo_table[] = { "noalias", s_ignore, 0 }, { "verstamp", s_ignore, 0 }, { "vreg", s_ignore, 0 }, -#endif /* ECOFF_DEBUGGING */ {NULL} /* end sentinel */ }; @@ -113,6 +122,58 @@ const pseudo_typeS obj_pseudo_table[] = #include "aout/aout64.h" void +elf_pop_insert () +{ + pop_insert (elf_pseudo_table); + if (ECOFF_DEBUGGING) + pop_insert (ecoff_debug_pseudo_table); +} + +static bfd_vma +elf_s_get_size (sym) + symbolS *sym; +{ + return S_GET_SIZE (sym); +} + +static void +elf_s_set_size (sym, sz) + symbolS *sym; + bfd_vma sz; +{ + S_SET_SIZE (sym, sz); +} + +static bfd_vma +elf_s_get_align (sym) + symbolS *sym; +{ + return S_GET_ALIGN (sym); +} + +static void +elf_s_set_align (sym, align) + symbolS *sym; + bfd_vma align; +{ + S_SET_ALIGN (sym, align); +} + +static void +elf_copy_symbol_attributes (dest, src) + symbolS *dest, *src; +{ + OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); +} + +static int +elf_sec_sym_ok_for_reloc (sec) + asection *sec; +{ + return obj_sec_sym_ok_for_reloc (sec); +} + +void elf_file_symbol (s) char *s; { @@ -231,9 +292,10 @@ obj_elf_common (ignore) { allocate_common: S_SET_VALUE (symbolP, (valueT) size); + S_SET_ALIGN (symbolP, temp); S_SET_EXTERNAL (symbolP); /* should be common, but this is how gas does it for now */ - S_SET_SEGMENT (symbolP, &bfd_und_section); + S_SET_SEGMENT (symbolP, bfd_und_section_ptr); } } else @@ -410,6 +472,10 @@ obj_elf_section (xxx) int i; flagword flags; +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + /* Get name of section. */ SKIP_WHITESPACE (); if (*input_line_pointer == '"') @@ -455,6 +521,11 @@ obj_elf_section (xxx) while (! is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; ++input_line_pointer; + +#ifdef md_elf_section_change_hook + md_elf_section_change_hook (); +#endif + return; } @@ -591,16 +662,23 @@ obj_elf_section (xxx) | ((attr & SHF_WRITE) ? 0 : SEC_READONLY) | ((attr & SHF_ALLOC) ? SEC_ALLOC | SEC_LOAD : 0) | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)); - if (type == SHT_PROGBITS) - flags |= SEC_ALLOC | SEC_LOAD; - else if (type == SHT_NOBITS) + if (special_sections[i].name == NULL) { - flags |= SEC_ALLOC; - flags &=~ SEC_LOAD; + if (type == SHT_PROGBITS) + flags |= SEC_ALLOC | SEC_LOAD; + else if (type == SHT_NOBITS) + { + flags |= SEC_ALLOC; + flags &=~ SEC_LOAD; + } } bfd_set_section_flags (stdoutput, sec, flags); +#ifdef md_elf_section_change_hook + md_elf_section_change_hook (); +#endif + demand_empty_rest_of_line (); } @@ -652,28 +730,18 @@ obj_elf_line (ignore) void obj_read_begin_hook () { -#ifdef ECOFF_DEBUGGING - ecoff_read_begin_hook (); -#endif + if (ECOFF_DEBUGGING) + ecoff_read_begin_hook (); } void obj_symbol_new_hook (symbolP) symbolS *symbolP; { -#if 0 /* BFD already takes care of this */ - elf32_symbol_type *esym = (elf32_symbol_type *) symbolP; + symbolP->sy_obj = 0; - /* There is an Elf_Internal_Sym and an Elf_External_Sym. For now, - just zero them out. */ - - bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym)); - bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym)); - bzero ((char *) &esym->tc_data, sizeof (esym->tc_data)); -#endif -#ifdef ECOFF_DEBUGGING - ecoff_symbol_new_hook (symbolP); -#endif + if (ECOFF_DEBUGGING) + ecoff_symbol_new_hook (symbolP); } void @@ -779,64 +847,65 @@ obj_elf_size (ignore) S_SET_SIZE (sym, exp.X_add_number); else { -#if 0 - static int warned; - if (!warned) - { - as_tsktsk (".size expressions not yet supported, ignored"); - warned++; - } -#endif + sym->sy_obj = (expressionS *) xmalloc (sizeof (expressionS)); + *sym->sy_obj = exp; } demand_empty_rest_of_line (); } +/* Handle the ELF .type pseudo-op. This sets the type of a symbol. + There are three syntaxes. The first (used on Solaris) is + .type SYM,#function + The second (used on UnixWare) is + .type SYM,@function + The third (reportedly to be used on Irix 6.0) is + .type SYM STT_FUNC + + FIXME: We do not fully support this pseudo-op. In fact, the only + case we do support is setting the type to STT_FUNC, which we do by + setting the BSF_FUNCTION flag. */ + static void obj_elf_type (ignore) int ignore; { - char *name = input_line_pointer; - char c = get_symbol_end (); - char *p; - int type = 0; + char *name; + char c; + int type; + const char *typename; symbolS *sym; - p = input_line_pointer; - *p = c; + name = input_line_pointer; + c = get_symbol_end (); + sym = symbol_find_or_make (name); + *input_line_pointer = c; + SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("expected comma after name in .type directive"); - egress: - ignore_rest_of_line (); - return; - } - input_line_pointer++; + if (*input_line_pointer == ',') + ++input_line_pointer; + SKIP_WHITESPACE (); - if (*input_line_pointer != '#' && *input_line_pointer != '@') - { - as_bad ("expected `#' or `@' after comma in .type directive"); - goto egress; - } - input_line_pointer++; - if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1)) - { - type = BSF_FUNCTION; - input_line_pointer += sizeof ("function") - 1; - } - else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1)) - { - input_line_pointer += sizeof ("object") - 1; - } + if (*input_line_pointer == '#' || *input_line_pointer == '@') + ++input_line_pointer; + + typename = input_line_pointer; + c = get_symbol_end (); + + type = 0; + if (strcmp (typename, "function") == 0 + || strcmp (typename, "STT_FUNC") == 0) + type = BSF_FUNCTION; + else if (strcmp (typename, "object") == 0 + || strcmp (typename, "STT_OBJECT") == 0) + ; else - { - as_bad ("unrecognized symbol type, ignored"); - goto egress; - } - demand_empty_rest_of_line (); - *p = 0; - sym = symbol_find_or_make (name); + as_bad ("ignoring unrecognized symbol type \"%s\"", typename); + + *input_line_pointer = c; + sym->bsym->flags |= type; + + demand_empty_rest_of_line (); } static void @@ -879,7 +948,10 @@ obj_elf_init_stab_section (seg) UnixWare ar crashes. */ bfd_set_section_alignment (stdoutput, seg, 2); + /* Make space for this first symbol. */ p = frag_more (12); + /* Zero it out. */ + memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4); strcpy (stabstr_name, segment_name (seg)); @@ -927,7 +999,7 @@ adjust_stab_sections (abfd, sec, xxx) bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); } -#ifdef ECOFF_DEBUGGING +/* #ifdef ECOFF_DEBUGGING */ /* This function is called by the ECOFF code. It is supposed to record the external symbol information so that the backend can @@ -936,11 +1008,11 @@ adjust_stab_sections (abfd, sec, xxx) in the symbol. */ void -obj_ecoff_set_ext (sym, ext) +elf_ecoff_set_ext (sym, ext) symbolS *sym; - EXTR *ext; + struct ecoff_extr *ext; { - sym->bsym->udata = (PTR) ext; + sym->bsym->udata.p = (PTR) ext; } /* This function is called by bfd_ecoff_debug_externals. It is @@ -952,9 +1024,9 @@ elf_get_extr (sym, ext) asymbol *sym; EXTR *ext; { - if (sym->udata == NULL) + if (sym->udata.p == NULL) return false; - *ext = *(EXTR *) sym->udata; + *ext = *(EXTR *) sym->udata.p; return true; } @@ -969,94 +1041,140 @@ elf_set_index (sym, indx) { } -#endif /* ECOFF_DEBUGGING */ +/* #endif /* ECOFF_DEBUGGING */ + +void +elf_frob_symbol (symp, puntp) + symbolS *symp; + int *puntp; +{ + if (ECOFF_DEBUGGING) + ecoff_frob_symbol (symp); + + if (symp->sy_obj) + { + switch (symp->sy_obj->X_op) + { + case O_subtract: + S_SET_SIZE (symp, + (S_GET_VALUE (symp->sy_obj->X_add_symbol) + + symp->sy_obj->X_add_number + - S_GET_VALUE (symp->sy_obj->X_op_symbol))); + break; + case O_constant: + S_SET_SIZE (symp, + (S_GET_VALUE (symp->sy_obj->X_add_symbol) + + symp->sy_obj->X_add_number)); + break; + default: + as_bad (".size expression too complicated to fix up"); + break; + } + } + free (symp->sy_obj); + symp->sy_obj = 0; + + /* Double check weak symbols. */ + if (symp->bsym->flags & BSF_WEAK) + { + if (S_IS_COMMON (symp)) + as_bad ("Symbol `%s' can not be both weak and common", + S_GET_NAME (symp)); + } +} void elf_frob_file () { bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); -#ifdef elf_tc_symbol - { - int i; - - for (i = 0; i < stdoutput->symcount; i++) - elf_tc_symbol (stdoutput, (PTR) (stdoutput->outsymbols[i]), - i + 1); - } -#endif - #ifdef elf_tc_final_processing elf_tc_final_processing (); #endif - /* Finally, we must make any target-specific sections. */ - -#ifdef elf_tc_make_sections - elf_tc_make_sections (stdoutput); -#endif - -#ifdef ECOFF_DEBUGGING - /* Generate the ECOFF debugging information. */ - { - const struct ecoff_debug_swap *debug_swap; - struct ecoff_debug_info debug; - char *buf; - asection *sec; + if (ECOFF_DEBUGGING) + /* Generate the ECOFF debugging information. */ + { + const struct ecoff_debug_swap *debug_swap; + struct ecoff_debug_info debug; + char *buf; + asection *sec; - debug_swap - = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; - know (debug_swap != (const struct ecoff_debug_swap *) NULL); - ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); + debug_swap + = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; + know (debug_swap != (const struct ecoff_debug_swap *) NULL); + ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); - /* Set up the pointers in debug. */ + /* Set up the pointers in debug. */ #define SET(ptr, offset, type) \ debug.ptr = (type) (buf + debug.symbolic_header.offset) - SET (line, cbLineOffset, unsigned char *); - SET (external_dnr, cbDnOffset, PTR); - SET (external_pdr, cbPdOffset, PTR); - SET (external_sym, cbSymOffset, PTR); - SET (external_opt, cbOptOffset, PTR); - SET (external_aux, cbAuxOffset, union aux_ext *); - SET (ss, cbSsOffset, char *); - SET (external_fdr, cbFdOffset, PTR); - SET (external_rfd, cbRfdOffset, PTR); - /* ssext and external_ext are set up just below. */ + SET (line, cbLineOffset, unsigned char *); + SET (external_dnr, cbDnOffset, PTR); + SET (external_pdr, cbPdOffset, PTR); + SET (external_sym, cbSymOffset, PTR); + SET (external_opt, cbOptOffset, PTR); + SET (external_aux, cbAuxOffset, union aux_ext *); + SET (ss, cbSsOffset, char *); + SET (external_fdr, cbFdOffset, PTR); + SET (external_rfd, cbRfdOffset, PTR); + /* ssext and external_ext are set up just below. */ #undef SET - /* Set up the external symbols. */ - debug.ssext = debug.ssext_end = NULL; - debug.external_ext = debug.external_ext_end = NULL; - if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, - elf_get_extr, elf_set_index)) - as_fatal ("Failed to set up debugging information: %s", - bfd_errmsg (bfd_error)); - - sec = bfd_get_section_by_name (stdoutput, ".mdebug"); - assert (sec != NULL); - - know (stdoutput->output_has_begun == false); - - /* We set the size of the section, call bfd_set_section_contents - to force the ELF backend to allocate a file position, and then - write out the data. FIXME: Is this really the best way to do - this? */ - sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); - - if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL, - (file_ptr) 0, (bfd_size_type) 0)) - as_fatal ("Can't start writing .mdebug section: %s", - bfd_errmsg (bfd_error)); - - know (stdoutput->output_has_begun == true); - know (sec->filepos != 0); - - if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, - sec->filepos)) - as_fatal ("Could not write .mdebug section: %s", - bfd_errmsg (bfd_error)); - } -#endif /* ECOFF_DEBUGGING */ + /* Set up the external symbols. */ + debug.ssext = debug.ssext_end = NULL; + debug.external_ext = debug.external_ext_end = NULL; + if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, + elf_get_extr, elf_set_index)) + as_fatal ("Failed to set up debugging information: %s", + bfd_errmsg (bfd_get_error ())); + + sec = bfd_get_section_by_name (stdoutput, ".mdebug"); + assert (sec != NULL); + + know (stdoutput->output_has_begun == false); + + /* We set the size of the section, call bfd_set_section_contents + to force the ELF backend to allocate a file position, and then + write out the data. FIXME: Is this really the best way to do + this? */ + sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); + + if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL, + (file_ptr) 0, (bfd_size_type) 0)) + as_fatal ("Can't start writing .mdebug section: %s", + bfd_errmsg (bfd_get_error ())); + + know (stdoutput->output_has_begun == true); + know (sec->filepos != 0); + + if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, + sec->filepos)) + as_fatal ("Could not write .mdebug section: %s", + bfd_errmsg (bfd_get_error ())); + } } + +const struct format_ops elf_format_ops = +{ + bfd_target_elf_flavour, + 0, + 1, + elf_frob_symbol, + elf_frob_file, + elf_s_get_size, elf_s_set_size, + elf_s_get_align, elf_s_set_align, + elf_copy_symbol_attributes, +#ifdef ECOFF_DEBUGGING + ecoff_generate_asm_lineno, +#else + 0, +#endif + 0, /* process_stab */ + elf_sec_sym_ok_for_reloc, + elf_pop_insert, + elf_ecoff_set_ext, + obj_read_begin_hook, + obj_symbol_new_hook, +}; diff --git a/gas/config/obj-multi.c b/gas/config/obj-multi.c new file mode 100644 index 0000000..d115093 --- /dev/null +++ b/gas/config/obj-multi.c @@ -0,0 +1,4 @@ +/* foo */ + +#include "as.h" + diff --git a/gas/config/te-multi.h b/gas/config/te-multi.h new file mode 100644 index 0000000..b8eda45 --- /dev/null +++ b/gas/config/te-multi.h @@ -0,0 +1,22 @@ +/* + * This file is te-generic.h and is intended to be a template for + * target environment specific header files. + * + * It is my intent that this file will evolve into a file suitable for config, + * compile, and copying as an aid for testing and porting. xoxorich. + */ + +/* Added these, because if we don't know what we're targetting we may + need an assembler version of libgcc, and that will use local + labels. */ +#define LOCAL_LABELS_DOLLAR 1 +#define LOCAL_LABELS_FB 1 + +/* these define interfaces */ +#ifdef OBJ_HEADER +#include OBJ_HEADER +#else +#include "obj-format.h" +#endif + +/* end of te-generic.h */ |