From patchwork Thu Mar 17 01:12:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Rzeszutek Wilk X-Patchwork-Id: 8606391 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B93889F3D1 for ; Thu, 17 Mar 2016 01:15:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 148A2202A1 for ; Thu, 17 Mar 2016 01:15:10 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3996C20279 for ; Thu, 17 Mar 2016 01:15:08 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1agMU8-0005hO-1K; Thu, 17 Mar 2016 01:12:20 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1agMU7-0005hE-BZ for xen-devel@lists.xenproject.org; Thu, 17 Mar 2016 01:12:19 +0000 Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id 91/4F-07924-0740AE65; Thu, 17 Mar 2016 01:12:16 +0000 X-Env-Sender: ketuzsezr@gmail.com X-Msg-Ref: server-11.tower-31.messagelabs.com!1458177133!3415388!1 X-Originating-IP: [209.85.220.194] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 8.11; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20050 invoked from network); 17 Mar 2016 01:12:14 -0000 Received: from mail-qk0-f194.google.com (HELO mail-qk0-f194.google.com) (209.85.220.194) by server-11.tower-31.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 17 Mar 2016 01:12:14 -0000 Received: by mail-qk0-f194.google.com with SMTP id e124so2042372qkc.3 for ; Wed, 16 Mar 2016 18:12:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=F3X42L/yhWTyB1tOpuOg6rCDQ0ZMIKmzcpol6NcBKXM=; b=D/O8N+PdxYH/JTR0dqKCvQ8XuyBGUtPQFj0toYoUc3Jsuc8xjijixD3xyjXMhcdLru tMbldbV3mwH0oRekyrzRGEErhfS3/S17VlKEbj0/ccDs8vh+1+6DjDBUX01jrQvvdnVO xGnyr5AYvKp8r2uLJQ7H2Qg0EerhVzdzvkMr2CPnhU9YFx8mXjcZy1EOFsHabyXnr1xC cBG0E2yu3cp+sp+Tpl1DzDck8ziKfxdTOHmnNsEP5gg6OOydWJfMWPo84lx3ok9p8By/ cH2IbZJqBYEQNKpmwaDIO4MhVAED5zKEtCM9wWjXawoV1aSmmSWrfeqUzx9mg7JPYcvM TCqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition:in-reply-to:user-agent; bh=F3X42L/yhWTyB1tOpuOg6rCDQ0ZMIKmzcpol6NcBKXM=; b=djYnL113zbp+PzoT/18ZUE02XAJmC+fyLwCE1TMyVj+yNr4pr5HIN4piQ3fTHUkr53 SsixoHHr99QeLMjFTslocLXPUZTRqZGt5Yqjznc9cl8SJ2dGcQwcsrd4y+uWi92AcXXV NuWxwUXztgCVQiHGSighTCL+/ZOxQRAz4ZzHUqaCyztRghKsiHo04P0gFoX9Bbj3tDZC Z5F7lhn04gU6MOrWgUTBDGcl2w2A+wwG/VkxDOilTNol5htP18vxcKVgOXBP3jX27e9k 2o4mdNoTDtMRftGzSRU3h94Y7CeoF99VQmkILAiW3tugqQ71hQOwcUZKvxWCMp4W1cjG 8GVQ== X-Gm-Message-State: AD7BkJLMqA4KXwPWUvG2/FQEo/dDVQKoOMfkFXCEIxKdtTptK+X+EvJBhnHp9eF79bx1zw== X-Received: by 10.55.81.3 with SMTP id f3mr10456590qkb.35.1458177133549; Wed, 16 Mar 2016 18:12:13 -0700 (PDT) Received: from localhost.localdomain (209-6-196-81.c3-0.smr-ubr2.sbo-smr.ma.cable.rcn.com. [209.6.196.81]) by smtp.gmail.com with ESMTPSA id 123sm2734162qhu.22.2016.03.16.18.12.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Mar 2016 18:12:13 -0700 (PDT) Date: Wed, 16 Mar 2016 21:12:10 -0400 From: Konrad Rzeszutek Wilk To: Konrad Rzeszutek Wilk Message-ID: <20160317011209.GD5173@localhost.localdomain> References: <1458064616-23101-1-git-send-email-konrad.wilk@oracle.com> <1458064616-23101-26-git-send-email-konrad.wilk@oracle.com> <56E9A730.2090203@arm.com> <20160316210231.GL18336@char.us.oracle.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20160316210231.GL18336@char.us.oracle.com> User-Agent: Mutt/1.5.24 (2015-08-30) Cc: Keir Fraser , andrew.cooper3@citrix.com, mpohlack@amazon.de, ross.lagerwall@citrix.com, Julien Grall , Stefano Stabellini , Jan Beulich , sasha.levin@oracle.com, xen-devel@lists.xenproject.org Subject: Re: [Xen-devel] [PATCH v4 25/34] build_id: Provide ld-embedded build-ids X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP > Let me try that. Please see inline patch which has your suggestion: From 20ddfe00c72bebd20f5f8c02283bdca5e1459616 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 15 Mar 2016 09:51:03 -0400 Subject: [PATCH v4 26/35] 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. 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. Hence we check for that or later version - if older version found we do not build the hypervisor with the build-id (and the return code is -ENODATA for xen_build_id() call). 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. Having any non-recognizable sections (.note, .data.note, etc) causes the boot to hang. Moving the .note in the .data section makes it work. It is also worth noting that the PE/COFF does not have any "comment" sections to the author. Lastly, we MUST call --binary-id=sha1 on all linker invocation so that symbol offsets don't changes (which means we have multiple binary ids - except that the last one is the final one). Without this change, the symbol table embedded in Xen are incorrect - some of the values it contains are offset by the size of the included build id. This obviously causes problems when resolving symbols. Suggested-by: Andrew Cooper Signed-off-by: Martin Pohlack Signed-off-by: Konrad Rzeszutek Wilk --- Cc: Stefano Stabellini Cc: Julien Grall Cc: Keir Fraser Cc: Jan Beulich Cc: Andrew Cooper v1: Rebase it on Martin's initial patch v2: Move it to XENVER hypercall v3: Fix EFI building (Ross's fix) v4: Don't use the third argument for length. v5: Use new structure for XENVER_build_id with variable buf. v6: Include Ross's fix. v7: Include detection of bin-utils for build-id support, add probing for size, and return -EPERM for XSM denied calls. v8: Build xen_build_id under ARM, required adding ELFSIZE in proper file. v9: Rebase on top XSM version class. v10: 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 v11: Rebase on staging. v12: Split patch in two. Always do --build-id call. Include the .note in .rodata. USe const void * and ssize_t v13: Use -S to make build_id.o and objcopy differently (Andrew suggested) v14: Put back the #ifdef LOCK_PROFILE on ARM. (Bad change). Move the _erodata around. --- Config.mk | 11 ++++ xen/arch/arm/Makefile | 2 +- xen/arch/arm/xen.lds.S | 14 ++++- xen/arch/x86/Makefile | 30 ++++++++-- xen/arch/x86/boot/mkelf32.c | 137 ++++++++++++++++++++++++++++++++++++++------ xen/arch/x86/xen.lds.S | 23 ++++++++ xen/common/version.c | 51 +++++++++++++++++ xen/include/xen/version.h | 3 + 8 files changed, 248 insertions(+), 23 deletions(-) diff --git a/Config.mk b/Config.mk index 79eb2bd..c8e89fe 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) + +# binutils 2.18 implement build-id. +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 17e9e3a..a3319ab 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -94,7 +94,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..aad26e3 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,9 +60,18 @@ SECTIONS *(.lockprofile.data) __lock_profile_end = .; #endif + } :text - _erodata = .; /* End of read-only data */ +#if defined(BUILD_ID) + .note : { + __note_gnu_build_id_start = .; + *(.note.gnu.build-id) + __note_gnu_build_id_end = .; + *(.note) + *(.note.*) } :text +#endif + _erodata = .; /* End of read-only data */ .data : { /* Data */ . = ALIGN(PAGE_SIZE); diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 8a100be..7db2e53 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -71,9 +71,16 @@ efi-y := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \ -O $(BASEDIR)/include/xen/compile.h ]; then \ echo '$(TARGET).efi'; fi) +ifdef build_id_linker +num_phdrs = 2 +else +num_phdrs = 1 +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) $(MAKE) -f $(BASEDIR)/Rules.mk -C test install: @@ -109,22 +116,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]* +build_id.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.gnu.build-id -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 @@ -137,6 +150,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),:) +ifdef build_id_linker +$(TARGET).efi: build_id.o +build_id_file := build_id.o +else +build_id_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 \ @@ -153,7 +173,7 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbol | $(guard) $(BASEDIR)/tools/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 $(build_id_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..d230e4c 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_extra = { + 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; Elf32_Ehdr in32_ehdr; Elf64_Ehdr in64_ehdr; Elf64_Phdr in64_phdr; - if ( argc != 5 ) + if ( argc != 6 ) { fprintf(stderr, "Usage: mkelf32 " - " \n"); + " \n"); return 1; } @@ -250,7 +280,13 @@ int main(int argc, char **argv) outimage = argv[2]; loadbase = strtoul(argv[3], NULL, 16); final_exec_addr = strtoull(argv[4], NULL, 16); - + num_phdrs = atoi(argv[5]); + if ( num_phdrs > 2 || num_phdrs < 1 ) + { + fprintf(stderr, "Number of program headers MUST be 1 or 2, got %d!\n", + num_phdrs); + return 1; + } infd = open(inimage, O_RDONLY); if ( infd == -1 ) { @@ -285,11 +321,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; } @@ -299,11 +334,36 @@ int main(int argc, char **argv) (void)lseek(infd, in64_phdr.p_offset, SEEK_SET); dat_siz = (u32)in64_phdr.p_filesz; - /* Do not use p_memsz: it does not include BSS alignment padding. */ /*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 +382,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_extra); + + /* Fill out the .note section. */ + out_shdr_extra.sh_size = note_sz; + out_shdr_extra.sh_addr = note_base; + out_shdr_extra.sh_offset = RAW_OFFSET + offset; + } + outfd = open(outimage, O_WRONLY|O_CREAT|O_TRUNC, 0775); if ( outfd == -1 ) { @@ -335,8 +420,15 @@ 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(¬e_phdr); + do_write(outfd, ¬e_phdr, sizeof(note_phdr)); + } + + if ( (bytes = RAW_OFFSET - sizeof(out_ehdr) - sizeof(out_phdr) - + ( num_phdrs > 1 ? sizeof(note_phdr) : 0 ) ) < 0 ) { fprintf(stderr, "Header overflow.\n"); return 1; @@ -355,9 +447,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_extra); + /* Append the .note section. */ + do_write(outfd, &out_shdr_extra, sizeof(out_shdr_extra)); + /* 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/xen.lds.S b/xen/arch/x86/xen.lds.S index 961f48f..705fa98 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 { @@ -75,6 +78,11 @@ SECTIONS *(.rodata) *(.rodata.*) +#if defined(BUILD_ID) && defined(EFI) + __note_gnu_build_id_start = .; + *(.note.gnu.build-id) + __note_gnu_build_id_end = .; +#endif . = ALIGN(8); /* Exception table */ @@ -96,6 +104,21 @@ SECTIONS _erodata = .; } :text +#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 : { + __note_gnu_build_id_start = .; + *(.note.gnu.build-id) + __note_gnu_build_id_end = .; + *(.note) + *(.note.*) + } :note :text +#endif + #ifdef EFI . = ALIGN(MB(2)); #endif diff --git a/xen/common/version.c b/xen/common/version.c index fc9bf42..af87371 100644 --- a/xen/common/version.c +++ b/xen/common/version.c @@ -1,5 +1,9 @@ #include +#include +#include +#include #include +#include const char *xen_compile_date(void) { @@ -61,6 +65,53 @@ const char *xen_deny(void) return ""; } +#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[]; + +int xen_build_id(const void **p, ssize_t *len) +{ + const Elf_Note *n = __note_gnu_build_id_start; + static bool_t checked = 0; + + if ( checked ) + { + *len = n->descsz; + *p = ELFNOTE_DESC(n); + return 0; + } + /* --build-id invoked with wrong parameters. */ + if ( __note_gnu_build_id_end <= __note_gnu_build_id_start ) + 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; + + *len = n->descsz; + *p = ELFNOTE_DESC(n); + + checked = 1; + return 0; +} + +#else + +int xen_build_id(const void **p, ssize_t *len) +{ + return -ENODATA; +} +#endif + /* * Local variables: * mode: C diff --git a/xen/include/xen/version.h b/xen/include/xen/version.h index 016a56c..a461c85 100644 --- a/xen/include/xen/version.h +++ b/xen/include/xen/version.h @@ -13,4 +13,7 @@ const char *xen_extra_version(void); const char *xen_changeset(void); const char *xen_banner(void); const char *xen_deny(void); +#include +int xen_build_id(const void **p, ssize_t *len); + #endif /* __XEN_VERSION_H__ */