/* write.c - emit .o file
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2023 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#endif
#ifndef TC_VALIDATE_FIX_SUB
-#ifdef UNDEFINED_DIFFERENCE_OK
-/* The PA needs this for PIC code generation. */
-#define TC_VALIDATE_FIX_SUB(FIX, SEG) \
- (md_register_arithmetic || (SEG) != reg_section)
-#else
-#define TC_VALIDATE_FIX_SUB(FIX, SEG) \
- ((md_register_arithmetic || (SEG) != reg_section) \
- && ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \
- || (FIX)->fx_r_type == BFD_RELOC_GPREL16))
-#endif
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
#endif
#ifndef TC_LINKRELAX_FIXUP
/* We generally attach relocs to frag chains. However, after we have
chained these all together into a segment, any relocs we add after
that must be attached to a segment. This will include relocs added
- in md_estimate_size_for_relax, for example. */
-static int frags_chained = 0;
+ in md_estimate_size_before_relax, for example. */
+static bool frags_chained = false;
-static int n_fixups;
+static unsigned int n_fixups;
#define RELOC_ENUM enum bfd_reloc_code_real
static fixS *
fix_new_internal (fragS *frag, /* Which frag? */
- int where, /* Where in that frag? */
- int size, /* 1, 2, or 4 usually. */
+ unsigned long where, /* Where in that frag? */
+ unsigned long size, /* 1, 2, or 4 usually. */
symbolS *add_symbol, /* X_add_symbol. */
symbolS *sub_symbol, /* X_op_symbol. */
offsetT offset, /* X_add_number. */
/* We've made fx_size a narrow field; check that it's wide enough. */
if (fixP->fx_size != size)
{
- as_bad (_("field fx_size too small to hold %d"), size);
+ as_bad (_("field fx_size too small to hold %lu"), size);
abort ();
}
fixP->fx_addsy = add_symbol;
fixP->fx_dot_frag = dot_frag;
fixP->fx_pcrel = pcrel;
fixP->fx_r_type = r_type;
- fixP->fx_im_disp = 0;
fixP->fx_pcrel_adjust = 0;
- fixP->fx_bit_fixP = 0;
fixP->fx_addnumber = 0;
fixP->fx_tcbit = 0;
fixP->fx_tcbit2 = 0;
/* Create a fixup relative to a symbol (plus a constant). */
fixS *
-fix_new (fragS *frag, /* Which frag? */
- int where, /* Where in that frag? */
- int size, /* 1, 2, or 4 usually. */
- symbolS *add_symbol, /* X_add_symbol. */
+fix_new (fragS *frag, /* Which frag? */
+ unsigned long where, /* Where in that frag? */
+ unsigned long size, /* 1, 2, or 4 usually. */
+ symbolS *add_symbol, /* X_add_symbol. */
offsetT offset, /* X_add_number. */
int pcrel, /* TRUE if PC-relative relocation. */
RELOC_ENUM r_type /* Relocation type. */)
{
return fix_new_internal (frag, where, size, add_symbol,
- (symbolS *) NULL, offset, pcrel, r_type, FALSE);
+ (symbolS *) NULL, offset, pcrel, r_type, false);
}
/* Create a fixup for an expression. Currently we only support fixups
fixS *
fix_new_exp (fragS *frag, /* Which frag? */
- int where, /* Where in that frag? */
- int size, /* 1, 2, or 4 usually. */
+ unsigned long where, /* Where in that frag? */
+ unsigned long size, /* 1, 2, or 4 usually. */
expressionS *exp, /* Expression. */
int pcrel, /* TRUE if PC-relative relocation. */
RELOC_ENUM r_type /* Relocation type. */)
}
return fix_new_internal (frag, where, size, add, sub, off, pcrel,
- r_type, FALSE);
+ r_type, false);
}
/* Create a fixup at the beginning of FRAG. The arguments are the same
as for fix_new, except that WHERE is implicitly 0. */
fixS *
-fix_at_start (fragS *frag, int size, symbolS *add_symbol,
+fix_at_start (fragS *frag, unsigned long size, symbolS *add_symbol,
offsetT offset, int pcrel, RELOC_ENUM r_type)
{
return fix_new_internal (frag, 0, size, add_symbol,
- (symbolS *) NULL, offset, pcrel, r_type, TRUE);
+ (symbolS *) NULL, offset, pcrel, r_type, true);
}
/* Generic function to determine whether a fixup requires a relocation. */
if (seg == absolute_section)
return;
- if (align > bfd_get_section_alignment (stdoutput, seg))
- bfd_set_section_alignment (stdoutput, seg, align);
+ if (align > bfd_section_alignment (seg))
+ bfd_set_section_alignment (seg, align);
}
int
if (seg == absolute_section)
return 0;
- return bfd_get_section_alignment (stdoutput, seg);
+ return bfd_section_alignment (seg);
}
/* Reset the section indices after removing the gas created sections. */
fragS dummy, *prev_frag = &dummy;
fixS fix_dummy, *prev_fix = &fix_dummy;
- for (; frchp; frchp = frchp->frch_next)
+ do
{
prev_frag->fr_next = frchp->frch_root;
prev_frag = frchp->frch_last;
seg_info (section)->fix_tail = frchp->fix_tail;
prev_fix = frchp->fix_tail;
}
- }
+ frchp = frchp->frch_next;
+ } while (frchp);
gas_assert (prev_frag != &dummy
&& prev_frag->fr_type != 0);
prev_frag->fr_next = 0;
/* Now that we've chained the frags together, we must add new fixups
to the segment, not to the frag chain. */
- frags_chained = 1;
+ frags_chained = true;
}
static void
{
switch (fragP->fr_type)
{
+ case rs_space_nop:
+ goto skip_align;
case rs_align:
case rs_align_code:
case rs_align_test:
#ifdef HANDLE_ALIGN
HANDLE_ALIGN (fragP);
#endif
+ skip_align:
know (fragP->fr_next != NULL);
fragP->fr_offset = (fragP->fr_next->fr_address
- fragP->fr_address
if (fragP->fr_offset < 0)
{
as_bad_where (fragP->fr_file, fragP->fr_line,
- _("attempt to .org/.space backwards? (%ld)"),
+ _("attempt to .org/.space/.nops backwards? (%ld)"),
(long) fragP->fr_offset);
fragP->fr_offset = 0;
}
- fragP->fr_type = rs_fill;
+ if (fragP->fr_type == rs_space_nop)
+ fragP->fr_type = rs_fill_nop;
+ else
+ fragP->fr_type = rs_fill;
break;
case rs_fill:
+ case rs_fill_nop:
break;
case rs_leb128:
dwarf2dbg_convert_frag (fragP);
break;
+ case rs_sframe:
+ sframe_convert_frag (fragP);
+ break;
+
case rs_machine_dependent:
md_convert_frag (stdoutput, sec, fragP);
gas_assert (fragP->fr_next == NULL
- || ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
- == fragP->fr_fix));
+ || (fragP->fr_next->fr_address - fragP->fr_address
+ == fragP->fr_fix));
/* After md_convert_frag, we make the frag into a ".space 0".
md_convert_frag() should set up any fixSs and constants
}
static void
-size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
+size_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx ATTRIBUTE_UNUSED)
{
flagword flags;
fragS *fragp;
else
size = 0;
- flags = bfd_get_section_flags (abfd, sec);
- if (size == 0 && bfd_get_section_size (sec) != 0 &&
+ flags = bfd_section_flags (sec);
+ if (size == 0 && bfd_section_size (sec) != 0 &&
(flags & SEC_HAS_CONTENTS) != 0)
return;
if (size > 0 && ! seginfo->bss)
flags |= SEC_HAS_CONTENTS;
- flags &= ~SEC_RELOC;
- x = bfd_set_section_flags (abfd, sec, flags);
+ x = bfd_set_section_flags (sec, flags);
gas_assert (x);
/* If permitted, allow the backend to pad out the section
newsize = size;
else
newsize = md_section_align (sec, size);
- x = bfd_set_section_size (abfd, sec, newsize);
+ x = bfd_set_section_size (sec, newsize);
gas_assert (x);
/* If the size had to be rounded up, add some padding in the last
as_bad_where (r->file, r->line, _("invalid reloc expression"));
sec = NULL;
}
- else if (sym != NULL)
+ else if (sym != NULL && sec != NULL)
{
/* Convert relocs against local symbols to refer to the
corresponding section symbol plus offset instead. Keep
prevent the offset from overflowing the relocated field,
unless it has enough bits to cover the whole address
space. */
- if (S_IS_LOCAL (sym) && !symbol_section_p (sym)
+ if (S_IS_LOCAL (sym)
+ && S_IS_DEFINED (sym)
+ && !symbol_section_p (sym)
&& (sec->use_rela_p
|| (howto->partial_inplace
&& (!howto->pc_relative
/* Since we're reducing to section symbols, don't attempt to reduce
anything that's already using one. */
if (symbol_section_p (sym))
- continue;
+ {
+ /* Mark the section symbol used in relocation so that it will
+ be included in the symbol table. */
+ symbol_mark_used_in_reloc (sym);
+ continue;
+ }
symsec = S_GET_SEGMENT (sym);
if (symsec == NULL)
/* The GNU toolchain uses an extension for ELF: a
section beginning with the magic string
.gnu.linkonce is a linkonce section. */
- && strncmp (segment_name (symsec), ".gnu.linkonce",
- sizeof ".gnu.linkonce" - 1) == 0))
+ && startswith (segment_name (symsec), ".gnu.linkonce")))
continue;
}
dump_section_relocs (abfd, sec, stderr);
}
+void
+as_bad_subtract (fixS *fixp)
+{
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("can't resolve %s - %s"),
+ fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
+ S_GET_NAME (fixp->fx_subsy));
+}
+
/* fixup_segment()
Go through all the fixS's in a segment and see which ones can be
{
valueT add_number;
fragS *fragP;
- segT add_symbol_segment = absolute_section;
if (fixP != NULL && abs_section_sym == NULL)
abs_section_sym = section_symbol (absolute_section);
/* If the linker is doing the relaxing, we must not do any fixups.
Well, strictly speaking that's not true -- we could do any that
- are PC-relative and don't cross regions that could change size.
- And for the i960 we might be able to turn callx/callj into bal
- anyways in cases where we know the maximum displacement. */
+ are PC-relative and don't cross regions that could change size. */
if (linkrelax && TC_LINKRELAX_FIXUP (this_segment))
{
for (; fixP; fixP = fixP->fx_next)
for (; fixP; fixP = fixP->fx_next)
{
+ segT add_symbol_segment = absolute_section;
+
#ifdef DEBUG5
fprintf (stderr, "\nprocessing fixup:\n");
print_fixup (fixP);
if (fixP->fx_subsy != NULL)
{
segT sub_symbol_segment;
+
resolve_symbol_value (fixP->fx_subsy);
sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
+
if (fixP->fx_addsy != NULL
&& sub_symbol_segment == add_symbol_segment
&& !S_FORCE_RELOC (fixP->fx_addsy, 0)
&& !S_FORCE_RELOC (fixP->fx_subsy, 0)
&& !TC_FORCE_RELOCATION_SUB_SAME (fixP, add_symbol_segment))
{
- add_number += S_GET_VALUE (fixP->fx_addsy);
- add_number -= S_GET_VALUE (fixP->fx_subsy);
+ add_number += S_GET_VALUE_WHERE (fixP->fx_addsy, fixP->fx_file, fixP->fx_line);
+ add_number -= S_GET_VALUE_WHERE (fixP->fx_subsy, fixP->fx_file, fixP->fx_line);
fixP->fx_offset = add_number;
fixP->fx_addsy = NULL;
fixP->fx_subsy = NULL;
&& !S_FORCE_RELOC (fixP->fx_subsy, 0)
&& !TC_FORCE_RELOCATION_SUB_ABS (fixP, add_symbol_segment))
{
- add_number -= S_GET_VALUE (fixP->fx_subsy);
+ add_number -= S_GET_VALUE_WHERE (fixP->fx_subsy, fixP->fx_file, fixP->fx_line);
fixP->fx_offset = add_number;
fixP->fx_subsy = NULL;
}
&& !S_FORCE_RELOC (fixP->fx_subsy, 0)
&& !TC_FORCE_RELOCATION_SUB_LOCAL (fixP, add_symbol_segment))
{
- add_number -= S_GET_VALUE (fixP->fx_subsy);
+ add_number -= S_GET_VALUE_WHERE (fixP->fx_subsy, fixP->fx_file, fixP->fx_line);
fixP->fx_offset = (add_number + fixP->fx_dot_value
+ fixP->fx_dot_frag->fr_address);
as_bad_where (fixP->fx_file, fixP->fx_line,
_("register value used as expression"));
else
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("can't resolve `%s' {%s section} - `%s' {%s section}"),
- fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
- segment_name (add_symbol_segment),
- S_GET_NAME (fixP->fx_subsy),
- segment_name (sub_symbol_segment));
+ as_bad_subtract (fixP);
}
else if (sub_symbol_segment != undefined_section
&& ! bfd_is_com_section (sub_symbol_segment)
&& MD_APPLY_SYM_VALUE (fixP))
- add_number -= S_GET_VALUE (fixP->fx_subsy);
+ add_number -= S_GET_VALUE_WHERE (fixP->fx_subsy, fixP->fx_file, fixP->fx_line);
}
if (fixP->fx_addsy)
/* This fixup was made when the symbol's segment was
SEG_UNKNOWN, but it is now in the local segment.
So we know how to do the address without relocation. */
- add_number += S_GET_VALUE (fixP->fx_addsy);
+ add_number += S_GET_VALUE_WHERE (fixP->fx_addsy, fixP->fx_file, fixP->fx_line);
fixP->fx_offset = add_number;
if (fixP->fx_pcrel)
add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
&& !S_FORCE_RELOC (fixP->fx_addsy, 0)
&& !TC_FORCE_RELOCATION_ABS (fixP))
{
- add_number += S_GET_VALUE (fixP->fx_addsy);
+ add_number += S_GET_VALUE_WHERE (fixP->fx_addsy, fixP->fx_file, fixP->fx_line);
fixP->fx_offset = add_number;
fixP->fx_addsy = NULL;
}
else if (add_symbol_segment != undefined_section
&& ! bfd_is_com_section (add_symbol_segment)
&& MD_APPLY_SYM_VALUE (fixP))
- add_number += S_GET_VALUE (fixP->fx_addsy);
+ add_number += S_GET_VALUE_WHERE (fixP->fx_addsy, fixP->fx_file, fixP->fx_line);
}
if (fixP->fx_pcrel)
symbol_mark_used_in_reloc (fixP->fx_subsy);
}
- if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && fixP->fx_size != 0)
+ if (!fixP->fx_no_overflow && fixP->fx_size != 0)
{
if (fixP->fx_size < sizeof (valueT))
{
mask = 0;
mask--; /* Set all bits to one. */
mask <<= fixP->fx_size * 8 - (fixP->fx_signed ? 1 : 0);
- if ((add_number & mask) != 0 && (add_number & mask) != mask)
+ if ((add_number & mask) != 0
+ && (fixP->fx_signed
+ ? (add_number & mask) != mask
+ : (-add_number & mask) != 0))
{
char buf[50], buf2[50];
- sprint_value (buf, fragP->fr_address + fixP->fx_where);
+ bfd_sprintf_vma (stdoutput, buf, fragP->fr_address + fixP->fx_where);
if (add_number > 1000)
- sprint_value (buf2, add_number);
+ bfd_sprintf_vma (stdoutput, buf2, add_number);
else
sprintf (buf2, "%ld", (long) add_number);
as_bad_where (fixP->fx_file, fixP->fx_line,
- _("value of %s too large for field of %d bytes at %s"),
+ ngettext ("value of %s too large for field "
+ "of %d byte at %s",
+ "value of %s too large for field "
+ "of %d bytes at %s",
+ fixP->fx_size),
buf2, fixP->fx_size, buf);
} /* Generic error checking. */
}
(long) add_number,
(long) (fragP->fr_address + fixP->fx_where));
#endif
- } /* Not a bit fix. */
+ }
#ifdef TC_VALIDATE_FIX
skip: ATTRIBUTE_UNUSED_LABEL
}
static void
-write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
+write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
+ void *xxx ATTRIBUTE_UNUSED)
{
segment_info_type *seginfo = seg_info (sec);
unsigned int n;
/* Extract relocs for this section from reloc_list. */
rp = &reloc_list;
+
my_reloc_list = NULL;
while ((r = *rp) != NULL)
{
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
{
int fx_size, slack;
- offsetT loc;
+ valueT loc;
arelent **reloc;
#ifndef RELOC_EXPANSION_POSSIBLE
arelent *rel;
as_bad_where (fixp->fx_file, fixp->fx_line,
_("internal error: fixup not contained within frag"));
+#ifdef obj_fixup_removed_symbol
+ if (fixp->fx_addsy && symbol_removed_p (fixp->fx_addsy))
+ obj_fixup_removed_symbol (&fixp->fx_addsy);
+ if (fixp->fx_subsy && symbol_removed_p (fixp->fx_subsy))
+ obj_fixup_removed_symbol (&fixp->fx_subsy);
+#endif
+
#ifndef RELOC_EXPANSION_POSSIBLE
*reloc = tc_gen_reloc (sec, fixp);
#else
}
r = r->next;
}
- relocs[n++] = *reloc;
+#ifdef GAS_SORT_RELOCS
+ if (n != 0 && (*reloc)->address < relocs[n - 1]->address)
+ {
+ size_t lo = 0;
+ size_t hi = n - 1;
+ bfd_vma look = (*reloc)->address;
+ while (lo < hi)
+ {
+ size_t mid = (lo + hi) / 2;
+ if (relocs[mid]->address > look)
+ hi = mid;
+ else
+ {
+ lo = mid + 1;
+ if (relocs[mid]->address == look)
+ break;
+ }
+ }
+ while (lo < hi && relocs[lo]->address == look)
+ lo++;
+ memmove (relocs + lo + 1, relocs + lo,
+ (n - lo) * sizeof (*relocs));
+ n++;
+ relocs[lo] = *reloc;
+ }
+ else
+#endif
+ relocs[n++] = *reloc;
install_reloc (sec, *reloc, fixp->fx_frag,
fixp->fx_file, fixp->fx_line);
#ifndef RELOC_EXPANSION_POSSIBLE
}
#endif
- if (n)
- {
- flagword flags = bfd_get_section_flags (abfd, sec);
- flags |= SEC_RELOC;
- bfd_set_section_flags (abfd, sec, flags);
- bfd_set_reloc (stdoutput, sec, relocs, n);
- }
+ bfd_set_reloc (stdoutput, sec, n ? relocs : NULL, n);
#ifdef SET_SECTION_RELOCS
SET_SECTION_RELOCS (sec, relocs, n);
}
static int
-compress_frag (struct z_stream_s *strm, const char *contents, int in_size,
+compress_frag (bool use_zstd, void *ctx, const char *contents, int in_size,
fragS **last_newf, struct obstack *ob)
{
int out_size;
as_fatal (_("can't extend frag"));
next_out = obstack_next_free (ob);
obstack_blank_fast (ob, avail_out);
- out_size = compress_data (strm, &contents, &in_size,
- &next_out, &avail_out);
+ out_size = compress_data (use_zstd, ctx, &contents, &in_size, &next_out,
+ &avail_out);
if (out_size < 0)
- return -1;
+ return -1;
f->fr_fix += out_size;
total_out_size += out_size;
compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
{
segment_info_type *seginfo = seg_info (sec);
- fragS *f;
- fragS *first_newf;
- fragS *last_newf;
- struct obstack *ob = &seginfo->frchainP->frch_obstack;
- bfd_size_type uncompressed_size = (bfd_size_type) sec->size;
- bfd_size_type compressed_size;
- const char *section_name;
- char *compressed_name;
- char *header;
- struct z_stream_s *strm;
- int x;
- flagword flags = bfd_get_section_flags (abfd, sec);
- unsigned int header_size, compression_header_size;
+ bfd_size_type uncompressed_size = sec->size;
+ flagword flags = bfd_section_flags (sec);
if (seginfo == NULL
- || sec->size < 32
- || (flags & (SEC_ALLOC | SEC_HAS_CONTENTS)) == SEC_ALLOC)
+ || uncompressed_size < 32
+ || (flags & SEC_HAS_CONTENTS) == 0)
return;
- section_name = bfd_get_section_name (stdoutput, sec);
- if (strncmp (section_name, ".debug_", 7) != 0)
+ const char *section_name = bfd_section_name (sec);
+ if (!startswith (section_name, ".debug_")
+ && !startswith (section_name, ".gnu.debuglto_.debug_")
+ && !startswith (section_name, ".gnu.linkonce.wi."))
return;
- strm = compress_init ();
- if (strm == NULL)
+ bool use_zstd = abfd->flags & BFD_COMPRESS_ZSTD;
+ void *ctx = compress_init (use_zstd);
+ if (ctx == NULL)
return;
- if (flag_compress_debug == COMPRESS_DEBUG_GABI_ZLIB)
- {
- compression_header_size
- = bfd_get_compression_header_size (stdoutput, NULL);
- header_size = compression_header_size;
- }
+ unsigned int header_size;
+ if ((abfd->flags & BFD_COMPRESS_GABI) == 0)
+ header_size = 12;
else
- {
- compression_header_size = 0;
- header_size = 12;
- }
+ header_size = bfd_get_compression_header_size (stdoutput, NULL);
/* Create a new frag to contain the compression header. */
- first_newf = frag_alloc (ob);
+ struct obstack *ob = &seginfo->frchainP->frch_obstack;
+ fragS *first_newf = frag_alloc (ob);
if (obstack_room (ob) < header_size)
first_newf = frag_alloc (ob);
if (obstack_room (ob) < header_size)
- as_fatal (_("can't extend frag %u chars"), header_size);
- last_newf = first_newf;
+ as_fatal (ngettext ("can't extend frag %lu char",
+ "can't extend frag %lu chars",
+ (unsigned long) header_size),
+ (unsigned long) header_size);
+ fragS *last_newf = first_newf;
obstack_blank_fast (ob, header_size);
last_newf->fr_type = rs_fill;
last_newf->fr_fix = header_size;
- header = last_newf->fr_literal;
- compressed_size = header_size;
+ char *header = last_newf->fr_literal;
+ bfd_size_type compressed_size = header_size;
/* Stream the frags through the compression engine, adding new frags
as necessary to accommodate the compressed output. */
- for (f = seginfo->frchainP->frch_root;
+ for (fragS *f = seginfo->frchainP->frch_root;
f;
f = f->fr_next)
{
gas_assert (f->fr_type == rs_fill);
if (f->fr_fix)
{
- out_size = compress_frag (strm, f->fr_literal, f->fr_fix,
+ out_size = compress_frag (use_zstd, ctx, f->fr_literal, f->fr_fix,
&last_newf, ob);
if (out_size < 0)
return;
{
while (count--)
{
- out_size = compress_frag (strm, fill_literal, (int) fill_size,
- &last_newf, ob);
+ out_size = compress_frag (use_zstd, ctx, fill_literal,
+ (int)fill_size, &last_newf, ob);
if (out_size < 0)
return;
compressed_size += out_size;
as_fatal (_("can't extend frag"));
next_out = obstack_next_free (ob);
obstack_blank_fast (ob, avail_out);
- x = compress_finish (strm, &next_out, &avail_out, &out_size);
+ int x = compress_finish (use_zstd, ctx, &next_out, &avail_out, &out_size);
if (x < 0)
return;
/* Update the section size and its name. */
bfd_update_compression_header (abfd, (bfd_byte *) header, sec);
- x = bfd_set_section_size (abfd, sec, compressed_size);
+ bool x = bfd_set_section_size (sec, compressed_size);
gas_assert (x);
- if (!compression_header_size)
+ if ((abfd->flags & BFD_COMPRESS_GABI) == 0
+ && section_name[1] == 'd')
{
- compressed_name = concat (".z", section_name + 1, (char *) NULL);
- bfd_section_name (stdoutput, sec) = compressed_name;
+ char *compressed_name = bfd_debug_name_to_zdebug (abfd, section_name);
+ bfd_rename_section (sec, compressed_name);
}
}
+#ifndef md_generate_nops
+/* Genenerate COUNT bytes of no-op instructions to WHERE. A target
+ backend must override this with proper no-op instructions. */
+
+static void
+md_generate_nops (fragS *f ATTRIBUTE_UNUSED,
+ char *where ATTRIBUTE_UNUSED,
+ offsetT count ATTRIBUTE_UNUSED,
+ int control ATTRIBUTE_UNUSED)
+{
+ as_bad (_("unimplemented .nops directive"));
+}
+#endif
+
static void
write_contents (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec,
/* Write out the frags. */
if (seginfo == NULL
- || !(bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
+ || !(bfd_section_flags (sec) & SEC_HAS_CONTENTS))
return;
for (f = seginfo->frchainP->frch_root;
char *fill_literal;
offsetT count;
- gas_assert (f->fr_type == rs_fill);
+ gas_assert (f->fr_type == rs_fill || f->fr_type == rs_fill_nop);
if (f->fr_fix)
{
x = bfd_set_section_contents (stdoutput, sec,
f->fr_literal, (file_ptr) offset,
(bfd_size_type) f->fr_fix);
if (!x)
- as_fatal (_("can't write %ld bytes to section %s of %s because: '%s'"),
- (long) f->fr_fix, sec->name,
- stdoutput->filename,
+ as_fatal (ngettext ("can't write %ld byte "
+ "to section %s of %s: '%s'",
+ "can't write %ld bytes "
+ "to section %s of %s: '%s'",
+ (long) f->fr_fix),
+ (long) f->fr_fix,
+ bfd_section_name (sec), bfd_get_filename (stdoutput),
bfd_errmsg (bfd_get_error ()));
offset += f->fr_fix;
}
- fill_literal = f->fr_literal + f->fr_fix;
+
fill_size = f->fr_var;
count = f->fr_offset;
+ fill_literal = f->fr_literal + f->fr_fix;
+
+ if (f->fr_type == rs_fill_nop)
+ {
+ gas_assert (count >= 0 && fill_size == 1);
+ if (count > 0)
+ {
+ char *buf = xmalloc (count);
+ md_generate_nops (f, buf, count, *fill_literal);
+ x = bfd_set_section_contents
+ (stdoutput, sec, buf, (file_ptr) offset,
+ (bfd_size_type) count);
+ if (!x)
+ as_fatal (ngettext ("can't fill %ld byte "
+ "in section %s of %s: '%s'",
+ "can't fill %ld bytes "
+ "in section %s of %s: '%s'",
+ (long) count),
+ (long) count,
+ bfd_section_name (sec),
+ bfd_get_filename (stdoutput),
+ bfd_errmsg (bfd_get_error ()));
+ offset += count;
+ free (buf);
+ }
+ continue;
+ }
+
gas_assert (count >= 0);
if (fill_size && count)
{
(file_ptr) offset,
(bfd_size_type) fill_size);
if (!x)
- as_fatal (_("can't fill %ld bytes in section %s of %s because '%s'"),
- (long) fill_size, sec->name,
- stdoutput->filename,
+ as_fatal (ngettext ("can't fill %ld byte "
+ "in section %s of %s: '%s'",
+ "can't fill %ld bytes "
+ "in section %s of %s: '%s'",
+ (long) fill_size),
+ (long) fill_size,
+ bfd_section_name (sec),
+ bfd_get_filename (stdoutput),
bfd_errmsg (bfd_get_error ()));
offset += fill_size;
}
(stdoutput, sec, buf, (file_ptr) offset,
(bfd_size_type) n_per_buf * fill_size);
if (!x)
- as_fatal (_("cannot fill %ld bytes in section %s of %s because: '%s'"),
- (long)(n_per_buf * fill_size), sec->name,
- stdoutput->filename,
+ as_fatal (ngettext ("can't fill %ld byte "
+ "in section %s of %s: '%s'",
+ "can't fill %ld bytes "
+ "in section %s of %s: '%s'",
+ (long) (n_per_buf * fill_size)),
+ (long) (n_per_buf * fill_size),
+ bfd_section_name (sec),
+ bfd_get_filename (stdoutput),
bfd_errmsg (bfd_get_error ()));
offset += n_per_buf * fill_size;
}
int nsyms;
asymbol **asympp;
symbolS *symp;
- bfd_boolean result;
+ bool result;
/* Count symbols. We can't rely on a count made by the loop in
write_object_file, because *_frob_file may add a new symbol or
- two. */
+ two. Generate unused section symbols only if needed. */
nsyms = 0;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
- nsyms++;
+ if (!symbol_removed_p (symp)
+ && (bfd_keep_unused_section_symbols (stdoutput)
+ || !symbol_section_p (symp)
+ || symbol_used_in_reloc_p (symp)))
+ nsyms++;
if (nsyms)
{
asympp = (asymbol **) bfd_alloc (stdoutput, amt);
symp = symbol_rootP;
- for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
- {
- asympp[i] = symbol_get_bfdsym (symp);
- if (asympp[i]->flags != BSF_SECTION_SYM
- || !(bfd_is_const_section (asympp[i]->section)
- && asympp[i]->section->symbol == asympp[i]))
- asympp[i]->flags |= BSF_KEEP;
- symbol_mark_written (symp);
- }
+ for (i = 0; i < nsyms; symp = symbol_next (symp))
+ if (!symbol_removed_p (symp)
+ && (bfd_keep_unused_section_symbols (stdoutput)
+ || !symbol_section_p (symp)
+ || symbol_used_in_reloc_p (symp)))
+ {
+ asympp[i] = symbol_get_bfdsym (symp);
+ if (asympp[i]->flags != BSF_SECTION_SYM
+ || !(bfd_is_const_section (asympp[i]->section)
+ && asympp[i]->section->symbol == asympp[i]))
+ asympp[i]->flags |= BSF_KEEP;
+ symbol_mark_written (symp);
+ /* Include this section symbol in the symbol table. */
+ if (symbol_section_p (symp))
+ asympp[i]->flags |= BSF_SECTION_SYM_USED;
+ i++;
+ }
}
else
asympp = 0;
do_not_pad_sections_to_alignment = 1;
alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
- if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
+ if ((bfd_section_flags (now_seg) & SEC_MERGE)
&& now_seg->entsize)
{
unsigned int entsize = now_seg->entsize;
const char *name;
size = bfd_elf_obj_attr_size (stdoutput);
- if (size)
+ if (size == 0)
+ return;
+
+ name = get_elf_backend_data (stdoutput)->obj_attrs_section;
+ if (!name)
+ name = ".gnu.attributes";
+ s = subseg_new (name, 0);
+ elf_section_type (s)
+ = get_elf_backend_data (stdoutput)->obj_attrs_section_type;
+ bfd_set_section_flags (s, SEC_READONLY | SEC_DATA);
+ frag_now_fix ();
+ p = frag_more (size);
+ bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
+
+ subsegs_finish_section (s);
+ relax_segment (seg_info (s)->frchainP->frch_root, s, 0);
+ size_seg (stdoutput, s, NULL);
+}
+
+/* Create a relocation against an entry in a GNU Build attribute section. */
+
+static void
+create_note_reloc (segT sec,
+ symbolS * sym,
+ bfd_size_type note_offset,
+ bfd_size_type desc2_offset,
+ offsetT desc2_size,
+ int reloc_type,
+ bfd_vma addend,
+ char * note)
+{
+ struct reloc_list * reloc;
+
+ reloc = XNEW (struct reloc_list);
+
+ /* We create a .b type reloc as resolve_reloc_expr_symbols() has already been called. */
+ reloc->u.b.sec = sec;
+ reloc->u.b.s = symbol_get_bfdsym (sym);
+ reloc->u.b.r.sym_ptr_ptr = & reloc->u.b.s;
+ reloc->u.b.r.address = note_offset + desc2_offset;
+ reloc->u.b.r.addend = addend;
+ reloc->u.b.r.howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
+
+ if (reloc->u.b.r.howto == NULL)
{
- name = get_elf_backend_data (stdoutput)->obj_attrs_section;
- if (!name)
- name = ".gnu.attributes";
- s = subseg_new (name, 0);
- elf_section_type (s)
- = get_elf_backend_data (stdoutput)->obj_attrs_section_type;
- bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
- frag_now_fix ();
- p = frag_more (size);
- bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
-
- subsegs_finish_section (s);
- relax_segment (seg_info (s)->frchainP->frch_root, s, 0);
- size_seg (stdoutput, s, NULL);
+ as_bad (_("unable to create reloc for build note"));
+ return;
+ }
+
+ reloc->file = N_("<gnu build note>");
+ reloc->line = 0;
+
+ reloc->next = reloc_list;
+ reloc_list = reloc;
+
+ /* For REL relocs, store the addend in the section. */
+ if (! sec->use_rela_p
+ /* The SH target is a special case that uses RELA relocs
+ but still stores the addend in the word being relocated. */
+ || strstr (bfd_get_target (stdoutput), "-sh") != NULL)
+ {
+ offsetT i;
+
+ /* Zero out the addend, since it is now stored in the note. */
+ reloc->u.b.r.addend = 0;
+
+ if (target_big_endian)
+ {
+ for (i = desc2_size; addend != 0 && i > 0; addend >>= 8, i--)
+ note[desc2_offset + i - 1] = (addend & 0xff);
+ }
+ else
+ {
+ for (i = 0; addend != 0 && i < desc2_size; addend >>= 8, i++)
+ note[desc2_offset + i] = (addend & 0xff);
+ }
}
}
-#endif
+
+static void
+maybe_generate_build_notes (void)
+{
+ segT sec;
+ char * note;
+ offsetT note_size;
+ offsetT total_size;
+ offsetT desc_size;
+ offsetT desc2_offset;
+ int desc_reloc;
+ symbolS * sym;
+ asymbol * bsym;
+
+ if (! flag_generate_build_notes
+ || bfd_get_section_by_name (stdoutput,
+ GNU_BUILD_ATTRS_SECTION_NAME) != NULL)
+ return;
+
+ /* Create a GNU Build Attribute section. */
+ sec = subseg_new (GNU_BUILD_ATTRS_SECTION_NAME, false);
+ elf_section_type (sec) = SHT_NOTE;
+ bfd_set_section_flags (sec, (SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA
+ | SEC_OCTETS));
+ bfd_set_section_alignment (sec, 2);
+
+ /* Work out the size of the notes that we will create,
+ and the relocation we should use. */
+ if (bfd_arch_bits_per_address (stdoutput) <= 32)
+ {
+ note_size = 28;
+ desc_size = 8; /* Two 4-byte offsets. */
+ desc2_offset = 24;
+
+ /* FIXME: The BFD backend for the CRX target does not support the
+ BFD_RELOC_32, even though it really should. Likewise for the
+ CR16 target. So we have special case code here... */
+ if (strstr (bfd_get_target (stdoutput), "-crx") != NULL)
+ desc_reloc = BFD_RELOC_CRX_NUM32;
+ else if (strstr (bfd_get_target (stdoutput), "-cr16") != NULL)
+ desc_reloc = BFD_RELOC_CR16_NUM32;
+ else
+ desc_reloc = BFD_RELOC_32;
+ }
+ else
+ {
+ note_size = 36;
+ desc_size = 16; /* Two 8-byte offsets. */
+ desc2_offset = 28;
+ /* FIXME: The BFD backend for the IA64 target does not support the
+ BFD_RELOC_64, even though it really should. The HPPA backend
+ has a similar issue, although it does not support BFD_RELOCs at
+ all! So we have special case code to handle these targets. */
+ if (strstr (bfd_get_target (stdoutput), "-ia64") != NULL)
+ desc_reloc = target_big_endian ? BFD_RELOC_IA64_DIR32MSB : BFD_RELOC_IA64_DIR32LSB;
+ else if (strstr (bfd_get_target (stdoutput), "-hppa") != NULL)
+ desc_reloc = 80; /* R_PARISC_DIR64. */
+ else
+ desc_reloc = BFD_RELOC_64;
+ }
+
+ /* We have to create a note for *each* code section.
+ Linker garbage collection might discard some. */
+ total_size = 0;
+ note = NULL;
+
+ for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+ if ((bsym = symbol_get_bfdsym (sym)) != NULL
+ && bsym->flags & BSF_SECTION_SYM
+ && bsym->section != NULL
+ /* Skip linkonce sections - we cannot use these section symbols as they may disappear. */
+ && (bsym->section->flags & (SEC_CODE | SEC_LINK_ONCE)) == SEC_CODE
+ /* Not all linkonce sections are flagged... */
+ && !startswith (S_GET_NAME (sym), ".gnu.linkonce"))
+ {
+ /* Create a version note. */
+ frag_now_fix ();
+ note = frag_more (note_size);
+ memset (note, 0, note_size);
+
+ if (target_big_endian)
+ {
+ note[3] = 8; /* strlen (name) + 1. */
+ note[7] = desc_size; /* Two N-byte offsets. */
+ note[10] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
+ note[11] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
+ }
+ else
+ {
+ note[0] = 8; /* strlen (name) + 1. */
+ note[4] = desc_size; /* Two N-byte offsets. */
+ note[8] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
+ note[9] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
+ }
+
+ /* The a1 version number indicates that this note was
+ generated by the assembler and not the gcc annobin plugin. */
+ memcpy (note + 12, "GA$\ 13a1", 8);
+
+ /* Create a relocation to install the start address of the note... */
+ create_note_reloc (sec, sym, total_size, 20, desc_size / 2, desc_reloc, 0, note);
+
+ /* ...and another one to install the end address. */
+ create_note_reloc (sec, sym, total_size, desc2_offset,
+ desc_size / 2,
+ desc_reloc,
+ bfd_section_size (bsym->section),
+ note);
+
+ /* Mark the section symbol used in relocation so that it will be
+ included in the symbol table. */
+ symbol_mark_used_in_reloc (sym);
+
+ total_size += note_size;
+ /* FIXME: Maybe add a note recording the assembler command line and version ? */
+ }
+
+ /* Install the note(s) into the section. */
+ if (total_size)
+ bfd_set_section_contents (stdoutput, sec, (bfd_byte *) note, 0, total_size);
+ subsegs_finish_section (sec);
+ relax_segment (seg_info (sec)->frchainP->frch_root, sec, 0);
+ size_seg (stdoutput, sec, NULL);
+}
+#endif /* OBJ_ELF */
/* Write the object file. */
resolve_local_symbol_values ();
resolve_reloc_expr_symbols ();
- PROGRESS (1);
+#ifdef OBJ_ELF
+ if (IS_ELF)
+ maybe_generate_build_notes ();
+#endif
#ifdef tc_frob_file_before_adjust
tc_frob_file_before_adjust ();
if (symbol_rootP)
{
symbolS *symp;
- bfd_boolean skip_next_symbol = FALSE;
+ bool skip_next_symbol = false;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
{
/* Don't do anything besides moving the value of the
symbol from the GAS value-field to the BFD value-field. */
symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
- skip_next_symbol = FALSE;
+ skip_next_symbol = false;
continue;
}
if (S_IS_COMMON (symp)
&& !TC_FAKE_LABEL (sname)
- && !S_IS_WEAKREFR (symp)
- && (!S_IS_EXTERNAL (symp) || S_IS_LOCAL (symp)))
+ && !S_IS_WEAKREFR (symp))
{
expressionS *e = symbol_get_value_expression (symp);
- as_bad (_("Local symbol `%s' can't be equated to common symbol `%s'"),
+ as_bad (_("`%s' can't be equated to common symbol `%s'"),
sname, S_GET_NAME (e->X_add_symbol));
}
if (S_GET_SEGMENT (symp) == reg_section)
symbol warned about. Don't let anything object-format or
target-specific muck with it; it's ready for output. */
if (symbol_get_bfdsym (symp)->flags & BSF_WARNING)
- skip_next_symbol = TRUE;
+ skip_next_symbol = true;
}
}
- PROGRESS (1);
-
/* Now do any format-specific adjustments to the symbol table, such
as adding file symbols. */
#ifdef tc_adjust_symtab
#endif
/* Stop if there is an error. */
- if (had_errors ())
+ if (!flag_always_generate_output && had_errors ())
return;
/* Now that all the sizes are known, and contents correct, we can
#ifdef obj_coff_generate_pdata
obj_coff_generate_pdata ();
#endif
+
bfd_map_over_sections (stdoutput, write_relocs, (char *) 0);
#ifdef tc_frob_file_after_relocs
contents of the debug sections. This needs to be done before
we start writing any sections, because it will affect the file
layout, which is fixed once we start writing contents. */
- if (flag_compress_debug)
+ if (flag_compress_debug != COMPRESS_DEBUG_NONE)
{
+ flagword flags = BFD_COMPRESS;
if (flag_compress_debug == COMPRESS_DEBUG_GABI_ZLIB)
- stdoutput->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI;
- else
- stdoutput->flags |= BFD_COMPRESS;
- bfd_map_over_sections (stdoutput, compress_debug, (char *) 0);
+ flags = BFD_COMPRESS | BFD_COMPRESS_GABI;
+ else if (flag_compress_debug == COMPRESS_DEBUG_ZSTD)
+ flags = BFD_COMPRESS | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD;
+ stdoutput->flags |= flags & bfd_applicable_file_flags (stdoutput);
+ if ((stdoutput->flags & BFD_COMPRESS) != 0)
+ bfd_map_over_sections (stdoutput, compress_debug, (char *) 0);
}
bfd_map_over_sections (stdoutput, write_contents, (char *) 0);
}
#ifdef TC_GENERIC_RELAX_TABLE
+#ifndef md_generic_table_relax_frag
+#define md_generic_table_relax_frag relax_frag
+#endif
+
/* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE. */
long
const relax_typeS *table;
target = fragP->fr_offset;
- address = fragP->fr_address;
+ address = fragP->fr_address + fragP->fr_fix;
table = TC_GENERIC_RELAX_TABLE;
this_state = fragP->fr_subtype;
start_type = this_type = table + this_state;
negative. Don't allow this in case the negative reach is
large enough to require a larger branch instruction. */
else if (target < address)
- target = fragP->fr_next->fr_address + stretch;
+ return 0;
}
}
- aim = target - address - fragP->fr_fix;
+ aim = target - address;
#ifdef TC_PCREL_ADJUST
- /* Currently only the ns32k family needs this. */
+ /* Currently only the ns32k and arc needs this. */
aim += TC_PCREL_ADJUST (fragP);
#endif
if (offset % fragP->fr_var != 0)
{
as_bad_where (fragP->fr_file, fragP->fr_line,
- _("alignment padding (%lu bytes) not a multiple of %ld"),
+ ngettext ("alignment padding (%lu byte) "
+ "not a multiple of %ld",
+ "alignment padding (%lu bytes) "
+ "not a multiple of %ld",
+ (unsigned long) offset),
(unsigned long) offset, (long) fragP->fr_var);
offset -= (offset % fragP->fr_var);
}
break;
case rs_space:
+ case rs_space_nop:
break;
case rs_machine_dependent:
address += dwarf2dbg_estimate_size_before_relax (fragP);
break;
+ case rs_sframe:
+ /* Initial estimate can be set to atleast 1 byte. */
+ address += sframe_estimate_size_before_relax (fragP);
+ break;
+
default:
BAD_CASE (fragP->fr_type);
break;
if (flag_warn_displacement)
{
char buf[50];
- sprint_value (buf, (addressT) lie->addnum);
+
+ bfd_sprintf_vma (stdoutput, buf,
+ (addressT) lie->addnum);
as_warn_where (fragP->fr_file, fragP->fr_line,
_(".word %s-%s+%s didn't fit"),
S_GET_NAME (lie->add),
case rs_org:
{
- addressT target = offset;
+ offsetT target = offset;
addressT after;
if (symbolP)
/* Growth may be negative, but variable part of frag
cannot have fewer than 0 chars. That is, we can't
.org backwards. */
- if (address + fragP->fr_fix > target)
+ if ((offsetT) (address + fragP->fr_fix) > target)
{
growth = 0;
break;
case rs_space:
+ case rs_space_nop:
growth = 0;
if (symbolP)
{
|| ! S_IS_DEFINED (symbolP))
{
as_bad_where (fragP->fr_file, fragP->fr_line,
- _(".space specifies non-absolute value"));
+ _(".space, .nops or .fill specifies non-absolute value"));
/* Prevent repeat of this error message. */
fragP->fr_symbol = 0;
}
}
as_warn_where (fragP->fr_file, fragP->fr_line,
- _(".space or .fill with negative value, ignored"));
+ _(".space, .nops or .fill with negative value, ignored"));
fragP->fr_symbol = 0;
}
else
#ifdef TC_GENERIC_RELAX_TABLE
/* The default way to relax a frag is to look through
TC_GENERIC_RELAX_TABLE. */
- growth = relax_frag (segment, fragP, stretch);
+ growth = md_generic_table_relax_frag (segment, fragP,
+ stretch);
#endif /* TC_GENERIC_RELAX_TABLE */
#endif
break;
growth = dwarf2dbg_relax_frag (fragP);
break;
+ case rs_sframe:
+ growth = sframe_relax_frag (fragP);
+ break;
+
default:
BAD_CASE (fragP->fr_type);
break;
print_fixup (fixS *fixp)
{
indent_level = 1;
- fprintf (stderr, "fix ");
- fprintf_vma (stderr, (bfd_vma)((bfd_hostptr_t) fixp));
- fprintf (stderr, " %s:%d",fixp->fx_file, fixp->fx_line);
+ fprintf (stderr, "fix %p %s:%d", fixp, fixp->fx_file, fixp->fx_line);
if (fixp->fx_pcrel)
fprintf (stderr, " pcrel");
if (fixp->fx_pcrel_adjust)
fprintf (stderr, " pcrel_adjust=%d", fixp->fx_pcrel_adjust);
- if (fixp->fx_im_disp)
- {
-#ifdef TC_NS32K
- fprintf (stderr, " im_disp=%d", fixp->fx_im_disp);
-#else
- fprintf (stderr, " im_disp");
-#endif
- }
if (fixp->fx_tcbit)
fprintf (stderr, " tcbit");
if (fixp->fx_done)
fprintf (stderr, " done");
- fprintf (stderr, "\n size=%d frag=", fixp->fx_size);
- fprintf_vma (stderr, (bfd_vma) ((bfd_hostptr_t) fixp->fx_frag));
- fprintf (stderr, " where=%ld offset=%lx addnumber=%lx",
- (long) fixp->fx_where,
- (unsigned long) fixp->fx_offset,
- (unsigned long) fixp->fx_addnumber);
+ fprintf (stderr, "\n size=%d frag=%p", fixp->fx_size, fixp->fx_frag);
+ fprintf (stderr, " where=%ld offset=%" PRIx64 " addnumber=%" PRIx64,
+ fixp->fx_where, (uint64_t) fixp->fx_offset,
+ (uint64_t) fixp->fx_addnumber);
fprintf (stderr, "\n %s (%d)", bfd_get_reloc_code_name (fixp->fx_r_type),
fixp->fx_r_type);
if (fixp->fx_addsy)