diff options
author | obrien <obrien@FreeBSD.org> | 2001-06-26 17:56:02 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2001-06-26 17:56:02 +0000 |
commit | d43a7bbb99a2035bb5b098269ab303836cba2a35 (patch) | |
tree | ddacc0ba1bc0b52c92dc61a0e5d20195f811f28e /contrib | |
parent | a65699192dc08784842d088e15ddeef079bca2ce (diff) | |
download | FreeBSD-src-d43a7bbb99a2035bb5b098269ab303836cba2a35.zip FreeBSD-src-d43a7bbb99a2035bb5b098269ab303836cba2a35.tar.gz |
We use the stock (2.11.2) version of this now.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/binutils/gas/config/tc-i386.c | 694 | ||||
-rw-r--r-- | contrib/binutils/gas/config/te-freebsd.h | 2 | ||||
-rw-r--r-- | contrib/binutils/ld/configure.host | 2 | ||||
-rw-r--r-- | contrib/binutils/ld/configure.tgt | 13 | ||||
-rw-r--r-- | contrib/binutils/ld/ld.1 | 21 |
5 files changed, 419 insertions, 313 deletions
diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c index db2e18b..9227a2d 100644 --- a/contrib/binutils/gas/config/tc-i386.c +++ b/contrib/binutils/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. @@ -73,6 +74,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 @@ -120,11 +124,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. */ @@ -244,6 +244,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; @@ -277,15 +278,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 @@ -301,10 +307,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 @@ -319,31 +327,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[] = { @@ -730,7 +745,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; } } @@ -742,6 +758,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 (); } @@ -1202,9 +1235,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]; @@ -1212,7 +1242,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; @@ -1512,11 +1542,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; @@ -1536,9 +1562,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) { @@ -1658,7 +1684,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; @@ -2676,10 +2702,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; @@ -2694,16 +2724,19 @@ md_assemble (line) i.prefixes -= 1; code16 ^= CODE16; } + /* Pentium4 branch hints. */ + if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ + || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) + { + prefix++; + i.prefixes--; + } if (i.prefix[REX_PREFIX]) { prefix++; i.prefixes--; } - size = 4; - if (code16) - size = 2; - if (i.prefixes != 0 && !intel_syntax) as_warn (_("skipping prefixes on this instruction")); @@ -2712,23 +2745,27 @@ 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]) *p++ = DATA_PREFIX_OPCODE; + if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE + || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE) + *p++ = i.prefix[SEG_PREFIX]; if (i.prefix[REX_PREFIX]) *p++ = i.prefix[REX_PREFIX]; *p = i.tm.base_opcode; /* 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); @@ -2743,10 +2780,16 @@ md_assemble (line) size = 1; if (i.prefix[ADDR_PREFIX]) { - insn_size += 1; FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); i.prefixes -= 1; } + /* Pentium4 branch hints. */ + if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ + || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) + { + FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]); + i.prefixes--; + } } else { @@ -2758,7 +2801,6 @@ md_assemble (line) if (i.prefix[DATA_PREFIX]) { - insn_size += 1; FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); i.prefixes -= 1; code16 ^= CODE16; @@ -2772,29 +2814,17 @@ md_assemble (line) if (i.prefix[REX_PREFIX]) { FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); - insn_size++; i.prefixes -= 1; } if (i.prefixes != 0 && !intel_syntax) as_warn (_("skipping prefixes on this instruction")); - 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; + p = frag_more (1 + size); + *p++ = i.tm.base_opcode; 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) { @@ -2827,7 +2857,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]) @@ -2852,7 +2881,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); @@ -2875,7 +2904,6 @@ md_assemble (line) { if (*q) { - insn_size += 1; p = frag_more (1); md_number_to_chars (p, (valueT) *q, 1); } @@ -2884,12 +2912,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; @@ -2899,7 +2925,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 @@ -2914,7 +2939,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 @@ -2948,7 +2972,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); } @@ -2995,11 +3018,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])); } } } @@ -3030,7 +3052,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); } @@ -3040,11 +3061,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; @@ -3060,9 +3077,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 @@ -3088,8 +3104,6 @@ md_assemble (line) } } - dwarf2_emit_insn (insn_size); - #ifdef DEBUG386 if (flag_debug) { @@ -3099,6 +3113,130 @@ md_assemble (line) } } +#ifndef LEX_AT +static char *lex_got PARAMS ((RELOC_ENUM *, int *)); + +/* Parse operands of the form + <symbol>@GOTOFF+<nnn> + 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 @@ -3106,6 +3244,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; @@ -3125,80 +3266,22 @@ i386_immediate (imm_start) input_line_pointer = imm_start; #ifndef LEX_AT - { - /* We can have operands of the form - <symbol>@GOTOFF+<nnn> - 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) { @@ -3252,35 +3335,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) { @@ -3290,7 +3376,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 *)); @@ -3303,6 +3391,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)) @@ -3363,104 +3454,54 @@ i386_displacement (disp_start, disp_end) } #endif #ifndef LEX_AT - { - /* We can have operands of the form - <symbol>@GOTOFF+<nnn> - 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. */ @@ -3793,12 +3834,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 != ')') @@ -3899,11 +3942,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; @@ -3917,10 +3956,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, @@ -3929,9 +3968,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. */ @@ -3941,12 +4006,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. @@ -3986,7 +4062,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; @@ -3999,51 +4075,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/contrib/binutils/gas/config/te-freebsd.h b/contrib/binutils/gas/config/te-freebsd.h index 2714933..2095b41 100644 --- a/contrib/binutils/gas/config/te-freebsd.h +++ b/contrib/binutils/gas/config/te-freebsd.h @@ -1,5 +1,5 @@ /* te-freebsd.h -- FreeBSD target environment declarations. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright 2000 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. diff --git a/contrib/binutils/ld/configure.host b/contrib/binutils/ld/configure.host index 9b43552..e26c2c0 100644 --- a/contrib/binutils/ld/configure.host +++ b/contrib/binutils/ld/configure.host @@ -84,7 +84,7 @@ i[3456]86-*-sco* | i[3456]86-*-isc*) HOSTING_LIBS='`if [ -f ../gcc/libgcc.a ] ; then echo ../gcc/libgcc.a ; else ${CC} -print-libgcc-file-name; fi` -lc `if [ -f ../gcc/crtend.o ]; then echo ../gcc/crtend.o; else ${CC} -print-file-name=crtend.o; fi` /lib/crtn.o' ;; -i[3456]86-*-linux*aout* | i[3456]86-*-linuxoldld) +i[3456]86-*-linux*aout* | i[3456]86-*-linux*oldld) HOSTING_CRT0=/usr/lib/crt0.o ;; diff --git a/contrib/binutils/ld/configure.tgt b/contrib/binutils/ld/configure.tgt index e9df7c6..aad927a 100644 --- a/contrib/binutils/ld/configure.tgt +++ b/contrib/binutils/ld/configure.tgt @@ -134,7 +134,7 @@ i[3456]86-*-linux*aout*) targ_emul=i386linux targ_extra_emuls=elf_i386 tdir_elf_i386=`echo ${targ_alias} | sed -e 's/aout//'` ;; -i[3456]86-*-linuxoldld) targ_emul=i386linux; targ_extra_emuls=elf_i386 ;; +i[3456]86-*-linux*oldld) targ_emul=i386linux; targ_extra_emuls=elf_i386 ;; i[3456]86-*-linux-gnu*) targ_emul=elf_i386 targ_extra_emuls=i386linux tdir_i386linux=${targ_alias}aout @@ -185,6 +185,7 @@ a29k-*-*) targ_emul=a29k ;; arm-*-aout | armel-*-aout) targ_emul=armaoutl ;; armeb-*-aout) targ_emul=armaoutb ;; arm-*-coff) targ_emul=armcoff ;; +arm-*-vxworks) targ_emul=armcoff ;; arm-*-freebsd*) targ_emul=armelf ;; arm-*-netbsd*) targ_emul=armnbsd ;; arm-*-rtems*) targ_emul=armelf ;; @@ -276,11 +277,11 @@ mips*el-*-rtems*) targ_emul=elf32elmip ;; mips*-*-rtems*) targ_emul=elf32ebmip ;; mips*el-*-vxworks*) targ_emul=elf32elmip ;; mips*-*-vxworks*) targ_emul=elf32ebmip ;; -mips*el-*-linux-gnu*) targ_emul=elf32lsmip - targ_extra_emuls="elf32bsmip mipslit mipsbig" +mips*el-*-linux-gnu*) targ_emul=elf32ltsmip + targ_extra_emuls="elf32btsmip elf64ltsmip elf64btsmip" ;; -mips*-*-linux-gnu*) targ_emul=elf32bsmip - targ_extra_emuls="elf32lsmip mipsbig mipslit" +mips*-*-linux-gnu*) targ_emul=elf32btsmip + targ_extra_emuls="elf32ltsmip elf64btsmip elf64ltsmip" ;; mips*-*-lnews*) targ_emul=mipslnews ;; mips*-*-sysv4*) targ_emul=elf32btsmip ;; @@ -325,7 +326,7 @@ powerpc-*-macos*) targ_emul=ppcmacos ;; powerpc-*-netware*) targ_emul=ppcnw ;; powerpcle-*-pe) targ_emul=ppcpe ;; powerpcle-*-winnt*) targ_emul=ppcpe ;; -powerpcle-*-cygwin*) targ_emul=ppcpe ;; +powerpcle-*-cygwin*) targ_emul=ppcpe ;; powerpc-*-aix*) targ_emul=aixppc ;; powerpc-*-beos*) targ_emul=aixppc ;; rs6000-*-aix*) targ_emul=aixrs6 ;; diff --git a/contrib/binutils/ld/ld.1 b/contrib/binutils/ld/ld.1 index 18275bf..06b7ef0 100644 --- a/contrib/binutils/ld/ld.1 +++ b/contrib/binutils/ld/ld.1 @@ -1,4 +1,5 @@ -.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 98, 1999, 2000 Free Software Foundation +.\" Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +.\" 2001 Free Software Foundation, Inc. .\" See section COPYING for conditions for redistribution .\" $FreeBSD$ .TH ld 1 "" "Free Software Foundation" "GNU Development Tools" @@ -29,6 +30,7 @@ ld \- the GNU linker .I input-format\c \&\|] .RB "[\|" \-Bstatic "\|]" +.RB "[\|" \-Bgroup "\|]" .RB "[\|" \-Bdynamic "\|]" .RB "[\|" \-Bsymbolic "\|]" .RB "[\|" "\-c\ "\c @@ -98,7 +100,7 @@ ld \- the GNU linker .RB "[\|" \-O\c .I level\c \&\|] -.RB "[\|" "\-oformat\ "\c +.RB "[\|" "\--oformat\ "\c .I output-format\c \&\|] .RB "[\|" "\-R\ "\c @@ -407,6 +409,19 @@ for which shared libraries are supported. This option is normally the default on such platforms. .TP +.B \-Bgroup +Set the \c +.B DF_1_GROUP +\c +flag in the \c +.B DT_FLAGS_1 +\c +entry in the dynamic section. This causes the runtime linker to handle +lookups in this object and its dependencies to be performed only inside +the group. No undefined symbols are allowed. This option is only +meaningful on ELF platforms which support shared libraries. + +.TP .B \-Bsymbolic When creating a shared library, bind references to global symbols to the definition within the shared library, if any. Normally, it is @@ -729,7 +744,7 @@ final binary. the optimizations. .TP -.BI "\-oformat " "output\-format" +.BI "\--oformat " "output\-format" Specify the binary format for the output object file. You don't usually need to specify this, as \c |