#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. */
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 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;
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
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;