aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/obj-coff.c121
-rw-r--r--gas/config/tc-i386.c6
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