From: Alan Modra Date: Wed, 23 May 2001 03:41:11 +0000 (+0000) Subject: Merge from mainline. X-Git-Tag: binutils-2_11_1~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a80684272f00101fbff801f8e30856bf7a6c786;p=thirdparty%2Fbinutils-gdb.git Merge from mainline. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afec33559cd..8946131e489 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,45 @@ +2001-05-23 Alan Modra + + Merge from mainline. + 2001-05-17 Alan Modra + * elf32-hppa.c (hppa_build_one_stub): Add an assert to check + plt.offset. + + 2001-05-16 Alan Modra + * section.c (asection): Add linker_has_input field. + (STD_SECTION): Adjust initialization to suit. + * ecoff.c (bfd_debug_section): Likewise. + * bfd-in2.h: Regenerate. + + 2001-05-07 Thiemo Seufer + * ecoff.c (bfd_debug_section): Fix initialization. + + 2001-05-12 Peter Targett + * cpu-arc.c (arch_info_struct): Add entry 'base' representing old + name for 'arc5' core versions. + (bfd_arc_arch): Make bfd_mach_arc_6 default. + * elf32-arc.c (arc_elf_object_p): Make E_ARC_MACH_ARC6 default + architecture. + (arc_elf_final_write_processing): Make bfd_mach_arc_6 default. + + 2001-05-08 Ian Lance Taylor + * coff-i386.c (coff_i386_reloc): Don't dump core if output_bfd is + NULL or is not COFF. + (coff_i386_rtype_to_howto): Don't dump core if output section + owner is not COFF. + + 2001-04-13 Roger Sayle + * coff-i386.c (TARGET_SYM): SEC_READONLY is an applicable section + flag on pe-i386 targets. + + 2001-04-26 H.J. Lu + * elf32-i386.c (elf_i386_check_relocs): Verify if r_symndx is + valid. + + 2001-04-05 David Mosberger + * elf32-i386.c (elf_i386_fake_sections): Treat ".reloc" as an + ordinary "progbits" section. + 2001-05-04 Richard Henderson * elf64-alpha.c (SREL16, SREL32, SREL64): Set pcrel_offset true. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index b8e864b2eed..9a666b64f65 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1114,6 +1114,10 @@ typedef struct sec /* A mark flag used by some of the linker backends. */ unsigned int linker_mark : 1; + /* Another mark flag used by some of the linker backends. Set for + output sections that have a input section. */ + unsigned int linker_has_input : 1; + /* A mark flag used by some linker backends for garbage collection. */ unsigned int gc_mark : 1; diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c index 83d67c4a875..7d4ab5ae398 100644 --- a/bfd/coff-i386.c +++ b/bfd/coff-i386.c @@ -1,5 +1,6 @@ /* BFD back-end for Intel 386 COFF files. - Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 Free Software Foundation, Inc. Written by Cygnus Support. @@ -128,7 +129,9 @@ coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, #ifdef COFF_WITH_PE /* FIXME: How should this case be handled? */ - if (reloc_entry->howto->type == R_IMAGEBASE) + if (reloc_entry->howto->type == R_IMAGEBASE + && output_bfd != NULL + && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour) diff -= pe_data (output_bfd)->pe_opthdr.ImageBase; #endif @@ -488,7 +491,9 @@ coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp) *addendp -= sym->n_value; } - if (rel->r_type == R_IMAGEBASE) + if (rel->r_type == R_IMAGEBASE + && (bfd_get_flavour(sec->output_section->owner) + == bfd_target_coff_flavour)) { *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase; } @@ -575,7 +580,7 @@ const bfd_target (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ #ifdef COFF_WITH_PE - | SEC_LINK_ONCE | SEC_LINK_DUPLICATES + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY #endif | SEC_CODE | SEC_DATA), diff --git a/bfd/cpu-arc.c b/bfd/cpu-arc.c index dbd7fb1bae5..2904ae32d52 100644 --- a/bfd/cpu-arc.c +++ b/bfd/cpu-arc.c @@ -1,5 +1,5 @@ /* BFD support for the ARC processor - Copyright 1994, 1995, 1997 Free Software Foundation, Inc. + Copyright 1994, 1995, 1997, 2001 Free Software Foundation, Inc. Contributed by Doug Evans (dje@cygnus.com). This file is part of BFD, the Binary File Descriptor library. @@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ print_name, \ 4, /* section alignment power */ \ default_p, \ - bfd_default_compatible, \ + bfd_default_compatible, \ bfd_default_scan, \ next, \ } @@ -41,13 +41,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static const bfd_arch_info_type arch_info_struct[] = { ARC ( bfd_mach_arc_5, "arc5", false, &arch_info_struct[1] ), - ARC ( bfd_mach_arc_6, "arc6", false, &arch_info_struct[2] ), - ARC ( bfd_mach_arc_7, "arc7", false, &arch_info_struct[3] ), + ARC ( bfd_mach_arc_5, "base", false, &arch_info_struct[2] ), + ARC ( bfd_mach_arc_6, "arc6", false, &arch_info_struct[3] ), + ARC ( bfd_mach_arc_7, "arc7", false, &arch_info_struct[4] ), ARC ( bfd_mach_arc_8, "arc8", false, NULL ), }; const bfd_arch_info_type bfd_arc_arch = - ARC ( bfd_mach_arc_5, "arc", true, &arch_info_struct[0] ); + ARC ( bfd_mach_arc_6, "arc", true, &arch_info_struct[0] ); /* Utility routines. */ diff --git a/bfd/ecoff.c b/bfd/ecoff.c index f22112bd75b..db606387e90 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -1,5 +1,5 @@ /* Generic ECOFF (Extended-COFF) routines. - Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Original version by Per Bothner. Full support added by Ian Lance Taylor, ian@cygnus.com. @@ -74,20 +74,28 @@ static unsigned int ecoff_armap_hash PARAMS ((CONST char *s, static asection bfd_debug_section = { - /* name, index, next, flags, set_vma, reloc_done, linker_mark, gc_mark */ - "*DEBUG*", 0, 0, 0, 0, 0, 0, 0, - /* vma, lma, _cooked_size, _raw_size, output_offset, output_section, */ - 0, 0, 0, 0, 0, NULL, - /* alig, reloc..., orel..., reloc_count, filepos, rel_..., line_... */ - 0, 0, 0, 0, 0, 0, 0, - /* userdata, contents, lineno, lineno_count */ - 0, 0, 0, 0, - /* comdat_info, moving_line_filepos, target_index, used_by_bfd, */ - NULL, 0, 0, 0, - /* cons, owner, symbol */ - 0, 0, (struct symbol_cache_entry *) NULL, - /* symbol_ptr_ptr, link_order_head, ..._tail */ - (struct symbol_cache_entry **) NULL, NULL, NULL + /* name, id, index, next, flags, user_set_vma, reloc_done, */ + "*DEBUG*", 0, 0, NULL, 0, 0, 0, + /* linker_mark, linker_has_input, gc_mark, segment_mark, */ + 0, 0, 0, 0, + /* vma, lma, _cooked_size, _raw_size, */ + 0, 0, 0, 0, + /* output_offset, output_section, alignment_power, */ + 0, NULL, 0, + /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ + NULL, NULL, 0, 0, 0, + /* line_filepos, userdata, contents, lineno, lineno_count, */ + 0, NULL, NULL, NULL, 0, + /* comdat, kept_section, moving_line_filepos, */ + NULL, NULL, 0, + /* target_index, used_by_bfd, constructor_chain, owner, */ + 0, NULL, NULL, NULL, + /* symbol, */ + (struct symbol_cache_entry *) NULL, + /* symbol_ptr_ptr, */ + (struct symbol_cache_entry **) NULL, + /* link_order_head, link_order_tail */ + NULL, NULL }; /* Create an ECOFF object. */ diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index 254b346362f..82b610435fa 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -1,5 +1,5 @@ /* ARC-specific support for 32-bit ELF - Copyright (C) 1994, 1995, 1997, 1999, 2000 Free Software Foundation, Inc. + Copyright 1994, 1995, 1997, 1999, 2001 Free Software Foundation, Inc. Contributed by Doug Evans (dje@cygnus.com). This file is part of BFD, the Binary File Descriptor library. @@ -57,18 +57,18 @@ static reloc_howto_type elf_arc_howto_table[] = /* A standard 32 bit relocation. */ HOWTO (R_ARC_32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - false, /* pc_relative */ - 0, /* bitpos */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "R_ARC_32", /* name */ - false, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ /* A 26 bit absolute branch, right shifted by 2. */ HOWTO (R_ARC_B26, /* type */ @@ -155,7 +155,7 @@ static boolean arc_elf_object_p (abfd) bfd *abfd; { - int mach = bfd_mach_arc_5; + int mach = bfd_mach_arc_6; if (elf_elfheader(abfd)->e_machine == EM_ARC) { @@ -163,10 +163,10 @@ arc_elf_object_p (abfd) switch (arch) { - default: case E_ARC_MACH_ARC5: mach = bfd_mach_arc_5; break; + default: case E_ARC_MACH_ARC6: mach = bfd_mach_arc_6; break; @@ -193,10 +193,10 @@ arc_elf_final_write_processing (abfd, linker) switch (bfd_get_mach (abfd)) { - default: case bfd_mach_arc_5: val = E_ARC_MACH_ARC5; break; + default: case bfd_mach_arc_6: val = E_ARC_MACH_ARC6; break; diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index fdcb3b4ff7e..e46ac4ac0f5 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -938,6 +938,7 @@ hppa_build_one_stub (gen_entry, in_arg) case hppa_stub_import: case hppa_stub_import_shared: + BFD_ASSERT (stub_entry->h->elf.plt.offset < (bfd_vma) -2); sym_value = (stub_entry->h->elf.plt.offset + hplink->splt->output_offset + hplink->splt->output_section->vma diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 4ad2c2be6aa..f4e1e500c32 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,5 +1,5 @@ /* Intel 80386/80486-specific support for 32-bit ELF - Copyright 1993, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -501,6 +501,20 @@ elf_i386_check_relocs (abfd, info, sec, relocs) r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_size / symtab_hdr->sh_entsize) + { + if (abfd->my_archive) + (*_bfd_error_handler) (_("%s(%s): bad symbol index: %d"), + bfd_get_filename (abfd->my_archive), + bfd_get_filename (abfd), + r_symndx); + else + (*_bfd_error_handler) (_("%s: bad symbol index: %d"), + bfd_get_filename (abfd), + r_symndx); + return false; + } + if (r_symndx < symtab_hdr->sh_info) h = NULL; else @@ -686,7 +700,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs) (*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"), bfd_get_filename (abfd), name); - } + } sreloc = bfd_get_section_by_name (dynobj, name); if (sreloc == NULL) @@ -2066,6 +2080,44 @@ elf_i386_finish_dynamic_sections (output_bfd, info) return true; } +/* Set the correct type for an x86 ELF section. We do this by the + section name, which is a hack, but ought to work. */ + +static boolean +elf_i386_fake_sections (abfd, hdr, sec) + bfd *abfd ATTRIBUTE_UNUSED; + Elf32_Internal_Shdr *hdr; + asection *sec; +{ + register const char *name; + + name = bfd_get_section_name (abfd, sec); + + if (strcmp (name, ".reloc") == 0) + /* + * This is an ugly, but unfortunately necessary hack that is + * needed when producing EFI binaries on x86. It tells + * elf.c:elf_fake_sections() not to consider ".reloc" as a section + * containing ELF relocation info. We need this hack in order to + * be able to generate ELF binaries that can be translated into + * EFI applications (which are essentially COFF objects). Those + * files contain a COFF ".reloc" section inside an ELFNN object, + * which would normally cause BFD to segfault because it would + * attempt to interpret this section as containing relocation + * entries for section "oc". With this hack enabled, ".reloc" + * will be treated as a normal data section, which will avoid the + * segfault. However, you won't be able to create an ELFNN binary + * with a section named "oc" that needs relocations, but that's + * the kind of ugly side-effects you get when detecting section + * types based on their names... In practice, this limitation is + * unlikely to bite. + */ + hdr->sh_type = SHT_PROGBITS; + + return true; +} + + #define TARGET_LITTLE_SYM bfd_elf32_i386_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 @@ -2096,5 +2148,6 @@ elf_i386_finish_dynamic_sections (output_bfd, info) #define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook #define elf_backend_relocate_section elf_i386_relocate_section #define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections +#define elf_backend_fake_sections elf_i386_fake_sections #include "elf32-target.h" diff --git a/bfd/section.c b/bfd/section.c index 13e10d30f67..71077c90453 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -1,5 +1,6 @@ /* Object file "section" support for the BFD library. - Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 Free Software Foundation, Inc. Written by Cygnus Support. @@ -362,6 +363,10 @@ CODE_FRAGMENT . {* A mark flag used by some of the linker backends. *} . unsigned int linker_mark : 1; . +. {* Another mark flag used by some of the linker backends. Set for +. output sections that have a input section. *} +. unsigned int linker_has_input : 1; +. . {* A mark flag used by some linker backends for garbage collection. *} . unsigned int gc_mark : 1; . @@ -564,11 +569,14 @@ static const asymbol global_syms[] = /* name, id, index, next, flags, user_set_vma, reloc_done, */ \ { NAME, IDX, 0, NULL, FLAGS, 0, 0, \ \ - /* linker_mark, gc_mark, segment_mark, vma, lma, _cooked_size, */ \ - 0, 1, 0, 0, 0, 0, \ + /* linker_mark, linker_has_input, gc_mark, segment_mark, */ \ + 0, 0, 1, 0, \ + \ + /* vma, lma, _cooked_size, _raw_size, */ \ + 0, 0, 0, 0, \ \ - /* _raw_size, output_offset, output_section, alignment_power, */ \ - 0, 0, (struct sec *) &SEC, 0, \ + /* output_offset, output_section, alignment_power, */ \ + 0, (struct sec *) &SEC, 0, \ \ /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ NULL, NULL, 0, 0, 0, \ diff --git a/gas/ChangeLog b/gas/ChangeLog index 2e480b81505..0b9cd66d257 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,175 @@ +2001-05-23 Alan Modra + + Merge from mainline. + 2001-05-22 Alan Modra + * config/tc-arc.c (md_assemble): Use is_end_of_line instead of + testing for NULs. + + 2001-05-16 Alan Modra + * config/tc-arc.c (md_assemble): Correct dwarf2_emit_insn param + for 8 byte insns. + * config/tc-i386.c (md_assemble): Call dwarf2_emit_insn before + opcodes are output rather than after. Delete insn_size. + * config/tc-v850.c (md_assemble): Similarly, but delete + total_insn_size. Update copyright. + + 2001-05-03 Alan Modra + * config/tc-i386.c (i386_displacement): Call as_bad for bad GOTOFF + expressions rather than triggering an assert. + + 2001-03-30 Alan Modra + * config/tc-i386.c (UNCOND_JUMP, COND_JUMP, COND_JUMP86): Decrement. + (md_relax_table): Remove first four unused entries. Increment + rlx_length by one throughout table, and update comments to suit. + (md_estimate_size_before_relax): Return size of current variable + part of frag to reflect reality when relaxing more than once. + + 2001-03-25 Alan Modra + * config/tc-i386.c (i386_scale): Accept an absolute expression for + scale factor, and return the end of the expression. + (i386_operand): Modify for above. + + 2001-03-13 Alan Modra + * config/tc-i386.c (RELOC_ENUM): Define. Use throughout file. + (NUM_FLAG_CODE): Define. + (lex_got): New function. + (got_reloc): New global var. + (x86_cons_fix_new): New function. + (x86_cons): New function. + (i386_immediate): Use lex_got here, replacing inline code. Change + "ignoring junk.." error message to "junk.." + (i386_displacement): Likewise. + * config/tc-i386.h (TC_PARSE_CONS_EXPRESSION): Define. + (x86_cons): Declare. + (TC_CONS_FIX_NEW): Define. + (x86_cons_fix_new): Declare. + + 2001-03-07 Alan Modra + * config/tc-i386.c (struct _i386_insn): Rename disp_reloc to reloc. + (md_assemble) : Use correct field of i.op[] + union. + : Use correct i.disp_reloc[]. + : Likewise. + + 2001-02-13 Alan Modra + * doc/c-i386.texi (i386-Arch): Add "jumps"/"nojumps" blurb. + Mention effect of < 386 architectures on jump promotion. + (i386-Jumps): xref above. Don't assume long disp is 32 bits. + + * config/tc-i386.c (no_cond_jump_promotion): New. + (set_cpu_arch): Parse "jumps" arch modifier. + (insn_size): Modify usage comment. + (ENCODE_RELAX_STATE): Reformat and protect macro arg. + (SIZE_FROM_RELAX_STATE): Rename to DISP_SIZE_FROM_RELAX_STATE. + (TYPE_FROM_RELAX_STATE): New define. + (UNCOND_JUMP, COND_JUMP): Renumber. + (md_relax_table): Reorder to suit. + (COND_JUMP86): New define. + (md_relax_table): Handle COND_JUMP86 cases. Add a few comments. + (md_assemble): Create frag var for jumps of max size, encode relax + state for COND_JUMP86. + (md_estimate_size_before_relax): Handle COND_JUMP86 cases, and + leave conditional jumps small if no_cond_jump_promotion. + (md_convert_frag): Likewise. + + 2001-05-10 Alan Modra + * config/tc-v850.c (md_estimate_size_before_relax): Rewrite. + (md_convert_frag): Don't bother clearing fr_var. + (md_pseudo_table): Correct initialization. + + 2001-05-12 Peter Targett + * config/tc-arc.c: Update copyright and tidy source comments. + (md_pseudo_table): Add directive .cpu back as an alias for + .option. Add .file and .line for dwarf2 support. + (arc_mach_type): Make bfd_mach_arc_6 default. + (md_longopts): Add entry 'pre-v6' representing old command line + option when assembling for 'arc5' core versions. + (md_parse_option): Make OPTION_ARC same as OPTION_ARC6, for new + default behaviour. + (arc_code_symbol): Make symbol value for @h30 fixup expression + equal to O_constant. + (md_assemble): Call dwarf2_emit_insn. + Include "dwarf2dbg2.h". Formatting fixes throughout file. + * config/tc-arc.h (DWARF2_LINE_MIN_INSN_LENGTH): Define. + * doc/c-arc.texi (ARC_CORE_DEFAULT): Update to new default. + + 2001-05-15 Alexandre Oliva + * config/tc-mn10300.c (mn10300_force_relocation): Don't + optimize differences between symbols in code sections to + constants. + (mn10300_fix_adjustable): Don't adjust to section+offset + relocations pointing at symbols in code sections. + + 2001-05-14 Alexandre Oliva + * config/tc-mn10300.c (md_assemble): Anchor dwarf2 line info + before a relaxable insns. + + 2001-05-13 Alexandre Oliva + * config/tc-mn10300.c (tc_gen_reloc): Don't reject differences + between symbols if the base symbol is in the current section; + emit a PC-relative relocation instead. + + 2001-05-09 Alexandre Oliva + * config/tc-mn10300.c (md_apply_fix3): Accept PC-relative relocs. + + 2001-05-06 Alexandre Oliva + * config/tc-mn10300.c (md_assemble): Subtract operand->shift + from offset in non-pcrel operands too. + + 2001-04-14 Alexandre Oliva + * config/tc-mn10300.c (md_assemble): Simplify offset adjustment of + pc-relative relocations not placed at the end of the instruction. + + 2001-04-06 Alexandre Oliva + * config/tc-mn10300.c (xr_registers): Added `pc'. + + 2001-03-30 Alan Modra + * config/tc-mn10300.c (md_estimate_size_before_relax): Rewrite. + + 2001-02-23 Richard Sandiford + * config/tc-mn10300.c (md_apply_fix3): Don't mark a fixup as + done if it's against a symbol. + + 2001-03-28 H.J. Lu + * read.c (equals): Set to local for COFF only if it hasn't been + defined before. + + 2001-03-27 Nick Papadonis + * read.c (equals): (for COFF) default symbols to being local. + + 2001-03-23 Richard Sandiford + * write.c (fix_new_exp): Print an error if passed a register. + + 2001-03-20 Alan Modra + * frags.h (struct frag): Add relax_marker. + * write.c (is_dnrange): Delete. + (relax_frag): Use correct types for `aim', `target', `address'. + Delete `offset', `was_address'. Test `relax_marker' instead of + using fragile (and slow) address test. + (relax_segment): Init and flip `relax_marker'. + + 2001-02-13 Ian Lance Taylor + * write.c (is_dnrange): Stop as soon as the address becomes + larger. + (relax_frag): Add segment parameter. Only call symbol_get_frag + once. Only call is_dnrange if the symbol is in the same segment, + and the symbol address is larger. + (relax_segment): Pass segment to md_relax_frag and relax_frag. + * write.h (relax_frag): Update declaration. + * config/tc-fr30.c (fr30_relax_frag): Add segment parameter. Pass + it to relax_frag. + * config/tc-m32r.c (m32r_relax_frag): Likewise. + * config/tc-m32r.h (md_relax_frag): Add segment parameter. + (m32r_relax_frag): Update declaration. + * config/tc-mips.h (md_relax_frag): Add segment parameter. + * config/tc-tic54x.h (md_relax_frag): Likewise. + * doc/internals.texi (CPU backend): Update documentation for + md_relax_frag. + + 2001-03-15 DJ Delorie + * stabs.c (s_stab_generic): Don't corrupt the notes obstack by + blindly freeing string if it isn't at the top of the obstack. + 2001-05-14 Richard Henderson * ehopt.c (eh_frame_convert_frag): Fix missed subtype adjustment @@ -143,7 +315,7 @@ * config/tc-i386.c (tc_i386_fix_adjustable): Fix GOTPCREL GOT entry. -001-02-18 David O'Brien +2001-02-18 David O'Brien * configure.in (cpu_type, arch): Add a generic FreeBSD specification as all FreeBSD platforms should look the same at this level. diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index 39ce4038711..45f54ac4fe3 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -1,5 +1,6 @@ /* tc-arc.c -- Assembler for the ARC - Copyright (C) 1994, 1995, 1997, 2000 Free Software Foundation, Inc. + Copyright 1994, 1995, 1997, 1999, 2000, 2001 + Free Software Foundation, Inc. Contributed by Doug Evans (dje@cygnus.com). This file is part of GAS, the GNU Assembler. @@ -27,6 +28,7 @@ #include "opcode/arc.h" #include "../opcodes/arc-ext.h" #include "elf/arc.h" +#include "dwarf2dbg.h" extern int arc_get_mach PARAMS ((char *)); extern int arc_operand_type PARAMS ((int)); @@ -75,7 +77,7 @@ const struct syntax_classes { #define MAXSYNTAXCLASS (sizeof (syntaxclass) / sizeof (struct syntax_classes)) const pseudo_typeS md_pseudo_table[] = { - { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */ + { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */ { "comm", arc_common, 0 }, { "common", arc_common, 0 }, { "lcomm", arc_common, 1 }, @@ -87,7 +89,10 @@ const pseudo_typeS md_pseudo_table[] = { { "4byte", cons, 4 }, { "word", cons, 4 }, { "option", arc_option, 0 }, + { "cpu", arc_option, 0 }, { "block", s_space, 0 }, + { "file", dwarf2_directive_file, 0 }, + { "loc", dwarf2_directive_loc, 0 }, { "extcondcode", arc_extoper, 0 }, { "extcoreregister", arc_extoper, 1 }, { "extauxregister", arc_extoper, 2 }, @@ -96,7 +101,7 @@ const pseudo_typeS md_pseudo_table[] = { }; /* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful */ + pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = "#;"; /* This array holds the chars that only start a comment at the beginning of @@ -111,12 +116,11 @@ const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ +/* Chars that mean this number is a floating point constant + As in 0f12.456 or 0d1.2345e12. */ const char FLT_CHARS[] = "rRsSfFdD"; /* Byte order. */ @@ -127,13 +131,13 @@ static int byte_order = DEFAULT_BYTE_ORDER; static segT arcext_section; /* One of bfd_mach_arc_n. */ -static int arc_mach_type = bfd_mach_arc_5; +static int arc_mach_type = bfd_mach_arc_6; /* Non-zero if the cpu type has been explicitly specified. */ static int mach_type_specified_p = 0; /* Non-zero if opcode tables have been initialized. - A .cpu command must appear before any instructions. */ + A .option command must appear before any instructions. */ static int cpu_tables_init_p = 0; static struct hash_control *arc_suffix_hash = NULL; @@ -141,19 +145,20 @@ static struct hash_control *arc_suffix_hash = NULL; const char *md_shortopts = ""; struct option md_longopts[] = { #define OPTION_EB (OPTION_MD_BASE + 0) - {"EB", no_argument, NULL, OPTION_EB}, + { "EB", no_argument, NULL, OPTION_EB }, #define OPTION_EL (OPTION_MD_BASE + 1) - {"EL", no_argument, NULL, OPTION_EL}, + { "EL", no_argument, NULL, OPTION_EL }, #define OPTION_ARC5 (OPTION_MD_BASE + 2) - {"marc5", no_argument, NULL, OPTION_ARC5}, + { "marc5", no_argument, NULL, OPTION_ARC5 }, + { "pre-v6", no_argument, NULL, OPTION_ARC5 }, #define OPTION_ARC6 (OPTION_MD_BASE + 3) - {"marc6", no_argument, NULL, OPTION_ARC6}, + { "marc6", no_argument, NULL, OPTION_ARC6 }, #define OPTION_ARC7 (OPTION_MD_BASE + 4) - {"marc7", no_argument, NULL, OPTION_ARC7}, + { "marc7", no_argument, NULL, OPTION_ARC7 }, #define OPTION_ARC8 (OPTION_MD_BASE + 5) - {"marc8", no_argument, NULL, OPTION_ARC8}, + { "marc8", no_argument, NULL, OPTION_ARC8 }, #define OPTION_ARC (OPTION_MD_BASE + 6) - {"marc", no_argument, NULL, OPTION_ARC}, + { "marc", no_argument, NULL, OPTION_ARC }, { NULL, no_argument, NULL, 0 } }; size_t md_longopts_size = sizeof (md_longopts); @@ -173,10 +178,10 @@ md_parse_option (c, arg) { switch (c) { - case OPTION_ARC: case OPTION_ARC5: arc_mach_type = bfd_mach_arc_5; break; + case OPTION_ARC: case OPTION_ARC6: arc_mach_type = bfd_mach_arc_6; break; @@ -213,7 +218,7 @@ ARC Options:\n\ /* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. - Opcode selection is defered until later because we might see a .cpu + Opcode selection is deferred until later because we might see a .option command. */ void @@ -225,16 +230,14 @@ md_begin () if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type)) as_warn ("could not set architecture and machine"); - /* This call is necessary because we need to - initialize `arc_operand_map' which may be needed before we see the - first insn. */ + /* This call is necessary because we need to initialize `arc_operand_map' + which may be needed before we see the first insn. */ arc_opcode_init_tables (arc_get_opcode_mach (arc_mach_type, target_big_endian)); } /* Initialize the various opcode and operand tables. MACH is one of bfd_mach_arc_xxx. */ - static void init_opcode_tables (mach) int mach; @@ -276,8 +279,10 @@ init_opcode_tables (mach) continue; /* Use symbol_create here instead of symbol_new so we don't try to output registers into the object file's symbol table. */ - symbol_table_insert (symbol_create (arc_reg_names[i].name, reg_section, - (int) &arc_reg_names[i], &zero_address_frag)); + symbol_table_insert (symbol_create (arc_reg_names[i].name, + reg_section, + (int) &arc_reg_names[i], + &zero_address_frag)); } /* Tell `.option' it's too late. */ @@ -356,7 +361,7 @@ arc_insert_operand (insn, operand, mods, reg, val, file, line) that would screw up references to ``.''. */ struct arc_fixup { - /* index into `arc_operands' */ + /* index into `arc_operands' */ int opindex; expressionS exp; }; @@ -380,7 +385,7 @@ md_assemble (str) static int init_tables_p = 0; /* Opcode table initialization is deferred until here because we have to - wait for a possible .cpu command. */ + wait for a possible .option command. */ if (!init_tables_p) { init_opcode_tables (arc_mach_type); @@ -626,7 +631,7 @@ md_assemble (str) /* Is there anything left to parse? We don't check for this at the top because we want to parse any trailing fake arguments in the syntax string. */ - if (*str == '\0') + if (is_end_of_line[(unsigned char) *str]) break; /* Parse the operand. */ @@ -734,7 +739,7 @@ md_assemble (str) while (isspace (*str)) ++str; - if (*str != '\0') + if (!is_end_of_line[(unsigned char) *str]) as_bad ("junk at end of line: `%s'", str); /* Is there a limm value? */ @@ -801,6 +806,7 @@ md_assemble (str) f = frag_more (8); md_number_to_chars (f, insn, 4); md_number_to_chars (f + 4, limm, 4); + dwarf2_emit_insn (8); } else if (limm_reloc_p) { @@ -811,6 +817,7 @@ md_assemble (str) { f = frag_more (4); md_number_to_chars (f, insn, 4); + dwarf2_emit_insn (4); } /* Create any fixups. */ @@ -911,7 +918,7 @@ arc_extoper (opertype) p++; } - /* just after name is now '\0' */ + /* just after name is now '\0' */ p = input_line_pointer; *p = c; SKIP_WHITESPACE (); @@ -924,7 +931,7 @@ arc_extoper (opertype) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ number = get_absolute_expression (); if (number < 0) @@ -947,7 +954,7 @@ arc_extoper (opertype) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ mode = input_line_pointer; if (!strncmp (mode, "r|w", 3)) @@ -989,7 +996,7 @@ arc_extoper (opertype) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ if (!strncmp (input_line_pointer, "cannot_shortcut", 15)) { @@ -1154,7 +1161,7 @@ arc_extinst (ignore) strcpy (syntax, name); name_len = strlen (name); - /* just after name is now '\0' */ + /* just after name is now '\0' */ p = input_line_pointer; *p = c; @@ -1167,7 +1174,7 @@ arc_extinst (ignore) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ opcode = get_absolute_expression (); SKIP_WHITESPACE (); @@ -1179,7 +1186,7 @@ arc_extinst (ignore) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ subopcode = get_absolute_expression (); if (subopcode < 0) @@ -1217,7 +1224,7 @@ arc_extinst (ignore) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ for (i = 0; i < (int) MAXSUFFIXCLASS; i++) { @@ -1245,7 +1252,7 @@ arc_extinst (ignore) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ for (i = 0; i < (int) MAXSYNTAXCLASS; i++) { @@ -1372,7 +1379,7 @@ arc_common (localScope) name = input_line_pointer; c = get_symbol_end (); - /* just after name is now '\0' */ + /* just after name is now '\0' */ p = input_line_pointer; *p = c; SKIP_WHITESPACE (); @@ -1384,7 +1391,7 @@ arc_common (localScope) return; } - input_line_pointer++; /* skip ',' */ + input_line_pointer++; /* skip ',' */ size = get_absolute_expression (); if (size < 0) @@ -1436,7 +1443,7 @@ arc_common (localScope) old_sec = now_seg; old_subsec = now_subseg; record_alignment (bss_section, align); - subseg_set (bss_section, 0); /* ??? subseg_set (bss_section, 1); ??? */ + subseg_set (bss_section, 0); /* ??? subseg_set (bss_section, 1); ??? */ if (align) /* Do alignment. */ @@ -1630,12 +1637,13 @@ arc_code_symbol (expressionP) { expressionS two; expressionP->X_op = O_right_shift; + expressionP->X_add_symbol->sy_value.X_op = O_constant; two.X_op = O_constant; two.X_add_symbol = two.X_op_symbol = NULL; two.X_add_number = 2; expressionP->X_op_symbol = make_expr_symbol (&two); } - /* Allow %st(sym1-sym2) */ + /* Allow %st(sym1-sym2) */ else if (expressionP->X_op == O_subtract && expressionP->X_add_symbol != NULL && expressionP->X_op_symbol != NULL @@ -1686,7 +1694,8 @@ md_operand (expressionP) arc_code_symbol (expressionP); } else - { /* It could be a register. */ + { + /* It could be a register. */ int i, l; struct arc_ext_operand_value *ext_oper = arc_ext_operands; p++; diff --git a/gas/config/tc-arc.h b/gas/config/tc-arc.h index e81611b844e..463400c5fcf 100644 --- a/gas/config/tc-arc.h +++ b/gas/config/tc-arc.h @@ -1,5 +1,5 @@ /* tc-arc.h - Macros and type defines for the ARC. - Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. + Copyright 1994, 1995, 1997, 2000, 2001 Free Software Foundation, Inc. Contributed by Doug Evans (dje@cygnus.com). This file is part of GAS, the GNU Assembler. @@ -66,3 +66,5 @@ arc_parse_cons_expression (EXP, NBYTES) extern void arc_cons_fix_new (); #define TC_CONS_FIX_NEW(FRAG, WHERE, NBYTES, EXP) \ arc_cons_fix_new (FRAG, WHERE, NBYTES, EXP) + +#define DWARF2_LINE_MIN_INSN_LENGTH 4 diff --git a/gas/config/tc-fr30.c b/gas/config/tc-fr30.c index c61a8affedd..d2cffc7b319 100644 --- a/gas/config/tc-fr30.c +++ b/gas/config/tc-fr30.c @@ -1,5 +1,5 @@ /* tc-fr30.c -- Assembler for the Fujitsu FR30. - Copyright (C) 1998, 1999, 2000 Free Software Foundation. + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -208,7 +208,8 @@ const relax_typeS md_relax_table[] = }; long -fr30_relax_frag (fragP, stretch) +fr30_relax_frag (segment, fragP, stretch) + segT segment; fragS * fragP; long stretch; { @@ -235,7 +236,7 @@ fr30_relax_frag (fragP, stretch) } else { - growth = relax_frag (fragP, stretch); + growth = relax_frag (segment, fragP, stretch); /* Long jump on odd halfword boundary? */ if (fragP->fr_subtype == 2 && (address & 3) != 0) diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 05bdcdcfcbd..2a13bd93298 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1,5 +1,6 @@ /* i386.c -- Assemble code for the Intel 80386 - Copyright (C) 1989, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 + Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -69,6 +70,9 @@ static void set_cpu_arch PARAMS ((int)); #ifdef BFD_ASSEMBLER static bfd_reloc_code_real_type reloc PARAMS ((int, int, int, bfd_reloc_code_real_type)); +#define RELOC_ENUM enum bfd_reloc_code_real +#else +#define RELOC_ENUM int #endif #ifndef DEFAULT_ARCH @@ -116,11 +120,7 @@ struct _i386_insn #define Operand_PCrel 1 /* Relocation type for operand */ -#ifdef BFD_ASSEMBLER - enum bfd_reloc_code_real disp_reloc[MAX_OPERANDS]; -#else - int disp_reloc[MAX_OPERANDS]; -#endif + RELOC_ENUM reloc[MAX_OPERANDS]; /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode the base index byte below. */ @@ -240,6 +240,7 @@ enum flag_code { CODE_32BIT, CODE_16BIT, CODE_64BIT }; +#define NUM_FLAG_CODE ((int) CODE_64BIT + 1) static enum flag_code flag_code; static int use_rela_relocations = 0; @@ -273,15 +274,20 @@ static const char *cpu_arch_name = NULL; /* CPU feature flags. */ static unsigned int cpu_arch_flags = CpuUnknownFlags|CpuNo64; +/* If set, conditional jumps are not automatically promoted to handle + larger than a byte offset. */ +static unsigned int no_cond_jump_promotion = 0; + /* Interface to relax_segment. - There are 2 relax states for 386 jump insns: one for conditional & - one for unconditional jumps. This is because these two types of - jumps add different sizes to frags when we're figuring out what - sort of jump to choose to reach a given label. */ + There are 3 major relax states for 386 jump insns because the + different types of jumps add different sizes to frags when we're + figuring out what sort of jump to choose to reach a given label. */ /* Types. */ +#define UNCOND_JUMP 0 #define COND_JUMP 1 -#define UNCOND_JUMP 2 +#define COND_JUMP86 2 + /* Sizes. */ #define CODE16 1 #define SMALL 0 @@ -297,10 +303,12 @@ static unsigned int cpu_arch_flags = CpuUnknownFlags|CpuNo64; #endif #endif -#define ENCODE_RELAX_STATE(type,size) \ - ((relax_substateT) ((type<<2) | (size))) -#define SIZE_FROM_RELAX_STATE(s) \ - ( (((s) & 0x3) == BIG ? 4 : (((s) & 0x3) == BIG16 ? 2 : 1)) ) +#define ENCODE_RELAX_STATE(type, size) \ + ((relax_substateT) (((type) << 2) | (size))) +#define TYPE_FROM_RELAX_STATE(s) \ + ((s) >> 2) +#define DISP_SIZE_FROM_RELAX_STATE(s) \ + ((((s) & 3) == BIG ? 4 : (((s) & 3) == BIG16 ? 2 : 1))) /* This table is used by relax_frag to promote short jumps to long ones where necessary. SMALL (short) jumps may be promoted to BIG @@ -315,31 +323,38 @@ const relax_typeS md_relax_table[] = /* The fields are: 1) most positive reach of this state, 2) most negative reach of this state, - 3) how many bytes this mode will add to the size of the current frag + 3) how many bytes this mode will have in the variable part of the frag 4) which index into the table to try if we can't fit into this one. */ - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, - - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG)}, - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG16)}, - /* dword conditionals adds 4 bytes to frag: - 1 extra opcode byte, 3 extra displacement bytes. */ + + /* UNCOND_JUMP states. */ + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)}, + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)}, + /* dword jmp adds 4 bytes to frag: + 0 extra opcode bytes, 4 displacement bytes. */ {0, 0, 4, 0}, - /* word conditionals add 2 bytes to frag: - 1 extra opcode byte, 1 extra displacement byte. */ + /* word jmp adds 2 byte2 to frag: + 0 extra opcode bytes, 2 displacement bytes. */ {0, 0, 2, 0}, - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)}, - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)}, - /* dword jmp adds 3 bytes to frag: - 0 extra opcode bytes, 3 extra displacement bytes. */ + /* COND_JUMP states. */ + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)}, + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)}, + /* dword conditionals adds 5 bytes to frag: + 1 extra opcode byte, 4 displacement bytes. */ + {0, 0, 5, 0}, + /* word conditionals add 3 bytes to frag: + 1 extra opcode byte, 2 displacement bytes. */ {0, 0, 3, 0}, - /* word jmp adds 1 byte to frag: - 0 extra opcode bytes, 1 extra displacement byte. */ - {0, 0, 1, 0} + /* COND_JUMP86 states. */ + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)}, + {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)}, + /* dword conditionals adds 5 bytes to frag: + 1 extra opcode byte, 4 displacement bytes. */ + {0, 0, 5, 0}, + /* word conditionals add 4 bytes to frag: + 1 displacement byte and a 3 byte long branch insn. */ + {0, 0, 4, 0} }; static const arch_entry cpu_arch[] = { @@ -726,7 +741,8 @@ set_cpu_arch (dummy) if (strcmp (string, cpu_arch[i].name) == 0) { cpu_arch_name = cpu_arch[i].name; - cpu_arch_flags = cpu_arch[i].flags | (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); + cpu_arch_flags = (cpu_arch[i].flags + | (flag_code == CODE_64BIT ? Cpu64 : CpuNo64)); break; } } @@ -738,6 +754,23 @@ set_cpu_arch (dummy) else as_bad (_("missing cpu architecture")); + no_cond_jump_promotion = 0; + if (*input_line_pointer == ',' + && ! is_end_of_line[(unsigned char) input_line_pointer[1]]) + { + char *string = ++input_line_pointer; + int e = get_symbol_end (); + + if (strcmp (string, "nojumps") == 0) + no_cond_jump_promotion = 1; + else if (strcmp (string, "jumps") == 0) + ; + else + as_bad (_("no such architecture modifier: `%s'"), string); + + *input_line_pointer = e; + } + demand_empty_rest_of_line (); } @@ -1198,9 +1231,6 @@ md_assemble (line) /* Points to template once we've found it. */ const template *t; - /* Count the size of the instruction generated. */ - int insn_size = 0; - int j; char mnemonic[MAX_MNEM_SIZE]; @@ -1208,7 +1238,7 @@ md_assemble (line) /* Initialize globals. */ memset (&i, '\0', sizeof (i)); for (j = 0; j < MAX_OPERANDS; j++) - i.disp_reloc[j] = NO_RELOC; + i.reloc[j] = NO_RELOC; memset (disp_expressions, '\0', sizeof (disp_expressions)); memset (im_expressions, '\0', sizeof (im_expressions)); save_stack_p = save_stack; @@ -1508,11 +1538,7 @@ md_assemble (line) { union i386_op temp_op; unsigned int temp_type; -#ifdef BFD_ASSEMBLER - enum bfd_reloc_code_real temp_reloc; -#else - int temp_reloc; -#endif + RELOC_ENUM temp_reloc; int xchg1 = 0; int xchg2 = 0; @@ -1532,9 +1558,9 @@ md_assemble (line) temp_op = i.op[xchg2]; i.op[xchg2] = i.op[xchg1]; i.op[xchg1] = temp_op; - temp_reloc = i.disp_reloc[xchg2]; - i.disp_reloc[xchg2] = i.disp_reloc[xchg1]; - i.disp_reloc[xchg1] = temp_reloc; + temp_reloc = i.reloc[xchg2]; + i.reloc[xchg2] = i.reloc[xchg1]; + i.reloc[xchg1] = temp_reloc; if (i.mem_operands == 2) { @@ -1654,7 +1680,7 @@ md_assemble (line) for (op = i.operands; --op >= 0;) if ((i.types[op] & Disp) - && i.op[op].imms->X_op == O_constant) + && i.op[op].disps->X_op == O_constant) { offsetT disp = i.op[op].disps->X_add_number; @@ -2672,10 +2698,14 @@ md_assemble (line) { register char *p; + /* Tie dwarf2 debug info to the address at the start of the insn. + We can't do this after the insn has been output as the current + frag may have been closed off. eg. by frag_var. */ + dwarf2_emit_insn (0); + /* Output jumps. */ if (i.tm.opcode_modifier & Jump) { - int size; int code16; int prefix; @@ -2696,10 +2726,6 @@ md_assemble (line) i.prefixes--; } - size = 4; - if (code16) - size = 2; - if (i.prefixes != 0 && !intel_syntax) as_warn (_("skipping prefixes on this instruction")); @@ -2708,8 +2734,7 @@ md_assemble (line) instruction we may generate in md_convert_frag. This is 2 bytes for the opcode and room for the prefix and largest displacement. */ - frag_grow (prefix + 2 + size); - insn_size += prefix + 1; + frag_grow (prefix + 2 + 4); /* Prefix and 1 opcode byte go in fr_fix. */ p = frag_more (prefix + 1); if (i.prefix[DATA_PREFIX]) @@ -2720,11 +2745,13 @@ md_assemble (line) /* 1 possible extra opcode + displacement go in var part. Pass reloc in fr_var. */ frag_var (rs_machine_dependent, - 1 + size, - i.disp_reloc[0], + 1 + 4, + i.reloc[0], ((unsigned char) *p == JUMP_PC_RELATIVE ? ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL) | code16 - : ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16), + : ((cpu_arch_flags & Cpu386) != 0 + ? ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16 + : ENCODE_RELAX_STATE (COND_JUMP86, SMALL) | code16)), i.op[0].disps->X_add_symbol, i.op[0].disps->X_add_number, p); @@ -2739,7 +2766,6 @@ md_assemble (line) size = 1; if (i.prefix[ADDR_PREFIX]) { - insn_size += 1; FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); i.prefixes -= 1; } @@ -2754,7 +2780,6 @@ md_assemble (line) if (i.prefix[DATA_PREFIX]) { - insn_size += 1; FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); i.prefixes -= 1; code16 ^= CODE16; @@ -2768,7 +2793,6 @@ md_assemble (line) if (i.prefix[REX_PREFIX]) { FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); - insn_size++; i.prefixes -= 1; } @@ -2777,20 +2801,18 @@ md_assemble (line) if (fits_in_unsigned_byte (i.tm.base_opcode)) { - insn_size += 1 + size; p = frag_more (1 + size); } else { /* Opcode can be at most two bytes. */ - insn_size += 2 + size; p = frag_more (2 + size); *p++ = (i.tm.base_opcode >> 8) & 0xff; } *p++ = i.tm.base_opcode & 0xff; fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[0].disps, 1, reloc (size, 1, 1, i.disp_reloc[0])); + i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0])); } else if (i.tm.opcode_modifier & JumpInterSegment) { @@ -2823,7 +2845,6 @@ md_assemble (line) as_warn (_("skipping prefixes on this instruction")); /* 1 opcode; 2 segment; offset */ - insn_size += prefix + 1 + 2 + size; p = frag_more (prefix + 1 + 2 + size); if (i.prefix[DATA_PREFIX]) @@ -2848,7 +2869,7 @@ md_assemble (line) } else fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[1].imms, 0, reloc (size, 0, 0, i.disp_reloc[0])); + i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1])); if (i.op[0].imms->X_op != O_constant) as_bad (_("can't handle non absolute segment in `%s'"), i.tm.name); @@ -2871,7 +2892,6 @@ md_assemble (line) { if (*q) { - insn_size += 1; p = frag_more (1); md_number_to_chars (p, (valueT) *q, 1); } @@ -2880,12 +2900,10 @@ md_assemble (line) /* Now the opcode; be careful about word order here! */ if (fits_in_unsigned_byte (i.tm.base_opcode)) { - insn_size += 1; FRAG_APPEND_1_CHAR (i.tm.base_opcode); } else { - insn_size += 2; p = frag_more (2); /* Put out high byte first: can't use md_number_to_chars! */ *p++ = (i.tm.base_opcode >> 8) & 0xff; @@ -2895,7 +2913,6 @@ md_assemble (line) /* Now the modrm byte and sib byte (if present). */ if (i.tm.opcode_modifier & Modrm) { - insn_size += 1; p = frag_more (1); md_number_to_chars (p, (valueT) (i.rm.regmem << 0 @@ -2910,7 +2927,6 @@ md_assemble (line) && i.rm.mode != 3 && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0)) { - insn_size += 1; p = frag_more (1); md_number_to_chars (p, (valueT) (i.sib.base << 0 @@ -2944,7 +2960,6 @@ md_assemble (line) } val = offset_in_range (i.op[n].disps->X_add_number, size); - insn_size += size; p = frag_more (size); md_number_to_chars (p, val, size); } @@ -2991,11 +3006,10 @@ md_assemble (line) size = 8; } - insn_size += size; p = frag_more (size); fix_new_exp (frag_now, p - frag_now->fr_literal, size, i.op[n].disps, pcrel, - reloc (size, pcrel, sign, i.disp_reloc[n])); + reloc (size, pcrel, sign, i.reloc[n])); } } } @@ -3026,7 +3040,6 @@ md_assemble (line) } val = offset_in_range (i.op[n].imms->X_add_number, size); - insn_size += size; p = frag_more (size); md_number_to_chars (p, val, size); } @@ -3036,11 +3049,7 @@ md_assemble (line) Need a 32-bit fixup (don't support 8bit non-absolute imms). Try to support other sizes ... */ -#ifdef BFD_ASSEMBLER - enum bfd_reloc_code_real reloc_type; -#else - int reloc_type; -#endif + RELOC_ENUM reloc_type; int size = 4; int sign = 0; @@ -3056,9 +3065,8 @@ md_assemble (line) size = 8; } - insn_size += size; p = frag_more (size); - reloc_type = reloc (size, 0, sign, i.disp_reloc[0]); + reloc_type = reloc (size, 0, sign, i.reloc[n]); #ifdef BFD_ASSEMBLER if (reloc_type == BFD_RELOC_32 && GOT_symbol @@ -3084,8 +3092,6 @@ md_assemble (line) } } - dwarf2_emit_insn (insn_size); - #ifdef DEBUG386 if (flag_debug) { @@ -3095,6 +3101,130 @@ md_assemble (line) } } +#ifndef LEX_AT +static char *lex_got PARAMS ((RELOC_ENUM *, int *)); + +/* Parse operands of the form + @GOTOFF+ + and similar .plt or .got references. + + If we find one, set up the correct relocation in RELOC and copy the + input string, minus the `@GOTOFF' into a malloc'd buffer for + parsing by the calling routine. Return this buffer, and if ADJUST + is non-null set it to the length of the string we removed from the + input line. Otherwise return NULL. */ +static char * +lex_got (reloc, adjust) + RELOC_ENUM *reloc; + int *adjust; +{ + static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" }; + static const struct { + const char *str; + const RELOC_ENUM rel[NUM_FLAG_CODE]; + } gotrel[] = { + { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } }, + { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } }, + { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } }, + { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } } + }; + char *cp; + unsigned int j; + + for (cp = input_line_pointer; *cp != '@'; cp++) + if (is_end_of_line[(unsigned char) *cp]) + return NULL; + + for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++) + { + int len; + + len = strlen (gotrel[j].str); + if (strncmp (cp + 1, gotrel[j].str, len) == 0) + { + if (gotrel[j].rel[(unsigned int) flag_code] != 0) + { + int first; + char *tmpbuf; + + *reloc = gotrel[j].rel[(unsigned int) flag_code]; + + if (GOT_symbol == NULL) + GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); + + /* Replace the relocation token with ' ', so that + errors like foo@GOTOFF1 will be detected. */ + first = cp - input_line_pointer; + tmpbuf = xmalloc (strlen (input_line_pointer)); + memcpy (tmpbuf, input_line_pointer, first); + tmpbuf[first] = ' '; + strcpy (tmpbuf + first + 1, cp + 1 + len); + if (adjust) + *adjust = len; + return tmpbuf; + } + + as_bad (_("@%s reloc is not supported in %s bit mode"), + gotrel[j].str, mode_name[(unsigned int) flag_code]); + return NULL; + } + } + + /* Might be a symbol version string. Don't as_bad here. */ + return NULL; +} + +/* x86_cons_fix_new is called via the expression parsing code when a + reloc is needed. We use this hook to get the correct .got reloc. */ +static RELOC_ENUM got_reloc = NO_RELOC; + +void +x86_cons_fix_new (frag, off, len, exp) + fragS *frag; + unsigned int off; + unsigned int len; + expressionS *exp; +{ + RELOC_ENUM r = reloc (len, 0, 0, got_reloc); + got_reloc = NO_RELOC; + fix_new_exp (frag, off, len, exp, 0, r); +} + +void +x86_cons (exp, size) + expressionS *exp; + int size; +{ + if (size == 4) + { + /* Handle @GOTOFF and the like in an expression. */ + char *save; + char *gotfree_input_line; + int adjust; + + save = input_line_pointer; + gotfree_input_line = lex_got (&got_reloc, &adjust); + if (gotfree_input_line) + input_line_pointer = gotfree_input_line; + + expression (exp); + + if (gotfree_input_line) + { + /* expression () has merrily parsed up to the end of line, + or a comma - in the wrong buffer. Transfer how far + input_line_pointer has moved to the right buffer. */ + input_line_pointer = (save + + (input_line_pointer - gotfree_input_line) + + adjust); + free (gotfree_input_line); + } + } + else + expression (exp); +} +#endif + static int i386_immediate PARAMS ((char *)); static int @@ -3102,6 +3232,9 @@ i386_immediate (imm_start) char *imm_start; { char *save_input_line_pointer; +#ifndef LEX_AT + char *gotfree_input_line; +#endif segT exp_seg = 0; expressionS *exp; @@ -3121,80 +3254,22 @@ i386_immediate (imm_start) input_line_pointer = imm_start; #ifndef LEX_AT - { - /* We can have operands of the form - @GOTOFF+ - Take the easy way out here and copy everything - into a temporary buffer... */ - register char *cp; - - cp = strchr (input_line_pointer, '@'); - if (cp != NULL) - { - char *tmpbuf; - int len = 0; - int first; - - /* GOT relocations are not supported in 16 bit mode. */ - if (flag_code == CODE_16BIT) - as_bad (_("GOT relocations not supported in 16 bit mode")); - - if (GOT_symbol == NULL) - GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); - - if (strncmp (cp + 1, "PLT", 3) == 0) - { - if (flag_code == CODE_64BIT) - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_PLT32; - else - i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32; - len = 3; - } - else if (strncmp (cp + 1, "GOTOFF", 6) == 0) - { - if (flag_code == CODE_64BIT) - as_bad ("GOTOFF relocations are unsupported in 64bit mode."); - i.disp_reloc[this_operand] = BFD_RELOC_386_GOTOFF; - len = 6; - } - else if (strncmp (cp + 1, "GOTPCREL", 8) == 0) - { - if (flag_code == CODE_64BIT) - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_GOTPCREL; - else - as_bad ("GOTPCREL relocations are supported only in 64bit mode."); - len = 8; - } - else if (strncmp (cp + 1, "GOT", 3) == 0) - { - if (flag_code == CODE_64BIT) - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_GOT32; - else - i.disp_reloc[this_operand] = BFD_RELOC_386_GOT32; - len = 3; - } - else - as_bad (_("bad reloc specifier in expression")); - - /* Replace the relocation token with ' ', so that errors like - foo@GOTOFF1 will be detected. */ - first = cp - input_line_pointer; - tmpbuf = (char *) alloca (strlen (input_line_pointer)); - memcpy (tmpbuf, input_line_pointer, first); - tmpbuf[first] = ' '; - strcpy (tmpbuf + first + 1, cp + 1 + len); - input_line_pointer = tmpbuf; - } - } + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); + if (gotfree_input_line) + input_line_pointer = gotfree_input_line; #endif exp_seg = expression (exp); SKIP_WHITESPACE (); if (*input_line_pointer) - as_bad (_("ignoring junk `%s' after expression"), input_line_pointer); + as_bad (_("junk `%s' after expression"), input_line_pointer); input_line_pointer = save_input_line_pointer; +#ifndef LEX_AT + if (gotfree_input_line) + free (gotfree_input_line); +#endif if (exp->X_op == O_absent || exp->X_op == O_big) { @@ -3248,35 +3323,38 @@ i386_immediate (imm_start) return 1; } -static int i386_scale PARAMS ((char *)); +static char *i386_scale PARAMS ((char *)); -static int +static char * i386_scale (scale) char *scale; { - if (!isdigit (*scale)) - goto bad_scale; + offsetT val; + char *save = input_line_pointer; + + input_line_pointer = scale; + val = get_absolute_expression (); - switch (*scale) + switch (val) { - case '0': - case '1': + case 0: + case 1: i.log2_scale_factor = 0; break; - case '2': + case 2: i.log2_scale_factor = 1; break; - case '4': + case 4: i.log2_scale_factor = 2; break; - case '8': + case 8: i.log2_scale_factor = 3; break; default: - bad_scale: as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), scale); - return 0; + input_line_pointer = save; + return NULL; } if (i.log2_scale_factor != 0 && ! i.index_reg) { @@ -3286,7 +3364,9 @@ i386_scale (scale) i.log2_scale_factor = 0; #endif } - return 1; + scale = input_line_pointer; + input_line_pointer = save; + return scale; } static int i386_displacement PARAMS ((char *, char *)); @@ -3299,6 +3379,9 @@ i386_displacement (disp_start, disp_end) register expressionS *exp; segT exp_seg = 0; char *save_input_line_pointer; +#ifndef LEX_AT + char *gotfree_input_line; +#endif int bigdisp = Disp32; if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) @@ -3359,104 +3442,54 @@ i386_displacement (disp_start, disp_end) } #endif #ifndef LEX_AT - { - /* We can have operands of the form - @GOTOFF+ - Take the easy way out here and copy everything - into a temporary buffer... */ - register char *cp; - - cp = strchr (input_line_pointer, '@'); - if (cp != NULL) - { - char *tmpbuf; - int len = 0; - int first; - - /* GOT relocations are not supported in 16 bit mode. */ - if (flag_code == CODE_16BIT) - as_bad (_("GOT relocations not supported in 16 bit mode")); - - if (GOT_symbol == NULL) - GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); - - if (strncmp (cp + 1, "PLT", 3) == 0) - { - if (flag_code == CODE_64BIT) - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_PLT32; - else - i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32; - len = 3; - } - else if (strncmp (cp + 1, "GOTOFF", 6) == 0) - { - if (flag_code == CODE_64BIT) - as_bad ("GOTOFF relocation is not supported in 64bit mode."); - i.disp_reloc[this_operand] = BFD_RELOC_386_GOTOFF; - len = 6; - } - else if (strncmp (cp + 1, "GOTPCREL", 8) == 0) - { - if (flag_code != CODE_64BIT) - as_bad ("GOTPCREL relocation is supported only in 64bit mode."); - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_GOTPCREL; - len = 8; - } - else if (strncmp (cp + 1, "GOT", 3) == 0) - { - if (flag_code == CODE_64BIT) - i.disp_reloc[this_operand] = BFD_RELOC_X86_64_GOT32; - else - i.disp_reloc[this_operand] = BFD_RELOC_386_GOT32; - len = 3; - } - else - as_bad (_("bad reloc specifier in expression")); - - /* Replace the relocation token with ' ', so that errors like - foo@GOTOFF1 will be detected. */ - first = cp - input_line_pointer; - tmpbuf = (char *) alloca (strlen (input_line_pointer)); - memcpy (tmpbuf, input_line_pointer, first); - tmpbuf[first] = ' '; - strcpy (tmpbuf + first + 1, cp + 1 + len); - input_line_pointer = tmpbuf; - } - } + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); + if (gotfree_input_line) + input_line_pointer = gotfree_input_line; #endif exp_seg = expression (exp); + SKIP_WHITESPACE (); + if (*input_line_pointer) + as_bad (_("junk `%s' after expression"), input_line_pointer); +#if GCC_ASM_O_HACK + RESTORE_END_STRING (disp_end + 1); +#endif + RESTORE_END_STRING (disp_end); + input_line_pointer = save_input_line_pointer; +#ifndef LEX_AT + if (gotfree_input_line) + free (gotfree_input_line); +#endif + #ifdef BFD_ASSEMBLER /* We do this to make sure that the section symbol is in the symbol table. We will ultimately change the relocation to be relative to the beginning of the section. */ - if (i.disp_reloc[this_operand] == BFD_RELOC_386_GOTOFF - || i.disp_reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) + if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF + || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) { + if (exp->X_op != O_symbol) + { + as_bad (_("bad expression used with @%s"), + (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL + ? "GOTPCREL" + : "GOTOFF")); + return 0; + } + if (S_IS_LOCAL (exp->X_add_symbol) && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section) section_symbol (S_GET_SEGMENT (exp->X_add_symbol)); - assert (exp->X_op == O_symbol); exp->X_op = O_subtract; exp->X_op_symbol = GOT_symbol; - if (i.disp_reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) - i.disp_reloc[this_operand] = BFD_RELOC_32_PCREL; + if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) + i.reloc[this_operand] = BFD_RELOC_32_PCREL; else - i.disp_reloc[this_operand] = BFD_RELOC_32; + i.reloc[this_operand] = BFD_RELOC_32; } #endif - SKIP_WHITESPACE (); - if (*input_line_pointer) - as_bad (_("ignoring junk `%s' after expression"), - input_line_pointer); -#if GCC_ASM_O_HACK - RESTORE_END_STRING (disp_end + 1); -#endif - RESTORE_END_STRING (disp_end); - input_line_pointer = save_input_line_pointer; - if (exp->X_op == O_absent || exp->X_op == O_big) { /* Missing or bad expr becomes absolute 0. */ @@ -3789,12 +3822,14 @@ i386_operand (operand_string) } /* Check for scale factor. */ - if (isdigit ((unsigned char) *base_string)) + if (*base_string != ')') { - if (!i386_scale (base_string)) + char *end_scale = i386_scale (base_string); + + if (!end_scale) return 0; - ++base_string; + base_string = end_scale; if (is_space_char (*base_string)) ++base_string; if (*base_string != ')') @@ -3895,11 +3930,7 @@ md_estimate_size_before_relax (fragP, segment) /* Symbol is undefined in this segment, or we need to keep a reloc so that weak symbols can be overridden. */ int size = (fragP->fr_subtype & CODE16) ? 2 : 4; -#ifdef BFD_ASSEMBLER - enum bfd_reloc_code_real reloc_type; -#else - int reloc_type; -#endif + RELOC_ENUM reloc_type; unsigned char *opcode; int old_fr_fix; @@ -3913,10 +3944,10 @@ md_estimate_size_before_relax (fragP, segment) old_fr_fix = fragP->fr_fix; opcode = (unsigned char *) fragP->fr_opcode; - switch (opcode[0]) + switch (TYPE_FROM_RELAX_STATE (fragP->fr_subtype)) { - case JUMP_PC_RELATIVE: - /* Make jmp (0xeb) a dword displacement jump. */ + case UNCOND_JUMP: + /* Make jmp (0xeb) a (d)word displacement jump. */ opcode[0] = 0xe9; fragP->fr_fix += size; fix_new (fragP, old_fr_fix, size, @@ -3925,9 +3956,35 @@ md_estimate_size_before_relax (fragP, segment) reloc_type); break; - default: + case COND_JUMP86: + if (no_cond_jump_promotion) + goto relax_guess; + + if (size == 2) + { + /* Negate the condition, and branch past an + unconditional jump. */ + opcode[0] ^= 1; + opcode[1] = 3; + /* Insert an unconditional jump. */ + opcode[2] = 0xe9; + /* We added two extra opcode bytes, and have a two byte + offset. */ + fragP->fr_fix += 2 + 2; + fix_new (fragP, old_fr_fix + 2, 2, + fragP->fr_symbol, + fragP->fr_offset, 1, + reloc_type); + break; + } + /* Fall through. */ + + case COND_JUMP: + if (no_cond_jump_promotion) + goto relax_guess; + /* This changes the byte-displacement jump 0x7N - to the dword-displacement jump 0x0f,0x8N. */ + to the (d)word-displacement jump 0x0f,0x8N. */ opcode[1] = opcode[0] + 0x10; opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* We've added an opcode byte. */ @@ -3937,12 +3994,23 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_offset, 1, reloc_type); break; + + default: + BAD_CASE (fragP->fr_subtype); + break; } frag_wane (fragP); return fragP->fr_fix - old_fr_fix; } - /* Guess a short jump. */ - return 1; + + relax_guess: + /* Guess size depending on current relax state. Initially the relax + state will correspond to a short jump and we return 1, because + the variable part of the frag (the branch offset) is one byte + long. However, we can relax a section more than once and in that + case we must either set fr_subtype back to the unrelaxed state, + or return the value for the appropriate branch. */ + return md_relax_table[fragP->fr_subtype].rlx_length; } /* Called after relax() is finished. @@ -3982,7 +4050,7 @@ md_convert_frag (abfd, sec, fragP) #ifdef BFD_ASSEMBLER /* Not needed otherwise? */ { - /* Local symbols which have already been resolved have a NULL frags. */ + /* Local symbols which have already been resolved have a NULL frag. */ fragS *sym_frag = symbol_get_frag (fragP->fr_symbol); if (sym_frag) target_address += sym_frag->fr_address; @@ -3995,51 +4063,65 @@ md_convert_frag (abfd, sec, fragP) /* Displacement from opcode start to fill into instruction. */ displacement_from_opcode_start = target_address - opcode_address; - switch (fragP->fr_subtype) + if ((fragP->fr_subtype & BIG) == 0) { - case ENCODE_RELAX_STATE (COND_JUMP, SMALL): - case ENCODE_RELAX_STATE (COND_JUMP, SMALL16): - case ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL): - case ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL16): /* Don't have to change opcode. */ extension = 1; /* 1 opcode + 1 displacement */ where_to_put_displacement = &opcode[1]; - break; + } + else + { + if (no_cond_jump_promotion + && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP) + as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required")); - case ENCODE_RELAX_STATE (COND_JUMP, BIG): - extension = 5; /* 2 opcode + 4 displacement */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - where_to_put_displacement = &opcode[2]; - break; + switch (fragP->fr_subtype) + { + case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG): + extension = 4; /* 1 opcode + 4 displacement */ + opcode[0] = 0xe9; + where_to_put_displacement = &opcode[1]; + break; - case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG): - extension = 4; /* 1 opcode + 4 displacement */ - opcode[0] = 0xe9; - where_to_put_displacement = &opcode[1]; - break; + case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16): + extension = 2; /* 1 opcode + 2 displacement */ + opcode[0] = 0xe9; + where_to_put_displacement = &opcode[1]; + break; - case ENCODE_RELAX_STATE (COND_JUMP, BIG16): - extension = 3; /* 2 opcode + 2 displacement */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - where_to_put_displacement = &opcode[2]; - break; + case ENCODE_RELAX_STATE (COND_JUMP, BIG): + case ENCODE_RELAX_STATE (COND_JUMP86, BIG): + extension = 5; /* 2 opcode + 4 displacement */ + opcode[1] = opcode[0] + 0x10; + opcode[0] = TWO_BYTE_OPCODE_ESCAPE; + where_to_put_displacement = &opcode[2]; + break; - case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16): - extension = 2; /* 1 opcode + 2 displacement */ - opcode[0] = 0xe9; - where_to_put_displacement = &opcode[1]; - break; + case ENCODE_RELAX_STATE (COND_JUMP, BIG16): + extension = 3; /* 2 opcode + 2 displacement */ + opcode[1] = opcode[0] + 0x10; + opcode[0] = TWO_BYTE_OPCODE_ESCAPE; + where_to_put_displacement = &opcode[2]; + break; - default: - BAD_CASE (fragP->fr_subtype); - break; + case ENCODE_RELAX_STATE (COND_JUMP86, BIG16): + extension = 4; + opcode[0] ^= 1; + opcode[1] = 3; + opcode[2] = 0xe9; + where_to_put_displacement = &opcode[3]; + break; + + default: + BAD_CASE (fragP->fr_subtype); + break; + } } + /* Now put displacement after opcode. */ md_number_to_chars ((char *) where_to_put_displacement, (valueT) (displacement_from_opcode_start - extension), - SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); + DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); fragP->fr_fix += extension; } diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index a68d5e49267..71e0c88be31 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -1,6 +1,7 @@ /* tc-i386.h -- Header file for tc-i386.c - Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 - Free Software Foundation. + Copyright 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -154,6 +155,15 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag)); #endif /* ! BFD_ASSEMBLER */ +#ifndef LEX_AT +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) x86_cons (EXP, NBYTES) +extern void x86_cons PARAMS ((expressionS *, int)); + +#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) x86_cons_fix_new(FRAG, OFF, LEN, EXP) +extern void x86_cons_fix_new + PARAMS ((fragS *, unsigned int, unsigned int, expressionS *)); +#endif + #define TC_FORCE_RELOCATION(fixp) tc_i386_force_relocation(fixp) extern int tc_i386_force_relocation PARAMS ((struct fix *)); diff --git a/gas/config/tc-m32r.c b/gas/config/tc-m32r.c index 7aabf5b0164..51ef9fec77b 100644 --- a/gas/config/tc-m32r.c +++ b/gas/config/tc-m32r.c @@ -1,5 +1,5 @@ /* tc-m32r.c -- Assembler for the Mitsubishi M32R. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 + Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -1384,7 +1384,8 @@ const relax_typeS md_relax_table[] = }; long -m32r_relax_frag (fragP, stretch) +m32r_relax_frag (segment, fragP, stretch) + segT segment; fragS *fragP; long stretch; { @@ -1411,7 +1412,7 @@ m32r_relax_frag (fragP, stretch) } else { - growth = relax_frag (fragP, stretch); + growth = relax_frag (segment, fragP, stretch); /* Long jump on odd halfword boundary? */ if (fragP->fr_subtype == 2 && (address & 3) != 0) diff --git a/gas/config/tc-m32r.h b/gas/config/tc-m32r.h index 9e04c19158c..2eaee0e0fb9 100644 --- a/gas/config/tc-m32r.h +++ b/gas/config/tc-m32r.h @@ -1,5 +1,6 @@ /* tc-m32r.h -- Header file for tc-m32r.c. - Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -54,9 +55,9 @@ extern void m32r_prepare_relax_scan (); #define md_prepare_relax_scan(fragP, address, aim, this_state, this_type) \ m32r_prepare_relax_scan (fragP, address, aim, this_state, this_type) #else -extern long m32r_relax_frag PARAMS ((fragS *, long)); -#define md_relax_frag(fragP, stretch) \ -m32r_relax_frag (fragP, stretch) +extern long m32r_relax_frag PARAMS ((segT, fragS *, long)); +#define md_relax_frag(segment, fragP, stretch) \ +m32r_relax_frag (segment, fragP, stretch) #endif /* Account for nop if 32 bit insn falls on odd halfword boundary. */ #define TC_CGEN_MAX_RELAX(insn, len) (6) diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index 561d5d7f0d5..c10b10a537d 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -1,5 +1,5 @@ /* tc-mips.h -- header file for tc-mips.c. - Copyright (C) 1993, 94, 95, 96, 97, 1999, 2000 + Copyright 1993, 1994, 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. Contributed by the OSF and Ralph Campbell. Written by Keith Knowles and Ralph Campbell, working independently. @@ -49,7 +49,7 @@ struct expressionS; relocation: */ #define MAX_GPREL_OFFSET (0x7FF4) -#define md_relax_frag(fragp, stretch) mips_relax_frag(fragp, stretch) +#define md_relax_frag(segment, fragp, stretch) mips_relax_frag(fragp, stretch) extern int mips_relax_frag PARAMS ((struct frag *, long)); #define md_undefined_symbol(name) (0) diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c index 51bc3fbeb86..9f3ee5f911c 100644 --- a/gas/config/tc-mn10300.c +++ b/gas/config/tc-mn10300.c @@ -1,5 +1,6 @@ /* tc-mn10300.c -- Assembler code for the Matsushita 10300 - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation. + Copyright 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -211,6 +212,7 @@ static const struct reg_name xr_registers[] = { "mcrl", 3 }, { "mcvf", 4 }, { "mdrq", 1 }, + { "pc", 0 }, { "sp", 0 }, { "xr0", 0 }, { "xr1", 1 }, @@ -935,7 +937,7 @@ md_assemble (str) struct mn10300_opcode *next_opcode; const unsigned char *opindex_ptr; int next_opindex, relaxable; - unsigned long insn, extension, size = 0, real_size; + unsigned long insn, extension, size = 0; char *f; int i; int match; @@ -1511,12 +1513,17 @@ keep_going: if (opcode->format == FMT_D4) size = 6; - real_size = size; - if (relaxable && fc > 0) { int type; + /* We want to anchor the line info to the previous frag (if + there isn't one, create it), so that, when the insn is + resized, we still get the right address for the beginning of + the region. */ + f = frag_more (0); + dwarf2_emit_insn (0); + /* bCC */ if (size == 2) { @@ -1727,24 +1734,7 @@ keep_going: /* Is the reloc pc-relative? */ pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0; - /* Gross. This disgusting hack is to make sure we - get the right offset for the 16/32 bit reloc in - "call" instructions. Basically they're a pain - because the reloc isn't at the end of the instruction. */ - if ((size == 5 || size == 7) - && (((insn >> 24) & 0xff) == 0xcd - || ((insn >> 24) & 0xff) == 0xdd)) - size -= 2; - - /* Similarly for certain bit instructions which don't - hav their 32bit reloc at the tail of the instruction. */ - if (size == 7 - && (((insn >> 16) & 0xffff) == 0xfe00 - || ((insn >> 16) & 0xffff) == 0xfe01 - || ((insn >> 16) & 0xffff) == 0xfe02)) - size -= 1; - - offset = size - reloc_size / 8; + offset = size - (reloc_size + operand->shift) / 8; /* Choose a proper BFD relocation type. */ if (pcrel) @@ -1787,9 +1777,9 @@ keep_going: fixP->fx_offset += offset; } } - } - dwarf2_emit_insn (real_size); + dwarf2_emit_insn (size); + } } /* If while processing a fixup, a reloc really needs to be created @@ -1815,6 +1805,45 @@ tc_gen_reloc (seg, fixp) if (fixp->fx_addsy && fixp->fx_subsy) { + /* If we got a difference between two symbols, and the + subtracted symbol is in the current section, use a + PC-relative relocation. If both symbols are in the same + section, the difference would have already been simplified + to a constant. */ + if (S_GET_SEGMENT (fixp->fx_subsy) == seg) + { + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->addend = (reloc->address - S_GET_VALUE (fixp->fx_subsy) + + fixp->fx_offset); + + switch (fixp->fx_r_type) + { + case BFD_RELOC_8: + reloc->howto = bfd_reloc_type_lookup (stdoutput, + BFD_RELOC_8_PCREL); + return reloc; + + case BFD_RELOC_16: + reloc->howto = bfd_reloc_type_lookup (stdoutput, + BFD_RELOC_16_PCREL); + return reloc; + + case BFD_RELOC_24: + reloc->howto = bfd_reloc_type_lookup (stdoutput, + BFD_RELOC_24_PCREL); + return reloc; + + case BFD_RELOC_32: + reloc->howto = bfd_reloc_type_lookup (stdoutput, + BFD_RELOC_32_PCREL); + return reloc; + + default: + /* Try to compute the absolute value below. */ + break; + } + } if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy)) || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section) @@ -1842,44 +1871,23 @@ md_estimate_size_before_relax (fragp, seg) fragS *fragp; asection *seg; { - if (fragp->fr_subtype == 0) - return 2; - if (fragp->fr_subtype == 3) - return 3; - if (fragp->fr_subtype == 6) - { - if (!S_IS_DEFINED (fragp->fr_symbol) - || seg != S_GET_SEGMENT (fragp->fr_symbol)) - { - fragp->fr_subtype = 7; - return 7; - } - else - return 5; - } - if (fragp->fr_subtype == 8) - { - if (!S_IS_DEFINED (fragp->fr_symbol) - || seg != S_GET_SEGMENT (fragp->fr_symbol)) - { - fragp->fr_subtype = 9; - return 6; - } - else - return 4; - } - if (fragp->fr_subtype == 10) - { - if (!S_IS_DEFINED (fragp->fr_symbol) - || seg != S_GET_SEGMENT (fragp->fr_symbol)) - { - fragp->fr_subtype = 12; - return 5; - } - else - return 2; - } - abort (); + if (fragp->fr_subtype == 6 + && (!S_IS_DEFINED (fragp->fr_symbol) + || seg != S_GET_SEGMENT (fragp->fr_symbol))) + fragp->fr_subtype = 7; + else if (fragp->fr_subtype == 8 + && (!S_IS_DEFINED (fragp->fr_symbol) + || seg != S_GET_SEGMENT (fragp->fr_symbol))) + fragp->fr_subtype = 9; + else if (fragp->fr_subtype == 10 + && (!S_IS_DEFINED (fragp->fr_symbol) + || seg != S_GET_SEGMENT (fragp->fr_symbol))) + fragp->fr_subtype = 12; + + if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) + abort (); + + return md_relax_table[fragp->fr_subtype].rlx_length; } long @@ -1939,14 +1947,17 @@ md_apply_fix3 (fixp, valuep, seg) switch (fixp->fx_r_type) { case BFD_RELOC_8: + case BFD_RELOC_8_PCREL: size = 1; break; case BFD_RELOC_16: + case BFD_RELOC_16_PCREL: size = 2; break; case BFD_RELOC_32: + case BFD_RELOC_32_PCREL: size = 4; break; @@ -1963,9 +1974,11 @@ md_apply_fix3 (fixp, valuep, seg) md_number_to_chars (fixpos, value, size); - fixp->fx_done = 1; - return 0; + /* If a symbol remains, pass the fixup, as a reloc, onto the linker. */ + if (fixp->fx_addsy == NULL) + fixp->fx_done = 1; + return 0; } /* Return nonzero if the fixup in FIXP will require a relocation, @@ -1980,6 +1993,15 @@ mn10300_force_relocation (fixp) || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 1; + /* Do not adjust relocations involving symbols in code sections, + because it breaks linker relaxations. This could be fixed in the + linker, but this fix is simpler, and it pretty much only affects + object size a little bit. */ + if ((S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE) + && fixp->fx_subsy + && S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)) + return 1; + return 0; } @@ -1998,6 +2020,13 @@ mn10300_fix_adjustable (fixp) || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 0; + /* Do not adjust relocations involving symbols in code sections, + because it breaks linker relaxations. This could be fixed in the + linker, but this fix is simpler, and it pretty much only affects + object size a little bit. */ + if (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE) + return 0; + return 1; } diff --git a/gas/config/tc-tic54x.h b/gas/config/tc-tic54x.h index b43cce1fdd8..9e7e4aab62e 100644 --- a/gas/config/tc-tic54x.h +++ b/gas/config/tc-tic54x.h @@ -1,5 +1,5 @@ /* tc-tic54x.h -- Header file for tc-tic54x.c - Copyright (C) 1999, 2000 Free Software Foundation. + Copyright 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Timothy Wall (twall@alum.mit.edu) This file is part of GAS, the GNU Assembler. @@ -108,7 +108,7 @@ extern void tic54x_start_line_hook (); tic54x_estimate_size_before_relax(f,s) extern int tic54x_estimate_size_before_relax(fragS *, segT); -#define md_relax_frag(f,s) tic54x_relax_frag(f,s) +#define md_relax_frag(seg, f,s) tic54x_relax_frag(f,s) extern int tic54x_relax_frag(fragS *, long); #define md_convert_frag(b,s,f) tic54x_convert_frag(b,s,f) diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index 579319505d8..ce676cd8442 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -1,5 +1,6 @@ /* tc-v850.c -- Assembler code for the NEC V850 - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation. + Copyright 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -604,8 +605,8 @@ const pseudo_typeS md_pseudo_table[] = { {"call_table_text", v850_call_table_text, 0}, {"v850e", set_machine, bfd_mach_v850e}, {"v850ea", set_machine, bfd_mach_v850ea}, - {"file", dwarf2_directive_file }, - {"loc", dwarf2_directive_loc }, + {"file", dwarf2_directive_file, 0}, + {"loc", dwarf2_directive_loc, 0}, { NULL, NULL, 0} }; @@ -1321,7 +1322,6 @@ md_convert_frag (abfd, sec, fragP) { fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode); - fragP->fr_var = 0; fragP->fr_fix += 2; } /* Out of range conditional branch. Emit a branch around a jump. */ @@ -1345,7 +1345,6 @@ md_convert_frag (abfd, sec, fragP) fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode + 1); - fragP->fr_var = 0; fragP->fr_fix += 6; } /* Out of range unconditional branch. Emit a jump. */ @@ -1355,7 +1354,6 @@ md_convert_frag (abfd, sec, fragP) fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode + 1); - fragP->fr_var = 0; fragP->fr_fix += 4; } else @@ -1702,7 +1700,6 @@ md_assemble (str) int relaxable = 0; unsigned long insn; unsigned long insn_size; - unsigned long total_insn_size = 0; char *f; int i; int match; @@ -2153,6 +2150,11 @@ md_assemble (str) input_line_pointer = str; + /* Tie dwarf2 debug info to the address at the start of the insn. + We can't do this after the insn has been output as the current + frag may have been closed off. eg. by frag_var. */ + dwarf2_emit_insn (0); + /* Write out the instruction. */ if (relaxable && fc > 0) @@ -2178,7 +2180,6 @@ md_assemble (str) md_number_to_chars (f, insn, insn_size); md_number_to_chars (f + 2, 0, 4); } - total_insn_size = insn_size; } else { @@ -2193,15 +2194,11 @@ md_assemble (str) insn_size = 2; f = frag_more (insn_size); - total_insn_size = insn_size; - md_number_to_chars (f, insn, insn_size); if (extra_data_after_insn) { f = frag_more (extra_data_len); - total_insn_size += extra_data_len; - md_number_to_chars (f, extra_data, extra_data_len); extra_data_after_insn = false; @@ -2274,8 +2271,6 @@ md_assemble (str) } input_line_pointer = saved_input_line_pointer; - - dwarf2_emit_insn (total_insn_size); } /* If while processing a fixup, a reloc really needs to be created @@ -2315,20 +2310,17 @@ tc_gen_reloc (seg, fixp) return reloc; } -/* Assume everything will fit in two bytes, then expand as necessary. */ +/* Return current size of variable part of frag. */ int md_estimate_size_before_relax (fragp, seg) fragS *fragp; asection *seg ATTRIBUTE_UNUSED; { - if (fragp->fr_subtype == 0) - fragp->fr_var = 4; - else if (fragp->fr_subtype == 2) - fragp->fr_var = 2; - else + if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) abort (); - return 2; + + return md_relax_table[fragp->fr_subtype].rlx_length; } long diff --git a/gas/doc/c-arc.texi b/gas/doc/c-arc.texi index fa33e4f196f..700a01d15d8 100644 --- a/gas/doc/c-arc.texi +++ b/gas/doc/c-arc.texi @@ -1,4 +1,4 @@ -@c Copyright (C) 2000, 2001 Free Software Foundation, Inc. +@c Copyright 2000, 2001 Free Software Foundation, Inc. @c This is part of the GAS manual. @c For copying conditions, see the file as.texinfo. @@ -13,7 +13,7 @@ @chapter ARC Dependent Features @end ifclear -@set ARC_CORE_DEFAULT 5 +@set ARC_CORE_DEFAULT 6 @cindex ARC support @menu diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index 110d5607d89..1527c8d78a1 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -1,4 +1,5 @@ -@c Copyright (C) 1991, 92, 93, 94, 95, 97, 1998 Free Software Foundation, Inc. +@c Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001 +@c Free Software Foundation, Inc. @c This is part of the GAS manual. @c For copying conditions, see the file as.texinfo. @ifset GENERIC @@ -26,7 +27,7 @@ extending the Intel architecture to 64-bits. * i386-Regs:: Register Naming * i386-Prefixes:: Instruction Prefixes * i386-Memory:: Memory References -* i386-jumps:: Handling of Jump Instructions +* i386-Jumps:: Handling of Jump Instructions * i386-Float:: Floating Point * i386-SIMD:: Intel's MMX and AMD's 3DNow! SIMD Operations * i386-16bit:: Writing 16-bit Code @@ -488,7 +489,7 @@ the default absolute addressing. Other addressing modes remain unchanged in x86-64 architecture, except registers used are 64-bit instead of 32-bit. -@node i386-jumps +@node i386-Jumps @section Handling of Jump Instructions @cindex jump optimization, i386 @@ -498,11 +499,11 @@ registers used are 64-bit instead of 32-bit. Jump instructions are always optimized to use the smallest possible displacements. This is accomplished by using byte (8-bit) displacement jumps whenever the target is sufficiently close. If a byte displacement -is insufficient a long (32-bit) displacement is used. We do not support +is insufficient a long displacement is used. We do not support word (16-bit) displacement jumps in 32-bit mode (i.e. prefixing the jump instruction with the @samp{data16} instruction prefix), since the 80386 insists upon masking @samp{%eip} to 16 bits after the word displacement -is added. +is added. (See also @pxref{i386-Arch}) Note that the @samp{jcxz}, @samp{jecxz}, @samp{loop}, @samp{loopz}, @samp{loope}, @samp{loopnz} and @samp{loopne} instructions only come in byte @@ -696,13 +697,33 @@ supported on the CPU specified. The choices for @var{cpu_type} are: @item @samp{sledgehammer} @end multitable -Apart from the warning, there is only one other effect on -@code{@value{AS}} operation; If you specify a CPU other than +Apart from the warning, there are only two other effects on +@code{@value{AS}} operation; Firstly, if you specify a CPU other than @samp{i486}, then shift by one instructions such as @samp{sarl $1, %eax} will automatically use a two byte opcode sequence. The larger three byte opcode sequence is used on the 486 (and when no architecture is specified) because it executes faster on the 486. Note that you can explicitly request the two byte opcode by writing @samp{sarl %eax}. +Secondly, if you specify @samp{i8086}, @samp{i186}, or @samp{i286}, +@emph{and} @samp{.code16} or @samp{.code16gcc} then byte offset +conditional jumps will be promoted when necessary to a two instruction +sequence consisting of a conditional jump of the opposite sense around +an unconditional jump to the target. + +Following the CPU architecture, you may specify @samp{jumps} or +@samp{nojumps} to control automatic promotion of conditional jumps. +@samp{jumps} is the default, and enables jump promotion; All external +jumps will be of the long variety, and file-local jumps will be promoted +as necessary. (@pxref{i386-Jumps}) @samp{nojumps} leaves external +conditional jumps as byte offset jumps, and warns about file-local +conditional jumps that @code{@value{AS}} promotes. +Unconditional jumps are treated as for @samp{jumps}. + +For example + +@smallexample + .arch i8086,nojumps +@end smallexample @node i386-Notes @section Notes diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi index a42bc0f50bd..eebb9bbc653 100644 --- a/gas/doc/internals.texi +++ b/gas/doc/internals.texi @@ -1,4 +1,7 @@ \input texinfo +@c Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +@c 2001 +@c Free Software Foundation, Inc. @setfilename internals.info @node Top @top Assembler Internals @@ -1166,9 +1169,10 @@ relocations. @item md_relax_frag @cindex md_relax_frag -This macro may be defined to relax a frag. GAS will call this with the frag -and the change in size of all previous frags; @code{md_relax_frag} should -return the change in size of the frag. @xref{Relaxation}. +This macro may be defined to relax a frag. GAS will call this with the +segment, the frag, and the change in size of all previous frags; +@code{md_relax_frag} should return the change in size of the frag. +@xref{Relaxation}. @item TC_GENERIC_RELAX_TABLE @cindex TC_GENERIC_RELAX_TABLE diff --git a/gas/frags.h b/gas/frags.h index c1c652bd89a..e4cb0509dbc 100644 --- a/gas/frags.h +++ b/gas/frags.h @@ -1,5 +1,5 @@ /* frags.h - Header file for the frag concept. - Copyright (C) 1987, 92, 93, 94, 95, 97, 98, 99, 2000 + Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -62,6 +62,10 @@ struct frag { struct list_info_struct *line; #endif + /* Flipped each relax pass so we can easily determine whether + fr_address has been adjusted. */ + unsigned int relax_marker:1; + /* What state is my tail in? */ relax_stateT fr_type; relax_substateT fr_subtype; diff --git a/gas/read.c b/gas/read.c index 2cdd1cbfdf7..d047a0f8b12 100644 --- a/gas/read.c +++ b/gas/read.c @@ -4856,12 +4856,26 @@ equals (sym_name, reassign) } else { +#ifdef OBJ_COFF + int local; + + symbolP = symbol_find (sym_name); + local = symbolP == NULL; + if (local) +#endif /* OBJ_COFF */ symbolP = symbol_find_or_make (sym_name); /* Permit register names to be redefined. */ if (!reassign && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section) as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); + +#ifdef OBJ_COFF + /* "set" symbols are local unless otherwise specified. */ + if (local) + SF_SET_LOCAL (symbolP); +#endif /* OBJ_COFF */ + pseudo_set (symbolP); } diff --git a/gas/stabs.c b/gas/stabs.c index faf3a9c12cc..eed11b31c69 100644 --- a/gas/stabs.c +++ b/gas/stabs.c @@ -1,5 +1,5 @@ /* Generic stabs parsing for gas. - Copyright (C) 1989, 90, 91, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -185,7 +185,7 @@ s_stab_generic (what, stab_secname, stabstr_secname) char *stabstr_secname; { long longint; - char *string; + char *string, *saved_string_obstack_end; int type; int other; int desc; @@ -199,12 +199,19 @@ s_stab_generic (what, stab_secname, stabstr_secname) 'd' indicating which type of .stab this is. */ if (what != 's') - string = ""; + { + string = ""; + saved_string_obstack_end = 0; + } else { int length; string = demand_copy_C_string (&length); + /* FIXME: We should probably find some other temporary storage + for string, rather than leaking memory if someone else + happens to use the notes obstack. */ + saved_string_obstack_end = notes.next_free; SKIP_WHITESPACE (); if (*input_line_pointer == ',') input_line_pointer++; @@ -335,8 +342,9 @@ s_stab_generic (what, stab_secname, stabstr_secname) stroff = get_stab_string_offset (string, stabstr_secname); if (what == 's') { - /* release the string */ - obstack_free (¬es, string); + /* Release the string, if nobody else has used the obstack. */ + if (saved_string_obstack_end == notes.next_free) + obstack_free (¬es, string); } /* At least for now, stabs in a special stab section are always diff --git a/gas/write.c b/gas/write.c index 9ef356fe55e..cfdc9b5e35f 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1,5 +1,6 @@ /* write.c - emit .o file - Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, + 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -283,6 +284,10 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type) case O_absent: break; + case O_register: + as_bad (_("register value used as expression")); + break; + case O_add: /* This comes up when _GLOBAL_OFFSET_TABLE_+(.-L0) is read, if the difference expression cannot immediately be reduced. */ @@ -2011,24 +2016,11 @@ write_object_file () #ifdef TC_GENERIC_RELAX_TABLE -static int is_dnrange PARAMS ((fragS *, fragS *)); - -/* Subroutines of relax_segment. */ -static int -is_dnrange (f1, f2) - fragS *f1; - fragS *f2; -{ - for (; f1; f1 = f1->fr_next) - if (f1->fr_next == f2) - return 1; - return 0; -} - /* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE. */ long -relax_frag (fragP, stretch) +relax_frag (segment, fragP, stretch) + segT segment; fragS *fragP; long stretch; { @@ -2036,20 +2028,26 @@ relax_frag (fragP, stretch) const relax_typeS *start_type; relax_substateT next_state; relax_substateT this_state; - long aim, target, growth; - symbolS *symbolP = fragP->fr_symbol; - long offset = fragP->fr_offset; - /* Recompute was_address by undoing "+= stretch" done by relax_segment. */ - unsigned long was_address = fragP->fr_address - stretch; - unsigned long address = fragP->fr_address; - const relax_typeS *table = TC_GENERIC_RELAX_TABLE; - + long growth; + offsetT aim; + addressT target; + addressT address; + symbolS *symbolP; + const relax_typeS *table; + + target = fragP->fr_offset; + address = fragP->fr_address; + table = TC_GENERIC_RELAX_TABLE; this_state = fragP->fr_subtype; start_type = this_type = table + this_state; - target = offset; + symbolP = fragP->fr_symbol; if (symbolP) { + fragS *sym_frag; + + sym_frag = symbol_get_frag (symbolP); + #ifndef DIFF_EXPR_OK #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER) know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) @@ -2057,23 +2055,20 @@ relax_frag (fragP, stretch) || (S_GET_SEGMENT (symbolP) == SEG_BSS) || (S_GET_SEGMENT (symbolP) == SEG_TEXT)); #endif - know (symbolP->sy_frag); + know (sym_frag != NULL); #endif know (!(S_GET_SEGMENT (symbolP) == absolute_section) - || symbolP->sy_frag == &zero_address_frag); - target += S_GET_VALUE (symbolP) + symbol_get_frag (symbolP)->fr_address; + || sym_frag == &zero_address_frag); + target += S_GET_VALUE (symbolP) + sym_frag->fr_address; /* If frag has yet to be reached on this pass, assume it will move by STRETCH just as we did. If this is not so, it will be because some frag - between grows, and that will force another pass. - - Beware zero-length frags. - - There should be a faster way to do this. */ + between grows, and that will force another pass. */ - if (symbol_get_frag (symbolP)->fr_address >= was_address - && is_dnrange (fragP, symbol_get_frag (symbolP))) + if (stretch != 0 + && sym_frag->relax_marker != fragP->relax_marker + && S_GET_SEGMENT (symbolP) == segment) { target += stretch; } @@ -2180,6 +2175,7 @@ relax_segment (segment_frag_root, segment) address = 0; for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) { + fragP->relax_marker = 0; fragP->fr_address = address; address += fragP->fr_fix; @@ -2249,14 +2245,15 @@ relax_segment (segment_frag_root, segment) long stretch; /* May be any size, 0 or negative. */ /* Cumulative number of addresses we have relaxed this pass. We may have relaxed more than one address. */ - long stretched; /* Have we stretched on this pass? */ + int stretched; /* Have we stretched on this pass? */ /* This is 'cuz stretch may be zero, when, in fact some piece of code grew, and another shrank. If a branch instruction doesn't fit anymore, we could be scrod. */ do { - stretch = stretched = 0; + stretch = 0; + stretched = 0; for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) { @@ -2265,6 +2262,7 @@ relax_segment (segment_frag_root, segment) offsetT offset; symbolS *symbolP; + fragP->relax_marker ^= 1; was_address = fragP->fr_address; address = fragP->fr_address += stretch; symbolP = fragP->fr_symbol; @@ -2364,8 +2362,8 @@ relax_segment (segment_frag_root, segment) case rs_org: { - long target = offset; - long after; + addressT target = offset; + addressT after; if (symbolP) { @@ -2429,12 +2427,12 @@ relax_segment (segment_frag_root, segment) case rs_machine_dependent: #ifdef md_relax_frag - growth = md_relax_frag (fragP, stretch); + growth = md_relax_frag (segment, fragP, stretch); #else #ifdef TC_GENERIC_RELAX_TABLE /* The default way to relax a frag is to look through TC_GENERIC_RELAX_TABLE. */ - growth = relax_frag (fragP, stretch); + growth = relax_frag (segment, fragP, stretch); #endif /* TC_GENERIC_RELAX_TABLE */ #endif break; @@ -2466,7 +2464,7 @@ relax_segment (segment_frag_root, segment) if (growth) { stretch += growth; - stretched++; + stretched = 1; } } /* For each frag in the segment. */ } diff --git a/gas/write.h b/gas/write.h index 9872e9d82b4..5bab7a21214 100644 --- a/gas/write.h +++ b/gas/write.h @@ -1,5 +1,5 @@ /* write.h - Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 2000 + Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -181,7 +181,7 @@ extern void record_alignment PARAMS ((segT seg, int align)); extern int get_recorded_alignment PARAMS ((segT seg)); extern void subsegs_finish PARAMS ((void)); extern void write_object_file PARAMS ((void)); -extern long relax_frag PARAMS ((fragS *, long)); +extern long relax_frag PARAMS ((segT, fragS *, long)); extern void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type)); diff --git a/ld/ChangeLog b/ld/ChangeLog index a964658523b..8fd07c07d03 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,56 @@ +2001-05-23 Alan Modra + + * ldlang.c (wild_doit): Use linker_has_input to reliably determine + whether an input section is the first one assigned to an output + section. + Assorted formatting fixes. + + Merge from mainline. + 2001-05-03 H.J. Lu + * emultempl/elf32.em: Include "libiberty.h". + (gld${EMULATION_NAME}_vercheck): Call basename () to get the + basename of the bfd filename. + (gld${EMULATION_NAME}_stat_needed): Likewise. + (gld${EMULATION_NAME}_try_needed): Likewise. + (gld${EMULATION_NAME}_open_dynamic_archive): Likewise. + + 2001-03-17 Ulrich Drepper + * emultmpl/elf32.em (gld${EMULATION_NAME}_search_needed): If NAME + is an absolute path look only for this file and not along the path. + (OPTION_GROUP): New macro. + Add new option Bgroup to longopts. + (gld*_parse_args): Handle GROUP_OPTION and recognize -z defs. + (gld*_list_options): Add -Bgroup and -z defs. + * ld.1: Document -Bgroup and -z defs. + * ld.texinfo: Likewise. + + 2001-02-01 Nick Clifton + * ld.1: Replace occurances of -oformat with --oformat. + + 2001-05-02 H.J. Lu + * ldfile.c: Include "libiberty.h". + * ldlex.l: Likewise. + * ldmisc.c (buystring): Removed. + * ldmisc.h: Likewise. + * ldfile.c: Replace buystring with xstrdup. + * ldlang.c: Likewise. + * ldlex.l: Likewise. + * ldmain.c: Likewise. + * ldmisc.c: Likewise. + * lexsup.c: Likewise. + * mpw-eppcmac.c: Likewise. + + 2001-04-28 Paul Sokolovsky + * ldlang.c (load_symbols): Give emulation a chance + to process unrecognized file before fatal error is + reported, not after. + + 2001-02-26 H.J. Lu + * ldlang.c (open_input_bfds): Set the bfd error handler so + that problems can be caught whilst loading symbols. + (record_bfd_errors): New function: Report BFD errors and mark + the executable output as being invalid. + 2001-04-02 Alan Modra * emulparams/hppalinux.sh (MAXPAGESIZE): Set to 64k. @@ -670,7 +723,7 @@ Tue Nov 14 00:59:19 2000 Denis Chertykov * scripttempl/elf.sc: Add .gnu.linkonce.wi.* to .debug_info sections. - * scripttempl/elf32var.sc: Ditto. + * scripttempl/elf32avr.sc: Ditto. * scripttempl/elfd10v.sc: Ditto. * scripttempl/elfd30v.sc: Ditto. * scripttempl/elfi370.sc: Ditto. @@ -867,8 +920,8 @@ Tue Nov 14 00:59:19 2000 Denis Chertykov 2000-07-05 Kenneth Block - * ld/lexsup.c: Add optional style to demangle switch - * ld/ld.texinfo: Document optional style to demangle switch. + * lexsup.c: Add optional style to demangle switch + * ld.texinfo: Document optional style to demangle switch. 2000-07-20 Hans-Peter Nilsson @@ -924,7 +977,7 @@ Tue Nov 14 00:59:19 2000 Denis Chertykov 2000-07-16 Charles Wilson - * src/ld/emultempl/pe.em (gld_*_open_dynamic_archive): New search + * emultempl/pe.em (gld_*_open_dynamic_archive): New search order for dynamic library '-lfoo' on pei386: libfoo.dll.a, foo.dll.a, libfoo.a, libfoo.dll, foo.dll. This fixes compatibility errors introduced by the old dynamic lib search order. @@ -1256,7 +1309,7 @@ Thu May 18 10:47:57 2000 Jeffrey A Law (law@cygnus.com) 2000-05-16 Charles Wilson - * ld/emultempl/pe.em (_open_dynamic_archive): New function: Search + * emultempl/pe.em (_open_dynamic_archive): New function: Search the library path for "foo.dll" and "libfoo.dll" dynamic libraries before searching for 'libfoo.a' in response to a '-Bdynamic -lfoo' link options. @@ -1563,7 +1616,7 @@ Fri Apr 7 15:56:57 2000 Andrew Cagney (gld_X_find_potential_libraries): New function. Search for libraries called "*.lib". - * scriptempl/pe.sc: Add .pdata section. + * scripttempl/pe.sc: Add .pdata section. 2000-02-23 Richard Henderson @@ -1624,9 +1677,9 @@ Fri Apr 7 15:56:57 2000 Andrew Cagney 2000-02-03 Timothy Wall - * ld/ldexp.c (fold_name): Make SIZEOF operator return byte count, not + * ldexp.c (fold_name): Make SIZEOF operator return byte count, not octet count. - * ld/ldlang.c (print_input_section, print_data_statement, + * ldlang.c (print_input_section, print_data_statement, print_reloc_statement, print_padding_statement): Print target address values and section sizes as bytes, not octets. (insert_pad) Calculate padding size in octets, and adjust "dot" diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 9ac2d414346..c0d52b10205 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c < ELF support by Ian Lance Taylor @@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" +#include "libiberty.h" #include @@ -130,7 +131,7 @@ static void gld${EMULATION_NAME}_vercheck (s) lang_input_statement_type *s; { - const char *soname, *f; + const char *soname; struct bfd_link_needed_list *l; if (global_vercheck_failed) @@ -141,19 +142,13 @@ gld${EMULATION_NAME}_vercheck (s) soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) - soname = bfd_get_filename (s->the_bfd); - - f = strrchr (soname, '/'); - if (f != NULL) - ++f; - else - f = soname; + soname = basename (bfd_get_filename (s->the_bfd)); for (l = global_vercheck_needed; l != NULL; l = l->next) { const char *suffix; - if (strcmp (f, l->name) == 0) + if (strcmp (soname, l->name) == 0) { /* Probably can't happen, but it's an easy check. */ continue; @@ -168,7 +163,7 @@ gld${EMULATION_NAME}_vercheck (s) suffix += sizeof ".so." - 1; - if (strncmp (f, l->name, suffix - l->name) == 0) + if (strncmp (soname, l->name, suffix - l->name) == 0) { /* Here we know that S is a dynamic object FOO.SO.VER1, and the object we are considering needs a dynamic object @@ -192,7 +187,6 @@ gld${EMULATION_NAME}_stat_needed (s) struct stat st; const char *suffix; const char *soname; - const char *f; if (global_found) return; @@ -230,17 +224,12 @@ gld${EMULATION_NAME}_stat_needed (s) soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) - soname = s->filename; - - f = strrchr (soname, '/'); - if (f != NULL) - ++f; - else - f = soname; + soname = basename (s->filename); - if (strncmp (f, global_needed->name, suffix - global_needed->name) == 0) + if (strncmp (soname, global_needed->name, + suffix - global_needed->name) == 0) einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", - global_needed->name, global_needed->by, f); + global_needed->name, global_needed->by, soname); } @@ -340,11 +329,7 @@ cat >>e${EMULATION_NAME}.c <filename, '/'); - if (soname) - soname++; - else - soname = abfd->filename; + soname = basename (abfd->filename); if (trace_file_tries) info_msg (_("found %s at %s\n"), soname, name); @@ -949,20 +934,13 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) if (bfd_check_format (entry->the_bfd, bfd_object) && (entry->the_bfd->flags & DYNAMIC) != 0) { - char *needed_name; - ASSERT (entry->is_archive && entry->search_dirs_flag); /* Rather than duplicating the logic above. Just use the - filename we recorded earlier. - - First strip off everything before the last '/'. */ - filename = strrchr (entry->filename, '/'); - filename++; + filename we recorded earlier. */ - needed_name = (char *) xmalloc (strlen (filename) + 1); - strcpy (needed_name, filename); - bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); + filename = xstrdup (basename (entry->filename)); + bfd_elf_set_dt_needed_name (entry->the_bfd, filename); } return true; @@ -1337,6 +1315,7 @@ cat >>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <> <<&\cr @@ -3683,7 +3696,7 @@ following @group SECTIONS @{ - .text 9+this_isnt_constant : + .text 9+this_isnt_constant : @{ *(.text) @} @} @end group @@ -3758,7 +3771,7 @@ identical values: @group SECTIONS @{ @dots{} .output1 : - @{ + @{ start_of_output_1 = ABSOLUTE(.); @dots{} @} @@ -4071,7 +4084,7 @@ non-interworking aware Thumb code. @cindex entry point, thumb @kindex --thumb-entry=@var{entry} The @samp{--thumb-entry} switch is a duplicate of the generic -@samp{--entry} switch, in that it sets the program's starting address. +@samp{--entry} switch, in that it sets the program's starting address. But it also sets the bottom bit of the address, so that it can be branched to using a BX instruction, and the program will start executing in Thumb mode straight away. @@ -4449,10 +4462,10 @@ This command does nothing whatever; it's only accepted for compatibility. @cindex @code{FORMAT} (MRI) @item FORMAT @var{output-format} Similar to the @code{OUTPUT_FORMAT} command in the more general linker -language, but restricted to one of these output formats: +language, but restricted to one of these output formats: @enumerate -@item +@item S-records, if @var{output-format} is @samp{S} @item @@ -4515,12 +4528,12 @@ If you have more than one @code{SECT} statement for the same @cindex GNU Free Documentation License GNU Free Documentation License - + Version 1.1, March 2000 Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/ld/ldfile.c b/ld/ldfile.c index fbb46851de3..0e4d0ec3a2e 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -1,5 +1,5 @@ /* Linker file opening and searching. - Copyright (C) 1991, 92, 93, 94, 95, 98, 99, 2000 + Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "ldgram.h" #include "ldlex.h" #include "ldemul.h" +#include "libiberty.h" #include @@ -231,23 +232,32 @@ ldfile_open_file (entry) else { search_arch_type *arch; + boolean found = false; /* Try to open or lib.a */ for (arch = search_arch_head; arch != (search_arch_type *) NULL; arch = arch->next) { - if (ldfile_open_file_search (arch->name, entry, "lib", ".a")) - return; + found = ldfile_open_file_search (arch->name, entry, "lib", ".a"); + if (found) + break; #ifdef VMS - if (ldfile_open_file_search (arch->name, entry, ":lib", ".a")) - return; + found = ldfile_open_file_search (arch->name, entry, ":lib", ".a"); + if (found) + break; #endif - if (ldemul_find_potential_libraries (arch->name, entry)) - return; + found = ldemul_find_potential_libraries (arch->name, entry); + if (found) + break; } - einfo (_("%F%P: cannot find %s\n"), entry->local_sym_name); + /* If we have found the file, we don't need to search directories + again. */ + if (found) + entry->search_dirs_flag = false; + else + einfo (_("%F%P: cannot find %s\n"), entry->local_sym_name); } } @@ -405,7 +415,7 @@ void ldfile_add_arch (in_name) CONST char *in_name; { - char *name = buystring (in_name); + char *name = xstrdup (in_name); search_arch_type *new = (search_arch_type *) xmalloc (sizeof (search_arch_type)); diff --git a/ld/ldlang.c b/ld/ldlang.c index 32097faf694..4fe0ee934ec 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,5 +1,6 @@ /* Linker command language support. - Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -41,9 +42,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include /* FORWARDS */ -static lang_statement_union_type *new_statement PARAMS ((enum statement_enum, - size_t, - lang_statement_list_type *)); +static lang_statement_union_type *new_statement + PARAMS ((enum statement_enum, size_t, lang_statement_list_type *)); /* LOCALS */ static struct obstack stat_obstack; @@ -127,6 +127,7 @@ static bfd_vma size_input_section fill_type, bfd_vma, boolean)); static void lang_finish PARAMS ((void)); static void ignore_bfd_errors PARAMS ((const char *, ...)); +static void record_bfd_errors PARAMS ((const char *, ...)); static void lang_check PARAMS ((void)); static void lang_common PARAMS ((void)); static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR)); @@ -190,18 +191,22 @@ struct unique_sections *unique_section_list; etree_type *base; /* Relocation base - or null */ -#if defined(__STDC__) || defined(ALMOST_STDC) +#if defined (__STDC__) || defined (ALMOST_STDC) #define cat(a,b) a##b #else #define cat(a,b) a/**/b #endif -/* Don't beautify the line below with "innocent" whitespace, it breaks the K&R C preprocessor! */ -#define new_stat(x, y) (cat (x,_type)*) new_statement (cat (x,_enum), sizeof (cat (x,_type)), y) +/* Don't beautify the line below with "innocent" whitespace, it breaks + the K&R C preprocessor! */ +#define new_stat(x, y) \ + (cat (x,_type)*) new_statement (cat (x,_enum), sizeof (cat (x,_type)), y) -#define outside_section_address(q) ((q)->output_offset + (q)->output_section->vma) +#define outside_section_address(q) \ + ((q)->output_offset + (q)->output_section->vma) -#define outside_symbol_address(q) ((q)->value + outside_section_address (q->section)) +#define outside_symbol_address(q) \ + ((q)->value + outside_section_address (q->section)) #define SECTION_NAME_MAP_LENGTH (16) @@ -243,14 +248,16 @@ walk_wild_section (ptr, section, file, callback, data) if (ptr->exclude_filename_list != NULL) { struct name_list *list_tmp; - for (list_tmp = ptr->exclude_filename_list; list_tmp; list_tmp = list_tmp->next) + for (list_tmp = ptr->exclude_filename_list; + list_tmp; + list_tmp = list_tmp->next) { boolean match; if (wildcardp (list_tmp->name)) - match = fnmatch (list_tmp->name, file->filename, 0) == 0 ? true : false; + match = fnmatch (list_tmp->name, file->filename, 0) == 0; else - match = strcmp (list_tmp->name, file->filename) == 0 ? true : false; + match = strcmp (list_tmp->name, file->filename) == 0; if (match) return; @@ -273,9 +280,9 @@ walk_wild_section (ptr, section, file, callback, data) if (section == NULL) match = true; else if (wildcard) - match = fnmatch (section, sname, 0) == 0 ? true : false; + match = fnmatch (section, sname, 0) == 0; else - match = strcmp (section, sname) == 0 ? true : false; + match = strcmp (section, sname) == 0; /* If this is a wild-card output section statement, exclude sections that match UNIQUE_SECTION_LIST. */ @@ -448,7 +455,7 @@ new_statement (type, size, list) We can be supplied with requests for input files more than once; they may, for example be split over serveral lines like foo.o(.text) - foo.o(.data) etc, so when asked for a file we check that we havn't + foo.o(.data) etc, so when asked for a file we check that we haven't got it already so we don't duplicate the bfd. */ static lang_input_statement_type * @@ -621,7 +628,7 @@ lang_memory_region_lookup (name) lang_memory_region_type *new = (lang_memory_region_type *) stat_alloc (sizeof (lang_memory_region_type)); - new->name = buystring (name); + new->name = xstrdup (name); new->next = (lang_memory_region_type *) NULL; *lang_memory_region_list_tail = new; @@ -1134,12 +1141,10 @@ wild_doit (ptr, section, output, file) flagword flags; if (output->bfd_section == NULL) - { - init_os (output); - first = true; - } - else - first = false; + init_os (output); + + first = ! output->bfd_section->linker_has_input; + output->bfd_section->linker_has_input = 1; /* Add a section reference to the list. */ new = new_stat (lang_input_section, ptr); @@ -1433,6 +1438,11 @@ load_symbols (entry, place) lang_statement_list_type *hold; err = bfd_get_error (); + + /* See if the emulation has some special knowledge. */ + if (ldemul_unrecognized_file (entry)) + return; + if (err == bfd_error_file_ambiguously_recognized) { char **p; @@ -1450,13 +1460,7 @@ load_symbols (entry, place) bfd_close (entry->the_bfd); entry->the_bfd = NULL; - /* See if the emulation has some special knowledge. */ - - if (ldemul_unrecognized_file (entry)) - return; - /* Try to interpret the file as a linker script. */ - ldfile_open_command_file (entry->filename); hold = stat_ptr; @@ -1675,7 +1679,8 @@ closest_target_match (target, data) /* Oh dear, we now have two potential candidates for a successful match. Compare their names and choose the better one. */ - if (name_compare (target->name, original->name) > name_compare (winner->name, original->name)) + if (name_compare (target->name, original->name) + > name_compare (winner->name, original->name)) winner = target; /* Keep on searching until wqe have checked them all. */ @@ -1771,7 +1776,8 @@ open_output (name) /* Try to find a target as similar as possible to the default target, but which has the desired endian characteristic. */ - (void) bfd_search_for_target (closest_target_match, (PTR) target); + (void) bfd_search_for_target (closest_target_match, + (PTR) target); /* Oh dear - we could not find any targets that satisfy our requirements. */ @@ -1894,6 +1900,7 @@ open_input_bfds (s, force) if (s->input_statement.real) { lang_statement_list_type add; + bfd_error_handler_type pfn; s->input_statement.target = current_target; @@ -1910,8 +1917,15 @@ open_input_bfds (s, force) lang_list_init (&add); + /* We need to know if an error occurs whilst loading the + symbols, since this means that a valid executable can + not be produced. */ + pfn = bfd_set_error_handler (record_bfd_errors); + load_symbols (&s->input_statement, &add); + bfd_set_error_handler (pfn); + if (add.head != NULL) { *add.tail = s->next; @@ -1971,7 +1985,7 @@ ldlang_add_undef (name) new->next = ldlang_undef_chain_list_head; ldlang_undef_chain_list_head = new; - new->name = buystring (name); + new->name = xstrdup (name); } /* Run through the list of undefineds created above and place them @@ -2664,7 +2678,8 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax) } #define IGNORE_SECTION(bfd, s) \ - (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \ + (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) \ + != (SEC_ALLOC | SEC_LOAD)) \ || bfd_section_size (bfd, s) == 0) /* Check to see if any allocated sections overlap with other allocated @@ -2787,8 +2802,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) case lang_output_section_statement_enum: { bfd_vma after; - lang_output_section_statement_type *os = &s->output_section_statement; + lang_output_section_statement_type *os; + os = &s->output_section_statement; if (os->bfd_section == NULL) /* This section was never actually created. */ break; @@ -2843,10 +2859,12 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) && ! link_info.relocateable && strcmp (os->region->name, "*default*") == 0 && lang_memory_region_list != NULL - && (strcmp (lang_memory_region_list->name, "*default*") != 0 + && (strcmp (lang_memory_region_list->name, + "*default*") != 0 || lang_memory_region_list->next != NULL)) einfo (_("%P: warning: no memory region specified for section `%s'\n"), - bfd_get_section_name (output_bfd, os->bfd_section)); + bfd_get_section_name (output_bfd, + os->bfd_section)); dot = os->region->current; @@ -2855,7 +2873,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) bfd_vma olddot; olddot = dot; - dot = align_power (dot, os->bfd_section->alignment_power); + dot = align_power (dot, + os->bfd_section->alignment_power); if (dot != olddot && config.warn_section_align) einfo (_("%P: warning: changing start of section %s by %u bytes\n"), @@ -3172,9 +3191,9 @@ lang_do_assignments (s, output_section_statement, fill, dot) case lang_output_section_statement_enum: { - lang_output_section_statement_type *os = - &(s->output_section_statement); + lang_output_section_statement_type *os; + os = &(s->output_section_statement); if (os->bfd_section != NULL) { dot = os->bfd_section->vma; @@ -3347,8 +3366,10 @@ lang_set_startof () h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true); if (h != NULL && h->type == bfd_link_hash_undefined) { - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + unsigned opb; + + opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); h->type = bfd_link_hash_defined; if (s->_cooked_size != 0) h->u.def.value = s->_cooked_size / opb; @@ -3435,6 +3456,53 @@ lang_finish () } } +/* This is the routine to handle BFD error messages. */ + +#ifdef ANSI_PROTOTYPES + +static void +record_bfd_errors (const char *s, ...) +{ + va_list p; + + einfo ("%P: "); + + va_start (p, s); + + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); + + einfo ("%X"); +} + +#else /* ! defined (ANSI_PROTOTYPES) */ + +static void +record_bfd_errors (va_alist) + va_dcl +{ + va_list p; + const char *s; + + einfo ("%P: "); + + va_start (p); + + s = va_arg (p, const char *); + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); + + einfo ("%X"); +} + +#endif /* ! defined (ANSI_PROTOTYPES) */ + /* This is a small function used when we want to ignore errors from BFD. */ @@ -4181,8 +4249,9 @@ lang_section_start (name, address) const char *name; etree_type *address; { - lang_address_statement_type *ad = new_stat (lang_address_statement, stat_ptr); + lang_address_statement_type *ad; + ad = new_stat (lang_address_statement, stat_ptr); ad->section_name = name; ad->address = address; } @@ -4575,9 +4644,7 @@ lang_record_phdrs () lang_final_phase_enum); if (! bfd_record_phdr (output_bfd, l->type, - l->flags == NULL ? false : true, - flags, - l->at == NULL ? false : true, + l->flags != NULL, flags, l->at != NULL, at, l->filehdr, l->phdrs, c, secs)) einfo (_("%F%P: bfd_record_phdr failed: %E\n")); } diff --git a/ld/ldlex.l b/ld/ldlex.l index d5f5d27d3b8..eecb9022f1a 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -1,6 +1,6 @@ %{ -/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 +/* Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -45,6 +45,7 @@ This was written by steve chamberlain #include "ldfile.h" #include "ldlex.h" #include "ldmain.h" +#include "libiberty.h" /* The type of top-level parser input. yylex and yyparse (indirectly) both check this. */ @@ -147,7 +148,7 @@ V_IDENTIFIER [*?.$_a-zA-Z]([*?.$_a-zA-Z0-9]|::)* "-" { RTOKEN('-');} "+" { RTOKEN('+');} -{FILENAMECHAR1}{SYMBOLCHARN}* { yylval.name = buystring(yytext); return NAME; } +{FILENAMECHAR1}{SYMBOLCHARN}* { yylval.name = xstrdup(yytext); return NAME; } "=" { RTOKEN('='); } "$"([0-9A-Fa-f])+ { @@ -333,17 +334,17 @@ V_IDENTIFIER [*?.$_a-zA-Z]([*?.$_a-zA-Z0-9]|::)* {FILENAMECHAR1}{NOCFILENAMECHAR}* { /* Filename without commas, needed to parse mri stuff */ - yylval.name = buystring(yytext); + yylval.name = xstrdup(yytext); return NAME; } {FILENAMECHAR1}{FILENAMECHAR}* { - yylval.name = buystring(yytext); + yylval.name = xstrdup(yytext); return NAME; } "-l"{FILENAMECHAR}+ { - yylval.name = buystring (yytext + 2); + yylval.name = xstrdup (yytext + 2); return LNAME; }