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

Re: [Xen-devel] [PATCH v5 19/28] build_id: Provide ld-embedded build-ids



On Fri, Apr 08, 2016 at 11:44:54AM -0600, Jan Beulich wrote:
> >>> On 08.04.16 at 19:06, <konrad.wilk@xxxxxxxxxx> wrote:
> > "Since you put the notes into .rodata anyway, why name the section .note"
> > 
> > Perhaps you mean - why name the section .note.gnu_build-id ?
> 
> Sure - .note or .note.*.
> 
> > So that when xen.efi is linked with this build_id.o (in v5, now called 
> > notes.o in v6)
> > it can encapsulate __note_gnu_build_id_start and __note_gnu_build_id_end 
> > around
> > it. I could change for EFI builds the xen.lds.S to be:
> > 
> >      *(.rodata.*)
> > +#if defined(BUILD_ID) && defined(EFI)
> > +/*
> > + * No mechanism to put an PT_NOTE in the EFI file - so put
> > + * it in .data section.
> > + */
> > +        . = ALIGN(4);
> > +
> > +       __note_gnu_build_id_start = .;
> > +       *(.rodata.note.gnu.build-id)
> > +       __note_gnu_build_id_end = .;
> > +       *(.note)
> > +       *(.note.*)
> > +#endif
> > 
> > But then it differes from the change for !EFI (Which would be naturally
> > called .note.gnu.build-id).
> 
> But that looks to be the right approach, accounting for the
> differences between ELF and COFF/PE. And btw., unless you did
> changes elsewhere I don't think this inclusion of .note and .note.*
> here would have the effect you want it to have.

We don't really have any other .note, which is good.

I tried to feed the linker a notes.o file with .rodata.note
and have the efi.lds.S ingest it:

       __note_gnu_build_id_start = .;
       *(.rodata.note)
       __note_gnu_build_id_end = .;

But it ignored it (no data, and __note_gnu_build_id_start == 
__note_gnu_build_id_end)
 If I left the name as .note or *(.note.*) it was OK.

Here is what I came up with. Going to test it shortly

From ff61823cef437fb8a69903b3ff14b0d06ccf743b Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Date: Wed, 6 Apr 2016 22:05:06 -0400
Subject: [PATCH] build_id: Provide ld-embedded build-ids

This patch enables the Elf to be built with the build-id
and provide in the Xen hypervisor the code to extract it.

The man-page for ld --build-id says it is:

"Request the creation of a ".note.gnu.build-id" ELF note
section or a ".build-id" COFF section.  The contents of the
note are unique bits identifying this linked file. style can be
"uuid" to use 128 random bits, "sha1" to use a 160-bit SHA1 hash
on the normative parts of the output contents, ..."

One can also retrieve the value of the build-id by doing
'readelf -n xen-syms'.

For EFI builds we re-use the same build-id that the xen-syms
was built with.

The version of ld that first implemented --build-id is v2.18.
We check for to see if the linker supports the --build-id
parameter and if so use it.

For x86 we have two binaries - the xen-syms and the xen - an
smaller version with lots of sections removed. To make it possible
for readelf -n xen we also modify mkelf32 and xen.lds.S to include
the PT_NOTE ELF section.

The EFI binary is more complicated. We only build one type of
binary and expanding the amount of sections the EFI binary has to
include an .note one is pointless - as there is no concept of
PT_NOTE. The best we can do is move the .note in the .rodata section.

Further development wise should move it to .buildid section
so that DataDirectory debug data nor CodeView can view it.
(The author has no clue what those are).

Note that in earlier patches the linker script had:

 __note_gnu_build_id_start = .;
 *(.rodata.note.gnu.build-id)
 __note_gnu_build_id_end = .;
 *(.note)
 *(.note.*)

Which meant you could have different ELF notes _outside_ the
__note_gnu_build_id_end. However for EFI builds we take the whole
.note* section and jam it in the EFI to be between
__note_gnu_build_id_start and __note_gnu_build_id_end.
To not make EFI be the odd-man out all the buids will ingest
the same type. This means if we had extra ELF Notes we have to
careful that the very first one is the --build-id (otherwise
xen_build_init will fail).

