[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] x86/EFI: use less crude a way of generating the build ID



commit eee5909e9d1e9fa991c7d76475612354c5a6729c
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Sep 1 15:19:40 2016 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Sep 1 15:19:40 2016 +0200

    x86/EFI: use less crude a way of generating the build ID
    
    Recent enough binutils (2.25 onwards) support --build-id also for
    COFF/PE output, and hence we should use that in favor of the original
    hack when possible.
    
    This gets complicated by the linker requiring at least one COFF object
    file to attach the .buildid section to. Hence the patch introduces a
    buildid.ihex (in order to avoid introducing binary files into the repo)
    which then gets converted to a binary minimal COFF object (no sections,
    no symbols).
    
    Also (to avoid both code fragment going out of sync) remove an unneeded
    ALIGN() from xen.lds.S: Adding an equivalent of it to the .buildid
    section would cause the _erodata symbol to become associated with the
    wrong section again (see commit 0970299de5 ["x86/EFI + Live Patch:
    avoid symbol address truncation"]). And it's pointless because the
    alignment already gets properly set by the input section(s).
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/Makefile         | 18 +++++++++-----
 xen/arch/x86/efi/Makefile     |  5 +++-
 xen/arch/x86/efi/buildid.ihex |  3 +++
 xen/arch/x86/efi/mkreloc.c    |  1 +
 xen/arch/x86/xen.lds.S        | 13 +++++++---
 xen/common/version.c          | 57 ++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 86 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 5b9e9da..b49d7cf 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -158,24 +158,30 @@ $(TARGET).efi: VIRT_BASE = 0x$(shell $(NM) 
efi/relocs-dummy.o | sed -n 's, A VIR
 $(TARGET).efi: ALT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A 
ALT_START$$,,p')
 # Don't use $(wildcard ...) here - at least make 3.80 expands this too early!
 $(TARGET).efi: guard = $(if $(shell echo efi/dis* | grep disabled),:)
+
 ifneq ($(build_id_linker),)
-$(TARGET).efi: note.o
+ifeq ($(call ld-ver-build-id,$(LD) $(filter -m%,$(EFI_LDFLAGS))),y)
+CFLAGS += -DBUILD_ID_EFI
+EFI_LDFLAGS += $(build_id_linker)
+note_file := efi/buildid.o
+else
 note_file := note.o
+endif
 else
 note_file :=
 endif
 
-$(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o 
$(BASEDIR)/common/symbols-dummy.o efi/mkreloc
+$(TARGET).efi: prelink-efi.o $(note_file) efi.lds efi/relocs-dummy.o 
$(BASEDIR)/common/symbols-dummy.o efi/mkreloc
        $(foreach base, $(VIRT_BASE) $(ALT_BASE), \
                  $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< 
efi/relocs-dummy.o \
-                       $(BASEDIR)/common/symbols-dummy.o -o 
$(@D)/.$(@F).$(base).0 &&) :
+                       $(BASEDIR)/common/symbols-dummy.o $(note_file) -o 
$(@D)/.$(@F).$(base).0 &&) :
        $(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) 
$(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S
        $(guard) $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).0 \
                | $(guard) $(BASEDIR)/tools/symbols $(all_symbols) --sysv 
--sort >$(@D)/.$(@F).0s.S
        $(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0r.o 
$(@D)/.$(@F).0s.o
        $(foreach base, $(VIRT_BASE) $(ALT_BASE), \
                  $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< \
-                       $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o -o 
$(@D)/.$(@F).$(base).1 &&) :
+                       $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o $(note_file) -o 
$(@D)/.$(@F).$(base).1 &&) :
        $(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) 
$(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S
        $(guard) $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).1 \
                | $(guard) $(BASEDIR)/tools/symbols $(all_symbols) --sysv 
--sort >$(@D)/.$(@F).1s.S
@@ -185,8 +191,8 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o 
$(BASEDIR)/common/symbol
        if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi
        rm -f $(@D)/.$(@F).[0-9]*
 
-efi/boot.init.o efi/runtime.o efi/compat.o: $(BASEDIR)/arch/x86/efi/built_in.o
-efi/boot.init.o efi/runtime.o efi/compat.o: ;
+efi/boot.init.o efi/runtime.o efi/compat.o efi/buildid.o: 
$(BASEDIR)/arch/x86/efi/built_in.o
+efi/boot.init.o efi/runtime.o efi/compat.o efi/buildid.o: ;
 
 asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c
        $(CC) $(filter-out -flto,$(CFLAGS)) -S -o $@ $<
diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile
index d62b14f..ad3fdf7 100644
--- a/xen/arch/x86/efi/Makefile
+++ b/xen/arch/x86/efi/Makefile
@@ -9,7 +9,10 @@ efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) 
.%.d,$(CFLAGS)) -c che
 efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 
2>disabled && echo y))
 efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); 
$(call create,runtime.o)))
 
-extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o
+extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o buildid.o
+
+%.o: %.ihex
+       $(OBJCOPY) -I ihex -O binary $< $@
 
 stub.o: $(extra-y)
 nogcov-$(efi) += stub.o
