#include "filenames.h"
#include "fnmatch.h"
#include "elf-bfd.h"
-#include "libbfd.h"
#include "coff/internal.h"
#include "libcoff.h"
#define SECTION_CONTEXT_SET_LMA (1 << 4) /* Set the sections' LMA address. */
#define SECTION_CONTEXT_ALTER_LMA (1 << 5) /* Increment or decrement the section's LMA address. */
#define SECTION_CONTEXT_SET_FLAGS (1 << 6) /* Set the section's flags. */
+#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 7) /* Remove relocations for this section. */
bfd_vma vma_val; /* Amount to change by or set to. */
bfd_vma lma_val; /* Amount to change by or set to. */
} do_debug_sections = nothing;
/* Whether to generate ELF common symbols with the STT_COMMON type. */
-static enum bfd_link_discard do_elf_stt_common = unchanged;
+static enum bfd_link_elf_stt_common do_elf_stt_common = unchanged;
/* Whether to change the leading character in symbol names. */
static bfd_boolean change_leading_char = FALSE;
OPTION_REDEFINE_SYM,
OPTION_REDEFINE_SYMS,
OPTION_REMOVE_LEADING_CHAR,
+ OPTION_REMOVE_RELOCS,
OPTION_RENAME_SECTION,
OPTION_REVERSE_BYTES,
OPTION_SECTION_ALIGNMENT,
{"output-target", required_argument, 0, 'O'},
{"preserve-dates", no_argument, 0, 'p'},
{"remove-section", required_argument, 0, 'R'},
+ {"remove-relocations", required_argument, 0, OPTION_REMOVE_RELOCS},
{"strip-all", no_argument, 0, 's'},
{"strip-debug", no_argument, 0, 'S'},
{"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
{"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
{"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
{"remove-section", required_argument, 0, 'R'},
+ {"remove-relocations", required_argument, 0, OPTION_REMOVE_RELOCS},
{"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
{"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
{"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
static const char *lookup_sym_redefinition (const char *);
+static const char *find_section_rename (const char *, flagword *);
\f
-static void
+ATTRIBUTE_NORETURN static void
copy_usage (FILE *stream, int exit_status)
{
fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
-j --only-section <name> Only copy section <name> into the output\n\
--add-gnu-debuglink=<file> Add section .gnu_debuglink linking to <file>\n\
-R --remove-section <name> Remove section <name> from the output\n\
+ --remove-relocations <name> Remove relocations from section <name>\n\
-S --strip-all Remove all symbol and relocation information\n\
-g --strip-debug Remove all debugging symbols & sections\n\
--strip-dwo Remove all DWO sections\n\
exit (exit_status);
}
-static void
+ATTRIBUTE_NORETURN static void
strip_usage (FILE *stream, int exit_status)
{
fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name);
Disable -D behavior (default)\n"));
fprintf (stream, _("\
-R --remove-section=<name> Also remove section <name> from the output\n\
+ --remove-relocations <name> Remove relocations from section <name>\n\
-s --strip-all Remove all symbol and relocation information\n\
-g -S -d --strip-debug Remove all debugging symbols & sections\n\
--strip-dwo Remove all DWO sections\n\
static struct section_list *
find_section_list (const char *name, bfd_boolean add, unsigned int context)
{
- struct section_list *p;
+ struct section_list *p, *match = NULL;
/* assert ((context & ((1 << 7) - 1)) != 0); */
}
/* If we are not adding a new name/pattern then
only check for a match if the context applies. */
- else if ((p->context & context)
- /* We could check for the presence of wildchar characters
- first and choose between calling strcmp and fnmatch,
- but is that really worth it ? */
- && fnmatch (p->pattern, name, 0) == 0)
- {
- p->used = TRUE;
- return p;
- }
+ else if (p->context & context)
+ {
+ /* We could check for the presence of wildchar characters
+ first and choose between calling strcmp and fnmatch,
+ but is that really worth it ? */
+ if (p->pattern [0] == '!')
+ {
+ if (fnmatch (p->pattern + 1, name, 0) == 0)
+ {
+ p->used = TRUE;
+ return NULL;
+ }
+ }
+ else
+ {
+ if (fnmatch (p->pattern, name, 0) == 0)
+ {
+ if (match == NULL)
+ match = p;
+ }
+ }
+ }
}
if (! add)
- return NULL;
+ {
+ if (match != NULL)
+ match->used = TRUE;
+ return match;
+ }
p = (struct section_list *) xmalloc (sizeof (struct section_list));
p->pattern = name;
to[dst_count++] = create_new_symbol (ptr, obfd);
}
- if (redefine_sym_list)
+ if (redefine_sym_list || section_rename_list)
{
- char *old_name, *new_name;
+ char *new_name;
- old_name = (char *) bfd_asymbol_name (sym);
- new_name = (char *) lookup_sym_redefinition (old_name);
+ new_name = (char *) lookup_sym_redefinition (name);
+ if (new_name == name
+ && (flags & BSF_SECTION_SYM) != 0)
+ new_name = (char *) find_section_rename (name, NULL);
bfd_asymbol_name (sym) = new_name;
name = new_name;
}
free (buf);
}
-/* Copy unkown object file IBFD onto OBFD.
+/* Copy unknown object file IBFD onto OBFD.
Returns TRUE upon success, FALSE otherwise. */
static bfd_boolean
|| change_leading_char
|| remove_leading_char
|| redefine_sym_list
+ || section_rename_list
|| weaken
|| add_symbols)
{
}
/* Check the section rename list for a new name of the input section
- ISECTION. Return the new name if one is found.
- Also set RETURNED_FLAGS to the flags to be used for this section. */
+ called OLD_NAME. Returns the new name if one is found and sets
+ RETURNED_FLAGS if non-NULL to the flags to be used for this section. */
static const char *
-find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
- flagword * returned_flags)
+find_section_rename (const char *old_name, flagword *returned_flags)
{
- const char * old_name = bfd_section_name (ibfd, isection);
- section_rename * srename;
-
- /* Default to using the flags of the input section. */
- * returned_flags = bfd_get_section_flags (ibfd, isection);
+ const section_rename *srename;
for (srename = section_rename_list; srename != NULL; srename = srename->next)
if (strcmp (srename->old_name, old_name) == 0)
{
- if (srename->flags != (flagword) -1)
- * returned_flags = srename->flags;
+ if (returned_flags != NULL && srename->flags != (flagword) -1)
+ *returned_flags = srename->flags;
return srename->new_name;
}
return;
/* Get the, possibly new, name of the output section. */
- name = find_section_rename (ibfd, isection, & flags);
+ name = bfd_section_name (ibfd, isection);
+ flags = bfd_get_section_flags (ibfd, isection);
+ name = find_section_rename (name, &flags);
/* Prefix sections. */
if ((prefix_alloc_sections_string)
return FALSE;
}
+/* Add section SECTION_PATTERN to the list of sections that will have their
+ relocations removed. */
+
+static void
+handle_remove_relocations_option (const char *section_pattern)
+{
+ find_section_list (section_pattern, TRUE, SECTION_CONTEXT_REMOVE_RELOCS);
+}
+
+/* Return TRUE if ISECTION from IBFD should have its relocations removed,
+ otherwise return FALSE. If the user has requested that relocations be
+ removed from a section that does not have relocations then this
+ function will still return TRUE. */
+
+static bfd_boolean
+discard_relocations (bfd *ibfd ATTRIBUTE_UNUSED, asection *isection)
+{
+ return (find_section_list (bfd_section_name (ibfd, isection), FALSE,
+ SECTION_CONTEXT_REMOVE_RELOCS) != NULL);
+}
+
+/* Wrapper for dealing with --remove-section (-R) command line arguments.
+ A special case is detected here, if the user asks to remove a relocation
+ section (one starting with ".rela." or ".rel.") then this removal must
+ be done using a different technique. */
+
+static void
+handle_remove_section_option (const char *section_pattern)
+{
+ if (strncmp (section_pattern, ".rela.", 6) == 0)
+ handle_remove_relocations_option (section_pattern + 5);
+ else if (strncmp (section_pattern, ".rel.", 5) == 0)
+ handle_remove_relocations_option (section_pattern + 4);
+ else
+ {
+ find_section_list (section_pattern, TRUE, SECTION_CONTEXT_REMOVE);
+ sections_removed = TRUE;
+ }
+}
+
/* Copy relocations in input section ISECTION of IBFD to an output
section with the same name in OBFDARG. If stripping then don't
copy any relocation info. */
osection = isection->output_section;
/* Core files and DWO files do not need to be relocated. */
- if (bfd_get_format (obfd) == bfd_core || strip_symbols == STRIP_NONDWO)
+ if (bfd_get_format (obfd) == bfd_core
+ || strip_symbols == STRIP_NONDWO
+ || discard_relocations (ibfd, isection))
relsize = 0;
else
{
{
status = 1;
bfd_nonfatal_message (NULL, ibfd, isection, NULL);
+ free (memhunk);
return;
}
{
status = 1;
bfd_nonfatal_message (NULL, obfd, osection, NULL);
+ free (memhunk);
return;
}
free (memhunk);
{
status = 1;
bfd_nonfatal_message (NULL, obfd, osection, NULL);
+ free (memhunk);
return;
}
free (memhunk);
special bfd section symbols, then mark it with BSF_KEEP. */
for (i = 0; i < relcount; i++)
{
- if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
+ /* See PRs 20923 and 20930 for reproducers for the NULL tests. */
+ if (relpp[i]->sym_ptr_ptr != NULL
+ && * relpp[i]->sym_ptr_ptr != NULL
+ && *relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
&& *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
&& *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
(*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
input_target = output_target = optarg;
break;
case 'R':
- find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE);
- sections_removed = TRUE;
+ handle_remove_section_option (optarg);
+ break;
+ case OPTION_REMOVE_RELOCS:
+ handle_remove_relocations_option (optarg);
break;
case 's':
strip_symbols = STRIP_ALL;
break;
case 'R':
- find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE);
- sections_removed = TRUE;
+ handle_remove_section_option (optarg);
+ break;
+
+ case OPTION_REMOVE_RELOCS:
+ handle_remove_relocations_option (optarg);
break;
case 'S':
{
case OPTION_CHANGE_SECTION_ADDRESS:
p->vma_val = val;
- /* Drop through. */
+ /* Fall through. */
case OPTION_CHANGE_SECTION_LMA:
p->lma_val = val;