Add an option to objcopy that creates padding sections that eliminate gaps between segments.
Resolves: RHEL-60807
This commit is contained in:
parent
ba8d9ed4da
commit
b754f74df9
253
binutils-rhivos-segment-gap.patch
Normal file
253
binutils-rhivos-segment-gap.patch
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
diff -rup binutils-2.41/binutils/doc/binutils.texi /home/nickc/binutils-2.41/binutils/doc/binutils.texi
|
||||||
|
--- binutils-2.41/binutils/doc/binutils.texi 2025-01-21 13:16:01.970763573 +0000
|
||||||
|
+++ /home/nickc/binutils-2.41/binutils/doc/binutils.texi 2025-01-21 12:22:23.561279546 +0000
|
||||||
|
@@ -1285,6 +1285,7 @@ objcopy [@option{-F} @var{bfdname}|@opti
|
||||||
|
[@option{--debugging}]
|
||||||
|
[@option{--gap-fill=}@var{val}]
|
||||||
|
[@option{--pad-to=}@var{address}]
|
||||||
|
+ [@option{--add-segment-padding-sections}]
|
||||||
|
[@option{--set-start=}@var{val}]
|
||||||
|
[@option{--adjust-start=}@var{incr}]
|
||||||
|
[@option{--change-addresses=}@var{incr}]
|
||||||
|
@@ -1666,6 +1667,18 @@ Pad the output file up to the load addre
|
||||||
|
done by increasing the size of the last section. The extra space is
|
||||||
|
filled in with the value specified by @option{--gap-fill} (default zero).
|
||||||
|
|
||||||
|
+@item --add-segment-padding-sections
|
||||||
|
+Add empty sections that eliminate any gaps between loadable segments.
|
||||||
|
+This option only works with ELF format files that contains both
|
||||||
|
+sections and segments. The added sections will have the SHT_NOBITS
|
||||||
|
+type and permissions that match the segment that they are padding.
|
||||||
|
+The sections names will be of the form .segment.pad.<N> where <N> is
|
||||||
|
+the number of the load segment that is being padded.
|
||||||
|
+
|
||||||
|
+Note - this option should not be used in conjunction with any other
|
||||||
|
+option that adds or removes sections, or changes their size in any
|
||||||
|
+way.
|
||||||
|
+
|
||||||
|
@item --set-start @var{val}
|
||||||
|
Set the start address (also known as the entry address) of the new
|
||||||
|
file to @var{val}. Not all object file formats support setting the
|
||||||
|
--- /dev/null 2025-01-21 09:02:16.359001262 +0000
|
||||||
|
+++ binutils-2.41/binutils/testsuite/binutils-all/add-segment-padding-sections.d 2025-01-21 13:13:49.615269853 +0000
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+#PROG: objcopy
|
||||||
|
+#name: objcopy --add-segment-padding-sections
|
||||||
|
+#source: bintest.s
|
||||||
|
+#ld: -e 0 --defsym external_symbol=0
|
||||||
|
+#objcopy: --add-segment-padding-sections
|
||||||
|
+#readelf: -lW
|
||||||
|
+
|
||||||
|
+#...
|
||||||
|
+[ ]+LOAD[ ]+0x[0-9a-f]+[ ]+0x[0-9a-f]+[ ]+0x[0-9a-f]+[ ]+0x[0-9a-f]+[ ]+0x[0-9a-f]+000.*
|
||||||
|
+#pass
|
||||||
|
--- binutils.orig/binutils/testsuite/binutils-all/objcopy.exp 2025-01-23 10:46:24.867490584 +0000
|
||||||
|
+++ binutils-2.35.2/binutils/testsuite/binutils-all/objcopy.exp 2025-01-23 10:48:05.957176799 +0000
|
||||||
|
@@ -1356,3 +1356,7 @@ if { [istarget pdp11-*-*] } {
|
||||||
|
}
|
||||||
|
|
||||||
|
objcopy_test "pr25662" $src executable "" "-T$srcdir/$subdir/pr25662.ld"
|
||||||
|
+
|
||||||
|
+if [is_elf_format] {
|
||||||
|
+ run_dump_test "add-segment-padding-sections"
|
||||||
|
+}
|
||||||
|
--- binutils.orig/binutils/objcopy.c 2025-01-23 10:46:24.874490631 +0000
|
||||||
|
+++ binutils-2.35.2/binutils/objcopy.c 2025-01-23 10:54:02.220653906 +0000
|
||||||
|
@@ -242,6 +242,9 @@ static bfd_boolean change_leading_char =
|
||||||
|
/* Whether to remove the leading character from global symbol names. */
|
||||||
|
static bfd_boolean remove_leading_char = FALSE;
|
||||||
|
|
||||||
|
+/* If true add sections that pad loadable segments so that there are no gaps between them. */
|
||||||
|
+static bfd_boolean add_segment_padding_sections = FALSE;
|
||||||
|
+
|
||||||
|
/* Whether to permit wildcard in symbol comparison. */
|
||||||
|
static bfd_boolean wildcard = FALSE;
|
||||||
|
|
||||||
|
@@ -306,6 +309,7 @@ enum command_line_switch
|
||||||
|
{
|
||||||
|
OPTION_ADD_SECTION=150,
|
||||||
|
OPTION_ADD_GNU_DEBUGLINK,
|
||||||
|
+ OPTION_ADD_SEGMENT_PADDING_SECTIONS,
|
||||||
|
OPTION_ADD_SYMBOL,
|
||||||
|
OPTION_ALT_MACH_CODE,
|
||||||
|
OPTION_CHANGE_ADDRESSES,
|
||||||
|
@@ -417,6 +421,7 @@ static struct option copy_options[] =
|
||||||
|
{
|
||||||
|
{"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
|
||||||
|
{"add-section", required_argument, 0, OPTION_ADD_SECTION},
|
||||||
|
+ {"add-segment-padding-sections", no_argument, 0, OPTION_ADD_SEGMENT_PADDING_SECTIONS},
|
||||||
|
{"add-symbol", required_argument, 0, OPTION_ADD_SYMBOL},
|
||||||
|
{"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
|
||||||
|
{"adjust-start", required_argument, 0, OPTION_CHANGE_START},
|
||||||
|
@@ -610,6 +615,7 @@ copy_usage (FILE *stream, int exit_statu
|
||||||
|
-b --byte <num> Select byte <num> in every interleaved block\n\
|
||||||
|
--gap-fill <val> Fill gaps between sections with <val>\n\
|
||||||
|
--pad-to <addr> Pad the last section up to address <addr>\n\
|
||||||
|
+ --add-segment-padding-sections Add padding sections so that load segments do not have gaps\n\
|
||||||
|
--set-start <addr> Set the start address to <addr>\n\
|
||||||
|
{--change-start|--adjust-start} <incr>\n\
|
||||||
|
Add <incr> to the start address\n\
|
||||||
|
@@ -2569,6 +2575,142 @@ check_new_section_flags (flagword flags,
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bfd_boolean
|
||||||
|
+is_loadable_segment (const Elf_Internal_Phdr * phdr)
|
||||||
|
+{
|
||||||
|
+ return phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bfd_vma
|
||||||
|
+page_align_down (bfd_vma pagesize, bfd_vma addr)
|
||||||
|
+{
|
||||||
|
+ return addr & ~ (pagesize - 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+add_padding_sections (bfd *ibfd, bfd *obfd)
|
||||||
|
+{
|
||||||
|
+ if (obfd == NULL) /* Paranoia. */
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|
||||||
|
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
|
||||||
|
+ {
|
||||||
|
+ non_fatal (_("the --add-segment-padding-sections option only works with ELF format files\n"));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (add_sections != NULL || update_sections != NULL || gap_fill_set || pad_to_set)
|
||||||
|
+ {
|
||||||
|
+ non_fatal (_("the --add-segment-padding-sections option does not work with other paddding/modifying options\n"));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const struct elf_backend_data * bed = get_elf_backend_data (ibfd);
|
||||||
|
+ const struct elf_obj_tdata * tdata = elf_tdata (ibfd);
|
||||||
|
+ const Elf_Internal_Ehdr * ehdr = elf_elfheader (ibfd);
|
||||||
|
+
|
||||||
|
+ if (bed == NULL || tdata == NULL || ehdr == NULL)
|
||||||
|
+ {
|
||||||
|
+ non_fatal ("could not find ELF data\n");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const Elf_Internal_Phdr * prev = NULL;
|
||||||
|
+ unsigned int i;
|
||||||
|
+ bfd_boolean sections_added = FALSE;
|
||||||
|
+
|
||||||
|
+ for (i = 1; i < ehdr->e_phnum; i++)
|
||||||
|
+ {
|
||||||
|
+ const Elf_Internal_Phdr * current = tdata->phdr + i;
|
||||||
|
+
|
||||||
|
+ if (! is_loadable_segment (current))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /* If this is the first loadable segment, just record it. */
|
||||||
|
+ if (prev == NULL)
|
||||||
|
+ {
|
||||||
|
+ prev = current;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bfd_vma prev_end = prev->p_vaddr + prev->p_memsz;
|
||||||
|
+ bfd_vma current_start = page_align_down (bed->commonpagesize, current->p_vaddr);
|
||||||
|
+
|
||||||
|
+ /* If the segments are not ordered by increasing p_vaddr then abort.
|
||||||
|
+ Note: the ELF standard requires that segments be sorted by p_vaddr,
|
||||||
|
+ but linker scripts are able to override this. */
|
||||||
|
+ if (current_start < prev_end)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ /* If the previous segment ended at the start of the
|
||||||
|
+ current segment then there is nothing to do. */
|
||||||
|
+ if (prev_end == current_start)
|
||||||
|
+ {
|
||||||
|
+ prev = current;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ flagword flags = SEC_LINKER_CREATED | SEC_ALLOC;
|
||||||
|
+
|
||||||
|
+ /* We do not add SEC_HAS_CONTENTS because we want to create a SHT_NOBITS
|
||||||
|
+ section. That way we will not take up (much) extra space in the file. */
|
||||||
|
+
|
||||||
|
+ if (prev->p_flags & PF_X)
|
||||||
|
+ flags |= SEC_CODE | SEC_READONLY;
|
||||||
|
+ else if (prev->p_flags & PF_R)
|
||||||
|
+ flags |= SEC_DATA | SEC_READONLY;
|
||||||
|
+ else if (prev->p_flags & PF_W)
|
||||||
|
+ flags |= SEC_DATA;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ prev = current;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#define SEGMENT_PADDING_SECTION_NAME ".segment.pad"
|
||||||
|
+ char * new_name;
|
||||||
|
+ if (asprintf (& new_name, SEGMENT_PADDING_SECTION_NAME ".%u", i - 1) < 1)
|
||||||
|
+ {
|
||||||
|
+ non_fatal ("unable to construct padding section name\n");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ asection * new_section = bfd_make_section_with_flags (obfd, new_name, flags);
|
||||||
|
+
|
||||||
|
+ if (new_section == NULL)
|
||||||
|
+ {
|
||||||
|
+ free (new_name);
|
||||||
|
+ non_fatal ("unable to make padding section\n");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bfd_vma new_size = (current_start - prev->p_vaddr) - prev->p_memsz;
|
||||||
|
+
|
||||||
|
+ if (! bfd_set_section_size (new_section, new_size))
|
||||||
|
+ {
|
||||||
|
+ bfd_nonfatal_message (NULL, obfd, new_section, NULL);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (! bfd_set_section_vma (new_section, prev_end))
|
||||||
|
+ {
|
||||||
|
+ bfd_nonfatal_message (NULL, obfd, new_section, NULL);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Do not free the name - it is used later on. */
|
||||||
|
+
|
||||||
|
+ sections_added = TRUE;
|
||||||
|
+ prev = current;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If we have added any sections, remove the section
|
||||||
|
+ to segment map so that it is regenerated. */
|
||||||
|
+ if (sections_added)
|
||||||
|
+ elf_seg_map (obfd) = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Copy object file IBFD onto OBFD.
|
||||||
|
Returns TRUE upon success, FALSE otherwise. */
|
||||||
|
|
||||||
|
@@ -3175,6 +3317,9 @@ copy_object (bfd *ibfd, bfd *obfd, const
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (add_segment_padding_sections)
|
||||||
|
+ add_padding_sections (ibfd, obfd);
|
||||||
|
+
|
||||||
|
/* Symbol filtering must happen after the output sections
|
||||||
|
have been created, but before their contents are set. */
|
||||||
|
dhandle = NULL;
|
||||||
|
@@ -5548,6 +5693,10 @@ copy_main (int argc, char *argv[])
|
||||||
|
pad_to_set = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case OPTION_ADD_SEGMENT_PADDING_SECTIONS:
|
||||||
|
+ add_segment_padding_sections = TRUE;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case OPTION_REMOVE_LEADING_CHAR:
|
||||||
|
remove_leading_char = TRUE;
|
||||||
|
break;
|
@ -2,7 +2,7 @@
|
|||||||
Summary: A GNU collection of binary utilities
|
Summary: A GNU collection of binary utilities
|
||||||
Name: binutils%{?_with_debug:-debug}
|
Name: binutils%{?_with_debug:-debug}
|
||||||
Version: 2.35.2
|
Version: 2.35.2
|
||||||
Release: 60%{?dist}
|
Release: 61%{?dist}
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
URL: https://sourceware.org/binutils
|
URL: https://sourceware.org/binutils
|
||||||
|
|
||||||
@ -506,6 +506,10 @@ Patch90: binutils-s390-arch15-gas-tests-fixes.patch
|
|||||||
# Lifetime: Fixed in 2.44
|
# Lifetime: Fixed in 2.44
|
||||||
Patch91: binutils-linker-diagnostic-message.patch
|
Patch91: binutils-linker-diagnostic-message.patch
|
||||||
|
|
||||||
|
# Purpose: Add option to objcopy to pad segments eliminating gaps.
|
||||||
|
# Lifetime: Permanent
|
||||||
|
Patch92: binutils-rhivos-segment-gap.patch
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
Provides: bundled(libiberty)
|
Provides: bundled(libiberty)
|
||||||
@ -1365,6 +1369,9 @@ exit 0
|
|||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jan 23 2025 Nick Clifton <nickc@redhat.com> - 2.35.2-61
|
||||||
|
- Add an option to objcopy that creates padding sections that eliminate gaps between segments. (RHEL-60807)
|
||||||
|
|
||||||
* Mon Jan 06 2025 Nick Clifton <nickc@redhat.com> - 2.35.2-60
|
* Mon Jan 06 2025 Nick Clifton <nickc@redhat.com> - 2.35.2-60
|
||||||
- Add a helpful linker diagnostic message about missing static libraries. (RHEL-69758)
|
- Add a helpful linker diagnostic message about missing static libraries. (RHEL-69758)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user