Note that we do call --binary-id=sha1 on all linker invocations.
We have to do to enforce that the symbol offsets don't changes
(the side effect is that we we would have multiple binary ids -
except that the last one is the final one).

Without this working the symbol table embedded in Xen ends
up incorrect - some of the values it contains would be offset by the
size of the included build id.

This obviously causes problems when resolving symbols.

Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Signed-off-by: Martin Pohlack <mpohlack@xxxxxxxxx>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>

---
Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
Cc: Julien Grall <julien.grall@xxxxxxx>
Cc: Keir Fraser <keir@xxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>

v1: Rebase it on Martin's initial patch
v2: Move it to XENVER hypercall
v3: Fix EFI building (Ross's fix)
    Don't use the third argument for length.
    Use new structure for XENVER_build_id with variable buf.
    Include Ross's fix.
    Include detection of bin-utils for build-id support, add
    probing for size, and return -EPERM for XSM denied calls.
    Build xen_build_id under ARM, required adding ELFSIZE in proper file.
    Rebase on top XSM version class.
v4:
    Include the build-id .note in the xen ELF binary.
    s/build_id/build_id_linker/
    For EFI build, moved the --build-id values in .data section
    Rebase on staging.
    Split patch in two. Always do --build-id call. Include the .note in
    .rodata. USe const void * and ssize_t
    Use -S to make build_id.o and objcopy differently (Andrew suggested)
v5: Put back the #ifdef LOCK_PROFILE on ARM. (Bad change). Move the _erodata
    around. s/ssize_t/unsigned int/
v6: Redid it per Jan's review.
v7: Move build-id note in .rodata.note for EFI builds only.
    Move build-id note in .rodata for EFI builds only. Retain
    it in .note. Change name of object file used by EFI builds to notes.o
---
---
 Config.mk                   |  11 ++++
 xen/arch/arm/Makefile       |   2 +-
 xen/arch/arm/xen.lds.S      |  16 +++++-
 xen/arch/x86/Makefile       |  30 +++++++++--
 xen/arch/x86/boot/mkelf32.c | 129 +++++++++++++++++++++++++++++++++++++++-----
 xen/arch/x86/efi/Makefile   |   2 +-
 xen/arch/x86/xen.lds.S      |  24 +++++++++
 xen/common/version.c        |  51 ++++++++++++++++++
 xen/include/xen/version.h   |   1 +
 9 files changed, 243 insertions(+), 23 deletions(-)

diff --git a/Config.mk b/Config.mk
index 79eb2bd..db70638 100644
--- a/Config.mk
+++ b/Config.mk
@@ -126,6 +126,17 @@ endef
 check-$(gcc) = $(call cc-ver-check,CC,0x040100,"Xen requires at least gcc-4.1")
 $(eval $(check-y))
 
+ld-ver-build-id = $(shell $(1) --build-id 2>&1 | \
+                                       grep -q unrecognized && echo n || echo 
y)
+
+export XEN_HAS_BUILD_ID ?= n
+ifeq ($(call ld-ver-build-id,$(LD)),n)
+build_id_linker :=
+else
+CFLAGS += -DBUILD_ID
+build_id_linker := --build-id=sha1
+endif
+
 # as-insn: Check whether assembler supports an instruction.
 # Usage: cflags-y += $(call as-insn "insn",option-yes,option-no)
 as-insn = $(if $(shell echo 'void _(void) { asm volatile ( $(2) ); }' \
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index bbd190e..d3489bd 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -92,7 +92,7 @@ $(TARGET)-syms: prelink.o xen.lds 
$(BASEDIR)/common/symbols-dummy.o
        $(NM) -pa --format=sysv $(@D)/.$(@F).1 \
                | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).1.S
        $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
            $(@D)/.$(@F).1.o -o $@
        rm -f $(@D)/.$(@F).[0-9]*
 
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 9909595..a5e635d 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -22,6 +22,9 @@ OUTPUT_ARCH(FORMAT)
 PHDRS
 {
   text PT_LOAD /* XXX should be AT ( XEN_PHYS_START ) */ ;
+#if defined(BUILD_ID)
+  note PT_NOTE ;
+#endif
 }
 SECTIONS
 {
@@ -57,10 +60,19 @@ SECTIONS
        *(.lockprofile.data)
        __lock_profile_end = .;
 #endif
-
-        _erodata = .;          /* End of read-only data */
   } :text
 
+#if defined(BUILD_ID)
+  . = ALIGN(4);
+  .note : {
+       __note_gnu_build_id_start = .;
+       *(.note)
+       *(.note.*)
+       __note_gnu_build_id_end = .;
+  } :note :text
+#endif
+  _erodata = .;                /* End of read-only data */
+
   .data : {                    /* Data */
        . = ALIGN(PAGE_SIZE);
        *(.data.page_aligned)
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 08a7b68..727e012 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -72,6 +72,12 @@ efi-y := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h 
-o \
                       -O $(BASEDIR)/include/xen/compile.h ]; then \
                          echo '$(TARGET).efi'; fi)
 
+ifneq ($(build_id_linker),)
+num_phdrs = --notes
+else
+num_phdrs =
+endif
+
 ifdef CONFIG_XSPLICE
 all_symbols = --all-symbols
 else
@@ -80,7 +86,8 @@ endif
 
 $(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
        ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
-       `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
+       `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` \
+       $(num_phdrs)
 
 .PHONY: test
 test:
@@ -114,22 +121,28 @@ $(BASEDIR)/common/symbols-dummy.o:
        $(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o
 
 $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
            $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
        $(NM) -pa --format=sysv $(@D)/.$(@F).0 \
                | $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort \
                >$(@D)/.$(@F).0.S
        $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
            $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
        $(NM) -pa --format=sysv $(@D)/.$(@F).1 \
                | $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort 
--warn-dup \
                >$(@D)/.$(@F).1.S
        $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
            $(@D)/.$(@F).1.o -o $@
        rm -f $(@D)/.$(@F).[0-9]*
 
+notes.o: $(TARGET)-syms
+       $(OBJCOPY) -O binary --only-section=.note $(BASEDIR)/xen-syms $@.bin
+       $(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
+               --rename-section=.data=.note -S $@.bin $@
+       rm -f $@.bin
+
 EFI_LDFLAGS = $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10
 EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0 --strip-debug
 EFI_LDFLAGS += --section-alignment=0x200000 --file-alignment=0x20
@@ -142,6 +155,13 @@ $(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: notes.o
+notes_file := notes.o
+else
+notes_file :=
+endif
+
 $(TARGET).efi: prelink-efi.o 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 \
@@ -158,7 +178,7 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o 
$(BASEDIR)/common/symbol
                | $(guard) $(BASEDIR)/tools/symbols $(all_symbols) --sysv 
--sort >$(@D)/.$(@F).1s.S
        $(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o 
$(@D)/.$(@F).1s.o
        $(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $< \
-                       $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o -o $@
+                       $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o $(notes_file) -o $@
        if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi
        rm -f $(@D)/.$(@F).[0-9]*
 
diff --git a/xen/arch/x86/boot/mkelf32.c b/xen/arch/x86/boot/mkelf32.c
index 993a7ee..fce1716 100644
--- a/xen/arch/x86/boot/mkelf32.c
+++ b/xen/arch/x86/boot/mkelf32.c
@@ -45,9 +45,9 @@ static Elf32_Ehdr out_ehdr = {
     0,                                       /* e_flags */
     sizeof(Elf32_Ehdr),                      /* e_ehsize */
     sizeof(Elf32_Phdr),                      /* e_phentsize */
-    1,                                       /* e_phnum */
+    1,  /* modify based on num_phdrs */      /* e_phnum */
     sizeof(Elf32_Shdr),                      /* e_shentsize */
-    3,                                       /* e_shnum */
+    3,  /* modify based on num_phdrs */      /* e_shnum */
     2                                        /* e_shstrndx */
 };
 
@@ -61,8 +61,20 @@ static Elf32_Phdr out_phdr = {
     PF_R|PF_W|PF_X,                          /* p_flags */
     64                                       /* p_align */
 };
+static Elf32_Phdr note_phdr = {
+    PT_NOTE,                                 /* p_type */
+    DYNAMICALLY_FILLED,                      /* p_offset */
+    DYNAMICALLY_FILLED,                      /* p_vaddr */
+    DYNAMICALLY_FILLED,                      /* p_paddr */
+    DYNAMICALLY_FILLED,                      /* p_filesz */
+    DYNAMICALLY_FILLED,                      /* p_memsz */
+    PF_R,                                    /* p_flags */
+    4                                        /* p_align */
+};
 
 static u8 out_shstrtab[] = "\0.text\0.shstrtab";
+/* If num_phdrs >= 2, we need to tack the .note. */
+static u8 out_shstrtab_extra[] = ".note\0";
 
 static Elf32_Shdr out_shdr[] = {
     { 0 },
@@ -90,6 +102,23 @@ static Elf32_Shdr out_shdr[] = {
     }
 };
 
+/*
+ * The 17 points to the '.note' in the out_shstrtab and out_shstrtab_extra
+ * laid out in the file.
+ */
+static Elf32_Shdr out_shdr_note = {
+      17,                                    /* sh_name */
+      SHT_NOTE,                              /* sh_type */
+      0,                                     /* sh_flags */
+      DYNAMICALLY_FILLED,                    /* sh_addr */
+      DYNAMICALLY_FILLED,                    /* sh_offset */
+      DYNAMICALLY_FILLED,                    /* sh_size */
+      0,                                     /* sh_link */
+      0,                                     /* sh_info */
+      4,                                     /* sh_addralign */
+      0                                      /* sh_entsize */
+};
+
 /* Some system header files define these macros and pollute our namespace. */
 #undef swap16
 #undef swap32
@@ -228,21 +257,22 @@ static void do_read(int fd, void *data, int len)
 int main(int argc, char **argv)
 {
     u64        final_exec_addr;
-    u32        loadbase, dat_siz, mem_siz;
+    u32        loadbase, dat_siz, mem_siz, note_base, note_sz, offset;
     char      *inimage, *outimage;
     int        infd, outfd;
     char       buffer[1024];
     int        bytes, todo, i;
+    int        num_phdrs = 1;
 
     Elf32_Ehdr in32_ehdr;
 
     Elf64_Ehdr in64_ehdr;
     Elf64_Phdr in64_phdr;
 
-    if ( argc != 5 )
+    if ( argc < 5 )
     {
         fprintf(stderr, "Usage: mkelf32 <in-image> <out-image> "
-                "<load-base> <final-exec-addr>\n");
+                "<load-base> <final-exec-addr> <number of program headers> 
[--notes]\n");
         return 1;
     }
 
@@ -250,6 +280,8 @@ int main(int argc, char **argv)
     outimage = argv[2];
     loadbase = strtoul(argv[3], NULL, 16);
     final_exec_addr = strtoull(argv[4], NULL, 16);
+    if ( argv[5] && (!strcmp(argv[5], "--notes")) )
+        num_phdrs = 2;
 
     infd = open(inimage, O_RDONLY);
     if ( infd == -1 )
@@ -285,11 +317,10 @@ int main(int argc, char **argv)
                 (int)in64_ehdr.e_phentsize, (int)sizeof(in64_phdr));
         return 1;
     }
-
-    if ( in64_ehdr.e_phnum != 1 )
+    if ( in64_ehdr.e_phnum != num_phdrs )
     {
-        fprintf(stderr, "Expect precisly 1 program header; found %d.\n",
-                (int)in64_ehdr.e_phnum);
+        fprintf(stderr, "Expect precisly %d program header; found %d.\n",
+                num_phdrs, (int)in64_ehdr.e_phnum);
         return 1;
     }
 
@@ -304,6 +335,32 @@ int main(int argc, char **argv)
     /*mem_siz = (u32)in64_phdr.p_memsz;*/
     mem_siz = (u32)(final_exec_addr - in64_phdr.p_vaddr);
 
+    note_sz = note_base = offset = 0;
+    if ( num_phdrs > 1 )
+    {
+        offset = in64_phdr.p_offset;
+        note_base = in64_phdr.p_vaddr;
+
+        (void)lseek(infd, in64_ehdr.e_phoff+sizeof(in64_phdr), SEEK_SET);
+        do_read(infd, &in64_phdr, sizeof(in64_phdr));
+        endianadjust_phdr64(&in64_phdr);
+
+        (void)lseek(infd, offset, SEEK_SET);
+
+        note_sz = in64_phdr.p_memsz;
+        note_base = in64_phdr.p_vaddr - note_base;
+
+        if ( in64_phdr.p_offset > dat_siz || offset > in64_phdr.p_offset )
+        {
+            fprintf(stderr, "Expected .note section within .text section!\n" \
+                    "Offset %ld not within %d!\n",
+                    in64_phdr.p_offset, dat_siz);
+            return 1;
+        }
+        /* Gets us the absolute offset within the .text section. */
+        offset = in64_phdr.p_offset - offset;
+    }
+
     /*
      * End the image on a page boundary. This gets round alignment bugs
      * in the boot- or chain-loader (e.g., kexec on the XenoBoot CD).
@@ -322,6 +379,31 @@ int main(int argc, char **argv)
     out_shdr[1].sh_size   = dat_siz;
     out_shdr[2].sh_offset = RAW_OFFSET + dat_siz + sizeof(out_shdr);
 
+    if ( num_phdrs > 1 )
+    {
+        /* We have two of them! */
+        out_ehdr.e_phnum = num_phdrs;
+        /* Extra .note section. */
+        out_ehdr.e_shnum++;
+
+        /* Fill out the PT_NOTE program header. */
+        note_phdr.p_vaddr   = note_base;
+        note_phdr.p_paddr   = note_base;
+        note_phdr.p_filesz  = note_sz;
+        note_phdr.p_memsz   = note_sz;
+        note_phdr.p_offset  = offset;
+
+        /* Tack on the .note\0 */
+        out_shdr[2].sh_size += sizeof(out_shstrtab_extra);
+        /* And move it past the .note section. */
+        out_shdr[2].sh_offset += sizeof(out_shdr_note);
+
+        /* Fill out the .note section. */
+        out_shdr_note.sh_size = note_sz;
+        out_shdr_note.sh_addr = note_base;
+        out_shdr_note.sh_offset = RAW_OFFSET + offset;
+    }
+
     outfd = open(outimage, O_WRONLY|O_CREAT|O_TRUNC, 0775);
     if ( outfd == -1 )
     {
@@ -335,8 +417,14 @@ int main(int argc, char **argv)
 
     endianadjust_phdr32(&out_phdr);
     do_write(outfd, &out_phdr, sizeof(out_phdr));
-    
-    if ( (bytes = RAW_OFFSET - sizeof(out_ehdr) - sizeof(out_phdr)) < 0 )
+
+    if ( num_phdrs > 1 )
+    {
+        endianadjust_phdr32(&note_phdr);
+        do_write(outfd, &note_phdr, sizeof(note_phdr));
+    }
+
+    if ( (bytes = RAW_OFFSET - sizeof(out_ehdr) - (num_phdrs * 
sizeof(out_phdr)) ) < 0 )
     {
         fprintf(stderr, "Header overflow.\n");
         return 1;
@@ -355,9 +443,22 @@ int main(int argc, char **argv)
         endianadjust_shdr32(&out_shdr[i]);
     do_write(outfd, &out_shdr[0], sizeof(out_shdr));
 
-    do_write(outfd, out_shstrtab, sizeof(out_shstrtab));
-    do_write(outfd, buffer, 4-((sizeof(out_shstrtab)+dat_siz)&3));
-
+    if ( num_phdrs > 1 )
+    {
+        endianadjust_shdr32(&out_shdr_note);
+        /* Append the .note section. */
+        do_write(outfd, &out_shdr_note, sizeof(out_shdr_note));
+        /* The normal strings - .text\0.. */
+        do_write(outfd, out_shstrtab, sizeof(out_shstrtab));
+        /* Our .note */
+        do_write(outfd, out_shstrtab_extra, sizeof(out_shstrtab_extra));
+        do_write(outfd, buffer, 
4-((sizeof(out_shstrtab)+sizeof(out_shstrtab_extra)+dat_siz)&3));
+    }
+    else
+    {
+        do_write(outfd, out_shstrtab, sizeof(out_shstrtab));
+        do_write(outfd, buffer, 4-((sizeof(out_shstrtab)+dat_siz)&3));
+    }
     close(infd);
     close(outfd);
 
diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile
index 5099430..a6dae4c 100644
--- a/xen/arch/x86/efi/Makefile
+++ b/xen/arch/x86/efi/Makefile
@@ -6,7 +6,7 @@ create = test -e $(1) || touch -t 199901010000 $(1)
 
 efi := y$(shell rm -f disabled)
 efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c 
check.c 2>disabled && echo y))
-efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 
2>disabled && echo y))
+efi := $(if $(efi),$(shell $(LD_EFI) -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
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 5eb825e..87297d0 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -31,6 +31,9 @@ OUTPUT_ARCH(i386:x86-64)
 PHDRS
 {
   text PT_LOAD ;
+#if defined(BUILD_ID) && !defined(EFI)
+  note PT_NOTE ;
+#endif
 }
 SECTIONS
 {
@@ -79,6 +82,17 @@ SECTIONS
        *(.rodata)
        *(.rodata.*)
 
+#if defined(BUILD_ID) && defined(EFI)
+/*
+ * No mechanism to put an PT_NOTE in the EFI file - so put
+ * it in .rodata section. (notes.o supplies us with .note).
+ */
+       . = ALIGN(4);
+       __note_gnu_build_id_start = .;
+       *(.note)
+       *(.note.*)
+       __note_gnu_build_id_end = .;
+#endif
        . = ALIGN(8);
        /* Exception table */
        __start___ex_table = .;
@@ -99,6 +113,16 @@ SECTIONS
        _erodata = .;
   } :text
 
+#if defined(BUILD_ID) && !defined(EFI)
+  . = ALIGN(4);
+  .note : {
+       __note_gnu_build_id_start = .;
+       *(.note)
+       *(.note.*)
+       __note_gnu_build_id_end = .;
+  } :note :text
+#endif
+
 #ifdef EFI
   . = ALIGN(MB(2));
 #else
diff --git a/xen/common/version.c b/xen/common/version.c
index fc9bf42..33a930a 100644
--- a/xen/common/version.c
+++ b/xen/common/version.c
@@ -1,4 +1,9 @@
 #include <xen/compile.h>
+#include <xen/init.h>
+#include <xen/errno.h>
+#include <xen/string.h>
+#include <xen/types.h>
+#include <xen/elf.h>
 #include <xen/version.h>
 
 const char *xen_compile_date(void)
@@ -61,6 +66,52 @@ const char *xen_deny(void)
     return "<denied>";
 }
 
+static const void *build_id_p;
+static unsigned int build_id_len;
+
+int xen_build_id(const void **p, unsigned int *len)
+{
+    if ( !build_id_len )
+        return -ENODATA;
+
+    *len = build_id_len;
+    *p = build_id_p;
+
+    return 0;
+}
+
+#ifdef BUILD_ID
+#define NT_GNU_BUILD_ID 3
+/* Defined in linker script. */
+extern const Elf_Note __note_gnu_build_id_start[], __note_gnu_build_id_end[];
+
+static int __init xen_build_init(void)
+{
+    const Elf_Note *n = __note_gnu_build_id_start;
+
+    /* --build-id invoked with wrong parameters. */
+    if ( __note_gnu_build_id_end <= &n[0] )
+        return -ENODATA;
+
+    /* Check for full Note header. */
+    if ( &n[1] > __note_gnu_build_id_end )
+        return -ENODATA;;
+
+    /* Check if we really have a build-id. */
+    if ( NT_GNU_BUILD_ID != n->type )
+        return -ENODATA;
+
+    /* Sanity check, name should be "GNU" for ld-generated build-id. */
+    if ( strncmp(ELFNOTE_NAME(n), "GNU", n->namesz) != 0 )
+        return -ENODATA;
+
+    build_id_len = n->descsz;
+    build_id_p = ELFNOTE_DESC(n);
+
+    return 0;
+}
+__initcall(xen_build_init);
+#endif
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/version.h b/xen/include/xen/version.h
index 2015c0b..400160f 100644
--- a/xen/include/xen/version.h
+++ b/xen/include/xen/version.h
@@ -13,5 +13,6 @@ const char *xen_extra_version(void);
 const char *xen_changeset(void);
 const char *xen_banner(void);
 const char *xen_deny(void);
+int xen_build_id(const void **p, unsigned int *len);
 
 #endif /* __XEN_VERSION_H__ */
-- 
2.4.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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