/* write.c - emit .o file
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 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
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
}
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
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. */
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);
for (; fixP; fixP = fixP->fx_next)
{
+ segT add_symbol_segment = absolute_section;
+
#ifdef DEBUG5
fprintf (stderr, "\nprocessing fixup:\n");
print_fixup (fixP);
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)
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,
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
return;
section_name = bfd_section_name (sec);
- if (strncmp (section_name, ".debug_", 7) != 0)
+ if (!startswith (section_name, ".debug_"))
return;
strm = compress_init ();
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;
return;
/* Create a GNU Build Attribute section. */
- sec = subseg_new (GNU_BUILD_ATTRS_SECTION_NAME, FALSE);
+ 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));
/* 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... */
- && strncmp (S_GET_NAME (sym), ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) != 0)
+ && !startswith (S_GET_NAME (sym), ".gnu.linkonce"))
{
/* Create a version note. */
frag_now_fix ();
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 ? */
}
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;
}
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;
}
}
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),
{
indent_level = 1;
fprintf (stderr, "fix ");
- fprintf_vma (stderr, (bfd_vma)((bfd_hostptr_t) fixp));
+ fprintf_vma (stderr, (bfd_vma) (uintptr_t) fixp);
fprintf (stderr, " %s:%d",fixp->fx_file, fixp->fx_line);
if (fixp->fx_pcrel)
fprintf (stderr, " pcrel");
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_vma (stderr, (bfd_vma) (uintptr_t) fixp->fx_frag);
fprintf (stderr, " where=%ld offset=%lx addnumber=%lx",
(long) fixp->fx_where,
(unsigned long) fixp->fx_offset,