diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/obj-coff.c | 121 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 6 |
2 files changed, 86 insertions, 41 deletions
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c index 8ead485..0239b76 100644 --- a/gas/config/obj-coff.c +++ b/gas/config/obj-coff.c @@ -212,47 +212,6 @@ obj_coff_bss (ignore) s_lcomm (0); } -/* Handle .weak. This is a GNU extension. */ - -static void -obj_coff_weak (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - char *name; - int c; - symbolS *symbolP; - - do - { - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - *input_line_pointer = c; - SKIP_WHITESPACE (); - -#if defined BFD_ASSEMBLER || defined S_SET_WEAK - S_SET_WEAK (symbolP); -#endif - -#ifdef TE_PE - S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK); -#else - S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT); -#endif - - if (c == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') - c = '\n'; - } - } - while (c == ','); - - demand_empty_rest_of_line (); -} - #ifdef BFD_ASSEMBLER static segT fetch_coff_debug_section PARAMS ((void)); @@ -1135,6 +1094,86 @@ obj_coff_val (ignore) demand_empty_rest_of_line (); } +/* Handle .weak. This is a GNU extension in formats other than PE. */ +static void +obj_coff_weak (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + char *name; + int c; + symbolS *symbolP; + + do + { + name = input_line_pointer; + c = get_symbol_end (); + if (*name == 0) + { + as_warn (_("badly formed .weak directive ignored")); + ignore_rest_of_line (); + return; + } + symbolP = symbol_find_or_make (name); + *input_line_pointer = c; + SKIP_WHITESPACE (); + +#if defined BFD_ASSEMBLER || defined S_SET_WEAK + S_SET_WEAK (symbolP); +#endif + +#ifdef TE_PE + /* See _Microsoft Portable Executable and Common Object + * File Format Specification_, section 5.5.3. + * Note that weak symbols without aux records are a GNU + * extension. + */ + S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK); + + if (c == '=') + { + symbolS *alternateP; + long characteristics = 2; + ++input_line_pointer; + if (*input_line_pointer == '=') + { + characteristics = 1; + ++input_line_pointer; + } + + SKIP_WHITESPACE(); + name = input_line_pointer; + c = get_symbol_end(); + if (*name == 0) + { + as_warn (_("alternate name missing in .weak directive")); + ignore_rest_of_line (); + return; + } + alternateP = symbol_find_or_make (name); + *input_line_pointer = c; + + S_SET_NUMBER_AUXILIARY (symbolP, 1); + SA_SET_SYM_TAGNDX (symbolP, alternateP); + SA_SET_SYM_FSIZE (symbolP, characteristics); + } +#else /* TE_PE */ + S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT); +#endif /* TE_PE */ + + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (*input_line_pointer == '\n') + c = '\n'; + } + + } + while (c == ','); + + demand_empty_rest_of_line (); +} + void coff_obj_read_begin_hook () { diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 823435f..cc95843 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -5280,6 +5280,12 @@ tc_gen_reloc (section, fixp) *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; + +#ifdef TE_PE + if (S_IS_WEAK (fixp->fx_addsy)) + rel->addend = rel->address - (*rel->sym_ptr_ptr)->value + 4; + else +#endif if (!use_rela_relocations) { /* HACK: Since i386 ELF uses Rel instead of Rela, encode the |