forked from pool/binutils
163 lines
4.6 KiB
Diff
163 lines
4.6 KiB
Diff
|
This is for userspace live patching, adding some space into
|
||
|
shared libs or executable (in the .ulp section) when one of the
|
||
|
input files contains a section named .ulp.track.
|
||
|
|
||
|
Index: bfd/elflink.c
|
||
|
===================================================================
|
||
|
--- bfd/elflink.c.orig 2019-09-09 15:19:43.000000000 +0200
|
||
|
+++ bfd/elflink.c 2019-11-18 18:02:54.000000000 +0100
|
||
|
@@ -22,6 +22,7 @@
|
||
|
#include "bfd.h"
|
||
|
#include "bfdlink.h"
|
||
|
#include "libbfd.h"
|
||
|
+#include "ulp.h"
|
||
|
#define ARCH_SIZE 0
|
||
|
#include "elf-bfd.h"
|
||
|
#include "safe-ctype.h"
|
||
|
@@ -7070,6 +7071,11 @@ bfd_elf_size_dynamic_sections (bfd *outp
|
||
|
s = bfd_get_linker_section (dynobj, ".gnu.version");
|
||
|
s->flags |= SEC_EXCLUDE;
|
||
|
}
|
||
|
+
|
||
|
+ if (bfd_is_ulp_enabled(output_bfd))
|
||
|
+ {
|
||
|
+ bfd_setup_ulp(info);
|
||
|
+ }
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
Index: bfd/elfxx-x86.c
|
||
|
===================================================================
|
||
|
--- bfd/elfxx-x86.c.orig 2019-09-09 15:19:43.000000000 +0200
|
||
|
+++ bfd/elfxx-x86.c 2019-11-18 18:02:54.000000000 +0100
|
||
|
@@ -23,6 +23,7 @@
|
||
|
#include "objalloc.h"
|
||
|
#include "elf/i386.h"
|
||
|
#include "elf/x86-64.h"
|
||
|
+#include "ulp.h"
|
||
|
|
||
|
/* The name of the dynamic interpreter. This is put in the .interp
|
||
|
section. */
|
||
|
@@ -952,6 +953,64 @@ _bfd_x86_elf_link_check_relocs (bfd *abf
|
||
|
return _bfd_elf_link_check_relocs (abfd, info);
|
||
|
}
|
||
|
|
||
|
+/* Check if input bfds are ulp-enabled by containing .ulp.track section */
|
||
|
+
|
||
|
+bfd_boolean
|
||
|
+bfd_x86_elf_is_ulp_enabled (struct bfd *input_bfd)
|
||
|
+{
|
||
|
+ while (input_bfd != NULL)
|
||
|
+ for (; input_bfd != NULL; input_bfd = input_bfd->link.next)
|
||
|
+ {
|
||
|
+ if (input_bfd->section_count == 0) continue;
|
||
|
+ if (bfd_get_section_by_name (input_bfd, ".ulp.track")) return TRUE;
|
||
|
+ }
|
||
|
+ return FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/* To be used by elf_link_hash_traverse when computing the ulp length */
|
||
|
+
|
||
|
+static bfd_boolean
|
||
|
+bfd_x86_elf_link_compute_ulp (struct elf_link_hash_entry *h, void *data)
|
||
|
+{
|
||
|
+ unsigned long *ulp_length = (unsigned long *) data;
|
||
|
+
|
||
|
+ if (h->dynindx != -1 && h->type == STT_FUNC && !h->def_dynamic)
|
||
|
+ {
|
||
|
+ ++(*ulp_length);
|
||
|
+ }
|
||
|
+ return TRUE;
|
||
|
+}
|
||
|
+
|
||
|
+/* Fill the user-space live patching section */
|
||
|
+
|
||
|
+bfd_boolean
|
||
|
+bfd_x86_elf_setup_ulp (struct bfd_link_info *info)
|
||
|
+{
|
||
|
+ struct elf_x86_link_hash_table *htab;
|
||
|
+ asection *ulp;
|
||
|
+ unsigned int ulp_length = 0;
|
||
|
+
|
||
|
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
|
||
|
+
|
||
|
+ elf_link_hash_traverse (elf_hash_table (info),
|
||
|
+ bfd_x86_elf_link_compute_ulp,
|
||
|
+ &ulp_length);
|
||
|
+
|
||
|
+ ulp = htab->ulp;
|
||
|
+
|
||
|
+ ulp->size = ulp_length * ULP_ENTRY_LEN;
|
||
|
+
|
||
|
+ ulp->contents = (bfd_byte *) bfd_malloc (ulp->size);
|
||
|
+ if (ulp->contents == NULL)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ if (!ulp->contents)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ memset(ulp->contents, 0x00, ulp->size);
|
||
|
+ return TRUE;
|
||
|
+}
|
||
|
+
|
||
|
/* Set the sizes of the dynamic sections. */
|
||
|
|
||
|
bfd_boolean
|
||
|
@@ -2935,7 +2994,26 @@ error_alignment:
|
||
|
|
||
|
htab->plt_second = sec;
|
||
|
}
|
||
|
- }
|
||
|
+
|
||
|
+ /* create sections to support user-space live patching */
|
||
|
+ if (bfd_x86_elf_is_ulp_enabled(info->input_bfds))
|
||
|
+ {
|
||
|
+ flagword flags = (bed->dynamic_sec_flags
|
||
|
+ | SEC_ALLOC
|
||
|
+ | SEC_CODE
|
||
|
+ | SEC_LOAD
|
||
|
+ | SEC_READONLY);
|
||
|
+
|
||
|
+ sec = bfd_make_section_anyway_with_flags (dynobj, ".ulp", flags);
|
||
|
+ if (sec == NULL)
|
||
|
+ info->callbacks->einfo (_("%F%P: failed to create ULP section\n"));
|
||
|
+
|
||
|
+ if (!bfd_set_section_alignment (dynobj, sec, plt_alignment))
|
||
|
+ goto error_alignment;
|
||
|
+
|
||
|
+ htab->ulp = sec;
|
||
|
+ }
|
||
|
+ }
|
||
|
|
||
|
if (!info->no_ld_generated_unwind_info)
|
||
|
{
|
||
|
Index: bfd/elfxx-x86.h
|
||
|
===================================================================
|
||
|
--- bfd/elfxx-x86.h.orig 2019-09-09 15:19:43.000000000 +0200
|
||
|
+++ bfd/elfxx-x86.h 2019-11-18 18:02:54.000000000 +0100
|
||
|
@@ -447,6 +447,7 @@ struct elf_x86_link_hash_table
|
||
|
asection *plt_second_eh_frame;
|
||
|
asection *plt_got;
|
||
|
asection *plt_got_eh_frame;
|
||
|
+ asection *ulp;
|
||
|
|
||
|
/* Parameters describing PLT generation, lazy or non-lazy. */
|
||
|
struct elf_x86_plt_layout plt;
|
||
|
Index: bfd/ulp.h
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ bfd/ulp.h 2019-11-18 18:02:54.000000000 +0100
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+extern bfd_boolean bfd_x86_elf_is_ulp_enabled
|
||
|
+ (struct bfd *);
|
||
|
+
|
||
|
+extern bfd_boolean bfd_x86_elf_setup_ulp
|
||
|
+ (struct bfd_link_info *);
|
||
|
+
|
||
|
+#define bfd_is_ulp_enabled bfd_x86_elf_is_ulp_enabled
|
||
|
+
|
||
|
+#define bfd_setup_ulp bfd_x86_elf_setup_ulp
|
||
|
+
|
||
|
+#define ULP_ENTRY_LEN 16
|
||
|
+
|