diff --git a/xen/arch/x86/efi/buildid.ihex b/xen/arch/x86/efi/buildid.ihex
new file mode 100644
index 0000000..a89046d
--- /dev/null
+++ b/xen/arch/x86/efi/buildid.ihex
@@ -0,0 +1,3 @@
+:10000000648600004D8DAD57140000000000000014
+:0400100000000000EC
+:00000001FF
diff --git a/xen/arch/x86/efi/mkreloc.c b/xen/arch/x86/efi/mkreloc.c
index 6e52a2e..bddcce0 100644
--- a/xen/arch/x86/efi/mkreloc.c
+++ b/xen/arch/x86/efi/mkreloc.c
@@ -342,6 +342,7 @@ int main(int argc, char *argv[])
          */
         if ( memcmp(sec1[i].name, ".initcal", sizeof(sec1[i].name)) == 0 ||
              memcmp(sec1[i].name, ".init.se", sizeof(sec1[i].name)) == 0 ||
+             memcmp(sec1[i].name, ".buildid", sizeof(sec1[i].name)) == 0 ||
              memcmp(sec1[i].name, ".lockpro", sizeof(sec1[i].name)) == 0 )
             continue;
 
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 2d1d43d..67cfda1 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -93,7 +93,7 @@ SECTIONS
        *(.rodata)
        *(.rodata.*)
 
-#if defined(BUILD_ID) && defined(EFI)
+#if defined(BUILD_ID) && defined(EFI) && !defined(BUILD_ID_EFI)
 /*
  * No mechanism to put an PT_NOTE in the EFI file - so put
  * it in .rodata section. (notes.o supplies us with .note.gnu.build-id).
@@ -122,19 +122,26 @@ SECTIONS
 #endif
   } :text
 
-#if defined(BUILD_ID) && !defined(EFI)
+#if defined(BUILD_ID)
+#if !defined(EFI)
 /*
  * What a strange section name. The reason is that on ELF builds this section
  * is extracted to notes.o (which then is ingested in the EFI file). But the
  * compiler may want to inject other things in the .note which we don't care
  * about - hence this unique name.
  */
-  . = ALIGN(4);
   .note.gnu.build-id : {
        __note_gnu_build_id_start = .;
        *(.note.gnu.build-id)
        __note_gnu_build_id_end = .;
   } :note :text
+#elif defined(BUILD_ID_EFI)
+  .buildid : {
+       __note_gnu_build_id_start = .;
+       *(.buildid)
+       __note_gnu_build_id_end = .;
+  } :text
+#endif
 #endif
   _erodata = .;
 
diff --git a/xen/common/version.c b/xen/common/version.c
index b2afe96..4375ea2 100644
--- a/xen/common/version.c
+++ b/xen/common/version.c
@@ -4,6 +4,7 @@
 #include <xen/lib.h>
 #include <xen/string.h>
 #include <xen/types.h>
+#include <xen/efi.h>
 #include <xen/elf.h>
 #include <xen/version.h>
 
@@ -117,10 +118,33 @@ int xen_build_id_check(const Elf_Note *n, unsigned int 
n_sz,
     return 0;
 }
 
+struct pe_external_debug_directory
+{
+    uint32_t characteristics;
+    uint32_t time_stamp;
+    uint16_t major_version;
+    uint16_t minor_version;
+#define PE_IMAGE_DEBUG_TYPE_CODEVIEW 2
+    uint32_t type;
+    uint32_t size;
+    uint32_t rva_of_data;
+    uint32_t filepos_of_data;
+};
+
+struct cv_info_pdb70
+{
+#define CVINFO_PDB70_CVSIGNATURE 0x53445352 /* "RSDS" */
+    uint32_t cv_signature;
+    unsigned char signature[16];
+    uint32_t age;
+    char pdb_filename[];
+};
+
 static int __init xen_build_init(void)
 {
     const Elf_Note *n = __note_gnu_build_id_start;
     unsigned int sz;
+    int rc;
 
     /* --build-id invoked with wrong parameters. */
     if ( __note_gnu_build_id_end <= &n[0] )
@@ -132,7 +156,38 @@ static int __init xen_build_init(void)
 
     sz = (void *)__note_gnu_build_id_end - (void *)n;
 
-    return xen_build_id_check(n, sz, &build_id_p, &build_id_len);
+    rc = xen_build_id_check(n, sz, &build_id_p, &build_id_len);
+
+#ifdef CONFIG_X86
+    /* Alternatively we may have a CodeView record from an EFI build. */
+    if ( rc && efi_enabled )
+    {
+        const struct pe_external_debug_directory *dir = (const void *)n;
+
+        /*
+         * Validate that the full-note-header check above won't prevent
+         * fall-through to the CodeView case here.
+         */
+        BUILD_BUG_ON(sizeof(*n) > sizeof(*dir));
+
+        if ( sz > sizeof(*dir) + sizeof(struct cv_info_pdb70) &&
+             dir->type == PE_IMAGE_DEBUG_TYPE_CODEVIEW &&
+             dir->size > sizeof(struct cv_info_pdb70) &&
+             XEN_VIRT_START + dir->rva_of_data == (unsigned long)(dir + 1) )
+        {
+            const struct cv_info_pdb70 *info = (const void *)(dir + 1);
+
+            if ( info->cv_signature == CVINFO_PDB70_CVSIGNATURE )
+            {
+                build_id_p = info->signature;
+                build_id_len = sizeof(info->signature);
+                rc = 0;
+            }
+        }
+    }
+#endif
+
+    return rc;
 }
 __initcall(xen_build_init);
 #endif
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.