static symbolS * obj_coff_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size) { addressT align = 0; if (*input_line_pointer == ',') { align = parse_align (0); if (align == (addressT) -1) return NULL; } S_SET_VALUE (symbolP, size); S_SET_EXTERNAL (symbolP); S_SET_SEGMENT (symbolP, bfd_com_section_ptr); symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; /* There is no S_SET_ALIGN (symbolP, align) in COFF/PE. Instead we must add a note to the .drectve section. */ if (align) { segT current_seg = now_seg; subsegT current_subseg = now_subseg; flagword oldflags; asection *sec; size_t pfxlen, numlen; char *frag; char numbuff[20]; sec = subseg_new (".drectve", 0); oldflags = bfd_get_section_flags (stdoutput, sec); if (oldflags == SEC_NO_FLAGS) { if (!bfd_set_section_flags (stdoutput, sec, TC_COFF_SECTION_DEFAULT_ATTRIBUTES)) as_warn (_("error setting flags for \"%s\": %s"), bfd_section_name (stdoutput, sec), bfd_errmsg (bfd_get_error ())); } /* Emit a string. Note no NUL-termination. */ pfxlen = strlen (" -aligncomm:") + 2 + strlen (S_GET_NAME (symbolP)) + 1; numlen = snprintf (numbuff, sizeof (numbuff), "%d", (int) align); frag = frag_more (pfxlen + numlen); (void) sprintf (frag, " -aligncomm:\"%s\",", S_GET_NAME (symbolP)); memcpy (frag + pfxlen, numbuff, numlen); /* Restore original subseg. */ subseg_set (current_seg, current_subseg); } return symbolP; }
void pecoff_obj_set_weak_hook (symbolS *symbolP) { symbolS *alternateP; /* See _Microsoft Portable Executable and Common Object File Format Specification_, section 5.5.3. Create a symbol representing the alternate value. coff_frob_symbol will set the value of this symbol from the value of the weak symbol itself. */ S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK); S_SET_NUMBER_AUXILIARY (symbolP, 1); SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP))); S_SET_EXTERNAL (alternateP); S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK); SA_SET_SYM_TAGNDX (symbolP, alternateP); }
void coff_frob_symbol (symbolS *symp, int *punt) { static symbolS *last_tagP; static stack *block_stack; static symbolS *set_end; symbolS *next_set_end = NULL; if (symp == &abs_symbol) { *punt = 1; return; } if (current_lineno_sym) coff_add_linesym (NULL); if (!block_stack) block_stack = stack_init (512, sizeof (symbolS*)); #ifdef TE_PE if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK && ! S_IS_WEAK (symp) && weak_is_altname (S_GET_NAME (symp))) { /* This is a weak alternate symbol. All processing of PECOFFweak symbols is done here, through the alternate. */ symbolS *weakp = symbol_find_noref (weak_altname2name (S_GET_NAME (symp)), 1); assert (weakp); assert (S_GET_NUMBER_AUXILIARY (weakp) == 1); if (! S_IS_WEAK (weakp)) { /* The symbol was turned from weak to strong. Discard altname. */ *punt = 1; return; } else if (symbol_equated_p (weakp)) { /* The weak symbol has an alternate specified; symp is unneeded. */ S_SET_STORAGE_CLASS (weakp, C_NT_WEAK); SA_SET_SYM_TAGNDX (weakp, symbol_get_value_expression (weakp)->X_add_symbol); S_CLEAR_EXTERNAL (symp); *punt = 1; return; } else { /* The weak symbol has been assigned an alternate value. Copy this value to symp, and set symp as weakp's alternate. */ if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK) { S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp)); S_SET_STORAGE_CLASS (weakp, C_NT_WEAK); } if (S_IS_DEFINED (weakp)) { /* This is a defined weak symbol. Copy value information from the weak symbol itself to the alternate symbol. */ symbol_set_value_expression (symp, symbol_get_value_expression (weakp)); symbol_set_frag (symp, symbol_get_frag (weakp)); S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp)); } else { /* This is an undefined weak symbol. Define the alternate symbol to zero. */ S_SET_VALUE (symp, 0); S_SET_SEGMENT (symp, absolute_section); } S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp))); S_SET_STORAGE_CLASS (symp, C_EXT); S_SET_VALUE (weakp, 0); S_SET_SEGMENT (weakp, undefined_section); } } #else /* TE_PE */ if (S_IS_WEAK (symp)) S_SET_STORAGE_CLASS (symp, C_WEAKEXT); #endif /* TE_PE */ if (!S_IS_DEFINED (symp) && !S_IS_WEAK (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT) S_SET_STORAGE_CLASS (symp, C_EXT); if (!SF_GET_DEBUG (symp)) { symbolS * real; if (!SF_GET_LOCAL (symp) && !SF_GET_STATICS (symp) && S_GET_STORAGE_CLASS (symp) != C_LABEL && symbol_constant_p (symp) && (real = symbol_find_noref (S_GET_NAME (symp), 1)) && S_GET_STORAGE_CLASS (real) == C_NULL && real != symp) { c_symbol_merge (symp, real); *punt = 1; return; } if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) { assert (S_GET_VALUE (symp) == 0); if (S_IS_WEAKREFD (symp)) *punt = 1; else S_SET_EXTERNAL (symp); } else if (S_GET_STORAGE_CLASS (symp) == C_NULL) { if (S_GET_SEGMENT (symp) == text_section && symp != seg_info (text_section)->sym) S_SET_STORAGE_CLASS (symp, C_LABEL); else S_SET_STORAGE_CLASS (symp, C_STAT); } if (SF_GET_PROCESS (symp)) { if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) { if (streq (S_GET_NAME (symp), ".bb")) stack_push (block_stack, (char *) &symp); else { symbolS *begin; begin = *(symbolS **) stack_pop (block_stack); if (begin == 0) as_warn (_("mismatched .eb")); else next_set_end = begin; } } if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) { union internal_auxent *auxp; coff_last_function = symp; if (S_GET_NUMBER_AUXILIARY (symp) < 1) S_SET_NUMBER_AUXILIARY (symp, 1); auxp = SYM_AUXENT (symp); memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); } if (S_GET_STORAGE_CLASS (symp) == C_EFCN) { if (coff_last_function == 0) as_fatal (_("C_EFCN symbol for %s out of scope"), S_GET_NAME (symp)); SA_SET_SYM_FSIZE (coff_last_function, (long) (S_GET_VALUE (symp) - S_GET_VALUE (coff_last_function))); next_set_end = coff_last_function; coff_last_function = 0; } } if (S_IS_EXTERNAL (symp)) S_SET_STORAGE_CLASS (symp, C_EXT); else if (SF_GET_LOCAL (symp)) *punt = 1; if (SF_GET_FUNCTION (symp)) symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION; } /* Double check weak symbols. */ if (S_IS_WEAK (symp) && S_IS_COMMON (symp)) as_bad (_("Symbol `%s' can not be both weak and common"), S_GET_NAME (symp)); if (SF_GET_TAG (symp)) last_tagP = symp; else if (S_GET_STORAGE_CLASS (symp) == C_EOS) next_set_end = last_tagP; #ifdef OBJ_XCOFF /* This is pretty horrible, but we have to set *punt correctly in order to call SA_SET_SYM_ENDNDX correctly. */ if (! symbol_used_in_reloc_p (symp) && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0 || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp)) && ! symbol_get_tc (symp)->output && S_GET_STORAGE_CLASS (symp) != C_FILE))) *punt = 1; #endif if (set_end != (symbolS *) NULL && ! *punt && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0 || (S_IS_DEFINED (symp) && ! S_IS_COMMON (symp) && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp))))) { SA_SET_SYM_ENDNDX (set_end, symp); set_end = NULL; } if (next_set_end != NULL) { if (set_end != NULL) as_warn ("Warning: internal error: forgetting to set endndx of %s", S_GET_NAME (set_end)); set_end = next_set_end; } #ifndef OBJ_XCOFF if (! *punt && S_GET_STORAGE_CLASS (symp) == C_FCN && streq (S_GET_NAME (symp), ".bf")) { if (coff_last_bf != NULL) SA_SET_SYM_ENDNDX (coff_last_bf, symp); coff_last_bf = symp; } #endif if (coffsymbol (symbol_get_bfdsym (symp))->lineno) { int i; struct line_no *lptr; alent *l; lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; for (i = 0; lptr; lptr = lptr->next) i++; lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno; /* We need i entries for line numbers, plus 1 for the first entry which BFD will override, plus 1 for the last zero entry (a marker for BFD). */ l = xmalloc ((i + 2) * sizeof (* l)); coffsymbol (symbol_get_bfdsym (symp))->lineno = l; l[i + 1].line_number = 0; l[i + 1].u.sym = NULL; for (; i > 0; i--) { if (lptr->frag) lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE; l[i] = lptr->l; lptr = lptr->next; } } }