-xsplice-build
+livepatch-build
=============
-xsplice-build is a tool for building xSplice patches from source code
+livepatch-build is a tool for building LivePatch patches from source code
patches. It takes as input, a Xen tree and a patch and outputs an
-`.xsplice` module containing containing the live patch.
+`.livepatch` module containing containing the live patch.
Quick start
-----------
$ git reset --hard
$ git clean -x -f -d
$ git checkout 346d4545569928b652c40c7815c1732676f8587c^
-$ cd ~/src/xsplice-build
+$ cd ~/src/livepatch-build
$ wget -q 'http://xenbits.xen.org/xsa/xsa106.patch'
-$ ./xsplice-build --xen-debug -s ~/src/xen -p xsa106.patch -o out
-Building xSplice patch: xsa106
+$ ./livepatch-build --xen-debug -s ~/src/xen -p xsa106.patch -o out
+Building LivePatch patch: xsa106
Xen directory: /home/ross/src/xen
-Patch file: /home/ross/src/xsplice-build/xsa106.patch
-Output directory: /home/ross/src/xsplice-build/out
+Patch file: /home/ross/src/livepatch-build/xsa106.patch
+Output directory: /home/ross/src/livepatch-build/out
================================================
Testing patch file...
Extracting new and modified ELF sections...
Processing xen/arch/x86/x86_emulate.o
Creating patch module...
-xsa106.xsplice created successfully
+xsa106.livepatch created successfully
-$ ls -lh out/xsa106.xsplice
--rw-rw-r--. 1 ross ross 418K Oct 12 12:02 out/xsa106.xsplice
+$ ls -lh out/xsa106.livepatch
+-rw-rw-r--. 1 ross ross 418K Oct 12 12:02 out/xsa106.livepatch
```
Project Status
This is prototype code:
* There's no way to apply built patches
* Patches cannot be built for some source patches
- * The output format does not correspond to the latest xSplice design
+ * The output format does not correspond to the latest LivePatch design
With no source patch modifications, live patches can be built for every
XSA that applies to x86 back to XSA-90 except for XSA-97, XSA-111,
License
-------
-xSplice is under the GPLv2 license.
+LivePatch is under the GPLv2 license.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
#define PATCH_INSN_SIZE 5
-struct xsplice_patch_func {
+struct livepatch_patch_func {
char *name;
unsigned long new_addr;
unsigned long old_addr;
struct section *sec;
struct rela *rela;
- sec = find_section_by_name(&kelf->sections, ".xsplice.ignore.functions");
+ sec = find_section_by_name(&kelf->sections, ".livepatch.ignore.functions");
if (!sec)
return;
struct rela *rela;
char *name;
- sec = find_section_by_name(&kelf->sections, ".xsplice.ignore.sections");
+ sec = find_section_by_name(&kelf->sections, ".livepatch.ignore.sections");
if (!sec)
return;
/* include load/unload sections */
list_for_each_entry(sec, &kelf->sections, list) {
- if (!strcmp(sec->name, ".xsplice.hooks.load") ||
- !strcmp(sec->name, ".xsplice.hooks.unload") ||
- !strcmp(sec->name, ".rela.xsplice.hooks.load") ||
- !strcmp(sec->name, ".rela.xsplice.hooks.unload")) {
+ if (!strcmp(sec->name, ".livepatch.hooks.load") ||
+ !strcmp(sec->name, ".livepatch.hooks.unload") ||
+ !strcmp(sec->name, ".rela.livepatch.hooks.load") ||
+ !strcmp(sec->name, ".rela.livepatch.hooks.unload")) {
sec->include = 1;
if (is_rela_section(sec)) {
/* include hook dependencies */
* used by the kpatch_[load|unload]() macros.
*/
list_for_each_entry(sym, &kelf->symbols, list)
- if (!strcmp(sym->name, "xsplice_load_data") ||
- !strcmp(sym->name, "xsplice_unload_data"))
+ if (!strcmp(sym->name, "livepatch_load_data") ||
+ !strcmp(sym->name, "livepatch_unload_data"))
sym->include = 0;
}
/* allocate section resources */
ALLOC_LINK(sec, &kelf->sections);
- sec->name = ".xsplice.strings";
+ sec->name = ".livepatch.strings";
/* set data */
sec->data = malloc(sizeof(*sec->data));
sym->sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
sym->type = STT_SECTION;
sym->bind = STB_LOCAL;
- sym->name = ".xsplice.strings";
+ sym->name = ".livepatch.strings";
}
static void kpatch_build_strings_section_data(struct kpatch_elf *kelf)
int size;
char *strtab;
- sec = find_section_by_name(&kelf->sections, ".xsplice.strings");
+ sec = find_section_by_name(&kelf->sections, ".livepatch.strings");
if (!sec)
ERROR("can't find .kpatch.strings");
* Rename local symbols to the filename#symbol format used by Xen's "special"
* symbol table.
*/
-static void xsplice_rename_local_symbols(struct kpatch_elf *kelf, char *hint)
+static void livepatch_rename_local_symbols(struct kpatch_elf *kelf, char *hint)
{
struct symbol *sym;
return sec;
}
-static void xsplice_create_patches_sections(struct kpatch_elf *kelf,
+static void livepatch_create_patches_sections(struct kpatch_elf *kelf,
struct lookup_table *table,
char *hint, int resolve)
{
struct symbol *sym, *strsym;
struct rela *rela;
struct lookup_result result;
- struct xsplice_patch_func *funcs;
+ struct livepatch_patch_func *funcs;
char *funcname;
/* count patched functions */
nr++;
/* create text/rela section pair */
- sec = create_section_pair(kelf, ".xsplice.funcs", sizeof(*funcs), nr);
+ sec = create_section_pair(kelf, ".livepatch.funcs", sizeof(*funcs), nr);
relasec = sec->rela;
funcs = sec->data->d_buf;
/* lookup strings symbol */
- strsym = find_symbol_by_name(&kelf->symbols, ".xsplice.strings");
+ strsym = find_symbol_by_name(&kelf->symbols, ".livepatch.strings");
if (!strsym)
- ERROR("can't find .xsplice.strings symbol");
+ ERROR("can't find .livepatch.strings symbol");
/* populate sections */
index = 0;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
rela->offset = index * sizeof(*funcs) +
- offsetof(struct xsplice_patch_func, new_addr);
+ offsetof(struct livepatch_patch_func, new_addr);
/*
* Add a relocation that will populate
rela->type = R_X86_64_64;
rela->addend = offset_of_string(&kelf->strings, funcname);
rela->offset = index * sizeof(*funcs) +
- offsetof(struct xsplice_patch_func, name);
+ offsetof(struct livepatch_patch_func, name);
index++;
}
log_debug("Create strings elements\n");
kpatch_create_strings_elements(kelf_out);
log_debug("Create patches sections\n");
- xsplice_create_patches_sections(kelf_out, lookup, hint,
+ livepatch_create_patches_sections(kelf_out, lookup, hint,
arguments.resolve);
kpatch_build_strings_section_data(kelf_out);
log_debug("Rename local symbols\n");
- xsplice_rename_local_symbols(kelf_out, hint);
+ livepatch_rename_local_symbols(kelf_out, hint);
/*
* At this point, the set of output sections and symbols is
--- /dev/null
+#!/bin/bash
+#
+# livepatch build script
+#
+# Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
+# Copyright (C) 2013,2014 Josh Poimboeuf <jpoimboe@redhat.com>
+# Copyright (C) 2015 Ross Lagerwall <ross.lagerwall@citrix.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This script takes a Xen tree, and a patch and outputs an livepatch
+# module intended to patch Xen at runtime.
+# Large amounts of this script are taken from kpatch's kpatch-build
+# script.
+
+SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
+CPUS="$(getconf _NPROCESSORS_ONLN)"
+DEBUG=n
+XEN_DEBUG=n
+SKIP=
+DEPENDS=
+PRELINK=
+XENSYMS=xen-syms
+
+warn() {
+ echo "ERROR: $1" >&2
+}
+
+die() {
+ if [[ -z $1 ]]; then
+ msg="LivePatch build failed"
+ else
+ msg="$1"
+ fi
+
+ warn "$msg."
+
+ exit 1
+}
+
+function make_patch_name()
+{
+ PATCHNAME=$(basename "$1")
+ if [[ "$PATCHNAME" =~ \.patch ]] || [[ "$PATCHNAME" =~ \.diff ]]; then
+ PATCHNAME="${PATCHNAME%.*}"
+ fi
+
+ # Only allow alphanumerics and '_' and '-' in the patch name. Everything
+ # else is replaced with '-'. Truncate to 48 chars.
+ echo ${PATCHNAME//[^a-zA-Z0-9_-]/-} |cut -c 1-48
+}
+
+# Do a full normal build
+function build_full()
+{
+ cd "${SRCDIR}/xen" || die
+ make "-j$CPUS" clean &> "${OUTPUT}/build_full_clean.log" || die
+ make "-j$CPUS" debug="$XEN_DEBUG" &> "${OUTPUT}/build_full_compile.log" || die
+ cp xen-syms "$OUTPUT"
+}
+
+# Build with special GCC flags
+function build_special()
+{
+ name=$1
+
+ cd "${SRCDIR}" || die
+
+ # Capture .o files from the patched build
+ export CROSS_COMPILE="${SCRIPTDIR}/livepatch-gcc "
+ export LIVEPATCH_BUILD_DIR="$(pwd)/"
+ export LIVEPATCH_CAPTURE_DIR="$OUTPUT/${name}"
+ mkdir -p "$LIVEPATCH_CAPTURE_DIR"
+
+ # Build with special GCC flags
+ cd "${SRCDIR}/xen" || die
+ sed -i 's/CFLAGS += -nostdinc/CFLAGS += -nostdinc -ffunction-sections -fdata-sections/' Rules.mk
+ make "-j$CPUS" debug="$XEN_DEBUG" &> "${OUTPUT}/build_${name}_compile.log" || die
+ sed -i 's/CFLAGS += -nostdinc -ffunction-sections -fdata-sections/CFLAGS += -nostdinc/' Rules.mk
+
+ unset LIVEPATCH_BUILD_DIR
+ unset LIVEPATCH_CAPTURE_DIR
+}
+
+function create_patch()
+{
+ echo "Extracting new and modified ELF sections..."
+
+ [[ -e "${OUTPUT}/original/changed_objs" ]] || die "no changed objects found"
+ [[ -e "${OUTPUT}/patched/changed_objs" ]] || die "no changed objects found"
+
+ cd "${OUTPUT}/original" || die
+ FILES="$(find xen -type f -name "*.o")"
+ cd "${OUTPUT}" || die
+ CHANGED=0
+ ERROR=0
+ debugopt=
+ [[ $DEBUG -eq 1 ]] && debugopt=-d
+
+ for i in $FILES; do
+ mkdir -p "output/$(dirname $i)" || die
+ echo "Processing ${i}"
+ echo "Run create-diff-object on $i" >> "${OUTPUT}/create-diff-object.log"
+ "${SCRIPTDIR}"/create-diff-object $debugopt $PRELINK "original/$i" "patched/$i" "$XENSYMS" "output/$i" &>> "${OUTPUT}/create-diff-object.log"
+ rc="${PIPESTATUS[0]}"
+ if [[ $rc = 139 ]]; then
+ warn "create-diff-object SIGSEGV"
+ if ls core* &> /dev/null; then
+ cp core* /tmp
+ die "core file at /tmp/$(ls core*)"
+ fi
+ die "no core file found, run 'ulimit -c unlimited' and try to recreate"
+ fi
+ # create-diff-object returns 3 if no functional change is found
+ [[ $rc -eq 0 ]] || [[ $rc -eq 3 ]] || ERROR=$(expr $ERROR "+" 1)
+ if [[ $rc -eq 0 ]]; then
+ CHANGED=1
+ fi
+ done
+
+ if [[ $ERROR -ne 0 ]]; then
+ die "$ERROR error(s) encountered"
+ fi
+
+ if [[ $CHANGED -eq 0 ]]; then
+ die "no functional changes found"
+ fi
+
+ # Create a dependency section
+ perl -e "print pack 'VVVZ*H*', 4, 20, 3, 'GNU', '${DEPENDS}'" > depends.bin
+
+ echo "Creating patch module..."
+ if [ -z "$PRELINK" ]; then
+ ld -r -o "${PATCHNAME}.livepatch" --build-id=sha1 $(find output -type f -name "*.o") || die
+ chmod +x "${PATCHNAME}.livepatch"
+ else
+ ld -r -o output.o --build-id=sha1 $(find output -type f -name "*.o") || die
+ "${SCRIPTDIR}"/prelink $debugopt output.o "${PATCHNAME}.livepatch" "$XENSYMS" &>> "${OUTPUT}/prelink.log" || die
+ fi
+
+ objcopy --add-section .livepatch.depends=depends.bin "${PATCHNAME}.livepatch"
+ objcopy --set-section-flags .livepatch.depends=alloc,readonly "${PATCHNAME}.livepatch"
+}
+
+usage() {
+ echo "usage: $(basename $0) [options]" >&2
+ echo " -h, --help Show this help message" >&2
+ echo " -s, --srcdir Xen source directory" >&2
+ echo " -p, --patch Patch file" >&2
+ echo " -o, --output Output directory" >&2
+ echo " -j, --cpus Number of CPUs to use" >&2
+ echo " -k, --skip Skip build or diff phase" >&2
+ echo " -d, --debug Enable debug logging" >&2
+ echo " --xen-debug Build debug Xen" >&2
+ echo " --xen-syms Build against a xen-syms" >&2
+ echo " --depends Required build-id" >&2
+ echo " --prelink Prelink" >&2
+}
+
+options=$(getopt -o hs:p:o:j:k:d -l "help,srcdir:patch:output:cpus:,skip:,debug,xen-debug,xen-syms:,depends:,prelink" -- "$@") || die "getopt failed"
+
+eval set -- "$options"
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -j|--cpus)
+ shift
+ CPUS="$1"
+ shift
+ ;;
+ -k|--skip)
+ shift
+ SKIP="$1"
+ shift
+ ;;
+ -d|--debug)
+ DEBUG=1
+ shift
+ ;;
+ --xen-debug)
+ XEN_DEBUG=y
+ shift
+ ;;
+ -s|--srcdir)
+ shift
+ srcarg="$1"
+ shift
+ ;;
+ -p|--patch)
+ shift
+ patcharg="$1"
+ shift
+ ;;
+ -o|--output)
+ shift
+ outputarg="$1"
+ shift
+ ;;
+ --xen-syms)
+ shift
+ XENSYMS="$(readlink -m -- "$1")"
+ [ -f "$XENSYMS" ] || die "xen-syms file does not exist"
+ shift
+ ;;
+ --depends)
+ shift
+ DEPENDS="$1"
+ shift
+ ;;
+ --prelink)
+ PRELINK=--resolve
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+[ -z "$srcarg" ] && die "Xen directory not given"
+[ -z "$patcharg" ] && die "Patchfile not given"
+[ -z "$outputarg" ] && die "Output directory not given"
+[ -z "$DEPENDS" ] && die "Build-id dependency not given"
+
+SRCDIR="$(readlink -m -- "$srcarg")"
+PATCHFILE="$(readlink -m -- "$patcharg")"
+OUTPUT="$(readlink -m -- "$outputarg")"
+
+[ -d "${SRCDIR}" ] || die "Xen directory does not exist"
+[ -f "${PATCHFILE}" ] || die "Patchfile does not exist"
+
+PATCHNAME=$(make_patch_name "${PATCHFILE}")
+
+echo "Building LivePatch patch: ${PATCHNAME}"
+echo
+echo "Xen directory: ${SRCDIR}"
+echo "Patch file: ${PATCHFILE}"
+echo "Output directory: ${OUTPUT}"
+echo "================================================"
+echo
+
+if [ "${SKIP}" != "build" ]; then
+ [ -e "${OUTPUT}" ] && die "Output directory exists"
+ mkdir -p "${OUTPUT}" || die
+
+ echo "Testing patch file..."
+ cd "$SRCDIR" || die
+ patch -s -N -p1 --dry-run < "$PATCHFILE" || die "source patch file failed to apply"
+
+ echo "Perform full initial build with ${CPUS} CPU(s)..."
+ build_full
+
+ echo "Apply patch and build with ${CPUS} CPU(s)..."
+ cd "$SRCDIR" || die
+ patch -s -N -p1 < "$PATCHFILE" || die
+ build_special patched
+
+ echo "Unapply patch and build with ${CPUS} CPU(s)..."
+ cd "$SRCDIR" || die
+ patch -s -R -p1 < "$PATCHFILE" || die
+ build_special original
+fi
+
+if [ "${SKIP}" != "diff" ]; then
+ [ -d "${OUTPUT}" ] || die "Output directory does not exist"
+
+ cd "${OUTPUT}" || die
+ create_patch
+ echo "${PATCHNAME}.livepatch created successfully"
+fi
--- /dev/null
+#!/bin/bash
+#
+# livepatch build script
+#
+# Copyright (C) 2015 Ross Lagerwall <ross.lagerwall@citrix.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Based on kpatch's kpatch-gcc script.
+
+TOOLCHAINCMD="$1"
+shift
+
+declare -a args=("$@")
+keep=no
+
+if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
+ while [ "$#" -gt 0 ]; do
+ if [ "$1" = "-o" ]; then
+ obj=$2
+ [[ $2 = */.tmp_*.o ]] && obj=${2/.tmp_/}
+ case "$obj" in
+ version.o|\
+ debug.o|\
+ *.xen-syms.*.o|\
+ .*.o)
+ break
+ ;;
+ *.o)
+ path="$(pwd)/$(dirname $obj)"
+ dir="${path#$LIVEPATCH_BUILD_DIR}"
+ if [ -n "$LIVEPATCH_CAPTURE_DIR" -a -d "$LIVEPATCH_CAPTURE_DIR" ]; then
+ echo "$dir/$obj" >> "${LIVEPATCH_CAPTURE_DIR}/changed_objs"
+ keep=yes
+ fi
+ break
+ ;;
+ *)
+ break
+ ;;
+ esac
+ fi
+ shift
+done
+fi
+
+"$TOOLCHAINCMD" "${args[@]}"
+ret="$?"
+
+if [[ "$keep" = "yes" ]] ; then
+ mkdir -p "$(dirname $LIVEPATCH_CAPTURE_DIR/$dir/$obj)"
+ cp "$obj" "$LIVEPATCH_CAPTURE_DIR/$dir/$obj"
+fi
+
+exit "$ret"
enum loglevel loglevel = NORMAL;
/* Resolve symbols using xen-syms */
-void xsplice_resolve_symbols(struct kpatch_elf *kelf,
+void livepatch_resolve_symbols(struct kpatch_elf *kelf,
struct lookup_table *table)
{
struct symbol *sym;
lookup = lookup_open(arguments.args[2]);
log_debug("Resolve symbols\n");
- xsplice_resolve_symbols(kelf, lookup);
+ livepatch_resolve_symbols(kelf, lookup);
/*
* Update rela section headers and rebuild the rela section data
+++ /dev/null
-#!/bin/bash
-#
-# xsplice build script
-#
-# Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
-# Copyright (C) 2013,2014 Josh Poimboeuf <jpoimboe@redhat.com>
-# Copyright (C) 2015 Ross Lagerwall <ross.lagerwall@citrix.com>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# This script takes a Xen tree, and a patch and outputs an xsplice
-# module intended to patch Xen at runtime.
-# Large amounts of this script are taken from kpatch's kpatch-build
-# script.
-
-SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
-CPUS="$(getconf _NPROCESSORS_ONLN)"
-DEBUG=n
-XEN_DEBUG=n
-SKIP=
-DEPENDS=
-PRELINK=
-XENSYMS=xen-syms
-
-warn() {
- echo "ERROR: $1" >&2
-}
-
-die() {
- if [[ -z $1 ]]; then
- msg="xSplice build failed"
- else
- msg="$1"
- fi
-
- warn "$msg."
-
- exit 1
-}
-
-function make_patch_name()
-{
- PATCHNAME=$(basename "$1")
- if [[ "$PATCHNAME" =~ \.patch ]] || [[ "$PATCHNAME" =~ \.diff ]]; then
- PATCHNAME="${PATCHNAME%.*}"
- fi
-
- # Only allow alphanumerics and '_' and '-' in the patch name. Everything
- # else is replaced with '-'. Truncate to 48 chars.
- echo ${PATCHNAME//[^a-zA-Z0-9_-]/-} |cut -c 1-48
-}
-
-# Do a full normal build
-function build_full()
-{
- cd "${SRCDIR}/xen" || die
- make "-j$CPUS" clean &> "${OUTPUT}/build_full_clean.log" || die
- make "-j$CPUS" debug="$XEN_DEBUG" &> "${OUTPUT}/build_full_compile.log" || die
- cp xen-syms "$OUTPUT"
-}
-
-# Build with special GCC flags
-function build_special()
-{
- name=$1
-
- cd "${SRCDIR}" || die
-
- # Capture .o files from the patched build
- export CROSS_COMPILE="${SCRIPTDIR}/xsplice-gcc "
- export XSPLICE_BUILD_DIR="$(pwd)/"
- export XSPLICE_CAPTURE_DIR="$OUTPUT/${name}"
- mkdir -p "$XSPLICE_CAPTURE_DIR"
-
- # Build with special GCC flags
- cd "${SRCDIR}/xen" || die
- sed -i 's/CFLAGS += -nostdinc/CFLAGS += -nostdinc -ffunction-sections -fdata-sections/' Rules.mk
- make "-j$CPUS" debug="$XEN_DEBUG" &> "${OUTPUT}/build_${name}_compile.log" || die
- sed -i 's/CFLAGS += -nostdinc -ffunction-sections -fdata-sections/CFLAGS += -nostdinc/' Rules.mk
-
- unset XSPLICE_BUILD_DIR
- unset XSPLICE_CAPTURE_DIR
-}
-
-function create_patch()
-{
- echo "Extracting new and modified ELF sections..."
-
- [[ -e "${OUTPUT}/original/changed_objs" ]] || die "no changed objects found"
- [[ -e "${OUTPUT}/patched/changed_objs" ]] || die "no changed objects found"
-
- cd "${OUTPUT}/original" || die
- FILES="$(find xen -type f -name "*.o")"
- cd "${OUTPUT}" || die
- CHANGED=0
- ERROR=0
- debugopt=
- [[ $DEBUG -eq 1 ]] && debugopt=-d
-
- for i in $FILES; do
- mkdir -p "output/$(dirname $i)" || die
- echo "Processing ${i}"
- echo "Run create-diff-object on $i" >> "${OUTPUT}/create-diff-object.log"
- "${SCRIPTDIR}"/create-diff-object $debugopt $PRELINK "original/$i" "patched/$i" "$XENSYMS" "output/$i" &>> "${OUTPUT}/create-diff-object.log"
- rc="${PIPESTATUS[0]}"
- if [[ $rc = 139 ]]; then
- warn "create-diff-object SIGSEGV"
- if ls core* &> /dev/null; then
- cp core* /tmp
- die "core file at /tmp/$(ls core*)"
- fi
- die "no core file found, run 'ulimit -c unlimited' and try to recreate"
- fi
- # create-diff-object returns 3 if no functional change is found
- [[ $rc -eq 0 ]] || [[ $rc -eq 3 ]] || ERROR=$(expr $ERROR "+" 1)
- if [[ $rc -eq 0 ]]; then
- CHANGED=1
- fi
- done
-
- if [[ $ERROR -ne 0 ]]; then
- die "$ERROR error(s) encountered"
- fi
-
- if [[ $CHANGED -eq 0 ]]; then
- die "no functional changes found"
- fi
-
- # Create a dependency section
- perl -e "print pack 'VVVZ*H*', 4, 20, 3, 'GNU', '${DEPENDS}'" > depends.bin
-
- echo "Creating patch module..."
- if [ -z "$PRELINK" ]; then
- ld -r -o "${PATCHNAME}.xsplice" --build-id=sha1 $(find output -type f -name "*.o") || die
- chmod +x "${PATCHNAME}.xsplice"
- else
- ld -r -o output.o --build-id=sha1 $(find output -type f -name "*.o") || die
- "${SCRIPTDIR}"/prelink $debugopt output.o "${PATCHNAME}.xsplice" "$XENSYMS" &>> "${OUTPUT}/prelink.log" || die
- fi
-
- objcopy --add-section .xsplice.depends=depends.bin "${PATCHNAME}.xsplice"
- objcopy --set-section-flags .xsplice.depends=alloc,readonly "${PATCHNAME}.xsplice"
-}
-
-usage() {
- echo "usage: $(basename $0) [options]" >&2
- echo " -h, --help Show this help message" >&2
- echo " -s, --srcdir Xen source directory" >&2
- echo " -p, --patch Patch file" >&2
- echo " -o, --output Output directory" >&2
- echo " -j, --cpus Number of CPUs to use" >&2
- echo " -k, --skip Skip build or diff phase" >&2
- echo " -d, --debug Enable debug logging" >&2
- echo " --xen-debug Build debug Xen" >&2
- echo " --xen-syms Build against a xen-syms" >&2
- echo " --depends Required build-id" >&2
- echo " --prelink Prelink" >&2
-}
-
-options=$(getopt -o hs:p:o:j:k:d -l "help,srcdir:patch:output:cpus:,skip:,debug,xen-debug,xen-syms:,depends:,prelink" -- "$@") || die "getopt failed"
-
-eval set -- "$options"
-
-while [[ $# -gt 0 ]]; do
- case "$1" in
- -h|--help)
- usage
- exit 0
- ;;
- -j|--cpus)
- shift
- CPUS="$1"
- shift
- ;;
- -k|--skip)
- shift
- SKIP="$1"
- shift
- ;;
- -d|--debug)
- DEBUG=1
- shift
- ;;
- --xen-debug)
- XEN_DEBUG=y
- shift
- ;;
- -s|--srcdir)
- shift
- srcarg="$1"
- shift
- ;;
- -p|--patch)
- shift
- patcharg="$1"
- shift
- ;;
- -o|--output)
- shift
- outputarg="$1"
- shift
- ;;
- --xen-syms)
- shift
- XENSYMS="$(readlink -m -- "$1")"
- [ -f "$XENSYMS" ] || die "xen-syms file does not exist"
- shift
- ;;
- --depends)
- shift
- DEPENDS="$1"
- shift
- ;;
- --prelink)
- PRELINK=--resolve
- shift
- ;;
- --)
- shift
- break
- ;;
- esac
-done
-
-[ -z "$srcarg" ] && die "Xen directory not given"
-[ -z "$patcharg" ] && die "Patchfile not given"
-[ -z "$outputarg" ] && die "Output directory not given"
-[ -z "$DEPENDS" ] && die "Build-id dependency not given"
-
-SRCDIR="$(readlink -m -- "$srcarg")"
-PATCHFILE="$(readlink -m -- "$patcharg")"
-OUTPUT="$(readlink -m -- "$outputarg")"
-
-[ -d "${SRCDIR}" ] || die "Xen directory does not exist"
-[ -f "${PATCHFILE}" ] || die "Patchfile does not exist"
-
-PATCHNAME=$(make_patch_name "${PATCHFILE}")
-
-echo "Building xSplice patch: ${PATCHNAME}"
-echo
-echo "Xen directory: ${SRCDIR}"
-echo "Patch file: ${PATCHFILE}"
-echo "Output directory: ${OUTPUT}"
-echo "================================================"
-echo
-
-if [ "${SKIP}" != "build" ]; then
- [ -e "${OUTPUT}" ] && die "Output directory exists"
- mkdir -p "${OUTPUT}" || die
-
- echo "Testing patch file..."
- cd "$SRCDIR" || die
- patch -s -N -p1 --dry-run < "$PATCHFILE" || die "source patch file failed to apply"
-
- echo "Perform full initial build with ${CPUS} CPU(s)..."
- build_full
-
- echo "Apply patch and build with ${CPUS} CPU(s)..."
- cd "$SRCDIR" || die
- patch -s -N -p1 < "$PATCHFILE" || die
- build_special patched
-
- echo "Unapply patch and build with ${CPUS} CPU(s)..."
- cd "$SRCDIR" || die
- patch -s -R -p1 < "$PATCHFILE" || die
- build_special original
-fi
-
-if [ "${SKIP}" != "diff" ]; then
- [ -d "${OUTPUT}" ] || die "Output directory does not exist"
-
- cd "${OUTPUT}" || die
- create_patch
- echo "${PATCHNAME}.xsplice created successfully"
-fi
+++ /dev/null
-#!/bin/bash
-#
-# xsplice build script
-#
-# Copyright (C) 2015 Ross Lagerwall <ross.lagerwall@citrix.com>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# Based on kpatch's kpatch-gcc script.
-
-TOOLCHAINCMD="$1"
-shift
-
-declare -a args=("$@")
-keep=no
-
-if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
- while [ "$#" -gt 0 ]; do
- if [ "$1" = "-o" ]; then
- obj=$2
- [[ $2 = */.tmp_*.o ]] && obj=${2/.tmp_/}
- case "$obj" in
- version.o|\
- debug.o|\
- *.xen-syms.*.o|\
- .*.o)
- break
- ;;
- *.o)
- path="$(pwd)/$(dirname $obj)"
- dir="${path#$XSPLICE_BUILD_DIR}"
- if [ -n "$XSPLICE_CAPTURE_DIR" -a -d "$XSPLICE_CAPTURE_DIR" ]; then
- echo "$dir/$obj" >> "${XSPLICE_CAPTURE_DIR}/changed_objs"
- keep=yes
- fi
- break
- ;;
- *)
- break
- ;;
- esac
- fi
- shift
-done
-fi
-
-"$TOOLCHAINCMD" "${args[@]}"
-ret="$?"
-
-if [[ "$keep" = "yes" ]] ; then
- mkdir -p "$(dirname $XSPLICE_CAPTURE_DIR/$dir/$obj)"
- cp "$obj" "$XSPLICE_CAPTURE_DIR/$dir/$obj"
-fi
-
-exit "$ret"