/* write.c - emit .o file
- Copyright (C) 1986-2021 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
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
dwarf2dbg_convert_frag (fragP);
break;
+ case rs_sframe:
+ sframe_convert_frag (fragP);
+ break;
+
case rs_machine_dependent:
md_convert_frag (stdoutput, sec, fragP);
if (size > 0 && ! seginfo->bss)
flags |= SEC_HAS_CONTENTS;
- flags &= ~SEC_RELOC;
x = bfd_set_section_flags (sec, flags);
gas_assert (x);
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
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)
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_section_flags (sec);
- flags |= SEC_RELOC;
- bfd_set_section_flags (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;
+ bfd_size_type uncompressed_size = sec->size;
flagword flags = bfd_section_flags (sec);
- unsigned int header_size, compression_header_size;
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_section_name (sec);
- if (!startswith (section_name, ".debug_"))
+ 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)
"can't extend frag %lu chars",
(unsigned long) header_size),
(unsigned long) header_size);
- last_newf = first_newf;
+ 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 (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);
+ char *compressed_name = bfd_debug_name_to_zdebug (abfd, section_name);
bfd_rename_section (sec, compressed_name);
}
}
bfd_get_filename (stdoutput),
bfd_errmsg (bfd_get_error ()));
offset += count;
- free (buf);
+#ifndef NO_LISTING
+ if (listing & LISTING_LISTING)
+ f->fr_opcode = buf;
+ else
+#endif
+ free (buf);
}
continue;
}
two. Generate unused section symbols only if needed. */
nsyms = 0;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
- if (bfd_keep_unused_section_symbols (stdoutput)
- || !symbol_section_p (symp)
- || symbol_used_in_reloc_p (symp))
+ 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; symp = symbol_next (symp))
- if (bfd_keep_unused_section_symbols (stdoutput)
- || !symbol_section_p (symp)
- || symbol_used_in_reloc_p (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
maybe_generate_build_notes ();
#endif
- PROGRESS (1);
-
#ifdef tc_frob_file_before_adjust
tc_frob_file_before_adjust ();
#endif
}
}
- PROGRESS (1);
-
/* Now do any format-specific adjustments to the symbol table, such
as adding file symbols. */
#ifdef tc_adjust_symtab
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);
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;
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, " 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)