/* objcopy.c -- copy object file from input to output, optionally massaging it.
- Copyright (C) 1991-2019 Free Software Foundation, Inc.
+ Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of GNU Binutils.
long symval;
flagword flags;
char * section;
- char * othersym;
+ const char * othersym;
};
typedef struct section_rename
PARSE_FLAG ("code", SEC_CODE);
PARSE_FLAG ("data", SEC_DATA);
PARSE_FLAG ("rom", SEC_ROM);
+ PARSE_FLAG ("exclude", SEC_EXCLUDE);
PARSE_FLAG ("share", SEC_COFF_SHARED);
PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
PARSE_FLAG ("merge", SEC_MERGE);
copy[len] = '\0';
non_fatal (_("unrecognized section flag `%s'"), copy);
fatal (_("supported flags: %s"),
- "alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings");
+ "alloc, load, noload, readonly, debug, code, data, rom, exclude, share, contents, merge, strings");
}
s = snext;
string can't be parsed. */
static flagword
-parse_symflags (const char *s, char **other)
+parse_symflags (const char *s, const char **other)
{
flagword ret;
const char *snext;
static bfd_boolean
is_dwo_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
{
- const char *name = bfd_section_name (sec);
- int len = strlen (name);
+ const char *name;
+ int len;
+
+ if (sec == NULL || (name = bfd_section_name (sec)) == NULL)
+ return FALSE;
+
+ len = strlen (name);
+ if (len < 5)
+ return FALSE;
return strncmp (name + len - 4, ".dwo", 4) == 0;
}
is_nondebug_keep_contents_section (bfd *ibfd, asection *isection)
{
/* Always keep ELF note sections. */
- if (ibfd->xvec->flavour == bfd_target_elf_flavour)
- return (elf_section_type (isection) == SHT_NOTE);
+ if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
+ return elf_section_type (isection) == SHT_NOTE;
/* Always keep the .buildid section for PE/COFF.
Strictly, this should be written "always keep the section storing the debug
directory", but that may be the .text section for objects produced by some
tools, which it is not sensible to keep. */
- if (ibfd->xvec->flavour == bfd_target_coff_flavour)
- return (strcmp (bfd_section_name (isection), ".buildid") == 0);
+ if (bfd_get_flavour (ibfd) == bfd_target_coff_flavour)
+ return strcmp (bfd_section_name (isection), ".buildid") == 0;
return FALSE;
}
{
elf_symbol_type *elf_sym;
- elf_sym = elf_symbol_from (sym->the_bfd, sym);
+ elf_sym = elf_symbol_from (sym);
if (elf_sym != NULL)
switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
{
return FALSE;
}
+/* Empty name is hopefully never a valid symbol name. */
+static const char * empty_name = "";
+
static bfd_boolean
need_sym_before (struct addsym_node **node, const char *sym)
{
{
if (!ptr->othersym)
break;
+ if (ptr->othersym == empty_name)
+ continue;
else if (strcmp (ptr->othersym, sym) == 0)
{
- free (ptr->othersym);
- ptr->othersym = ""; /* Empty name is hopefully never a valid symbol name. */
+ free ((char *) ptr->othersym);
+ ptr->othersym = empty_name;
*node = ptr;
return TRUE;
}
/* Check if we will remove the current leading character. */
rem_leading_char =
- (name[0] == bfd_get_symbol_leading_char (abfd))
- && (change_leading_char
- || (remove_leading_char
- && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
- || undefined
- || bfd_is_com_section (bfd_asymbol_section (sym)))));
+ (name[0] != '\0'
+ && name[0] == bfd_get_symbol_leading_char (abfd)
+ && (change_leading_char
+ || (remove_leading_char
+ && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || undefined
+ || bfd_is_com_section (bfd_asymbol_section (sym))))));
/* Check if we will add a new leading character. */
add_leading_char =
if (add_leading_char || prefix_symbols_string)
{
char *n, *ptr;
+ size_t len = strlen (name) + 1;
+
+ if (add_leading_char)
+ len++;
+ if (prefix_symbols_string)
+ len += strlen (prefix_symbols_string);
- ptr = n = (char *) xmalloc (1 + strlen (prefix_symbols_string)
- + strlen (name) + 1);
+ ptr = n = (char *) xmalloc (len);
if (add_leading_char)
*ptr++ = bfd_get_symbol_leading_char (obfd);
{
if (ptr->othersym)
{
- if (strcmp (ptr->othersym, ""))
+ if (ptr->othersym != empty_name)
fatal (_("'before=%s' not found"), ptr->othersym);
}
else
bfd_vma start;
bfd_vma end;
} objcopy_internal_note;
-
+
#define DEBUG_MERGE 0
#if DEBUG_MERGE
pnote1->note.namesz - 3 : pnote2->note.namesz - 3);
if (cmp)
return cmp;
-
+
if (pnote1->end < pnote2->start)
return -1;
if (pnote1->start > pnote2->end)
return -1;
if (pnote1->end > pnote2->end)
return 1;
-
+ if (pnote1->end < pnote2->end)
+ return -1;
+
/* Put OPEN notes before function notes. */
if (is_open_note (pnote1) && ! is_open_note (pnote2))
return -1;
if (! is_open_note (pnote1) && is_open_note (pnote2))
return 1;
-
+
return 0;
}
return 1; /* 1: F 2: O */
}
-
+
/* Sort by starting address. */
if (pnote1->start < pnote2->start)
return -1;
&& pnote2->note.namesz > 4
&& pnote1->note.namedata[3] != pnote2->note.namedata[3])
return pnote1->note.namedata[3] - pnote2->note.namedata[3];
-
+
return 0;
}
goto done;
}
}
-
+
/* Make a copy of the notes and convert to our internal format.
Minimum size of a note is 12 bytes. Also locate the version
notes and check them. */
address. */
end = (bfd_vma) -1;
break;
-
+
case 8:
if (! is_64bit (abfd))
{
start = bfd_get_64 (abfd, pnote->note.descdata);
end = bfd_get_64 (abfd, pnote->note.descdata + 8);
break;
-
+
default:
err = _("corrupt GNU build attribute note: bad description size");
goto done;
|| memcmp (back->note.namedata,
pnote->note.namedata, pnote->note.namesz) != 0)
break;
-
+
if (back->start == pnote->start
&& back->end == pnote->end)
{
if (! is_deleted_note (pnote))
merge_debug ("Unable to do anything with note at %#08lx\n",
(pnote->note.namedata - (char *) contents) - 12);
-#endif
+#endif
}
/* Resort the notes. */
bfd_vma prev_start = 0;
bfd_vma prev_end = 0;
- new = new_contents = xmalloc (size);
+ /* Not sure how, but the notes might grow in size.
+ (eg see PR 1774507). Allow for this here. */
+ new = new_contents = xmalloc (size * 2);
for (pnote = pnotes, old = contents;
pnote < pnotes_end;
pnote ++)
pnote->note.namesz
);
#endif
-
+
new_size = new - new_contents;
- memcpy (contents, new_contents, new_size);
- size = new_size;
+ if (new_size < size)
+ {
+ memcpy (contents, new_contents, new_size);
+ size = new_size;
+ }
free (new_contents);
done:
return size;
}
+static flagword
+check_new_section_flags (flagword flags, bfd * abfd, const char * secname)
+{
+ /* Only set the SEC_COFF_SHARED flag on COFF files.
+ The same bit value is used by ELF targets to indicate
+ compressed sections, and setting that flag here breaks
+ things. */
+ if ((flags & SEC_COFF_SHARED)
+ && bfd_get_flavour (abfd) != bfd_target_coff_flavour)
+ {
+ non_fatal (_("%s[%s]: Note - dropping 'share' flag as output format is not COFF"),
+ bfd_get_filename (abfd), secname);
+ flags &= ~ SEC_COFF_SHARED;
+ }
+ return flags;
+}
+
/* Copy object file IBFD onto OBFD.
Returns TRUE upon success, FALSE otherwise. */
void *dhandle;
enum bfd_architecture iarch;
unsigned int imach;
- unsigned int c, i;
+ unsigned int num_sec, i;
if (ibfd->xvec->byteorder != obfd->xvec->byteorder
&& ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
{
/* PR 17636: Call non-fatal so that we return to our parent who
may need to tidy temporary files. */
- non_fatal (_("Unable to change endianness of input file(s)"));
+ non_fatal (_("unable to change endianness of '%s'"),
+ bfd_get_archive_filename (ibfd));
+ return FALSE;
+ }
+
+ if (ibfd->read_only)
+ {
+ non_fatal (_("unable to modify '%s' due to errors"),
+ bfd_get_archive_filename (ibfd));
return FALSE;
}
return FALSE;
}
- if (ibfd->xvec->flavour != bfd_target_elf_flavour)
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
{
if ((do_debug_sections & compress) != 0
&& do_debug_sections != compress)
imach = bfd_get_mach (ibfd);
if (input_arch)
{
- if (bfd_get_arch_info (ibfd) == NULL
- || bfd_get_arch_info (ibfd)->arch == bfd_arch_unknown)
+ if (iarch == bfd_arch_unknown)
{
iarch = input_arch->arch;
imach = input_arch->mach;
non_fatal (_("Input file `%s' ignores binary architecture parameter."),
bfd_get_archive_filename (ibfd));
}
+ if (iarch == bfd_arch_unknown
+ && bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ && bfd_get_flavour (obfd) == bfd_target_elf_flavour)
+ {
+ const struct elf_backend_data *bed = get_elf_backend_data (obfd);
+ iarch = bed->arch;
+ imach = 0;
+ }
if (!bfd_set_arch_mach (obfd, iarch, imach)
&& (ibfd->target_defaulted
|| bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
pe_data_type *pe = pe_data (obfd);
/* Copy PE parameters before changing them. */
- if (ibfd->xvec->flavour == bfd_target_coff_flavour
+ if (bfd_get_flavour (ibfd) == bfd_target_coff_flavour
&& bfd_pei_p (ibfd))
pe->pe_opthdr = pe_data (ibfd)->pe_opthdr;
file_alignment, section_alignment);
}
+
+ if (preserve_dates
+ && bfd_get_flavour (ibfd) == bfd_target_coff_flavour
+ && bfd_pei_p (ibfd))
+ pe->timestamp = pe_data (ibfd)->coff.timestamp;
}
if (isympp)
pset = find_section_list (padd->name, FALSE,
SECTION_CONTEXT_SET_FLAGS);
if (pset != NULL)
- flags = pset->flags | SEC_HAS_CONTENTS;
+ {
+ flags = pset->flags | SEC_HAS_CONTENTS;
+ flags = check_new_section_flags (flags, obfd, padd->name);
+ }
else
flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
for (pdump = dump_sections; pdump != NULL; pdump = pdump->next)
{
+ FILE * f;
+ bfd_byte *contents;
+
osec = bfd_get_section_by_name (ibfd, pdump->name);
if (osec == NULL)
{
}
bfd_size_type size = bfd_section_size (osec);
- if (size == 0)
- {
- bfd_nonfatal_message (NULL, ibfd, osec,
- _("can't dump section - it is empty"));
- continue;
- }
+ /* Note - we allow the dumping of zero-sized sections,
+ creating an empty file. */
- FILE * f;
f = fopen (pdump->filename, FOPEN_WB);
if (f == NULL)
{
continue;
}
- bfd_byte *contents;
if (bfd_malloc_and_get_section (ibfd, osec, &contents))
{
- if (fwrite (contents, 1, size, f) != size)
+ if (size != 0 && fwrite (contents, 1, size, f) != size)
{
non_fatal (_("error writing section contents to %s (error: %s)"),
pdump->filename,
}
}
- c = bfd_count_sections (obfd);
- if (c != 0
+ num_sec = bfd_count_sections (obfd);
+ if (num_sec != 0
&& (gap_fill_set || pad_to_set))
{
asection **set;
increasing the section sizes as required to fill the gaps.
We write out the gap contents below. */
- osections = (asection **) xmalloc (c * sizeof (asection *));
+ osections = xmalloc (num_sec * sizeof (*osections));
set = osections;
bfd_map_over_sections (obfd, get_sections, &set);
- qsort (osections, c, sizeof (asection *), compare_section_lma);
+ qsort (osections, num_sec, sizeof (*osections), compare_section_lma);
- gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
- memset (gaps, 0, c * sizeof (bfd_size_type));
+ gaps = xmalloc (num_sec * sizeof (*gaps));
+ memset (gaps, 0, num_sec * sizeof (*gaps));
if (gap_fill_set)
{
- for (i = 0; i < c - 1; i++)
+ for (i = 0; i < num_sec - 1; i++)
{
flagword flags;
- bfd_size_type size;
- bfd_vma gap_start, gap_stop;
+ bfd_size_type size; /* Octets. */
+ bfd_vma gap_start, gap_stop; /* Octets. */
+ unsigned int opb1 = bfd_octets_per_byte (obfd, osections[i]);
+ unsigned int opb2 = bfd_octets_per_byte (obfd, osections[i+1]);
flags = bfd_section_flags (osections[i]);
if ((flags & SEC_HAS_CONTENTS) == 0
continue;
size = bfd_section_size (osections[i]);
- gap_start = bfd_section_lma (osections[i]) + size;
- gap_stop = bfd_section_lma (osections[i + 1]);
+ gap_start = bfd_section_lma (osections[i]) * opb1 + size;
+ gap_stop = bfd_section_lma (osections[i + 1]) * opb2;
if (gap_start < gap_stop)
{
if (!bfd_set_section_size (osections[i],
if (pad_to_set)
{
- bfd_vma lma;
- bfd_size_type size;
-
- lma = bfd_section_lma (osections[c - 1]);
- size = bfd_section_size (osections[c - 1]);
- if (lma + size < pad_to)
+ bfd_vma lma; /* Octets. */
+ bfd_size_type size; /* Octets. */
+ unsigned int opb = bfd_octets_per_byte (obfd, osections[num_sec - 1]);
+ bfd_vma _pad_to = pad_to * opb;
+
+ lma = bfd_section_lma (osections[num_sec - 1]) * opb;
+ size = bfd_section_size (osections[num_sec - 1]);
+ if (lma + size < _pad_to)
{
- if (!bfd_set_section_size (osections[c - 1], pad_to - lma))
+ if (!bfd_set_section_size (osections[num_sec - 1], _pad_to - lma))
{
- bfd_nonfatal_message (NULL, obfd, osections[c - 1],
+ bfd_nonfatal_message (NULL, obfd, osections[num_sec - 1],
_("can't add padding"));
status = 1;
}
else
{
- gaps[c - 1] = pad_to - (lma + size);
- if (max_gap < pad_to - (lma + size))
- max_gap = pad_to - (lma + size);
+ gaps[num_sec - 1] = _pad_to - (lma + size);
+ if (max_gap < _pad_to - (lma + size))
+ max_gap = _pad_to - (lma + size);
}
}
}
/* It is likely that output sections are in the same order
as the input sections, but do not assume that this is
the case. */
- if (strcmp (bfd_section_name (merged->sec),
- bfd_section_name (osec)) != 0)
+ if (merged->sec->output_section != osec)
{
for (merged = merged_note_sections;
merged != NULL;
merged = merged->next)
- if (strcmp (bfd_section_name (merged->sec),
- bfd_section_name (osec)) == 0)
+ if (merged->sec->output_section == osec)
break;
if (merged == NULL)
}
}
- if (gap_fill_set || pad_to_set)
+ if (gaps != NULL)
{
bfd_byte *buf;
buf = (bfd_byte *) xmalloc (max_gap);
memset (buf, gap_fill, max_gap);
- c = bfd_count_sections (obfd);
- for (i = 0; i < c; i++)
+ for (i = 0; i < num_sec; i++)
{
if (gaps[i] != 0)
{
status = 1;
return;
}
+
+ if (gnu_debuglink_filename != NULL)
+ {
+ non_fatal (_("--add-gnu-debuglink ignored for archive %s"),
+ bfd_get_filename (ibfd));
+ gnu_debuglink_filename = NULL;
+ }
+
/* This is a no-op on non-Coff targets. */
set_long_section_mode (obfd, ibfd, long_section_names);
flagword flags;
const char *err;
const char * name;
+ const char * new_name;
char *prefix = NULL;
bfd_boolean make_nobits;
unsigned int alignment;
/* Get the, possibly new, name of the output section. */
name = bfd_section_name (isection);
flags = bfd_section_flags (isection);
- name = find_section_rename (name, &flags);
+ if (bfd_get_flavour (ibfd) != bfd_get_flavour (obfd))
+ {
+ flags &= bfd_applicable_section_flags (ibfd);
+ flags &= bfd_applicable_section_flags (obfd);
+ }
+ new_name = find_section_rename (name, &flags);
+ if (new_name != name)
+ {
+ name = new_name;
+ flags = check_new_section_flags (flags, obfd, name);
+ }
/* Prefix sections. */
- if ((prefix_alloc_sections_string)
- && (bfd_section_flags (isection) & SEC_ALLOC))
+ if (prefix_alloc_sections_string
+ && (bfd_section_flags (isection) & SEC_ALLOC) != 0)
prefix = prefix_alloc_sections_string;
else if (prefix_sections_string)
prefix = prefix_sections_string;
p = find_section_list (bfd_section_name (isection), FALSE,
SECTION_CONTEXT_SET_FLAGS);
if (p != NULL)
- flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
+ {
+ flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
+ flags = check_new_section_flags (flags, obfd, bfd_section_name (isection));
+ }
else if (strip_symbols == STRIP_NONDEBUG
&& (flags & (SEC_ALLOC | SEC_GROUP)) != 0
&& !is_nondebug_keep_contents_section (ibfd, isection))
{
flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP);
- if (obfd->xvec->flavour == bfd_target_elf_flavour)
+ if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
{
make_nobits = TRUE;
alignment = p->alignment;
else
alignment = bfd_section_alignment (isection);
-
+
/* FIXME: This is probably not enough. If we change the LMA we
may have to recompute the header for the file as well. */
if (!bfd_set_section_alignment (osection, alignment))
if (gsym != NULL)
{
gsym->flags |= BSF_KEEP;
- if (ibfd->xvec->flavour == bfd_target_elf_flavour)
+ if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
elf_group_id (isection) = gsym;
}
}
status = 1;
bfd_nonfatal_message (NULL, ibfd, isection,
_("relocation count is negative"));
+ free (relpp);
return;
}
}
temp_relpp [temp_relcount++] = relpp [i];
}
relcount = temp_relcount;
- if (isection->orelocation == NULL)
+ if (relpp != isection->orelocation)
free (relpp);
relpp = temp_relpp;
}
if (relcount == 0)
{
osection->flags &= ~SEC_RELOC;
- free (relpp);
+ if (relpp != isection->orelocation)
+ free (relpp);
}
}
}
s = strchr (optarg, '=');
if (s == NULL)
fatal (_("bad format for --set-section-alignment: argument needed"));
-
+
align = atoi (s + 1);
if (align <= 0)
fatal (_("bad format for --set-section-alignment: numeric argument needed"));
align >>= 1;
++palign;
}
-
+
if (align != 1)
/* Number has more than on 1, i.e. wasn't a power of 2. */
fatal (_("bad format for --set-section-alignment: alignment is not a power of two"));
p->alignment = palign;
}
break;
-
+
case OPTION_RENAME_SECTION:
{
flagword flags;