X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fread.c;h=8e1b06edf6bdad5e0f412bc1b22de8f57ef4ac1c;hb=6be47f0c48cbd58921a25e7493ca79a6f596dffe;hp=21c42b27342fb8e2c687417bcdacc4c16e3905b7;hpb=d2ae702c466d7d01de50427a048df0cfd5b90e24;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/read.c b/gas/read.c index 21c42b2734..8e1b06edf6 100644 --- a/gas/read.c +++ b/gas/read.c @@ -1,7 +1,5 @@ /* read.c - read a source file - - Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -244,9 +242,6 @@ static void do_align (int, char *, int, int); static void s_align (int, int); static void s_altmacro (int); static void s_bad_end (int); -#ifdef OBJ_ELF -static void s_gnu_attribute (int); -#endif static void s_reloc (int); static int hex_float (int, char *); static segT get_known_segmented_expression (expressionS * expP); @@ -268,8 +263,11 @@ read_begin (void) obstack_begin (¬es, chunksize); obstack_begin (&cond_obstack, chunksize); +#ifndef tc_line_separator_chars +#define tc_line_separator_chars line_separator_chars +#endif /* Use machine dependent syntax. */ - for (p = line_separator_chars; *p; p++) + for (p = tc_line_separator_chars; *p; p++) is_end_of_line[(unsigned char) *p] = 2; /* Use more. FIXME-SOMEDAY. */ @@ -378,9 +376,6 @@ static const pseudo_typeS potable[] = { {"func", s_func, 0}, {"global", s_globl, 0}, {"globl", s_globl, 0}, -#ifdef OBJ_ELF - {"gnu_attribute", s_gnu_attribute, 0}, -#endif {"hword", cons, 2}, {"if", s_if, (int) O_ne}, {"ifb", s_ifb, 1}, @@ -1312,10 +1307,10 @@ read_a_source_file (char *name) } /* Convert O_constant expression EXP into the equivalent O_big representation. - Take the sign of the number from X_unsigned rather than X_add_number. */ + Take the sign of the number from SIGN rather than X_add_number. */ static void -convert_to_bignum (expressionS *exp) +convert_to_bignum (expressionS *exp, int sign) { valueT value; unsigned int i; @@ -1328,8 +1323,8 @@ convert_to_bignum (expressionS *exp) } /* Add a sequence of sign bits if the top bit of X_add_number is not the sign of the original value. */ - if ((exp->X_add_number < 0) != !exp->X_unsigned) - generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK; + if ((exp->X_add_number < 0) == !sign) + generic_bignum[i++] = sign ? LITTLENUM_MASK : 0; exp->X_op = O_big; exp->X_add_number = i; } @@ -1636,7 +1631,7 @@ read_symbol_name (void) name_end = start + len; name = start + sofar; } - + *name++ = (char) C; } *name = 0; @@ -1678,7 +1673,7 @@ read_symbol_name (void) ignore_rest_of_line (); return NULL; } - + SKIP_WHITESPACE (); return start; @@ -2292,139 +2287,6 @@ s_globl (int ignore ATTRIBUTE_UNUSED) mri_comment_end (stop, stopc); } -#ifdef OBJ_ELF -#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0) - -static inline int -skip_past_char (char ** str, char c) -{ - if (**str == c) - { - (*str)++; - return 0; - } - else - return -1; -} -#define skip_past_comma(str) skip_past_char (str, ',') - -/* Parse an attribute directive for VENDOR. - Returns the attribute number read, or zero on error. */ -int -s_vendor_attribute (int vendor) -{ - expressionS exp; - int type; - int tag; - unsigned int i = 0; - char *s = NULL; - - /* Read the first number or name. */ - skip_whitespace (input_line_pointer); - s = input_line_pointer; - if (ISDIGIT (*input_line_pointer)) - { - expression (& exp); - if (exp.X_op != O_constant) - goto bad; - tag = exp.X_add_number; - } - else - { - char *name; - - /* A name may contain '_', but no other punctuation. */ - for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_'; - ++input_line_pointer) - i++; - if (i == 0) - goto bad; - - name = (char *) alloca (i + 1); - memcpy (name, s, i); - name[i] = '\0'; - -#ifndef CONVERT_SYMBOLIC_ATTRIBUTE -#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1 -#endif - - tag = CONVERT_SYMBOLIC_ATTRIBUTE (name); - if (tag == -1) - { - as_bad (_("Attribute name not recognised: %s"), name); - ignore_rest_of_line (); - return 0; - } - } - - type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag); - - if (skip_past_comma (&input_line_pointer) == -1) - goto bad; - if (type & 1) - { - expression (& exp); - if (exp.X_op != O_constant) - { - as_bad (_("expected numeric constant")); - ignore_rest_of_line (); - return 0; - } - i = exp.X_add_number; - } - if ((type & 3) == 3 - && skip_past_comma (&input_line_pointer) == -1) - { - as_bad (_("expected comma")); - ignore_rest_of_line (); - return 0; - } - if (type & 2) - { - int len; - - skip_whitespace (input_line_pointer); - if (*input_line_pointer != '"') - goto bad_string; - s = demand_copy_C_string (&len); - } - - switch (type & 3) - { - case 3: - bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s); - break; - case 2: - bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s); - break; - case 1: - bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i); - break; - default: - abort (); - } - - demand_empty_rest_of_line (); - return tag; -bad_string: - as_bad (_("bad string constant")); - ignore_rest_of_line (); - return 0; -bad: - as_bad (_("expected , ")); - ignore_rest_of_line (); - return 0; -} - -/* Parse a .gnu_attribute directive. */ - -static void -s_gnu_attribute (int ignored ATTRIBUTE_UNUSED) -{ - s_vendor_attribute (OBJ_ATTR_GNU); -} -#endif /* OBJ_ELF */ - /* Handle the MRI IRP and IRPC pseudo-ops. */ void @@ -3989,19 +3851,22 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes); #ifndef TC_PARSE_CONS_EXPRESSION #ifdef BITFIELD_CONS_EXPRESSIONS -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (parse_bitfield_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE) static void parse_bitfield_cons (expressionS *exp, unsigned int nbytes); #endif #ifdef REPEAT_CONS_EXPRESSIONS -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (parse_repeat_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE) static void parse_repeat_cons (expressionS *exp, unsigned int nbytes); #endif /* If we haven't gotten one yet, just call expression. */ #ifndef TC_PARSE_CONS_EXPRESSION -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (expression (EXP), TC_PARSE_CONS_RETURN_NONE) #endif #endif @@ -4009,7 +3874,7 @@ void do_parse_cons_expression (expressionS *exp, int nbytes ATTRIBUTE_UNUSED) { - TC_PARSE_CONS_EXPRESSION (exp, nbytes); + (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes); } @@ -4052,6 +3917,14 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ c = 0; do { + TC_PARSE_CONS_RETURN_TYPE ret = TC_PARSE_CONS_RETURN_NONE; +#ifdef TC_CONS_FIX_CHECK + fixS **cur_fix = &frchain_now->fix_tail; + + if (*cur_fix != NULL) + cur_fix = &(*cur_fix)->fx_next; +#endif + #ifdef TC_M68K if (flag_m68k_mri) parse_mri_cons (&exp, (unsigned int) nbytes); @@ -4064,7 +3937,7 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ ignore_rest_of_line (); return; } - TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); + ret = TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); } if (rva) @@ -4074,7 +3947,10 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ else as_fatal (_("rva without symbol")); } - emit_expr (&exp, (unsigned int) nbytes); + emit_expr_with_reloc (&exp, (unsigned int) nbytes, ret); +#ifdef TC_CONS_FIX_CHECK + TC_CONS_FIX_CHECK (&exp, nbytes, *cur_fix); +#endif ++c; } while (*input_line_pointer++ == ','); @@ -4217,6 +4093,14 @@ s_reloc (int ignore ATTRIBUTE_UNUSED) void emit_expr (expressionS *exp, unsigned int nbytes) +{ + emit_expr_with_reloc (exp, nbytes, TC_PARSE_CONS_RETURN_NONE); +} + +void +emit_expr_with_reloc (expressionS *exp, + unsigned int nbytes, + TC_PARSE_CONS_RETURN_TYPE reloc) { operatorT op; char *p; @@ -4226,10 +4110,9 @@ emit_expr (expressionS *exp, unsigned int nbytes) if (need_pass_2) return; - /* Grow the current frag now so that dot_value does not get invalidated - if the frag were to fill up in the frag_more() call below. */ frag_grow (nbytes); dot_value = frag_now_fix (); + dot_frag = frag_now; #ifndef NO_LISTING #ifdef OBJ_ELF @@ -4360,6 +4243,12 @@ emit_expr (expressionS *exp, unsigned int nbytes) p = frag_more ((int) nbytes); + if (reloc != TC_PARSE_CONS_RETURN_NONE) + { + emit_expr_fix (exp, nbytes, frag_now, p, reloc); + return; + } + #ifndef WORKING_DOT_WORD /* If we have the difference of two symbols in a word, save it on the broken_words list. See the code in write.c. */ @@ -4390,7 +4279,7 @@ emit_expr (expressionS *exp, unsigned int nbytes) if (op == O_constant && nbytes > sizeof (valueT)) { extra_digit = exp->X_unsigned ? 0 : -1; - convert_to_bignum (exp); + convert_to_bignum (exp, !exp->X_unsigned); op = O_big; } @@ -4518,23 +4407,41 @@ emit_expr (expressionS *exp, unsigned int nbytes) } } else - emit_expr_fix (exp, nbytes, frag_now, p); + emit_expr_fix (exp, nbytes, frag_now, p, TC_PARSE_CONS_RETURN_NONE); } void -emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p) +emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p, + TC_PARSE_CONS_RETURN_TYPE r ATTRIBUTE_UNUSED) { - memset (p, 0, nbytes); + int offset = 0; + unsigned int size = nbytes; + + memset (p, 0, size); /* Generate a fixS to record the symbol value. */ #ifdef TC_CONS_FIX_NEW - TC_CONS_FIX_NEW (frag, p - frag->fr_literal, nbytes, exp); + TC_CONS_FIX_NEW (frag, p - frag->fr_literal + offset, size, exp, r); #else - { - bfd_reloc_code_real_type r; + if (r != TC_PARSE_CONS_RETURN_NONE) + { + reloc_howto_type *reloc_howto; - switch (nbytes) + reloc_howto = bfd_reloc_type_lookup (stdoutput, r); + size = bfd_get_reloc_size (reloc_howto); + + if (size > nbytes) + { + as_bad (_("%s relocations do not fit in %u bytes\n"), + reloc_howto->name, nbytes); + return; + } + else if (target_big_endian) + offset = nbytes - size; + } + else + switch (size) { case 1: r = BFD_RELOC_8; @@ -4552,13 +4459,11 @@ emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p) r = BFD_RELOC_64; break; default: - as_bad (_("unsupported BFD relocation size %u"), nbytes); - r = BFD_RELOC_32; - break; + as_bad (_("unsupported BFD relocation size %u"), size); + return; } - fix_new_exp (frag, p - frag->fr_literal, (int) nbytes, exp, - 0, r); - } + fix_new_exp (frag, p - frag->fr_literal + offset, size, + exp, 0, r); #endif } @@ -4684,6 +4589,7 @@ parse_bitfield_cons (exp, nbytes) exp->X_add_number = value; exp->X_op = O_constant; exp->X_unsigned = 1; + exp->X_extrabit = 0; } } @@ -4693,9 +4599,7 @@ parse_bitfield_cons (exp, nbytes) #ifdef TC_M68K static void -parse_mri_cons (exp, nbytes) - expressionS *exp; - unsigned int nbytes; +parse_mri_cons (expressionS *exp, unsigned int nbytes) { if (*input_line_pointer != '\'' && (input_line_pointer[1] != '\'' @@ -5243,12 +5147,12 @@ emit_leb128_expr (expressionS *exp, int sign) } else if (op == O_constant && sign - && (exp->X_add_number < 0) != !exp->X_unsigned) + && (exp->X_add_number < 0) == !exp->X_extrabit) { /* We're outputting a signed leb128 and the sign of X_add_number doesn't reflect the sign of the original value. Convert EXP to a correctly-extended bignum instead. */ - convert_to_bignum (exp); + convert_to_bignum (exp, exp->X_extrabit); op = O_big; } @@ -5933,8 +5837,8 @@ add_include_dir (char *path) { include_dir_count++; include_dirs = - (char **) realloc (include_dirs, - include_dir_count * sizeof (*include_dirs)); + (char **) xrealloc (include_dirs, + include_dir_count * sizeof (*include_dirs)); } include_dirs[include_dir_count - 1] = path; /* New one. */