Esempio n. 1
0
void
itbl_init (void)
{
  struct itbl_entry *e, **es;
  e_processor procn;
  e_type type;

  if (!itbl_have_entries)
    return;

  /* Since register names don't have a prefix, put them in the symbol table so
     they can't be used as symbols.  This simplifies argument parsing as
     we can let gas parse registers for us.  */
  /* Use symbol_create instead of symbol_new so we don't try to
     output registers into the object file's symbol table.  */

  for (type = e_regtype0; type < e_nregtypes; type++)
    for (procn = e_p0; procn < e_nprocs; procn++)
      {
	es = get_entries (procn, type);
	for (e = *es; e; e = e->next)
	  {
	    symbol_table_insert (symbol_create (e->name, reg_section,
						e->value, &zero_address_frag));
	  }
      }
  append_insns_as_macros ();
}
Esempio n. 2
0
static void handle_attribute_alias(const attribute_t *attribute,
                                   entity_t *entity)
{
	const attribute_argument_t *argument = attribute->a.arguments;
	string_t const *const string = get_argument_string(argument);
	if (string == NULL) {
		errorf(&attribute->pos, "attribute 'alias' requires a string argument");
		return;
	}
	symbol_t *const symbol = symbol_table_insert(string->begin);
	switch (entity->kind) {
	case ENTITY_VARIABLE:
		entity->variable.alias.symbol = symbol;
		break;
	case ENTITY_FUNCTION:
		entity->function.alias.symbol = symbol;
		break;
	default:
		warningf(WARN_OTHER, &attribute->pos, "alias attribute on %N ignored",
		         entity);
		return;
	}
	declaration_t *decl = &entity->declaration;
	if (decl->storage_class == STORAGE_CLASS_EXTERN) {
		/* code generator will ignore the extern declaration */
		warningf(WARN_OTHER, &entity->base.pos,
		         "extern storage class ignored for alias %N", entity);
	}

	ARR_APP1(entity_t*, alias_entities, entity);
}
Esempio n. 3
0
static entity_t *create_gnu_builtin_libc(const char *name, type_t *type)
{
	obstack_printf(&symbol_obstack, "__builtin_%s", name);
	symbol_t *symbol = finalize_symbol_string();
	entity_t *entity = create_builtin_function(BUILTIN_LIBC, symbol, type);
	entity->function.actual_name = symbol_table_insert(name);
	return entity;
}
Esempio n. 4
0
static symbol_t *intern_register_token(token_kind_t id, const char *string)
{
	assert(id < T_LAST_TOKEN);
	symbol_t *symbol = symbol_table_insert(string);
	if (token_symbols[id] == NULL)
		token_symbols[id] = symbol;
	return symbol;
}
Esempio n. 5
0
static entity_t *create_builtin_firm(ir_builtin_kind kind, const char *name,
                                     type_t *type)
{
	symbol_t *symbol = symbol_table_insert(name);
	entity_t *entity = record_builtin_function(BUILTIN_FIRM, symbol, type);
	entity->function.b.firm_builtin_kind = kind;
	return entity;
}
Esempio n. 6
0
void
cgen_asm_record_register (char *name, int number)
{
  /* 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 (name, reg_section,
				      number, &zero_address_frag));
}
Esempio n. 7
0
static symbol_t *finalize_symbol_string(void)
{
	obstack_1grow(&symbol_obstack, '\0');
	char *string = obstack_finish(&symbol_obstack);
	symbol_t *symbol = symbol_table_insert(string);
	if (symbol->string != string)
		obstack_free(&symbol_obstack, string);
	return symbol;
}
Esempio n. 8
0
int register_new_token(const char *token)
{
	int token_id = ARR_LEN(token_symbols);
	
	symbol_t *symbol = symbol_table_insert(token);
	symbol->ID       = token_id;
	ARR_APP1(symbol_t*, token_symbols, symbol);

	return token_id;
}
Esempio n. 9
0
static entity_t *create_gnu_builtin_chk(const char *name, unsigned chk_arg_pos,
                                        type_t *type)
{
	obstack_printf(&symbol_obstack, "__builtin___%s_chk", name);
	symbol_t *symbol = finalize_symbol_string();
	entity_t *entity = create_builtin_function(BUILTIN_LIBC_CHECK, symbol, type);
	entity->function.actual_name   = symbol_table_insert(name);
	entity->function.b.chk_arg_pos = chk_arg_pos;
	return entity;
}
Esempio n. 10
0
static void handle_attribute_asm(const attribute_t *attribute,
                                 entity_t *entity)
{
	attribute_argument_t *argument = attribute->a.arguments;
	assert(argument->kind == ATTRIBUTE_ARGUMENT_EXPRESSION);
	expression_t *expression = argument->v.expression;
	if (expression->kind != EXPR_STRING_LITERAL)
		errorf(&attribute->pos, "Invalid asm attribute expression");
	symbol_t *sym = symbol_table_insert(expression->string_literal.value->begin);
	entity->function.actual_name = sym;
	assert(argument->next == NULL);
}
Esempio n. 11
0
/*
 *			symbol_find_or_make()
 *
 * If a symbol name does not exist, create it as undefined, and insert
 * it into the symbol table. Return a pointer to it.
 */
symbolS *
symbol_find_or_make(
char *name)
{
  register symbolS *	symbolP;

  symbolP = symbol_table_lookup (name);
  if (symbolP == NULL)
    {
      symbolP = symbol_new (name, N_UNDF, 0, 0, 0, & zero_address_frag);
      symbol_table_insert (symbolP);
    }
  return (symbolP);
}
Esempio n. 12
0
static symbolS *
tag_find_or_make (char *name)
{
  symbolS *symbolP;

  if ((symbolP = tag_find (name)) == NULL)
    {
      symbolP = symbol_new (name, undefined_section,
			    0, &zero_address_frag);

      tag_insert (S_GET_NAME (symbolP), symbolP);
      symbol_table_insert (symbolP);
    }

  return symbolP;
}
Esempio n. 13
0
void
colon(		/* just seen "x:" - rattle symbols & frags */
char *sym_name) /* symbol name, as a cannonical string */
		/* We copy this string: OK to alter later. */
{
  register struct symbol * symbolP; /* symbol we are working with */

  if (frchain_now == NULL)
    {
      know(flagseen['n']);
      as_fatal("with -n a section directive must be seen before assembly "
	       "can begin");
    }
  if ((symbolP = symbol_table_lookup( sym_name )))
    {
      /*
       *	Now check for undefined symbols
       */
      if ((symbolP -> sy_type & N_TYPE) == N_UNDF)
	{
	  temp = symbolP->sy_desc;
	  if(   symbolP -> sy_other == 0
	     /* bug #50416 -O causes this not to work for:
	     && ((symbolP->sy_desc) & (~REFERENCE_TYPE)) == 0
	     */
	     && (temp & (~(REFERENCE_TYPE | N_WEAK_REF | N_WEAK_DEF |
			   N_ARM_THUMB_DEF |
			   N_NO_DEAD_STRIP | REFERENCED_DYNAMICALLY))) == 0
	     && symbolP -> sy_value == 0)
	    {
	      symbolP -> sy_frag  = frag_now;
	      symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
	      know( N_UNDF == 0 );
	      symbolP -> sy_type |= N_SECT; /* keep N_EXT bit */
	      symbolP -> sy_other = frchain_now->frch_nsect;
	      symbolP -> sy_desc &= ~REFERENCE_TYPE;
	      symbolP -> sy_desc &= ~N_WEAK_REF;
	      symbol_assign_index(symbolP);
	      if((symbolP->sy_desc & N_WEAK_DEF) == N_WEAK_DEF &&
		 (frchain_now->frch_section.flags & S_COALESCED) != S_COALESCED)
		  as_fatal("symbol: %s can't be a weak_definition (currently "
			   "only supported in section of type coalesced)",
			   sym_name);
#ifdef NeXT_MOD	/* generate stabs for debugging assembly code */
	      if(flagseen['g'])
		  make_stab_for_symbol(symbolP);
#endif
	    }
	  else
	    {
	      as_fatal( "Symbol \"%s\" is already defined as \"%s\"/%d.%d."
			TA_DFMT ".",
		      sym_name,
		      seg_name [(int) N_TYPE_seg [symbolP -> sy_type & N_TYPE]],
		      symbolP -> sy_other, symbolP -> sy_desc,
			TA_DFT_CAST(symbolP -> sy_value));
	    }
	}
      else
	{
	  as_fatal("Symbol %s already defined.",sym_name);
	}
    }
  else
    {
      symbolP = symbol_new (sym_name,
			    N_SECT,
	      		    frchain_now->frch_nsect,
			    0,
			    (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
			    frag_now);
      symbol_table_insert (symbolP);
      symbol_assign_index (symbolP);
#ifdef NeXT_MOD	/* generate stabs for debugging assembly code */
      if(flagseen['g'])
	  make_stab_for_symbol(symbolP);
#endif
    }
#ifdef tc_frob_label
    tc_frob_label(symbolP);
#endif
}
Esempio n. 14
0
void write_jna_decls(FILE *output, const translation_unit_t *unit)
{
	out          = output;
	global_scope = &unit->scope;

	pset_new_init(&avoid_symbols);

	print_to_file(out);
	fprintf(out, "/* WARNING: Automatically generated file */\n");
	fputs("import com.sun.jna.Native;\n", out);
	fputs("import com.sun.jna.Pointer;\n", out);
	fputs("\n", out);

	const char *register_libname = libname;
	if (register_libname == NULL)
		register_libname = "library";

	/* TODO: where to get the name from? */
	fputs("public class binding {\n", out);
	fputs("\tstatic {\n", out);
	fprintf(out, "\t\tNative.register(\"%s\");\n", register_libname);
	fputs("\t}\n", out);
	fputs("\n", out);

	/* read the avoid list */
	FILE *avoid = fopen("avoid.config", "r");
	if (avoid != NULL) {
		for (;;) {
			char buf[1024];
			char *res = fgets(buf, sizeof(buf), avoid);
			if (res == NULL)
				break;
			if (buf[0] == 0)
				continue;

			size_t len = strlen(buf);
			if (buf[len-1] == '\n')
				buf[len-1] = 0;

			char *str = malloc(len+1);
			memcpy(str, buf, len+1);
			symbol_t *symbol = symbol_table_insert(str);
			pset_new_insert(&avoid_symbols, symbol);
		}
		fclose(avoid);
	}

	/* write structs,unions + enums */
	entity_t *entity = unit->scope.entities;
	for ( ; entity != NULL; entity = entity->base.next) {
		if (entity->kind == ENTITY_ENUM) {
			if (find_enum_typedef(&entity->enume) != NULL)
				continue;
			write_enum(entity->base.symbol, &entity->enume);
		} else if (entity->kind == ENTITY_TYPEDEF) {
			type_t *type = entity->declaration.type;
			if (type->kind == TYPE_ENUM) {
				write_enum(entity->base.symbol, type->enumt.enume);
			}
		}

#if 0
		if (is_type_compound(type)) {
			write_compound(entity->base.symbol, &type->compound);
		}
#endif
	}

	/* write functions */
	entity = unit->scope.entities;
	for ( ; entity != NULL; entity = entity->base.next) {
		if (entity->kind != ENTITY_FUNCTION)
			continue;
		if (entity->base.pos.is_system_header)
			continue;
		if (entity->function.elf_visibility != ELF_VISIBILITY_DEFAULT)
			continue;
		if (output_limits != NULL) {
			bool              in_limits  = false;
			char const *const input_name = entity->base.pos.input_name;
			for (output_limit *limit = output_limits; limit != NULL;
			     limit = limit->next) {
			    if (streq(limit->filename, input_name)) {
					in_limits = true;
					break;
				}
			}
			if (!in_limits)
				continue;
		}

		if (pset_new_contains(&avoid_symbols, entity->base.symbol))
			continue;
		write_function(entity);
	}

	fputs("}\n", out);

	pset_new_destroy(&avoid_symbols);
}
Esempio n. 15
0
/*
 * Summary of operand().
 *
 * in:	Input_line_pointer points to 1st char of operand, which may
 *	be a space.
 *
 * out:	A expressionS. X_seg determines how to understand the rest of the
 *	expressionS.
 *	The operand may have been empty: in this case X_seg == SEG_NONE.
 *	Input_line_pointer -> (next non-blank) char after operand.
 *
 */
static
segT
operand(
expressionS *expressionP)
{
    char c, q;
    char *name;	/* points to name of symbol */
    struct symbol *symbolP; /* Points to symbol */


	SKIP_WHITESPACE();	/* Leading whitespace is part of operand. */
	c = *input_line_pointer++;/* Input_line_pointer -> past char in c. */

	if(isdigit(c)){
	    signed_expr_t
			number; /* offset or (absolute) value */
	    int digit;		/* value of next digit in current radix */
				/* invented for humans only, hope */
				/* optimising compiler flushes it! */
	    int radix;		/* 8, 10 or 16 */
				/* 0 means we saw start of a floating- */
				/* point constant. */
	    int maxdig;		/* Highest permitted digit value. */
	    int	too_many_digits;/* If we see >= this number of */
				/* digits, assume it is a bignum. */
	    char *digit_2;	/* -> 2nd digit of number. */
	    int	small;		/* TRUE if fits in 32 bits. */
	    int	force_bignum;	/* TRUE if number is 0xb...  */

	    force_bignum = FALSE;
	    /*
	     * These two initiaizations are to shut up compiler warning as the
	     * may be used with out being set.  There used only if radix != 0
	     * when the number is not a floating-point number.
	     */
	    maxdig = 0;
	    too_many_digits = 0;

	    if(c == '0'){ /* non-decimal radix */
		c = *input_line_pointer++;
		if(c == 'x' || c=='X'){
		    c = *input_line_pointer++; /* read past "0x" or "0X" */
		    maxdig = 16;
		    radix = 16;
		    too_many_digits = 9;
		}
		/*
		 * If we have "0b" and some hex digits then treat it as a hex
		 * number and return a bignum.   This is for hex immediate
		 * bit-patterns for floating-point immediate constants.
		 */
		else if((c == 'b' || c == 'B') &&
			(*input_line_pointer != '\0') &&
			strchr("0123456789abcdefABCDEF",
			       *input_line_pointer) != NULL){
		    force_bignum = TRUE;
		    c = *input_line_pointer++; /* read past "0b" or "0B" */
		    maxdig = 16;
		    radix = 16;
		    too_many_digits = 9;
		}
		else{
		    /*
		     * If it says '0f' and the line ends or it DOESN'T look like
		     * a floating point #, its a local label ref.
		     */
		    if(c == 'f' &&
		       (*input_line_pointer == '\0' ||
			(strchr("+-.0123456789", *input_line_pointer) == NULL &&
			 strchr(md_EXP_CHARS, *input_line_pointer) == NULL) )){
			maxdig = 10;
			radix = 10;
			too_many_digits = 11;
			c = '0';
			input_line_pointer -= 2;
		    }
		    else if(c != '\0' && strchr(md_FLT_CHARS, c) != NULL){
			radix = 0;/* Start of floating-point constant. */
				  /* input_line_pointer -> 1st char of number */
			expressionP->X_add_number =
				- (isupper(c) ? tolower(c) : c);
		    }
		    else{	/* By elimination, assume octal radix. */
			radix = 8;
			maxdig = 10;	/* Un*x sux. Compatibility. */
			too_many_digits = 11;
		    }
		}
		/* c == char after "0" or "0x" or "0X" or "0e" etc.*/
	    }
	    else{
		maxdig = 10;
		radix = 10;
		too_many_digits = 11;
	    }

	    /*
	     * Expressions are now evaluated as 64-bit values so the number
	     * digits allowed is twice that for 32-bit expressions.
	     */
	    too_many_digits *= 2;

	    if(radix != 0){ /* Fixed-point integer constant. */
			    /* May be bignum, or may fit in 32 bits. */
		/*
		 * Most numbers fit into 32 bits, and we want this case to be
		 * fast.  So we pretend it will fit into 32 bits. If, after
		 * making up a 32 bit number, we realize that we have scanned
		 * more digits than comfortably fit into 32 bits, we re-scan the
		 * digits coding them into a bignum.  For decimal and octal
		 * numbers we are conservative: some numbers may be assumed
		 * bignums when in fact they do fit into 32 bits.  Numbers of
		 * any radix can have excess leading zeros: we strive to
		 * recognise this and cast them back into 32 bits.  We must
		 * check that the bignum really is more than 32 bits, and
		 * change it back to a 32-bit number if it fits.  The number we
		 * are looking for is expected to be positive, but if it fits
		 * into 32 bits as an unsigned number, we let it be a 32-bit
		 * number. The cavalier approach is for speed in ordinary cases.
		 */
		digit_2 = input_line_pointer;
		for(number = 0;
		    (digit = hex_value[(int)c]) < maxdig;
		    c = *input_line_pointer++){
		    number = number * radix + digit;
		}
		/* c contains character after number. */
		/* Input_line_pointer -> char after c. */
		small = input_line_pointer - digit_2 < too_many_digits;
		if(force_bignum == TRUE)
		      small = FALSE;
		if(small == FALSE){
		    /*
		     * Manufacture a bignum.
		     */
		    /* -> high order littlenum of the bignum. */
		    LITTLENUM_TYPE *leader;
		    /* -> littlenum we are frobbing now. */
		    LITTLENUM_TYPE *pointer;
		    long carry;

		    leader = generic_bignum;
		    generic_bignum [0] = 0;
		    /* We could just use digit_2, but lets be mnemonic. */
		    input_line_pointer = --digit_2; /* -> 1st digit. */
		    c = *input_line_pointer++;
		    for( ;
			(carry = hex_value[(int)c]) < maxdig;
			c = * input_line_pointer++){
			for(pointer = generic_bignum;
			    pointer <= leader;
			    pointer++){
			    long work;

			    work = carry + radix * *pointer;
			    *pointer = work & LITTLENUM_MASK;
			    carry = work >> LITTLENUM_NUMBER_OF_BITS;
			}
			if(carry){
			    if(leader < generic_bignum +
					SIZE_OF_LARGE_NUMBER - 1){
					/* Room to grow a longer bignum. */
				*++leader = carry;
			    }
			}
		    }
		    /* Again, C is char after number, */
		    /* input_line_pointer -> after C. */
		    /* know(BITS_PER_INT == 32); */
		    know(LITTLENUM_NUMBER_OF_BITS == 16);
		    /* Hence the constant "2" in the next line. */
		    if(leader < generic_bignum + 2 && force_bignum == FALSE)
		    {		/* Will fit into 32 bits. */
			number = ((generic_bignum[1] & LITTLENUM_MASK) <<
				   LITTLENUM_NUMBER_OF_BITS) |
			  	  (generic_bignum[0] & LITTLENUM_MASK);
			small = TRUE;
		    }
		    else{
			/* Number of littlenums in the bignum. */
			number = leader - generic_bignum + 1;
		    }
		}
		if(small){
		    /*
		     * Here with number, in correct radix. c is the next char.
		     * Note that unlike Un*x, we allow "011f" "0x9f" to both
		     * mean the same as the (conventional) "9f". This is simply
		     * easier than checking for strict canonical form.
		     */
		    if(number < 10){
			if(c == 'b'){
			    /*
			     * Backward ref to local label.
			     * Because it is backward, expect it to be DEFINED.
			     */
			    /*
			     * Construct a local label.
			     */
			    name = local_label_name((int)number, 0);
			    symbolP = symbol_table_lookup(name);
			    if((symbolP != NULL) &&
			       (symbolP->sy_type & N_TYPE) != N_UNDF){
				/* Expected path: symbol defined. */
				/* Local labels are never absolute. Don't waste
				   time checking absoluteness. */
				know((symbolP->sy_type & N_TYPE) == N_SECT);
				expressionP->X_add_symbol = symbolP;
				expressionP->X_add_number = 0;
				expressionP->X_seg        = SEG_SECT;
			    }
			    else{ /* Either not seen or not defined. */
				as_warn("Backw. ref to unknown label \"%lld\","
				"0 assumed.", number);
				expressionP->X_add_number = 0;
				expressionP->X_seg        = SEG_ABSOLUTE;
			    }
			}
			else if(c == 'f'){
			    /*
			     * Forward reference. Expect symbol to be
			     * undefined or unknown. Undefined: seen it
			     * before. Unknown: never seen it in this pass.
			     * Construct a local label name, then an
			     * undefined symbol.  Don't create a XSEG frag
			     * for it: caller may do that.
			     * Just return it as never seen before.
			     */
			    name = local_label_name((int)number, 1);
			    symbolP = symbol_table_lookup(name);
			    if(symbolP != NULL){
				/* We have no need to check symbol
				   properties. */
				know((symbolP->sy_type & N_TYPE) == N_UNDF ||
				     (symbolP->sy_type & N_TYPE) == N_SECT);
			    }
			    else{
				symbolP = symbol_new(name, N_UNDF, 0,0,0,
						     &zero_address_frag);
				symbol_table_insert(symbolP);
			    }
			    expressionP->X_add_symbol      = symbolP;
			    expressionP->X_seg             = SEG_UNKNOWN;
			    expressionP->X_subtract_symbol = NULL;
			    expressionP->X_add_number      = 0;
			}
			else{	/* Really a number, not a local label. */
			    ignore_c_ll_or_ull(c);
			    expressionP->X_add_number = number;
			    expressionP->X_seg        = SEG_ABSOLUTE;
			    input_line_pointer--; /* restore following char */
		        }
		    }
		    else{ /* a number >= 10 */
			ignore_c_ll_or_ull(c);
			expressionP->X_add_number = number;
			expressionP->X_seg        = SEG_ABSOLUTE;
			input_line_pointer--; /* restore following char */
		    }
		} /* not a small number encode returning a bignum */
		else{
		    ignore_c_ll_or_ull(c);
		    expressionP->X_add_number = number;
		    expressionP->X_seg = SEG_BIG;
		    input_line_pointer--; /* -> char following number. */
		} /* if (small) */
	    } /* (If integer constant) */
Esempio n. 16
0
void init_symbol_table(void)
{
	obstack_init(&symbol_obstack);
	symbol_table_init_(&symbol_table);
	sym_anonymous = symbol_table_insert("<anonymous>");
}
Esempio n. 17
0
static void register_pp_token(pp_token_kind_t const id, char const *const string)
{
	assert(id < TP_LAST_TOKEN);
	symbol_t *const symbol = symbol_table_insert(string);
	symbol->pp_ID = id;
}
Esempio n. 18
0
static void
obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
{
  symbolS *symbolP = NULL;

  dim_index = 0;
  if (def_symbol_in_progress == NULL)
    {
      as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
      demand_empty_rest_of_line ();
      return;
    }

  /* Set the section number according to storage class.  */
  switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
    {
    case C_STRTAG:
    case C_ENTAG:
    case C_UNTAG:
      SF_SET_TAG (def_symbol_in_progress);
      /* Fall through.  */
    case C_FILE:
    case C_TPDEF:
      SF_SET_DEBUG (def_symbol_in_progress);
      S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
      break;

    case C_EFCN:
      SF_SET_LOCAL (def_symbol_in_progress);	/* Do not emit this symbol.  */
      /* Fall through.  */
    case C_BLOCK:
      SF_SET_PROCESS (def_symbol_in_progress);	/* Will need processing before writing.  */
      /* Fall through.  */
    case C_FCN:
      {
	const char *name;

	S_SET_SEGMENT (def_symbol_in_progress, text_section);

	name = S_GET_NAME (def_symbol_in_progress);
	if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
	  {
	    switch (name[1])
	      {
	      case 'b':
		/* .bf */
		if (! in_function ())
		  as_warn (_("`%s' symbol without preceding function"), name);
		/* Will need relocating.  */
		SF_SET_PROCESS (def_symbol_in_progress);
		clear_function ();
		break;
#ifdef TE_PE
	      case 'e':
		/* .ef */
		/* The MS compilers output the actual endline, not the
		   function-relative one... we want to match without
		   changing the assembler input.  */
		SA_SET_SYM_LNNO (def_symbol_in_progress,
				 (SA_GET_SYM_LNNO (def_symbol_in_progress)
				  + coff_line_base));
		break;
#endif
	      }
	  }
      }
      break;

#ifdef C_AUTOARG
    case C_AUTOARG:
#endif /* C_AUTOARG */
    case C_AUTO:
    case C_REG:
    case C_ARG:
    case C_REGPARM:
    case C_FIELD:

    /* According to the COFF documentation:

       http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html

       A special section number (-2) marks symbolic debugging symbols,
       including structure/union/enumeration tag names, typedefs, and
       the name of the file. A section number of -1 indicates that the
       symbol has a value but is not relocatable. Examples of
       absolute-valued symbols include automatic and register variables,
       function arguments, and .eos symbols.

       But from Ian Lance Taylor:

       http://sources.redhat.com/ml/binutils/2000-08/msg00202.html

       the actual tools all marked them as section -1. So the GNU COFF
       assembler follows historical COFF assemblers.

       However, it causes problems for djgpp

       http://sources.redhat.com/ml/binutils/2000-08/msg00210.html

       By defining STRICTCOFF, a COFF port can make the assembler to
       follow the documented behavior.  */
#ifdef STRICTCOFF
    case C_MOS:
    case C_MOE:
    case C_MOU:
    case C_EOS:
#endif
      SF_SET_DEBUG (def_symbol_in_progress);
      S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
      break;

#ifndef STRICTCOFF
    case C_MOS:
    case C_MOE:
    case C_MOU:
    case C_EOS:
      S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
      break;
#endif

    case C_EXT:
    case C_WEAKEXT:
#ifdef TE_PE
    case C_NT_WEAK:
#endif
    case C_STAT:
    case C_LABEL:
      /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
      break;

    default:
    case C_USTATIC:
    case C_EXTDEF:
    case C_ULABEL:
      as_warn (_("unexpected storage class %d"),
	       S_GET_STORAGE_CLASS (def_symbol_in_progress));
      break;
    }

  /* Now that we have built a debug symbol, try to find if we should
     merge with an existing symbol or not.  If a symbol is C_EFCN or
     absolute_section or untagged SEG_DEBUG it never merges.  We also
     don't merge labels, which are in a different namespace, nor
     symbols which have not yet been defined since they are typically
     unique, nor do we merge tags with non-tags.  */

  /* Two cases for functions.  Either debug followed by definition or
     definition followed by debug.  For definition first, we will
     merge the debug symbol into the definition.  For debug first, the
     lineno entry MUST point to the definition function or else it
     will point off into space when obj_crawl_symbol_chain() merges
     the debug symbol into the real symbol.  Therefor, let's presume
     the debug symbol is a real function reference.  */

  /* FIXME-SOON If for some reason the definition label/symbol is
     never seen, this will probably leave an undefined symbol at link
     time.  */

  if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
      || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
      || (streq (bfd_get_section_name (stdoutput,
				       S_GET_SEGMENT (def_symbol_in_progress)),
		 "*DEBUG*")
	  && !SF_GET_TAG (def_symbol_in_progress))
      || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
      || ! symbol_constant_p (def_symbol_in_progress)
      || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL
      || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
    {
      /* If it already is at the end of the symbol list, do nothing */
      if (def_symbol_in_progress != symbol_lastP)
	{
	  symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
	  symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
			 &symbol_lastP);
	}
    }
  else
    {
      /* This symbol already exists, merge the newly created symbol
	 into the old one.  This is not mandatory. The linker can
	 handle duplicate symbols correctly. But I guess that it save
	 a *lot* of space if the assembly file defines a lot of
	 symbols. [loic]  */

      /* The debug entry (def_symbol_in_progress) is merged into the
	 previous definition.  */

      c_symbol_merge (def_symbol_in_progress, symbolP);
      symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);

      def_symbol_in_progress = symbolP;

      if (SF_GET_FUNCTION (def_symbol_in_progress)
	  || SF_GET_TAG (def_symbol_in_progress)
	  || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
	{
	  /* For functions, and tags, and static symbols, the symbol
	     *must* be where the debug symbol appears.  Move the
	     existing symbol to the current place.  */
	  /* If it already is at the end of the symbol list, do nothing.  */
	  if (def_symbol_in_progress != symbol_lastP)
	    {
	      symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
	      symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
	    }
	}
    }

  if (SF_GET_TAG (def_symbol_in_progress))
    {
      symbolS *oldtag;

      oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress));
      if (oldtag == NULL || ! SF_GET_TAG (oldtag))
	tag_insert (S_GET_NAME (def_symbol_in_progress),
		    def_symbol_in_progress);
    }

  if (SF_GET_FUNCTION (def_symbol_in_progress))
    {
      know (sizeof (def_symbol_in_progress) <= sizeof (long));
      set_function (def_symbol_in_progress);
      SF_SET_PROCESS (def_symbol_in_progress);

      if (symbolP == NULL)
	/* That is, if this is the first time we've seen the
	   function.  */
	symbol_table_insert (def_symbol_in_progress);

    }

  def_symbol_in_progress = NULL;
  demand_empty_rest_of_line ();
}
Esempio n. 19
0
/*
 * layout_indirect_symbols() setups the indirect symbol tables by looking up or
 * creating symbol from the indirect symbol names and recording the symbol
 * pointers.  It returns the total count of indirect symbol table entries.
 */
static
uint32_t
layout_indirect_symbols(void)
{
    struct frchain *frchainP;
    uint32_t section_type, total, count, stride;
    isymbolS *isymbolP;
    symbolS *symbolP;

	/*
	 * Mark symbols that only appear in a lazy section with 
	 * REFERENCE_FLAG_UNDEFINED_LAZY.  To do this we first make sure a
	 * symbol exists for all non-lazy symbols.  Then we make a pass looking
	 * up the lazy symbols and if not there we make the symbol and mark it
	 * with REFERENCE_FLAG_UNDEFINED_LAZY.
	 */
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    section_type = frchainP->frch_section.flags & SECTION_TYPE;
	    if(section_type == S_NON_LAZY_SYMBOL_POINTERS){
		for(isymbolP = frchainP->frch_isym_root;
		    isymbolP != NULL;
		    isymbolP = isymbolP->isy_next){
/*
(void)symbol_find_or_make(isymbolP->isy_name);
*/
		    symbolP = symbol_find(isymbolP->isy_name);
		    if(symbolP == NULL){
			symbolP = symbol_new(isymbolP->isy_name, N_UNDF, 0, 0,
					     0, &zero_address_frag);
			symbol_table_insert(symbolP);
		    }
		}
	    }
	}
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    section_type = frchainP->frch_section.flags & SECTION_TYPE;
	    if(section_type == S_LAZY_SYMBOL_POINTERS ||
	       section_type == S_SYMBOL_STUBS){
		for(isymbolP = frchainP->frch_isym_root;
		    isymbolP != NULL;
		    isymbolP = isymbolP->isy_next){

		    symbolP = symbol_find(isymbolP->isy_name);
		    if(symbolP == NULL){
			symbolP = symbol_find_or_make(isymbolP->isy_name);
			symbolP->sy_desc |= REFERENCE_FLAG_UNDEFINED_LAZY;
		    }
		}
	    }
	}

	total = 0;
	for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
	    section_type = frchainP->frch_section.flags & SECTION_TYPE;
	    if(section_type == S_LAZY_SYMBOL_POINTERS ||
	       section_type == S_NON_LAZY_SYMBOL_POINTERS ||
	       section_type == S_SYMBOL_STUBS){
		count = 0;
		for(isymbolP = frchainP->frch_isym_root;
		    isymbolP != NULL;
		    isymbolP = isymbolP->isy_next){

/*
symbolP = symbol_find_or_make(isymbolP->isy_name);
*/
		    symbolP = symbol_find(isymbolP->isy_name);
		    if(symbolP == NULL){
			symbolP = symbol_new(isymbolP->isy_name, N_UNDF, 0, 0,
					     0, &zero_address_frag);
			symbol_table_insert(symbolP);
		    }
		    isymbolP->isy_symbol = symbolP;
		    count++;
		}
		/*
		 * Check for missing indirect symbols.
		 */
		if(section_type == S_SYMBOL_STUBS)
		    stride = frchainP->frch_section.reserved2;
		else
		    stride = sizeof(signed_target_addr_t);
		if(frchainP->frch_section.size / stride != count)
		    as_bad("missing indirect symbols for section (%s,%s)",
			    frchainP->frch_section.segname,
			    frchainP->frch_section.sectname);
		/*
		 * Set the index into the indirect symbol table for this
		 * section into the reserved1 field.
		 */
		frchainP->frch_section.reserved1 = total;
		total += count;
	    }
	}
	return(total);
}