├── kmodsrc ├── x86 │ ├── libudis86 │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── syn.h │ │ ├── input.h │ │ ├── syn.c │ │ ├── extern.h │ │ ├── udis86.c │ │ ├── decode.h │ │ ├── syn-att.c │ │ ├── syn-intel.c │ │ ├── types.h │ │ └── input.c │ └── udis86.h ├── ksplice-rmsyms.lds ├── offsets.h ├── ksplice.lds.S ├── old_code_loader.c ├── arm │ └── ksplice-arch.c ├── Makefile.in ├── new_code_loader.c ├── offsets.c └── ksplice.h ├── autogen.sh ├── AUTHORS ├── .gitignore ├── INSTALL ├── aclocal.m4 ├── Verbose.pm ├── ksplice-cc.pl ├── README ├── kernel-utsname.c ├── m4 └── ac_prog_perl_modules.m4 ├── ksplice-patch ├── ksplice-shadow.h └── ksplice-patch.h ├── configure.ac ├── ChangeLog ├── Makefile.in ├── ksplice-view.in ├── ksplice-obj.pl.in ├── ksplice-undo.in ├── Ksplice.pm.in ├── objcommon.h ├── Makefile.ksplice ├── objcommon.c ├── ksplice-apply.in ├── inspect.c └── COPYING /kmodsrc/x86/libudis86/.gitignore: -------------------------------------------------------------------------------- 1 | /itab.c 2 | /itab.h 3 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | aclocal -I m4 || exit 1 4 | autoconf || exit 1 5 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Jeff Arnold 2 | Anders Kaseorg 3 | Tim Abbott 4 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += kudis86.o 2 | kudis86-objs += \ 3 | itab.o \ 4 | input.o \ 5 | decode.o \ 6 | syn.o \ 7 | syn-intel.o \ 8 | syn-att.o \ 9 | udis86.o 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.8 2 | *~ 3 | .*.sw? 4 | *.orig 5 | *.rej 6 | 7 | cscope.out 8 | /autom4te.cache/ 9 | /config.log 10 | /config.status 11 | /inspect 12 | /kernel-utsname 13 | /ksplice-apply 14 | /ksplice-create 15 | /ksplice-obj.pl 16 | /Ksplice.pm 17 | /ksplice-undo 18 | /ksplice-view 19 | /Makefile 20 | /objmanip 21 | /kmodsrc/Makefile 22 | -------------------------------------------------------------------------------- /kmodsrc/ksplice-rmsyms.lds: -------------------------------------------------------------------------------- 1 | SECTIONS { 2 | /DISCARD/ : { 3 | *(.ksplice_extract .ksplice_relocs.ksplice_extract) 4 | } 5 | .ksplice_init_relocs : { 6 | ksplice_init_relocs = .; 7 | KEEP(*(.ksplice_relocs*)) 8 | ksplice_init_relocs_end = .; 9 | } 10 | .ksplice_system_map : { 11 | ksplice_system_map = .; 12 | KEEP(*(.ksplice_system_map)) 13 | ksplice_system_map_end = .; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kmodsrc/offsets.h: -------------------------------------------------------------------------------- 1 | struct table_section { 2 | const char *sect; 3 | int entry_size; 4 | int entry_contents_size; 5 | int entry_align; 6 | int has_addr; 7 | int relative_addr; 8 | int addr_offset; 9 | const char *other_sect; 10 | int relative_other; 11 | int other_offset; 12 | const char *crc_sect; 13 | int crc_size; 14 | }; 15 | 16 | struct ksplice_config { 17 | int ignore_devinit; 18 | int ignore_cpuinit; 19 | int ignore_meminit; 20 | }; 21 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Ksplice 2 | Copyright (C) 2007-2009 Ksplice, Inc. 3 | Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License, version 2. 7 | 8 | For more information about Ksplice, please see . 9 | 10 | Installation instructions: 11 | $ ./configure 12 | $ make 13 | $ make install 14 | 15 | Notable Build Dependencies: 16 | - GNU binary file descriptor (BFD) library (version 2.15 or later) 17 | (available in Debian's binutils-dev package and in other distributions) 18 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | # generated automatically by aclocal 1.11.1 -*- Autoconf -*- 2 | 3 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 4 | # 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. 5 | # This file is free software; the Free Software Foundation 6 | # gives unlimited permission to copy and/or distribute it, 7 | # with or without modifications, as long as this notice is preserved. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 11 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12 | # PARTICULAR PURPOSE. 13 | 14 | m4_include([m4/ac_prog_perl_modules.m4]) 15 | -------------------------------------------------------------------------------- /kmodsrc/ksplice.lds.S: -------------------------------------------------------------------------------- 1 | #define PTR_KEEP_SQUASH(section) \ 2 | .##section : { \ 3 | section = .; \ 4 | KEEP(*(.##section##*)) \ 5 | section##_end = .; \ 6 | } 7 | #define PTR_KEEP(section) \ 8 | .##section : { \ 9 | section = .; \ 10 | KEEP(*(.##section)) \ 11 | section##_end = .; \ 12 | } 13 | SECTIONS { 14 | .text : { *(.text .text.* .exit.text .sched.text) } 15 | PTR_KEEP_SQUASH(ksplice_relocs) 16 | PTR_KEEP_SQUASH(ksplice_sections) 17 | PTR_KEEP_SQUASH(ksplice_patches) 18 | PTR_KEEP(ksplice_symbols) 19 | PTR_KEEP(ksplice_system_map) 20 | PTR_KEEP(ksplice_call_pre_apply) 21 | PTR_KEEP(ksplice_call_check_apply) 22 | PTR_KEEP(ksplice_call_apply) 23 | PTR_KEEP(ksplice_call_post_apply) 24 | PTR_KEEP(ksplice_call_fail_apply) 25 | PTR_KEEP(ksplice_call_pre_reverse) 26 | PTR_KEEP(ksplice_call_check_reverse) 27 | PTR_KEEP(ksplice_call_reverse) 28 | PTR_KEEP(ksplice_call_post_reverse) 29 | PTR_KEEP(ksplice_call_fail_reverse) 30 | PTR_KEEP(parainstructions) 31 | } 32 | -------------------------------------------------------------------------------- /Verbose.pm: -------------------------------------------------------------------------------- 1 | package Verbose; 2 | use strict; 3 | use warnings; 4 | 5 | our $AUTOLOAD; 6 | our $level = 0; 7 | 8 | sub import { 9 | my $self = shift; 10 | my $minlevel = 0; 11 | foreach (@_) { 12 | if (m/^:(\d+)$/) { 13 | $minlevel = $1; 14 | } else { 15 | &make_verbose($minlevel, $_, (caller)[0]); 16 | } 17 | } 18 | } 19 | 20 | sub AUTOLOAD { 21 | &make_verbose($AUTOLOAD, (caller)[0]); 22 | goto &$AUTOLOAD; 23 | } 24 | 25 | sub debugcall { 26 | my ($minlevel, $name, @args) = @_; 27 | local $" = ', '; 28 | print "+ $name(@args)\n" if ($level >= $minlevel); 29 | } 30 | 31 | sub make_verbose { 32 | no strict 'refs'; 33 | no warnings qw(redefine prototype); 34 | my ($minlevel, $sym, $pkg) = @_; 35 | $sym = "${pkg}::$sym" unless $sym =~ /::/; 36 | my $name = $sym; 37 | $name =~ s/.*::// or $name =~ s/^&//; 38 | my ($sref, $call, $proto); 39 | if (defined(&$sym)) { 40 | $sref = \&$sym; 41 | $call = '&$sref'; 42 | $proto = prototype $sref; 43 | } else { 44 | $call = "CORE::$name"; 45 | $proto = prototype $call; 46 | } 47 | $proto = '@' unless defined($proto); 48 | my $code = "package $pkg; sub ($proto) { Verbose::debugcall($minlevel, \"$name\", \@_); $call(\@_); }"; 49 | *{$sym} = eval($code); 50 | } 51 | 52 | 1; 53 | -------------------------------------------------------------------------------- /ksplice-cc.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (C) 2008-2009 Ksplice, Inc. 4 | # Authors: Anders Kaseorg, Jeff Arnold, Tim Abbott 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License, version 2. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 17 | # 02110-1301, USA. 18 | 19 | use strict; 20 | use warnings; 21 | use IPC::Open3; 22 | use Cwd qw(abs_path); 23 | use File::Basename; 24 | 25 | my $dir = abs_path(dirname($0) . "/ksplice-patch"); 26 | my @cmd; 27 | foreach (@ARGV) { 28 | if (/^-ksplice-cflags-api=1$/) { 29 | push @cmd, "-I$dir"; 30 | push @cmd, qw(-D__DATE__="<{DATE...}>" -D__TIME__="<{TIME}>"); 31 | } else { 32 | push @cmd, $_; 33 | } 34 | } 35 | 36 | my $pid = open3('<&STDIN', '>&STDOUT', \*ERROR, @cmd); 37 | while () { 38 | next if /^(?::\d+:\d+)?: warning: "(?:__DATE__|__TIME__)" redefined(?: \[-Wbuiltin-macro-redefined\])?$/; 39 | print STDERR; 40 | } 41 | close ERROR; 42 | waitpid($pid, 0) == $pid and ($? & 127) == 0 or die; 43 | exit($? >> 8); 44 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Ksplice 2 | ======= 3 | 4 | This set of tools serves the purpose of creating from a standard patch a 5 | binary patch that can be applied to a running Linux kernel without a need of 6 | rebooting. 7 | 8 | It stops the kernel, performs neccessary checks and applies the binary patch. 9 | The kernel is then resumed with a new code running. 10 | 11 | WHAT DO I NEED? 12 | --------------- 13 | * System.map and .config from your running kernel (a build dir at best) 14 | * sources of your running kernel 15 | * toolkit used to build your running kernel (or as much akin as possible) 16 | * and finally: the patch to be applied 17 | 18 | STEP BY STEP HOWTO 19 | ------------------ 20 | 1. create a configuration dir to prepare the build 21 | a) put there System.map 22 | b) put there a build dir named "build" (or a link if you have one already) 23 | c) create flags file there with flags passed to make during the normal 24 | kernel build, like O=path, typically the "build" dir [optional] 25 | 26 | 2. run ksplice-create to create a binary patch 27 | $ ksplice-create --patch=patch --config=confdir -j X kernel_source_dir 28 | where 29 | patch is a diff to be applied (and create a binary patch for) 30 | confdir is a dir from step 1. 31 | kernel_source_dir is a dir with kernel sources 32 | -j means how many jobs (X) to run in parallel [optional] 33 | Additionally --description may be supplied. It is shown by ksplice-view 34 | later. 35 | 36 | 3. run ksplice-apply to update your running kernel 37 | your binary patch is ready, so it can be applied: 38 | ksplice-apply ksplice-ID.tar.gz 39 | 40 | 4. check the applied patches by ksplice-view 41 | -------------------------------------------------------------------------------- /kmodsrc/x86/udis86.h: -------------------------------------------------------------------------------- 1 | /* udis86 - udis86.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UDIS86_H 27 | #define UDIS86_H 28 | 29 | #include "libudis86/types.h" 30 | #include "libudis86/extern.h" 31 | #include "libudis86/itab.h" 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /kernel-utsname.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2008-2009 Ksplice, Inc. 2 | * Authors: Tim Abbott, Anders Kaseorg, Jeff Arnold 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #define _GNU_SOURCE 19 | #include "objcommon.h" 20 | #include 21 | 22 | static void print_section(struct superbfd *sbfd, const char *fieldname, 23 | const char *sectname) 24 | { 25 | asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname); 26 | assert(sect != NULL); 27 | struct supersect *ss = fetch_supersect(sbfd, sect); 28 | printf("%s: %s\n", fieldname, read_string(ss, ss->contents.data)); 29 | } 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | bfd *ibfd; 34 | 35 | assert(argc >= 1); 36 | bfd_init(); 37 | ibfd = bfd_openr(argv[1], NULL); 38 | assert(ibfd); 39 | 40 | char **matching; 41 | assert(bfd_check_format_matches(ibfd, bfd_object, &matching)); 42 | 43 | struct superbfd *sbfd = fetch_superbfd(ibfd); 44 | 45 | print_section(sbfd, "Sysname", ".uts_sysname"); 46 | print_section(sbfd, "Machine", ".uts_machine"); 47 | print_section(sbfd, "Release", ".uts_release"); 48 | print_section(sbfd, "Version", ".uts_version"); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /m4/ac_prog_perl_modules.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ac_prog_perl_modules.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AC_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks to see if the given perl modules are available. If true the shell 12 | # commands in ACTION-IF-TRUE are executed. If not the shell commands in 13 | # ACTION-IF-FALSE are run. Note if $PERL is not set (for example by 14 | # calling AC_CHECK_PROG, or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl) 15 | # will be run. 16 | # 17 | # Example: 18 | # 19 | # AC_CHECK_PERL_MODULES(Text::Wrap Net::LDAP, , 20 | # AC_MSG_WARN(Need some Perl modules) 21 | # 22 | # LICENSE 23 | # 24 | # Copyright (c) 2009 Dean Povey 25 | # 26 | # Copying and distribution of this file, with or without modification, are 27 | # permitted in any medium without royalty provided the copyright notice 28 | # and this notice are preserved. 29 | 30 | AC_DEFUN([AC_PROG_PERL_MODULES],[dnl 31 | ac_perl_modules="$1" 32 | # Make sure we have perl 33 | if test -z "$PERL"; then 34 | AC_CHECK_PROG(PERL,perl,perl) 35 | fi 36 | 37 | if test "x$PERL" != x; then 38 | ac_perl_modules_failed=0 39 | for ac_perl_module in $ac_perl_modules; do 40 | AC_MSG_CHECKING(for perl module $ac_perl_module) 41 | 42 | # Would be nice to log result here, but can't rely on autoconf internals 43 | $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 44 | if test $? -ne 0; then 45 | AC_MSG_RESULT(no); 46 | ac_perl_modules_failed=1 47 | else 48 | AC_MSG_RESULT(ok); 49 | fi 50 | done 51 | 52 | # Run optional shell commands 53 | if test "$ac_perl_modules_failed" = 0; then 54 | : 55 | $2 56 | else 57 | : 58 | $3 59 | fi 60 | else 61 | AC_MSG_WARN(could not find perl) 62 | fi])dnl 63 | -------------------------------------------------------------------------------- /ksplice-patch/ksplice-shadow.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ksplice-patch.h" 4 | 5 | struct shadow_field { 6 | void *obj; 7 | void *data; 8 | int *key; 9 | struct list_head list; 10 | }; 11 | 12 | LIST_HEAD(shadow_list); 13 | DEFINE_SPINLOCK(shadow_lock); 14 | 15 | int init_shadow_field_type(int *shadow_key, typeof(GFP_KERNEL) gfp_flags) 16 | { 17 | return 0; 18 | } 19 | 20 | void *init_shadow_field(int *shadow_key, void *obj, int size, 21 | typeof(GFP_KERNEL) gfp_flags) 22 | { 23 | struct shadow_field *shadow = kmalloc(sizeof(*shadow), gfp_flags); 24 | if (shadow == NULL) 25 | return NULL; 26 | shadow->obj = obj; 27 | shadow->key = shadow_key; 28 | shadow->data = kmalloc(size, gfp_flags); 29 | if (shadow->data == NULL) { 30 | kfree(shadow); 31 | return NULL; 32 | } 33 | spin_lock(&shadow_lock); 34 | list_add(&shadow->list, &shadow_list); 35 | spin_unlock(&shadow_lock); 36 | return shadow->data; 37 | } 38 | 39 | void cleanup_shadow_field(int *shadow_key, void *obj) 40 | { 41 | struct shadow_field *shadow; 42 | spin_lock(&shadow_lock); 43 | list_for_each_entry(shadow, &shadow_list, list) { 44 | if (shadow->obj == obj && shadow->key == shadow_key) { 45 | list_del(&shadow->list); 46 | kfree(shadow->data); 47 | kfree(shadow); 48 | goto out; 49 | } 50 | } 51 | out: 52 | spin_unlock(&shadow_lock); 53 | } 54 | 55 | void *get_shadow_field(int *shadow_key, void *obj) 56 | { 57 | struct shadow_field *shadow; 58 | void *data = NULL; 59 | spin_lock(&shadow_lock); 60 | list_for_each_entry(shadow, &shadow_list, list) { 61 | if (shadow->obj == obj && shadow->key == shadow_key) { 62 | data = shadow->data; 63 | goto out; 64 | } 65 | } 66 | out: 67 | spin_unlock(&shadow_lock); 68 | return data; 69 | } 70 | 71 | void cleanup_shadow_field_type(int *shadow_key) 72 | { 73 | struct shadow_field *shadow, *n; 74 | spin_lock(&shadow_lock); 75 | list_for_each_entry_safe(shadow, n, &shadow_list, list) { 76 | if (shadow->key == shadow_key) { 77 | list_del(&shadow->list); 78 | kfree(shadow->data); 79 | kfree(shadow); 80 | } 81 | } 82 | spin_unlock(&shadow_lock); 83 | } 84 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/syn.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | /* ----------------------------------------------------------------------------- 27 | * syn.h 28 | * 29 | * Copyright (c) 2006, Vivek Mohan 30 | * All rights reserved. See LICENSE 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | #ifndef UD_SYN_H 34 | #define UD_SYN_H 35 | 36 | #include "types.h" 37 | #ifndef __UD_STANDALONE__ 38 | # include 39 | #endif /* __UD_STANDALONE__ */ 40 | 41 | extern const char* ud_reg_tab[]; 42 | 43 | static void mkasm(struct ud* u, const char* fmt, ...) 44 | { 45 | va_list ap; 46 | va_start(ap, fmt); 47 | u->insn_fill += vsprintf((char*) u->insn_buffer + u->insn_fill, fmt, ap); 48 | va_end(ap); 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /kmodsrc/old_code_loader.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2009 Ksplice, Inc. 2 | * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #ifdef KSPLICE_STANDALONE 19 | #include "ksplice.h" 20 | #else 21 | #include 22 | #endif 23 | 24 | extern struct ksplice_reloc ksplice_relocs[], ksplice_relocs_end[]; 25 | extern struct ksplice_section ksplice_sections[], ksplice_sections_end[]; 26 | extern struct ksplice_symbol ksplice_symbols[], ksplice_symbols_end[]; 27 | #ifdef KSPLICE_STANDALONE 28 | extern struct ksplice_system_map ksplice_system_map[], ksplice_system_map_end[]; 29 | #endif /* KSPLICE_STANDALONE */ 30 | 31 | /* Defined in new_code_loader.c */ 32 | #define change KSPLICE_UNIQ(change) 33 | extern struct ksplice_mod_change change; 34 | 35 | static struct ksplice_code old_code = { 36 | .relocs = ksplice_relocs, 37 | .relocs_end = ksplice_relocs_end, 38 | .sections = ksplice_sections, 39 | .sections_end = ksplice_sections_end, 40 | .symbols = ksplice_symbols, 41 | .symbols_end = ksplice_symbols_end, 42 | #ifdef KSPLICE_STANDALONE 43 | .system_map = ksplice_system_map, 44 | .system_map_end = ksplice_system_map_end, 45 | #endif /* KSPLICE_STANDALONE */ 46 | }; 47 | 48 | static int init_old_code(void) 49 | { 50 | change.old_code = old_code; 51 | return init_ksplice_mod_change(&change); 52 | } 53 | 54 | static void cleanup_old_code(void) 55 | { 56 | cleanup_ksplice_mod_change(&change); 57 | } 58 | 59 | module_init(init_old_code); 60 | module_exit(cleanup_old_code); 61 | 62 | MODULE_AUTHOR("Ksplice, Inc."); 63 | MODULE_DESCRIPTION("Ksplice rebootless update old code module"); 64 | #ifdef KSPLICE_VERSION 65 | MODULE_VERSION(KSPLICE_VERSION); 66 | #endif 67 | MODULE_LICENSE("GPL v2"); 68 | -------------------------------------------------------------------------------- /kmodsrc/arm/ksplice-arch.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2009 Ksplice, Inc. 2 | * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #include 19 | #define KSPLICE_IP(x) thread_saved_pc(x) 20 | #define KSPLICE_SP(x) thread_saved_fp(x) 21 | 22 | static struct ksplice_symbol trampoline_symbol = { 23 | .name = NULL, 24 | .label = "", 25 | }; 26 | 27 | static const struct ksplice_reloc_howto trampoline_howto = { 28 | .type = KSPLICE_HOWTO_RELOC, 29 | .pcrel = 1, 30 | .size = 4, 31 | .dst_mask = 0x00ffffffL, 32 | .rightshift = 2, 33 | .signed_addend = 1, 34 | }; 35 | 36 | static const struct ksplice_reloc trampoline_reloc = { 37 | .symbol = &trampoline_symbol, 38 | .insn_addend = -8, 39 | .target_addend = 0, 40 | .howto = &trampoline_howto, 41 | }; 42 | 43 | static abort_t trampoline_target(struct ksplice_mod_change *change, 44 | unsigned long addr, unsigned long *new_addr) 45 | { 46 | abort_t ret; 47 | uint32_t word; 48 | if (probe_kernel_read(&word, (void *)addr, sizeof(word)) == -EFAULT) 49 | return NO_MATCH; 50 | 51 | if ((word & 0xff000000) != 0xea000000) 52 | return NO_MATCH; 53 | 54 | ret = read_reloc_value(change, &trampoline_reloc, addr, new_addr); 55 | if (ret != OK) 56 | return ret; 57 | 58 | *new_addr += addr; 59 | return OK; 60 | } 61 | 62 | static abort_t prepare_trampoline(struct ksplice_mod_change *change, 63 | struct ksplice_patch *p) 64 | { 65 | p->size = 4; 66 | *(uint32_t *)p->contents = 0xea000000; 67 | return write_reloc_value(change, &trampoline_reloc, 68 | (unsigned long)p->contents, 69 | p->repladdr - p->oldaddr); 70 | } 71 | 72 | static abort_t handle_paravirt(struct ksplice_mod_change *change, 73 | unsigned long pre_addr, unsigned long run_addr, 74 | int *matched) 75 | { 76 | *matched = 0; 77 | return OK; 78 | } 79 | 80 | static bool valid_stack_ptr(const struct thread_info *tinfo, const void *p) 81 | { 82 | return p > (const void *)tinfo 83 | && p <= (const void *)tinfo + THREAD_SIZE - sizeof(long); 84 | } 85 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/input.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/input.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_INPUT_H 27 | #define UD_INPUT_H 28 | 29 | #include "types.h" 30 | 31 | uint8_t inp_next(struct ud*); 32 | uint8_t inp_peek(struct ud*); 33 | uint8_t inp_uint8(struct ud*); 34 | uint16_t inp_uint16(struct ud*); 35 | uint32_t inp_uint32(struct ud*); 36 | uint64_t inp_uint64(struct ud*); 37 | void inp_move(struct ud*, size_t); 38 | void inp_back(struct ud*); 39 | 40 | /* inp_init() - Initializes the input system. */ 41 | #define inp_init(u) \ 42 | do { \ 43 | u->inp_curr = 0; \ 44 | u->inp_fill = 0; \ 45 | u->inp_ctr = 0; \ 46 | u->inp_end = 0; \ 47 | } while (0) 48 | 49 | /* inp_start() - Should be called before each de-code operation. */ 50 | #define inp_start(u) u->inp_ctr = 0 51 | 52 | /* inp_back() - Resets the current pointer to its position before the current 53 | * instruction disassembly was started. 54 | */ 55 | #define inp_reset(u) \ 56 | do { \ 57 | u->inp_curr -= u->inp_ctr; \ 58 | u->inp_ctr = 0; \ 59 | } while (0) 60 | 61 | /* inp_sess() - Returns the pointer to current session. */ 62 | #define inp_sess(u) (u->inp_sess) 63 | 64 | /* inp_cur() - Returns the current input byte. */ 65 | #define inp_curr(u) ((u)->inp_cache[(u)->inp_curr]) 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/syn.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | /* ----------------------------------------------------------------------------- 28 | * Intel Register Table - Order Matters (types.h)! 29 | * ----------------------------------------------------------------------------- 30 | */ 31 | const char* ud_reg_tab[] = 32 | { 33 | "al", "cl", "dl", "bl", 34 | "ah", "ch", "dh", "bh", 35 | "spl", "bpl", "sil", "dil", 36 | "r8b", "r9b", "r10b", "r11b", 37 | "r12b", "r13b", "r14b", "r15b", 38 | 39 | "ax", "cx", "dx", "bx", 40 | "sp", "bp", "si", "di", 41 | "r8w", "r9w", "r10w", "r11w", 42 | "r12w", "r13W" , "r14w", "r15w", 43 | 44 | "eax", "ecx", "edx", "ebx", 45 | "esp", "ebp", "esi", "edi", 46 | "r8d", "r9d", "r10d", "r11d", 47 | "r12d", "r13d", "r14d", "r15d", 48 | 49 | "rax", "rcx", "rdx", "rbx", 50 | "rsp", "rbp", "rsi", "rdi", 51 | "r8", "r9", "r10", "r11", 52 | "r12", "r13", "r14", "r15", 53 | 54 | "es", "cs", "ss", "ds", 55 | "fs", "gs", 56 | 57 | "cr0", "cr1", "cr2", "cr3", 58 | "cr4", "cr5", "cr6", "cr7", 59 | "cr8", "cr9", "cr10", "cr11", 60 | "cr12", "cr13", "cr14", "cr15", 61 | 62 | "dr0", "dr1", "dr2", "dr3", 63 | "dr4", "dr5", "dr6", "dr7", 64 | "dr8", "dr9", "dr10", "dr11", 65 | "dr12", "dr13", "dr14", "dr15", 66 | 67 | "mm0", "mm1", "mm2", "mm3", 68 | "mm4", "mm5", "mm6", "mm7", 69 | 70 | "st0", "st1", "st2", "st3", 71 | "st4", "st5", "st6", "st7", 72 | 73 | "xmm0", "xmm1", "xmm2", "xmm3", 74 | "xmm4", "xmm5", "xmm6", "xmm7", 75 | "xmm8", "xmm9", "xmm10", "xmm11", 76 | "xmm12", "xmm13", "xmm14", "xmm15", 77 | 78 | "rip" 79 | }; 80 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/extern.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/extern.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_EXTERN_H 27 | #define UD_EXTERN_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "types.h" 34 | 35 | /* ============================= PUBLIC API ================================= */ 36 | 37 | extern void ud_init(struct ud*); 38 | 39 | extern void ud_set_mode(struct ud*, uint8_t); 40 | 41 | extern void ud_set_pc(struct ud*, uint64_t); 42 | 43 | extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); 44 | 45 | extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t); 46 | 47 | #ifndef __UD_STANDALONE__ 48 | extern void ud_set_input_file(struct ud*, FILE*); 49 | #endif /* __UD_STANDALONE__ */ 50 | 51 | extern void ud_set_vendor(struct ud*, unsigned); 52 | 53 | extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); 54 | 55 | extern void ud_input_skip(struct ud*, size_t); 56 | 57 | extern int ud_input_end(struct ud*); 58 | 59 | extern unsigned int ud_decode(struct ud*); 60 | 61 | extern unsigned int ud_disassemble(struct ud*); 62 | 63 | extern void ud_translate_intel(struct ud*); 64 | 65 | extern void ud_translate_att(struct ud*); 66 | 67 | extern char* ud_insn_asm(struct ud* u); 68 | 69 | extern uint8_t* ud_insn_ptr(struct ud* u); 70 | 71 | extern uint64_t ud_insn_off(struct ud*); 72 | 73 | extern char* ud_insn_hex(struct ud*); 74 | 75 | extern unsigned int ud_insn_len(struct ud* u); 76 | 77 | extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); 78 | 79 | extern void ud_set_user_opaque_data(struct ud*, void*); 80 | 81 | extern void *ud_get_user_opaque_data(struct ud*); 82 | 83 | /* ========================================================================== */ 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | #endif 89 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([Ksplice], [1.0], [jslaby@suse.cz]) 2 | AC_SUBST([KSPLICE_API_VERSION], [2]) 3 | 4 | # needed for bfd and iberty 5 | AC_CHECK_LIB([dl], [dlopen]) 6 | AC_CHECK_LIB([z], [deflate]) 7 | 8 | AC_ARG_WITH([libbfd], 9 | [ --with-libbfd=FILE path to libbfd.a], 10 | [ac_libbfd=$withval], 11 | [ac_libbfd=NONE]) 12 | 13 | AC_ARG_WITH([libiberty], 14 | [ --with-libiberty=FILE path to libiberty.a], 15 | [ac_libiberty=$withval], 16 | [ac_libiberty=NONE]) 17 | 18 | AC_ARG_WITH([bfd-include-dir], 19 | [ --with-bfd-include-dir=DIR 20 | path to directory containing bfd.h], 21 | [ac_bfd_include_dir=$withval], 22 | [ac_bfd_include_dir=NONE]) 23 | 24 | AC_PROG_CC 25 | 26 | if test "$ac_libiberty" = "NONE"; then 27 | AC_CHECK_LIB([iberty], [objalloc_create]) 28 | else 29 | LIBS="$ac_libiberty $LIBS" 30 | fi 31 | if test "$ac_libbfd" = "NONE"; then 32 | ac_libbfd=auto 33 | AC_CHECK_LIB([bfd], [bfd_openr], , [ac_libbfd=NONE]) 34 | else 35 | LIBS="$ac_libbfd $LIBS" 36 | fi 37 | 38 | if test "$ac_bfd_include_dir" != "NONE"; then 39 | CPPFLAGS="$CPPFLAGS -I$ac_bfd_include_dir" 40 | fi 41 | 42 | AC_CHECK_HEADERS([bfd.h], , [BFD_H="no"]) 43 | 44 | AC_CHECK_MEMBER([struct bfd_hash_table.entsize], 45 | [CPPFLAGS="$CPPFLAGS -DBFD_HASH_TABLE_HAS_ENTSIZE"], 46 | [], 47 | [[#include ]]) 48 | 49 | if ! test -e "objmanip-static"; then 50 | if test "$ac_libbfd" = "NONE"; then 51 | echo 52 | echo "Ksplice could not locate libbfd.a and/or libiberty.a on your system." 53 | echo "You can obtain these libraries from the GNU binutils collection." 54 | echo "These libraries are available on many Linux distributions as a" 55 | echo "package called 'binutils-dev' or 'binutils-devel'." 56 | echo "If your distribution does not provide GNU binutils, you can install" 57 | echo "GNU binutils from source -- see http://www.gnu.org/software/binutils/." 58 | echo 59 | echo "If these libraries are already installed on your system, then you need" 60 | echo "to tell Ksplice where to find them by running configure again:" 61 | echo 62 | echo " ./configure --with-libbfd= --with-libiberty=" 63 | echo 64 | exit 1 65 | fi 66 | 67 | if test "$BFD_H" = "no"; then 68 | echo 69 | echo "Ksplice could not locate bfd.h on your system." 70 | echo "If this header file is already installed on your system, then you need" 71 | echo "to tell Ksplice where to find it by running configure again:" 72 | echo 73 | echo " ./configure --with-bfd-include-dir=" 74 | echo 75 | exit 1 76 | fi 77 | fi 78 | 79 | AC_PATH_PROG([PATCH], [patch]) 80 | AC_PATH_PROG([POD2MAN], [pod2man]) 81 | if test "$PATCH" = ""; then 82 | echo 83 | echo "Ksplice could not locate patch on your system." 84 | echo 85 | exit 1 86 | fi 87 | if test "$POD2MAN" = ""; then 88 | echo 89 | echo "Ksplice could not locate pod2man on your system." 90 | echo 91 | exit 1 92 | fi 93 | 94 | AC_PROG_PERL_MODULES([Cwd Getopt::Long File::Basename File::Copy File::Path File::Spec::Functions File::Temp Fatal IPC::Open2 IPC::Open3 Pod::Usage Text::ParseWords], , 95 | [AC_MSG_ERROR([Missing some required perl modules])]) 96 | 97 | AC_CONFIG_FILES([Makefile kmodsrc/Makefile]) 98 | AC_OUTPUT 99 | -------------------------------------------------------------------------------- /kmodsrc/Makefile.in: -------------------------------------------------------------------------------- 1 | prefix = @prefix@ 2 | datarootdir = @datarootdir@ 3 | datadir = @datadir@ 4 | 5 | ksplice-script = $(datadir)/ksplice/ksplice-obj.pl 6 | 7 | KSPLICE_KID ?= $(error "You must set KSPLICE_KID.") 8 | KSPLICE_VERSION ?= $(error "You must set KSPLICE_VERSION.") 9 | map_printk ?= $(error "You must set map_printk.") 10 | 11 | ifneq ($(KSPLICE_STANDALONE),) 12 | KSPLICE_CFLAGS += -DKSPLICE_STANDALONE 13 | endif 14 | KSPLICE_CFLAGS += -DKSPLICE_KID=$(KSPLICE_KID) 15 | KSPLICE_CFLAGS += -DMAP_PRINTK=0x$(map_printk)L 16 | 17 | comma ?= , 18 | name-fix ?= $(subst $(comma),_,$(subst -,_,$(1))) 19 | target = $(call name-fix,$(mod)) 20 | KSPLICE_MID = $(KSPLICE_KID)_$(target) 21 | KSPLICE = ksplice-$(KSPLICE_MID) 22 | KSPLICE_CORE = ksplice-$(KSPLICE_KID) 23 | 24 | quiet_cmd_ksplice-collect = COLLECT $@ 25 | cmd_ksplice-collect = \ 26 | $(ksplice-script) finalize $< $<.final $* && \ 27 | $(LD) --script=$(obj)/ksplice.lds -r -o $@ $<.final 28 | 29 | ksplice-mod-cflags = $(KSPLICE_CFLAGS) \ 30 | "-DKSPLICE_MID=$(KSPLICE_MID)" \ 31 | $(addprefix -DKSPLICE_TARGET=,$(target)) \ 32 | "-DKSPLICE_VERSION=\"$(KSPLICE_VERSION)\"" 33 | 34 | ksplice-new-code-objs = new-code-$(target).o collect-new-code-$(mod).o 35 | ksplice-old-code-objs = old-code-$(target).o collect-old-code-$(mod).o 36 | 37 | ifneq ($(KSPLICE_STANDALONE),) 38 | ifeq ($(KSPLICE_SKIP_CORE),) 39 | obj-m += $(KSPLICE_CORE).o 40 | endif 41 | UDIS86 = x86/libudis86 42 | kudis86 += \ 43 | $(UDIS86)/itab.o \ 44 | $(UDIS86)/input.o \ 45 | $(UDIS86)/decode.o \ 46 | $(UDIS86)/syn.o \ 47 | $(UDIS86)/syn-intel.o \ 48 | $(UDIS86)/syn-att.o \ 49 | $(UDIS86)/udis86.o 50 | $(KSPLICE_CORE)-objs = $(fake-ksplice.o) ksplice-rmsyms.o $(kudis86) 51 | fake-ksplice.o = ksplice.o 52 | $(obj)/$(KSPLICE_CORE).o: fake-ksplice.o = 53 | endif 54 | 55 | define ksplice-mod-vars 56 | ifneq ($(KSPLICE_SHORT_NAME_HACK),) 57 | obj-m += $(KSPLICE)-n.o $(KSPLICE)-o.o 58 | $(KSPLICE)-n-objs = $(ksplice-new-code-objs) 59 | $(KSPLICE)-o-objs = $(ksplice-old-code-objs) 60 | else 61 | obj-m += $(KSPLICE)-new.o $(KSPLICE)-old.o 62 | $(KSPLICE)-new-objs = $(ksplice-new-code-objs) 63 | $(KSPLICE)-old-objs = $(ksplice-old-code-objs) 64 | endif 65 | CFLAGS_new-code-$(target).o = $(ksplice-mod-cflags) 66 | CFLAGS_old-code-$(target).o = $(ksplice-mod-cflags) 67 | CPPFLAGS_ksplice.lds = $(ksplice-mod-cflags) -P 68 | endef 69 | 70 | $(foreach mod,$(KSPLICE_MODULES),$(eval $(ksplice-mod-vars))) 71 | 72 | ifneq ($(KSPLICE_MODULES),) 73 | $(foreach mod,$(KSPLICE_MODULES),$(obj)/new-code-$(target).o): $(obj)/%.o: $(src)/new_code_loader.c FORCE 74 | $(call if_changed_rule,cc_o_c) 75 | $(foreach mod,$(KSPLICE_MODULES),$(obj)/old-code-$(target).o): $(obj)/%.o: $(src)/old_code_loader.c FORCE 76 | $(call if_changed_rule,cc_o_c) 77 | endif 78 | 79 | $(obj)/collect-new-code-%.o: $(obj)/%.o.KSPLICE_new_code $(obj)/ksplice.lds FORCE 80 | $(call if_changed,ksplice-collect) 81 | $(obj)/collect-old-code-%.o: $(obj)/%.o.KSPLICE_old_code $(obj)/ksplice.lds FORCE 82 | $(call if_changed,ksplice-collect) 83 | 84 | ifeq ($(quiet_cmd_cpp_lds_S),) 85 | quiet_cmd_cpp_lds_S = LDS $@ 86 | cmd_cpp_lds_S = $(CPP) -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) $(cpp_flags) -D__ASSEMBLY__ -o $@ $< 87 | 88 | %.lds: %.lds.S FORCE 89 | $(call if_changed_dep,cpp_lds_S) 90 | endif 91 | 92 | $(obj)/ksplice.lds: $(src)/ksplice.lds.S FORCE 93 | $(call if_changed_dep,cpp_lds_S) 94 | 95 | CFLAGS_offsets.o += $(KSPLICE_CFLAGS) 96 | ifeq ($(KSPLICE_SKIP_CORE),) 97 | extra-y += offsets.o 98 | endif 99 | 100 | ifneq ($(KSPLICE_STANDALONE),) 101 | CFLAGS_ksplice.o += $(KSPLICE_CFLAGS) 102 | 103 | quiet_cmd_ksplice-rmsyms = RMSYMS $@ 104 | cmd_ksplice-rmsyms = \ 105 | $(ksplice-script) rmsyms $< $<.rmsyms && \ 106 | $(LD) --script=$(src)/ksplice-rmsyms.lds -r -o $@ $<.rmsyms 107 | $(obj)/ksplice-rmsyms.o: $(obj)/ksplice.o $(obj)/offsets.o FORCE 108 | $(call if_changed,ksplice-rmsyms) 109 | endif # KSPLICE_STANDALONE 110 | -------------------------------------------------------------------------------- /kmodsrc/new_code_loader.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2009 Ksplice, Inc. 2 | * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #ifdef KSPLICE_STANDALONE 19 | #include "ksplice.h" 20 | #else 21 | #include 22 | #endif 23 | 24 | extern struct ksplice_reloc ksplice_relocs[], ksplice_relocs_end[]; 25 | extern struct ksplice_section ksplice_sections[], ksplice_sections_end[]; 26 | extern struct ksplice_symbol ksplice_symbols[], ksplice_symbols_end[]; 27 | extern struct ksplice_patch ksplice_patches[], ksplice_patches_end[]; 28 | extern const typeof(int (*)(void)) ksplice_call_pre_apply[], 29 | ksplice_call_pre_apply_end[], ksplice_call_check_apply[], 30 | ksplice_call_check_apply_end[]; 31 | extern const typeof(void (*)(void)) ksplice_call_apply[], 32 | ksplice_call_apply_end[], ksplice_call_post_apply[], 33 | ksplice_call_post_apply_end[], ksplice_call_fail_apply[], 34 | ksplice_call_fail_apply_end[]; 35 | extern const typeof(int (*)(void)) ksplice_call_pre_reverse[], 36 | ksplice_call_pre_reverse_end[], ksplice_call_check_reverse[], 37 | ksplice_call_check_reverse_end[]; 38 | extern const typeof(void (*)(void)) ksplice_call_reverse[], 39 | ksplice_call_reverse_end[], ksplice_call_post_reverse[], 40 | ksplice_call_post_reverse_end[], ksplice_call_fail_reverse[], 41 | ksplice_call_fail_reverse_end[]; 42 | 43 | #ifdef KSPLICE_STANDALONE 44 | extern struct ksplice_system_map ksplice_system_map[], ksplice_system_map_end[]; 45 | #endif /* KSPLICE_STANDALONE */ 46 | 47 | #define change KSPLICE_UNIQ(change) 48 | struct ksplice_mod_change change = { 49 | .name = "ksplice_" __stringify(KSPLICE_MID), 50 | .kid = __stringify(KSPLICE_KID), 51 | .target_name = __stringify(KSPLICE_TARGET), 52 | #ifdef KSPLICE_STANDALONE 53 | .map_printk = MAP_PRINTK, 54 | #endif /* KSPLICE_STANDALONE */ 55 | .new_code_mod = THIS_MODULE, 56 | .new_code = { 57 | .relocs = ksplice_relocs, 58 | .relocs_end = ksplice_relocs_end, 59 | .sections = ksplice_sections, 60 | .sections_end = ksplice_sections_end, 61 | .symbols = ksplice_symbols, 62 | .symbols_end = ksplice_symbols_end, 63 | #ifdef KSPLICE_STANDALONE 64 | .system_map = ksplice_system_map, 65 | .system_map_end = ksplice_system_map_end, 66 | #endif /* KSPLICE_STANDALONE */ 67 | }, 68 | .patches = ksplice_patches, 69 | .patches_end = ksplice_patches_end, 70 | .hooks = { 71 | [KS_APPLY] = { 72 | .pre = ksplice_call_pre_apply, 73 | .pre_end = ksplice_call_pre_apply_end, 74 | .check = ksplice_call_check_apply, 75 | .check_end = ksplice_call_check_apply_end, 76 | .intra = ksplice_call_apply, 77 | .intra_end = ksplice_call_apply_end, 78 | .post = ksplice_call_post_apply, 79 | .post_end = ksplice_call_post_apply_end, 80 | .fail = ksplice_call_fail_apply, 81 | .fail_end = ksplice_call_fail_apply_end, 82 | }, 83 | [KS_REVERSE] = { 84 | .pre = ksplice_call_pre_reverse, 85 | .pre_end = ksplice_call_pre_reverse_end, 86 | .check = ksplice_call_check_reverse, 87 | .check_end = ksplice_call_check_reverse_end, 88 | .intra = ksplice_call_reverse, 89 | .intra_end = ksplice_call_reverse_end, 90 | .post = ksplice_call_post_reverse, 91 | .post_end = ksplice_call_post_reverse_end, 92 | .fail = ksplice_call_fail_reverse, 93 | .fail_end = ksplice_call_fail_reverse_end, 94 | }, 95 | }, 96 | }; 97 | EXPORT_SYMBOL_GPL(change); 98 | 99 | static int init_new_code(void) 100 | { 101 | return 0; 102 | } 103 | 104 | static void cleanup_new_code(void) 105 | { 106 | cleanup_ksplice_mod_change(&change); 107 | } 108 | 109 | module_init(init_new_code); 110 | module_exit(cleanup_new_code); 111 | 112 | MODULE_AUTHOR("Ksplice, Inc."); 113 | MODULE_DESCRIPTION("Ksplice rebootless update new code module"); 114 | #ifdef KSPLICE_VERSION 115 | MODULE_VERSION(KSPLICE_VERSION); 116 | #endif 117 | MODULE_LICENSE("GPL v2"); 118 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2012-07-10 : 1.0 2 | - Development happens now in git, look for changes there 3 | 4 | 2011-07-28 : 0.9.9.1 5 | - Removed unnecessary zlib detection from configure.ac 6 | 7 | 2009-08-21 : 0.9.9 8 | - Added support for applying an already unpacked update tree 9 | - Fixed ksplice-create when installed to a prefix other than /usr/local 10 | - Improved stack check completeness for self-restarting syscalls 11 | 12 | 2009-07-12 : 0.9.8 13 | - Improved error handling in the Ksplice perl utilities 14 | - Updated Ksplice for kernel 2.6.30 15 | - Fixed several bugs in the handling of bugline patches 16 | 17 | 2009-03-10 : 0.9.7 18 | - Fixed a bug where Ksplice relocations were sometimes written pointing 19 | to the middle of patched sections 20 | - Fixed a Makefile bug where the Ksplice core module was compiled twice 21 | - Renamed or reorganized several data structures in the Ksplice kernel code 22 | - Changed the Ksplice module names from primary/helper to old_code/new_code 23 | 24 | 2009-01-21 : 0.9.6 25 | - Fixed a Makefile bug that prevented the initial prebuild from succeeding 26 | - Documented the ksplice-create --series, --git, and --build-modules options 27 | - Added support for changing CRCs of exported symbols 28 | - Added pre-post matching of altinstructions and other table sections 29 | - Fixed a build failure due to depmod when using a kbuild output directory 30 | 31 | 2008-12-19 : 0.9.5 32 | - Added support for building updates from Git commits in ksplice-create 33 | - Prevent reversing Ksplice updates that have been partially cold applied 34 | 35 | 2008-11-21 : 0.9.4 36 | - Added support for patching kernels built in a separate Kbuild output 37 | directory (O=dir) 38 | - Added additional metadata to the Ksplice update tarballs 39 | - Updated Ksplice for kernel 2.6.28 40 | 41 | 2008-11-07 : 0.9.3 42 | - Added hooks for calling functions at various points during the update process 43 | - Added support for applying an update only to loaded target modules 44 | - Added support for building updated target modules along with a Ksplice update 45 | - Added run-pre matching of the bug table, exception table, and exported 46 | symbol table 47 | - Improved robustness of the stack check with respect to optimized tail calls 48 | - Fixed several bugs in the run-pre matching disassembly code 49 | - Added patching of rodata sections that did not change in size 50 | - Added patching of bug table entries whose line numbers changed 51 | - Added an experimental API for shadow data structures 52 | 53 | 2008-10-17 : 0.9.2 54 | - Added run-pre matching of string sections 55 | - Fixed safety_record handling for patch reversals 56 | - Improved performance substantially in both userspace and kernelspace 57 | - Added support for patching kernels whose text is mapped read-only 58 | - Added support for patching compilation units involving markers 59 | - Improved the udis86 disassembler's support for disassembling the kernel 60 | 61 | 2008-09-26 : 0.9.1 62 | - Replaced objdiff with an improved matching algorithm in objmanip keep-primary 63 | - Added support for moving functions between compilation units 64 | - Various safety improvements 65 | 66 | 2008-09-12 : 0.9.0 67 | - Added support for ARM architecture (requires an -ffunction-sections kernel) 68 | - Rewrote the relocation handling code to ease porting to other architectures 69 | - Modified the update build system so that it uses the kernel build system 70 | - Switched the module control interface from /proc to /sys 71 | - Switched the preferred debugging interface from printk to debugfs 72 | - Restructured the kernel code to make it easier to merge Ksplice into Linux 73 | - Simplified ksplice-create by moving all ELF manipulation to objmanip 74 | - Added libudis86 for enhanced run-pre matching 75 | - Added support for automatically modifying the exported symbol table 76 | - Various safety improvements 77 | 78 | 2008-06-22 : 0.8.7 79 | - Updated the nop table for binutils 2.18 80 | - Improved relocation handling on x86-64 81 | 82 | 2008-05-25 : 0.8.6 83 | - Removed some compiler warnings 84 | 85 | 2008-05-24 : 0.8.5 86 | - Added a workaround for Fedora System.map problem 87 | - Improved the page table code 88 | - Improved kernel stack check debugging 89 | 90 | 2008-04-29 : 0.8.4 91 | - Fixed architecture detection on ASP Linux 92 | 93 | 2008-04-28 : 0.8.3 94 | - Improved kernel stack check 95 | 96 | 2008-04-27 : 0.8.2 97 | - Improved kernel stack check 98 | 99 | 2008-04-24 : 0.8.1 100 | - Fixed 2.6.25 init_mm problem 101 | 102 | 2008-04-22 : 0.8.0 103 | - Initial release 104 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | srcdir = @srcdir@ 2 | VPATH = $(srcdir) 3 | 4 | prefix = @prefix@ 5 | exec_prefix = @exec_prefix@ 6 | bindir = @bindir@ 7 | sbindir = @sbindir@ 8 | libexecdir = @libexecdir@ 9 | mandir = @mandir@ 10 | datadir = @datadir@ 11 | datarootdir = @datarootdir@ 12 | 13 | CC = @CC@ 14 | CFLAGS = @CFLAGS@ 15 | CPPFLAGS = @CPPFLAGS@ 16 | LDFLAGS = @LDFLAGS@ 17 | LIBS = @LIBS@ 18 | PACKAGE_VERSION = @PACKAGE_VERSION@ 19 | KSPLICE_API_VERSION = @KSPLICE_API_VERSION@ 20 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 21 | 22 | perl_primary = ksplice-create ksplice-view ksplice-apply ksplice-undo Ksplice.pm ksplice-obj.pl 23 | perl_man = $(patsubst %,%.8,$(filter-out Ksplice.pm ksplice-obj.pl,$(perl_primary))) 24 | objutils = objmanip inspect kernel-utsname 25 | itab = kmodsrc/x86/libudis86/itab.h kmodsrc/x86/libudis86/itab.c 26 | 27 | have_static := $(wildcard $(srcdir)/objmanip-static) 28 | 29 | default: $(perl_primary) $(perl_man) objutils $(itab) 30 | @echo "Ready for 'make install'" 31 | 32 | ifeq ($(strip $(have_static)),) 33 | 34 | objutils: $(objutils) 35 | 36 | $(addprefix install-,$(objutils)): install-%: % 37 | install -m755 -D $< $(DESTDIR)$(libexecdir)/ksplice-$* 38 | 39 | else 40 | 41 | objutils: 42 | 43 | $(addprefix install-,$(objutils)): install-%: %-static 44 | install -m755 -D $< $(DESTDIR)$(libexecdir)/ksplice-$* 45 | 46 | endif 47 | 48 | $(perl_primary): %: %.in Makefile 49 | sed 's|PACKAGE_VERSION|$(PACKAGE_VERSION)|;s|KSPLICE_API_VERSION|$(KSPLICE_API_VERSION)|;s|PACKAGE_BUGREPORT|$(PACKAGE_BUGREPORT)|;s|KSPLICE_DATA_DIR|$(datadir)/ksplice|;s|KSPLICE_LIBEXEC_DIR|$(libexecdir)|' $< > $@ 50 | 51 | $(perl_man): %.8: % 52 | pod2man --center="Ksplice" --release="Ksplice v$(PACKAGE_VERSION)" --section=8 $< $@ 53 | 54 | $(objutils): %: %.c objcommon.c objcommon.h kmodsrc/ksplice.h 55 | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $< $(srcdir)/objcommon.c $(LIBS) -o $@ 56 | 57 | kmodsrcfiles = \ 58 | kmodsrc/ksplice.c \ 59 | kmodsrc/ksplice.h \ 60 | kmodsrc/x86/ksplice-arch.c \ 61 | kmodsrc/arm/ksplice-arch.c \ 62 | kmodsrc/old_code_loader.c \ 63 | kmodsrc/new_code_loader.c \ 64 | kmodsrc/Makefile \ 65 | kmodsrc/ksplice.lds.S \ 66 | kmodsrc/ksplice-rmsyms.lds \ 67 | kmodsrc/offsets.c \ 68 | kmodsrc/offsets.h \ 69 | kmodsrc/x86/udis86.h \ 70 | kmodsrc/x86/libudis86/decode.c \ 71 | kmodsrc/x86/libudis86/itab.c \ 72 | kmodsrc/x86/libudis86/syn-att.c \ 73 | kmodsrc/x86/libudis86/syn-intel.c \ 74 | kmodsrc/x86/libudis86/input.c \ 75 | kmodsrc/x86/libudis86/syn.c \ 76 | kmodsrc/x86/libudis86/udis86.c \ 77 | kmodsrc/x86/libudis86/decode.h \ 78 | kmodsrc/x86/libudis86/input.h \ 79 | kmodsrc/x86/libudis86/syn.h \ 80 | kmodsrc/x86/libudis86/extern.h \ 81 | kmodsrc/x86/libudis86/itab.h \ 82 | kmodsrc/x86/libudis86/types.h 83 | 84 | $(itab): kmodsrc/x86/libudis86/x86optable.xml kmodsrc/x86/libudis86/opgen.py 85 | cd kmodsrc/x86/libudis86 && python opgen.py x86optable.xml 86 | 87 | $(addprefix install-,$(kmodsrcfiles)): install-%: % 88 | install -m644 -D $< $(DESTDIR)$(datadir)/ksplice/$< 89 | 90 | install: default $(addprefix install-,$(objutils)) $(addprefix install-,$(kmodsrcfiles)) 91 | install -m644 -D ksplice-create.8 $(DESTDIR)$(mandir)/man8/ksplice-create.8 92 | install -m644 -D ksplice-apply.8 $(DESTDIR)$(mandir)/man8/ksplice-apply.8 93 | install -m644 -D ksplice-undo.8 $(DESTDIR)$(mandir)/man8/ksplice-undo.8 94 | install -m644 -D ksplice-view.8 $(DESTDIR)$(mandir)/man8/ksplice-view.8 95 | install -m755 -D ksplice-create $(DESTDIR)$(bindir)/ksplice-create 96 | install -m755 -D ksplice-view $(DESTDIR)$(sbindir)/ksplice-view 97 | install -m755 -D ksplice-apply $(DESTDIR)$(sbindir)/ksplice-apply 98 | install -m755 -D ksplice-undo $(DESTDIR)$(sbindir)/ksplice-undo 99 | install -m755 -D $(srcdir)/ksplice-cc.pl $(DESTDIR)$(datadir)/ksplice/ksplice-cc.pl 100 | install -m755 -D $(srcdir)/ksplice-obj.pl $(DESTDIR)$(datadir)/ksplice/ksplice-obj.pl 101 | install -m644 -D $(srcdir)/ksplice-patch/ksplice-patch.h $(DESTDIR)$(datadir)/ksplice/ksplice-patch/ksplice-patch.h 102 | install -m644 -D $(srcdir)/ksplice-patch/ksplice-shadow.h $(DESTDIR)$(datadir)/ksplice/ksplice-patch/ksplice-shadow.h 103 | install -m644 -D $(srcdir)/Makefile.ksplice $(DESTDIR)$(datadir)/ksplice/Makefile.ksplice 104 | install -m644 -D Ksplice.pm $(DESTDIR)$(datadir)/ksplice/Ksplice.pm 105 | install -m644 -D Verbose.pm $(DESTDIR)$(datadir)/ksplice/Verbose.pm 106 | 107 | clean: 108 | rm -f $(perl_primary) 109 | rm -f $(perl_man) 110 | rm -f $(objutils) 111 | 112 | distclean: clean 113 | rm -f Makefile kmodsrc/Makefile 114 | rm -f $(objutils:=-static) 115 | rm -f $(itab) 116 | rm -f configure config.status config.log 117 | -------------------------------------------------------------------------------- /ksplice-view.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (C) 2007-2009 Ksplice, Inc. 4 | # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License, version 2. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 17 | # 02110-1301, USA. 18 | 19 | use strict; 20 | use warnings; 21 | use lib 'KSPLICE_DATA_DIR'; 22 | use Ksplice; 23 | 24 | my ($kid, $mid, $module, $update, $file); 25 | GetOptions(@common_options, 26 | "id=s" => \$kid, 27 | "file=s" => \$file) or pod2usage(1); 28 | 29 | pod2usage(1) if($help || scalar(@ARGV) != 0); 30 | my $actions = (defined $kid) + (defined $file); 31 | pod2usage(1) if($actions > 1); 32 | 33 | view_kid() if(defined $kid); 34 | view_file() if(defined $file); 35 | view_list() if($actions == 0); 36 | 37 | exit(0); 38 | 39 | sub view_kid { 40 | $kid =~ s/^ksplice[_-]//; 41 | $kid =~ s/[-_].*$//; # In case we got an mid instead 42 | $update = "ksplice_$kid"; 43 | if(!update_loaded($kid)) { 44 | print "Ksplice id $kid is not present in the kernel\n"; 45 | exit(0); 46 | } 47 | my $stage = get_stage($kid); 48 | print "Ksplice id $kid is present in the kernel and is $stage.\n\n"; 49 | my $source_diff = get_patch($kid); 50 | return if($source_diff eq ""); 51 | print "Here is the source code patch associated with this update:\n"; 52 | print $source_diff; 53 | } 54 | 55 | sub view_file { 56 | chdir(unpack_update($file)); 57 | open(PATCH, '<', "patch") or die $!; 58 | local $/; 59 | print ; 60 | close(PATCH); 61 | } 62 | 63 | sub show_kid { 64 | my ($kid) = @_; 65 | if ($Verbose::level < 0) { 66 | print "$kid\n"; 67 | } else { 68 | my $desc = get_short_description($kid); 69 | if (defined($desc)) { 70 | print "$kid: $desc"; 71 | } else { 72 | print "$kid: no description available\n"; 73 | } 74 | } 75 | } 76 | 77 | sub view_list { 78 | foreach(split(/\n/, runstr("lsmod"))) { 79 | next unless my ($mid) = m/^ksplice_(\S*)\s/; 80 | $module = "ksplice_$mid"; 81 | ($kid = $mid) =~ s/[-_].*$//; 82 | next unless (-e "/sys/module/$module/ksplice/stage"); 83 | open STAGE, '<', "/sys/module/$module/ksplice/stage" or die 84 | "Unable to read stage file; are you root?"; 85 | show_kid($kid) if( eq "applied\n"); 86 | close STAGE; 87 | } 88 | if (-e "/sys/kernel/ksplice") { 89 | chdir("/sys/kernel/ksplice"); 90 | foreach $update (glob("*")) { 91 | ($kid = $update) =~ s/^ksplice_//; 92 | show_kid($kid) if(get_stage($kid) eq "applied"); 93 | } 94 | } 95 | } 96 | 97 | =head1 NAME 98 | 99 | ksplice-view - View in-kernel or on-disk Ksplice kernel updates 100 | 101 | =head1 SYNOPSIS 102 | 103 | B 104 | 105 | B B<--id=>I 106 | 107 | B B<--file=>{I | I} 108 | 109 | =head1 DESCRIPTION 110 | 111 | When called with no arguments, B lists the identification tags of 112 | all of the Ksplice updates that are currently present in the running kernel, 113 | along with their descriptions. 114 | 115 | B can report about a specific Ksplice update when given the 116 | update's identification tag I (if the update is in the kernel) or 117 | given the update's tarball filename I or unpacked tree root 118 | I (if the update is on disk). 119 | 120 | =head1 OPTIONS 121 | 122 | =over 8 123 | 124 | =item B<--id=>I 125 | 126 | Report information about the Ksplice update I currently loaded in 127 | the running kernel. 128 | 129 | =item B<--file=>{I | I} 130 | 131 | Report information about the Ksplice update on disk as the tarball 132 | I or unpacked as the tree I. 133 | 134 | =item B<-q> 135 | 136 | Output only the update IDs, one per line, omitting descriptions. 137 | 138 | =back 139 | 140 | =head1 SEE ALSO 141 | 142 | L, L, L 143 | 144 | =head1 BUGS 145 | 146 | Please report bugs to . 147 | 148 | =head1 AUTHORS 149 | 150 | Jeff Arnold, Anders Kaseorg, and Tim Abbott 151 | 152 | =head1 COPYRIGHT 153 | 154 | Copyright (C) 2007-2009 Ksplice, Inc. 155 | 156 | This is free software and documentation. You can redistribute and/or modify it 157 | under the terms of the GNU General Public License, version 2. 158 | 159 | =cut 160 | -------------------------------------------------------------------------------- /ksplice-obj.pl.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (C) 2008-2009 Ksplice, Inc. 4 | # Authors: Anders Kaseorg, Jeff Arnold, Tim Abbott 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License, version 2. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 17 | # 02110-1301, USA. 18 | 19 | use strict; 20 | use warnings; 21 | use lib 'KSPLICE_DATA_DIR'; 22 | use Ksplice; 23 | 24 | $Verbose::level = $ENV{KSPLICE_VERBOSE} if (defined $ENV{KSPLICE_VERBOSE}); 25 | 26 | sub empty_diff { 27 | my ($out) = @_; 28 | my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; 29 | unlink "$obj.KSPLICE_new_code" if (-e "$obj.KSPLICE_new_code"); 30 | unlink "$obj.KSPLICE_old_code" if (-e "$obj.KSPLICE_old_code"); 31 | open OUT, '>', "$out.tmp"; 32 | close OUT; 33 | rename "$out.tmp", $out; 34 | } 35 | 36 | sub do_snap { 37 | my ($out) = @_; 38 | my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; 39 | die if (!-e $obj); 40 | unlink "$obj.KSPLICE_pre" if (-e "$obj.KSPLICE_pre"); 41 | empty_diff($out); 42 | } 43 | 44 | sub do_diff { 45 | my ($out) = @_; 46 | my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; 47 | my $obj_pre = "$obj.KSPLICE_pre"; 48 | die if (!-e $obj); 49 | die "Patch creates new object $obj" if (!-e $obj_pre); 50 | if (system('cmp', '-s', '--', $obj_pre, $obj) == 0) { 51 | unlink $obj_pre; 52 | return empty_diff($out); 53 | } 54 | 55 | runval("$libexecdir/ksplice-objmanip", $obj, "$obj.KSPLICE_new_code", "keep-new-code", "$obj.KSPLICE_pre", $ENV{KSPLICE_KID}); 56 | return empty_diff($out) if (!-e "$obj.KSPLICE_new_code"); 57 | 58 | open OUT, '>', "$out.tmp"; 59 | print OUT "1\n"; 60 | close OUT; 61 | rename "$out.tmp", $out; 62 | 63 | runval("$libexecdir/ksplice-objmanip", $obj_pre, "$obj.KSPLICE_old_code", "keep-old-code"); 64 | } 65 | 66 | sub do_old_code { 67 | my ($out) = @_; 68 | my ($obj) = $out =~ /^(.*)\.KSPLICE_old_code$/ or die; 69 | my $obj_pre = "$obj.KSPLICE_pre"; 70 | -e $obj_pre or $obj_pre = $obj; 71 | runval("$libexecdir/ksplice-objmanip", $obj_pre, "$obj.KSPLICE_old_code", "keep-old-code"); 72 | } 73 | 74 | sub link_objs { 75 | my ($out, @ins) = @_; 76 | if (@ins == 0) { 77 | runval(shellwords($ENV{AR}), "rcs", $out); 78 | } elsif (@ins == 1) { 79 | copy @ins, $out; 80 | } else { 81 | runval(shellwords($ENV{LD}), "-r", "-o", $out, @ins); 82 | } 83 | } 84 | 85 | sub do_combine { 86 | my ($out, @ins) = @_; 87 | my @new_code_objs; 88 | my @old_code_objs; 89 | foreach my $in (@ins) { 90 | if (my ($obj) = $in =~ /^(.*)\.KSPLICE$/) { 91 | next if (!-s $in); 92 | push @new_code_objs, "$obj.KSPLICE_new_code"; 93 | push @old_code_objs, "$obj.KSPLICE_old_code"; 94 | } elsif (($obj) = $in =~ /^(.*)\.KSPLICE_old_code$/) { 95 | push @old_code_objs, "$obj.KSPLICE_old_code" 96 | unless (@old_code_objs && $old_code_objs[$#old_code_objs] eq "$obj.KSPLICE_old_code"); 97 | } elsif ("$in.KSPLICE" eq $out) { 98 | my $pre = "$in.KSPLICE_pre"; 99 | if (system('cmp', '-s', '--', $pre, $in) == 0) { 100 | unlink $pre; 101 | } 102 | } else { 103 | die "Unexpected input $in for $out"; 104 | } 105 | } 106 | 107 | return empty_diff($out) unless (@old_code_objs); 108 | 109 | my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; 110 | link_objs("$obj.KSPLICE_new_code", @new_code_objs); 111 | link_objs("$obj.KSPLICE_old_code", @old_code_objs); 112 | 113 | open OUT, '>', "$out.tmp"; 114 | print OUT "1\n"; 115 | close OUT; 116 | rename "$out.tmp", $out; 117 | } 118 | 119 | sub do_finalize { 120 | my ($in, $out, $target) = @_; 121 | my $ret = runval_raw("$libexecdir/ksplice-objmanip", $in, $out, "finalize", $target); 122 | if ($ret == 0) { 123 | } elsif ($ret >> 8 == 66) { 124 | runval(shellwords($ENV{AR}), "rcs", $out); 125 | } else { 126 | child_error(); 127 | } 128 | } 129 | 130 | sub do_rmsyms { 131 | my ($in, $out) = @_; 132 | runval("$libexecdir/ksplice-objmanip", $in, $out, "rmsyms"); 133 | } 134 | 135 | sub do_system_map_lookup { 136 | my ($symarg) = @_; 137 | open(SYMS, "<", "$ENV{KSPLICE_CONFIG_DIR}/System.map") or die; 138 | my $line; 139 | while (defined($line = )) { 140 | my ($addr, $type, $sym, $mod) = split(/\s+/, $line); 141 | if ($sym eq $symarg) { print $addr; last; } 142 | } 143 | close(SYMS); 144 | } 145 | 146 | my %handlers = ( 147 | 'snap' => \&do_snap, 148 | 'diff' => \&do_diff, 149 | 'old_code' => \&do_old_code, 150 | 'combine' => \&do_combine, 151 | 'finalize' => \&do_finalize, 152 | 'rmsyms' => \&do_rmsyms, 153 | 'system_map_lookup' => \&do_system_map_lookup, 154 | ); 155 | 156 | my ($cmd, @args) = @ARGV; 157 | if (exists $handlers{$cmd}) { 158 | my $handler = $handlers{$cmd}; 159 | &$handler(@args); 160 | } else { 161 | print "Usage: ksplice-obj.pl ", join('|', keys %handlers), " ...\n"; 162 | exit(1); 163 | }; 164 | -------------------------------------------------------------------------------- /ksplice-patch/ksplice-patch.h: -------------------------------------------------------------------------------- 1 | #ifndef _KSPLICE_PATCH_H 2 | #define _KSPLICE_PATCH_H 3 | 4 | #define KSPLICE_OPTION_ASSUME_RODATA 0 5 | #define KSPLICE_OPTION_MATCH_DATA_EARLY 1 6 | 7 | struct ksplice_option { 8 | int type; 9 | const void *target; 10 | } __attribute__((packed)); 11 | 12 | #ifdef __KERNEL__ 13 | 14 | #include 15 | #include 16 | 17 | #ifndef __used 18 | #define __used __attribute_used__ 19 | #endif 20 | 21 | #define ksplice_call_int(name, fn) \ 22 | static typeof(int (*)(void)) __ksplice_##name##_##fn __used \ 23 | __attribute__((__section__(".ksplice_call_" #name))) = fn 24 | 25 | #define ksplice_call_void(name, fn) \ 26 | static typeof(void (*)(void)) __ksplice_##name##_##fn __used \ 27 | __attribute__((__section__(".ksplice_call_" #name))) = fn 28 | 29 | #define ksplice_pre_apply(fn) ksplice_call_int(pre_apply, fn) 30 | #define ksplice_check_apply(fn) ksplice_call_int(check_apply, fn) 31 | #define ksplice_apply(fn) ksplice_call_void(apply, fn) 32 | #define ksplice_post_apply(fn) ksplice_call_void(post_apply, fn) 33 | #define ksplice_fail_apply(fn) ksplice_call_void(fail_apply, fn) 34 | 35 | #define ksplice_pre_reverse(fn) ksplice_call_int(pre_reverse, fn) 36 | #define ksplice_check_reverse(fn) ksplice_call_int(check_reverse, fn) 37 | #define ksplice_reverse(fn) ksplice_call_void(reverse, fn) 38 | #define ksplice_post_reverse(fn) ksplice_call_void(post_reverse, fn) 39 | #define ksplice_fail_reverse(fn) ksplice_call_void(fail_reverse, fn) 40 | 41 | 42 | #define ksplice_assume_rodata(obj) \ 43 | ksplice_option(KSPLICE_OPTION_ASSUME_RODATA, obj) 44 | 45 | #define ksplice_match_data_early(obj) \ 46 | ksplice_option(KSPLICE_OPTION_MATCH_DATA_EARLY, obj) 47 | 48 | #if BITS_PER_LONG == 32 49 | #define KSPLICE_PTR ".long" 50 | #elif BITS_PER_LONG == 64 51 | #define KSPLICE_PTR ".quad" 52 | #endif /* BITS_PER_LONG */ 53 | 54 | #define ksplice_option(num, obj) \ 55 | __asm__(".pushsection \".ksplice_options\", \"a\"\n" \ 56 | "\t.long " __stringify(num) "\n" \ 57 | "\t" KSPLICE_PTR " " #obj "\n" \ 58 | ".popsection") 59 | 60 | int init_shadow_field_type(int *shadow_key, typeof(GFP_KERNEL) gfp_flags); 61 | void *init_shadow_field(int *shadow_key, void *obj, int size, 62 | typeof(GFP_KERNEL) gfp_flags); 63 | void cleanup_shadow_field(int *shadow_key, void *obj); 64 | void *get_shadow_field(int *shadow_key, void *obj); 65 | void cleanup_shadow_field_type(int *shadow_key); 66 | 67 | 68 | #define __DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, \ 69 | init_field_type_fn, init_field_fn, get_field_fn, \ 70 | make_field_fn, cleanup_field_fn, \ 71 | cleanup_field_type_fn, shadow_key, init_field) \ 72 | static int shadow_key = 0; \ 73 | int init_field_type_fn(void) \ 74 | { \ 75 | return init_shadow_field_type(&shadow_key, gfp_flags); \ 76 | } \ 77 | field_type *init_field_fn(base_type *obj, typeof(GFP_KERNEL) flags) \ 78 | { \ 79 | field_type *data = init_shadow_field(&shadow_key, (void *)obj, \ 80 | sizeof(*data), flags); \ 81 | if (data != NULL) \ 82 | init_field(data); \ 83 | return data; \ 84 | } \ 85 | void cleanup_field_fn(base_type *obj) \ 86 | { \ 87 | cleanup_shadow_field(&shadow_key, obj); \ 88 | } \ 89 | field_type *get_field_fn(base_type *obj) \ 90 | { \ 91 | return get_shadow_field(&shadow_key, obj); \ 92 | } \ 93 | field_type *make_field_fn(base_type *obj, typeof(GFP_KERNEL) flags) \ 94 | { \ 95 | void *data = get_shadow_field(&shadow_key, (void *)obj); \ 96 | if (data == NULL) \ 97 | data = init_field_fn(obj, flags); \ 98 | return data; \ 99 | } \ 100 | void cleanup_field_type_fn(void) \ 101 | { \ 102 | return cleanup_shadow_field_type(&shadow_key); \ 103 | } \ 104 | struct eat_trailing_semicolon 105 | 106 | #define DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, name, init_field) \ 107 | __DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, \ 108 | init_##name##_shadows, init_##name##_shadow, \ 109 | get_##name##_shadow, make_##name##_shadow, \ 110 | cleanup_##name##_shadow, cleanup_##name##_shadows,\ 111 | shadow_key_##name, init_field); \ 112 | ksplice_check_apply(init_##name##_shadows); \ 113 | ksplice_post_reverse(cleanup_##name##_shadows); \ 114 | ksplice_fail_apply(cleanup_##name##_shadows) 115 | 116 | #define __DECLARE_SHADOW_FIELD(base_type, field_type, init_field_type_fn, \ 117 | init_field_fn, get_field_fn, make_field_fn, \ 118 | cleanup_field_fn, cleanup_field_type_fn) \ 119 | int init_field_type_fn(void); \ 120 | field_type *init_field_fn(base_type *obj, typeof(GFP_KERNEL) flags); \ 121 | void cleanup_field_fn(base_type *obj); \ 122 | field_type *get_field_fn(base_type *obj); \ 123 | field_type *make_field_fn(base_type *obj, typeof(GFP_KERNEL) flags); \ 124 | void cleanup_field_type_fn(void) 125 | 126 | #define DECLARE_SHADOW_FIELD(base_type, field_type, name) \ 127 | __DECLARE_SHADOW_FIELD(base_type, field_type, init_##name##_shadows, \ 128 | init_##name##_shadow, get_##name##_shadow, \ 129 | make_##name##_shadow, cleanup_##name##_shadow, \ 130 | cleanup_##name##_shadows) 131 | 132 | #endif /* __KERNEL__ */ 133 | 134 | #endif /* _KSPLICE_PATCH_H */ 135 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/udis86.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udis86.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include "input.h" 28 | #include "extern.h" 29 | 30 | #ifndef __UD_STANDALONE__ 31 | # include 32 | # include 33 | #endif /* __UD_STANDALONE__ */ 34 | 35 | /* ============================================================================= 36 | * ud_init() - Initializes ud_t object. 37 | * ============================================================================= 38 | */ 39 | extern void 40 | ud_init(struct ud* u) 41 | { 42 | memset((void*)u, 0, sizeof(struct ud)); 43 | ud_set_mode(u, 16); 44 | u->mnemonic = UD_Iinvalid; 45 | ud_set_pc(u, 0); 46 | #ifndef __UD_STANDALONE__ 47 | ud_set_input_file(u, stdin); 48 | #endif /* __UD_STANDALONE__ */ 49 | } 50 | 51 | /* ============================================================================= 52 | * ud_disassemble() - disassembles one instruction and returns the number of 53 | * bytes disassembled. A zero means end of disassembly. 54 | * ============================================================================= 55 | */ 56 | extern unsigned int 57 | ud_disassemble(struct ud* u) 58 | { 59 | if (ud_input_end(u)) 60 | return 0; 61 | 62 | 63 | u->insn_buffer[0] = u->insn_hexcode[0] = 0; 64 | 65 | 66 | if (ud_decode(u) == 0) 67 | return 0; 68 | if (u->translator) 69 | u->translator(u); 70 | return ud_insn_len(u); 71 | } 72 | 73 | /* ============================================================================= 74 | * ud_set_mode() - Set Disassemly Mode. 75 | * ============================================================================= 76 | */ 77 | extern void 78 | ud_set_mode(struct ud* u, uint8_t m) 79 | { 80 | switch(m) { 81 | case 16: 82 | case 32: 83 | case 64: u->dis_mode = m ; return; 84 | default: u->dis_mode = 16; return; 85 | } 86 | } 87 | 88 | /* ============================================================================= 89 | * ud_set_vendor() - Set vendor. 90 | * ============================================================================= 91 | */ 92 | extern void 93 | ud_set_vendor(struct ud* u, unsigned v) 94 | { 95 | switch(v) { 96 | case UD_VENDOR_INTEL: 97 | u->vendor = v; 98 | break; 99 | case UD_VENDOR_ANY: 100 | u->vendor = v; 101 | break; 102 | default: 103 | u->vendor = UD_VENDOR_AMD; 104 | } 105 | } 106 | 107 | /* ============================================================================= 108 | * ud_set_pc() - Sets code origin. 109 | * ============================================================================= 110 | */ 111 | extern void 112 | ud_set_pc(struct ud* u, uint64_t o) 113 | { 114 | u->pc = o; 115 | } 116 | 117 | /* ============================================================================= 118 | * ud_set_syntax() - Sets the output syntax. 119 | * ============================================================================= 120 | */ 121 | extern void 122 | ud_set_syntax(struct ud* u, void (*t)(struct ud*)) 123 | { 124 | u->translator = t; 125 | } 126 | 127 | /* ============================================================================= 128 | * ud_insn() - returns the disassembled instruction 129 | * ============================================================================= 130 | */ 131 | extern char* 132 | ud_insn_asm(struct ud* u) 133 | { 134 | return u->insn_buffer; 135 | } 136 | 137 | /* ============================================================================= 138 | * ud_insn_offset() - Returns the offset. 139 | * ============================================================================= 140 | */ 141 | extern uint64_t 142 | ud_insn_off(struct ud* u) 143 | { 144 | return u->insn_offset; 145 | } 146 | 147 | 148 | /* ============================================================================= 149 | * ud_insn_hex() - Returns hex form of disassembled instruction. 150 | * ============================================================================= 151 | */ 152 | extern char* 153 | ud_insn_hex(struct ud* u) 154 | { 155 | return u->insn_hexcode; 156 | } 157 | 158 | /* ============================================================================= 159 | * ud_insn_ptr() - Returns code disassembled. 160 | * ============================================================================= 161 | */ 162 | extern uint8_t* 163 | ud_insn_ptr(struct ud* u) 164 | { 165 | return u->inp_sess; 166 | } 167 | 168 | /* ============================================================================= 169 | * ud_insn_len() - Returns the count of bytes disassembled. 170 | * ============================================================================= 171 | */ 172 | extern unsigned int 173 | ud_insn_len(struct ud* u) 174 | { 175 | return u->inp_ctr; 176 | } 177 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/decode.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_DECODE_H 27 | #define UD_DECODE_H 28 | 29 | #define MAX_INSN_LENGTH 15 30 | 31 | /* register classes */ 32 | #define T_NONE 0 33 | #define T_GPR 1 34 | #define T_MMX 2 35 | #define T_CRG 3 36 | #define T_DBG 4 37 | #define T_SEG 5 38 | #define T_XMM 6 39 | 40 | /* itab prefix bits */ 41 | #define P_none ( 0 ) 42 | #define P_c1 ( 1 << 0 ) 43 | #define P_C1(n) ( ( n >> 0 ) & 1 ) 44 | #define P_rexb ( 1 << 1 ) 45 | #define P_REXB(n) ( ( n >> 1 ) & 1 ) 46 | #define P_depM ( 1 << 2 ) 47 | #define P_DEPM(n) ( ( n >> 2 ) & 1 ) 48 | #define P_c3 ( 1 << 3 ) 49 | #define P_C3(n) ( ( n >> 3 ) & 1 ) 50 | #define P_inv64 ( 1 << 4 ) 51 | #define P_INV64(n) ( ( n >> 4 ) & 1 ) 52 | #define P_rexw ( 1 << 5 ) 53 | #define P_REXW(n) ( ( n >> 5 ) & 1 ) 54 | #define P_c2 ( 1 << 6 ) 55 | #define P_C2(n) ( ( n >> 6 ) & 1 ) 56 | #define P_def64 ( 1 << 7 ) 57 | #define P_DEF64(n) ( ( n >> 7 ) & 1 ) 58 | #define P_rexr ( 1 << 8 ) 59 | #define P_REXR(n) ( ( n >> 8 ) & 1 ) 60 | #define P_oso ( 1 << 9 ) 61 | #define P_OSO(n) ( ( n >> 9 ) & 1 ) 62 | #define P_aso ( 1 << 10 ) 63 | #define P_ASO(n) ( ( n >> 10 ) & 1 ) 64 | #define P_rexx ( 1 << 11 ) 65 | #define P_REXX(n) ( ( n >> 11 ) & 1 ) 66 | #define P_ImpAddr ( 1 << 12 ) 67 | #define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) 68 | 69 | /* rex prefix bits */ 70 | #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) 71 | #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) 72 | #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) 73 | #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) 74 | #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ 75 | ( P_REXR(n) << 2 ) | \ 76 | ( P_REXX(n) << 1 ) | \ 77 | ( P_REXB(n) << 0 ) ) 78 | 79 | /* scable-index-base bits */ 80 | #define SIB_S(b) ( ( b ) >> 6 ) 81 | #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) 82 | #define SIB_B(b) ( ( b ) & 7 ) 83 | 84 | /* modrm bits */ 85 | #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) 86 | #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) 87 | #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) 88 | #define MODRM_RM(b) ( ( b ) & 7 ) 89 | 90 | /* operand type constants -- order is important! */ 91 | 92 | enum ud_operand_code { 93 | OP_NONE, 94 | 95 | OP_A, OP_E, OP_M, OP_G, 96 | OP_I, 97 | 98 | OP_AL, OP_CL, OP_DL, OP_BL, 99 | OP_AH, OP_CH, OP_DH, OP_BH, 100 | 101 | OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b, 102 | OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b, 103 | 104 | OP_AX, OP_CX, OP_DX, OP_BX, 105 | OP_SI, OP_DI, OP_SP, OP_BP, 106 | 107 | OP_rAX, OP_rCX, OP_rDX, OP_rBX, 108 | OP_rSP, OP_rBP, OP_rSI, OP_rDI, 109 | 110 | OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11, 111 | OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15, 112 | 113 | OP_eAX, OP_eCX, OP_eDX, OP_eBX, 114 | OP_eSP, OP_eBP, OP_eSI, OP_eDI, 115 | 116 | OP_ES, OP_CS, OP_SS, OP_DS, 117 | OP_FS, OP_GS, 118 | 119 | OP_ST0, OP_ST1, OP_ST2, OP_ST3, 120 | OP_ST4, OP_ST5, OP_ST6, OP_ST7, 121 | 122 | OP_J, OP_S, OP_O, 123 | OP_I1, OP_I3, 124 | 125 | OP_V, OP_W, OP_Q, OP_P, 126 | 127 | OP_R, OP_C, OP_D, OP_VR, OP_PR 128 | } UD_ATTR_PACKED; 129 | 130 | 131 | /* operand size constants */ 132 | 133 | enum ud_operand_size { 134 | SZ_NA = 0, 135 | SZ_Z = 1, 136 | SZ_V = 2, 137 | SZ_P = 3, 138 | SZ_WP = 4, 139 | SZ_DP = 5, 140 | SZ_MDQ = 6, 141 | SZ_RDQ = 7, 142 | 143 | /* the following values are used as is, 144 | * and thus hard-coded. changing them 145 | * will break internals 146 | */ 147 | SZ_B = 8, 148 | SZ_W = 16, 149 | SZ_D = 32, 150 | SZ_Q = 64, 151 | SZ_T = 80, 152 | SZ_O = 128, 153 | } UD_ATTR_PACKED; 154 | 155 | 156 | /* A single operand of an entry in the instruction table. 157 | * (internal use only) 158 | */ 159 | struct ud_itab_entry_operand 160 | { 161 | enum ud_operand_code type; 162 | enum ud_operand_size size; 163 | }; 164 | 165 | 166 | /* A single entry in an instruction table. 167 | *(internal use only) 168 | */ 169 | struct ud_itab_entry 170 | { 171 | enum ud_mnemonic_code mnemonic; 172 | struct ud_itab_entry_operand operand1; 173 | struct ud_itab_entry_operand operand2; 174 | struct ud_itab_entry_operand operand3; 175 | uint32_t prefix; 176 | }; 177 | 178 | extern const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ); 179 | 180 | #endif /* UD_DECODE_H */ 181 | 182 | /* vim:cindent 183 | * vim:expandtab 184 | * vim:ts=4 185 | * vim:sw=4 186 | */ 187 | -------------------------------------------------------------------------------- /kmodsrc/offsets.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2008-2009 Ksplice, Inc. 2 | * Authors: Anders Kaseorg, Tim Abbott, Jeff Arnold 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #ifdef CONFIG_PARAVIRT 27 | #include 28 | #endif /* CONFIG_PARAVIRT */ 29 | #include 30 | #include "offsets.h" 31 | 32 | const struct ksplice_config config 33 | __attribute__((section(".ksplice_config"))) = { 34 | /* Introduction of .cpuinit, .devinit, .meminit sections */ 35 | #ifndef CONFIG_HOTPLUG 36 | .ignore_devinit = 1, 37 | #endif /* !CONFIG_HOTPLUG */ 38 | #ifndef CONFIG_HOTPLUG_CPU 39 | .ignore_cpuinit = 1, 40 | #endif /* !CONFIG_HOTPLUG_CPU */ 41 | #ifndef CONFIG_MEMORY_HOTPLUG 42 | .ignore_meminit = 1, 43 | #endif /* !CONFIG_MEMORY_HOTPLUG */ 44 | }; 45 | 46 | #define FIELD_ENDOF(t, f) (offsetof(t, f) + FIELD_SIZEOF(t, f)) 47 | 48 | const struct table_section table_sections[] 49 | __attribute__((section(".ksplice_table_sections"))) = { 50 | #ifdef CONFIG_X86 51 | { 52 | .sect = ".altinstructions", 53 | .entry_size = sizeof(struct alt_instr), 54 | .entry_contents_size = FIELD_ENDOF(struct alt_instr, 55 | replacementlen), 56 | .entry_align = __alignof__(struct alt_instr), 57 | .has_addr = 1, 58 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) 59 | .relative_addr = 1, 60 | .addr_offset = offsetof(struct alt_instr, instr_offset), 61 | .relative_other = 1, 62 | .other_sect = ".altinstr_replacement", 63 | .other_offset = offsetof(struct alt_instr, repl_offset), 64 | #else 65 | .addr_offset = offsetof(struct alt_instr, instr), 66 | .other_sect = ".altinstr_replacement", 67 | .other_offset = offsetof(struct alt_instr, replacement), 68 | #endif 69 | }, 70 | #endif /* CONFIG_X86 */ 71 | #ifdef CONFIG_GENERIC_BUG 72 | { 73 | .sect = "__bug_table", 74 | .entry_size = sizeof(struct bug_entry), 75 | .entry_contents_size = FIELD_ENDOF(struct bug_entry, flags), 76 | .entry_align = __alignof__(struct bug_entry), 77 | .has_addr = 1, 78 | #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS 79 | .relative_addr = 1, 80 | .addr_offset = offsetof(struct bug_entry, bug_addr_disp), 81 | .relative_other = 1, 82 | .other_offset = offsetof(struct bug_entry, file_disp), 83 | #else 84 | .addr_offset = offsetof(struct bug_entry, bug_addr), 85 | #endif 86 | }, 87 | #endif /* CONFIG_GENERIC_BUG */ 88 | { 89 | .sect = "__ex_table", 90 | .entry_size = sizeof(struct exception_table_entry), 91 | .entry_align = __alignof__(struct exception_table_entry), 92 | .has_addr = 1, 93 | .addr_offset = offsetof(struct exception_table_entry, insn), 94 | .other_sect = ".fixup", 95 | .other_offset = offsetof(struct exception_table_entry, fixup), 96 | }, 97 | { 98 | .sect = "__tracepoints", 99 | .entry_size = sizeof(struct tracepoint), 100 | .entry_align = __alignof__(struct tracepoint), 101 | .other_sect = "__tracepoints_strings", 102 | .other_offset = offsetof(struct tracepoint, name), 103 | }, 104 | #ifdef CONFIG_PARAVIRT 105 | { 106 | .sect = ".parainstructions", 107 | .entry_size = sizeof(struct paravirt_patch_site), 108 | .entry_contents_size = FIELD_ENDOF(struct paravirt_patch_site, 109 | clobbers), 110 | .entry_align = __alignof__(struct paravirt_patch_site), 111 | .has_addr = 1, 112 | .addr_offset = offsetof(struct paravirt_patch_site, instr), 113 | }, 114 | #endif /* CONFIG_PARAVIRT */ 115 | { 116 | .sect = ".smp_locks", 117 | .entry_size = sizeof(u32), 118 | .entry_align = 4, 119 | .has_addr = 1, 120 | .relative_addr = 1, 121 | .addr_offset = 0, 122 | }, 123 | { 124 | .sect = "__ksymtab", 125 | .entry_size = sizeof(struct kernel_symbol), 126 | .entry_align = __alignof__(struct kernel_symbol), 127 | .other_offset = offsetof(struct kernel_symbol, name), 128 | #ifdef CONFIG_MODVERSIONS 129 | .crc_size = sizeof(unsigned long), 130 | .crc_sect = "__kcrctab", 131 | #endif /* CONFIG_MODVERSIONS */ 132 | }, 133 | { 134 | .sect = "__ksymtab_gpl", 135 | .entry_size = sizeof(struct kernel_symbol), 136 | .entry_align = __alignof__(struct kernel_symbol), 137 | .other_offset = offsetof(struct kernel_symbol, name), 138 | #ifdef CONFIG_MODVERSIONS 139 | .crc_size = sizeof(unsigned long), 140 | .crc_sect = "__kcrctab_gpl", 141 | #endif /* CONFIG_MODVERSIONS */ 142 | }, 143 | #ifdef CONFIG_UNUSED_SYMBOLS 144 | /* f71d20e961474dde77e6558396efb93d6ac80a4b was after 2.6.17 */ 145 | { 146 | .sect = "__ksymtab_unused_gpl", 147 | .entry_size = sizeof(struct kernel_symbol), 148 | .entry_align = __alignof__(struct kernel_symbol), 149 | .other_offset = offsetof(struct kernel_symbol, name), 150 | #ifdef CONFIG_MODVERSIONS 151 | .crc_size = sizeof(unsigned long), 152 | .crc_sect = "__kcrctab_unused_gpl", 153 | #endif /* CONFIG_MODVERSIONS */ 154 | }, 155 | { 156 | .sect = "__ksymtab_unused", 157 | .entry_size = sizeof(struct kernel_symbol), 158 | .entry_align = __alignof__(struct kernel_symbol), 159 | .other_offset = offsetof(struct kernel_symbol, name), 160 | #ifdef CONFIG_MODVERSIONS 161 | .crc_size = sizeof(unsigned long), 162 | .crc_sect = "__kcrctab_unused", 163 | #endif /* CONFIG_MODVERSIONS */ 164 | }, 165 | #endif /* CONFIG_UNUSED_SYMBOLS */ 166 | { 167 | .sect = "__ksymtab_gpl_future", 168 | .entry_size = sizeof(struct kernel_symbol), 169 | .entry_align = __alignof__(struct kernel_symbol), 170 | .other_offset = offsetof(struct kernel_symbol, name), 171 | #ifdef CONFIG_MODVERSIONS 172 | .crc_size = sizeof(unsigned long), 173 | .crc_sect = "__kcrctab_gpl_future", 174 | #endif /* CONFIG_MODVERSIONS */ 175 | }, 176 | }; 177 | 178 | const char *__attribute__((section(".uts_sysname"))) sysname = UTS_SYSNAME; 179 | const char *__attribute__((section(".uts_release"))) release = UTS_RELEASE; 180 | const char *__attribute__((section(".uts_version"))) version = UTS_VERSION; 181 | const char *__attribute__((section(".uts_machine"))) machine = UTS_MACHINE; 182 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/syn-att.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-att.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | 32 | /* ----------------------------------------------------------------------------- 33 | * opr_cast() - Prints an operand cast. 34 | * ----------------------------------------------------------------------------- 35 | */ 36 | static void 37 | opr_cast(struct ud* u, struct ud_operand* op) 38 | { 39 | switch(op->size) { 40 | case 16 : case 32 : 41 | mkasm(u, "*"); break; 42 | default: break; 43 | } 44 | } 45 | 46 | /* ----------------------------------------------------------------------------- 47 | * gen_operand() - Generates assembly output for each operand. 48 | * ----------------------------------------------------------------------------- 49 | */ 50 | static void 51 | gen_operand(struct ud* u, struct ud_operand* op) 52 | { 53 | switch(op->type) { 54 | case UD_OP_REG: 55 | mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 56 | break; 57 | 58 | case UD_OP_MEM: 59 | if (u->br_far) opr_cast(u, op); 60 | if (u->pfx_seg) 61 | mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 62 | if (op->offset == 8) { 63 | if (op->lval.sbyte < 0) 64 | mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff); 65 | else mkasm(u, "0x%x", op->lval.sbyte); 66 | } 67 | else if (op->offset == 16) 68 | mkasm(u, "0x%x", op->lval.uword); 69 | else if (op->offset == 32) 70 | mkasm(u, "0x%lx", op->lval.udword); 71 | else if (op->offset == 64) 72 | mkasm(u, "0x" FMT64 "x", op->lval.uqword); 73 | 74 | if (op->base) 75 | mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 76 | if (op->index) { 77 | if (op->base) 78 | mkasm(u, ","); 79 | else mkasm(u, "("); 80 | mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 81 | } 82 | if (op->scale) 83 | mkasm(u, ",%d", op->scale); 84 | if (op->base || op->index) 85 | mkasm(u, ")"); 86 | break; 87 | 88 | case UD_OP_IMM: 89 | switch (op->size) { 90 | case 8: mkasm(u, "$0x%x", op->lval.ubyte); break; 91 | case 16: mkasm(u, "$0x%x", op->lval.uword); break; 92 | case 32: mkasm(u, "$0x%lx", op->lval.udword); break; 93 | case 64: mkasm(u, "$0x" FMT64 "x", op->lval.uqword); break; 94 | default: break; 95 | } 96 | break; 97 | 98 | case UD_OP_JIMM: 99 | switch (op->size) { 100 | case 8: 101 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); 102 | break; 103 | case 16: 104 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); 105 | break; 106 | case 32: 107 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); 108 | break; 109 | default:break; 110 | } 111 | break; 112 | 113 | case UD_OP_PTR: 114 | switch (op->size) { 115 | case 32: 116 | mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg, 117 | op->lval.ptr.off & 0xFFFF); 118 | break; 119 | case 48: 120 | mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg, 121 | op->lval.ptr.off); 122 | break; 123 | } 124 | break; 125 | 126 | default: return; 127 | } 128 | } 129 | 130 | /* ============================================================================= 131 | * translates to AT&T syntax 132 | * ============================================================================= 133 | */ 134 | extern void 135 | ud_translate_att(struct ud *u) 136 | { 137 | int size = 0; 138 | 139 | /* check if P_OSO prefix is used */ 140 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 141 | switch (u->dis_mode) { 142 | case 16: 143 | mkasm(u, "o32 "); 144 | break; 145 | case 32: 146 | case 64: 147 | mkasm(u, "o16 "); 148 | break; 149 | } 150 | } 151 | 152 | /* check if P_ASO prefix was used */ 153 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 154 | switch (u->dis_mode) { 155 | case 16: 156 | mkasm(u, "a32 "); 157 | break; 158 | case 32: 159 | mkasm(u, "a16 "); 160 | break; 161 | case 64: 162 | mkasm(u, "a32 "); 163 | break; 164 | } 165 | } 166 | 167 | if (u->pfx_lock) 168 | mkasm(u, "lock "); 169 | if (u->pfx_rep) 170 | mkasm(u, "rep "); 171 | if (u->pfx_repne) 172 | mkasm(u, "repne "); 173 | 174 | /* special instructions */ 175 | switch (u->mnemonic) { 176 | case UD_Iretf: 177 | mkasm(u, "lret "); 178 | break; 179 | case UD_Idb: 180 | mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte); 181 | return; 182 | case UD_Ijmp: 183 | case UD_Icall: 184 | if (u->br_far) mkasm(u, "l"); 185 | mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 186 | break; 187 | case UD_Ibound: 188 | case UD_Ienter: 189 | if (u->operand[0].type != UD_NONE) 190 | gen_operand(u, &u->operand[0]); 191 | if (u->operand[1].type != UD_NONE) { 192 | mkasm(u, ","); 193 | gen_operand(u, &u->operand[1]); 194 | } 195 | return; 196 | default: 197 | mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 198 | } 199 | 200 | if (u->c1) 201 | size = u->operand[0].size; 202 | else if (u->c2) 203 | size = u->operand[1].size; 204 | else if (u->c3) 205 | size = u->operand[2].size; 206 | 207 | if (size == 8) 208 | mkasm(u, "b"); 209 | else if (size == 16) 210 | mkasm(u, "w"); 211 | else if (size == 64) 212 | mkasm(u, "q"); 213 | 214 | mkasm(u, " "); 215 | 216 | if (u->operand[2].type != UD_NONE) { 217 | gen_operand(u, &u->operand[2]); 218 | mkasm(u, ", "); 219 | } 220 | 221 | if (u->operand[1].type != UD_NONE) { 222 | gen_operand(u, &u->operand[1]); 223 | mkasm(u, ", "); 224 | } 225 | 226 | if (u->operand[0].type != UD_NONE) 227 | gen_operand(u, &u->operand[0]); 228 | } 229 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/syn-intel.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-intel.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | 32 | /* ----------------------------------------------------------------------------- 33 | * opr_cast() - Prints an operand cast. 34 | * ----------------------------------------------------------------------------- 35 | */ 36 | static void 37 | opr_cast(struct ud* u, struct ud_operand* op) 38 | { 39 | switch(op->size) { 40 | case 8: mkasm(u, "byte " ); break; 41 | case 16: mkasm(u, "word " ); break; 42 | case 32: mkasm(u, "dword "); break; 43 | case 64: mkasm(u, "qword "); break; 44 | case 80: mkasm(u, "tword "); break; 45 | default: break; 46 | } 47 | if (u->br_far) 48 | mkasm(u, "far "); 49 | else if (u->br_near) 50 | mkasm(u, "near "); 51 | } 52 | 53 | /* ----------------------------------------------------------------------------- 54 | * gen_operand() - Generates assembly output for each operand. 55 | * ----------------------------------------------------------------------------- 56 | */ 57 | static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) 58 | { 59 | switch(op->type) { 60 | case UD_OP_REG: 61 | mkasm(u, ud_reg_tab[op->base - UD_R_AL]); 62 | break; 63 | 64 | case UD_OP_MEM: { 65 | 66 | int op_f = 0; 67 | 68 | if (syn_cast) 69 | opr_cast(u, op); 70 | 71 | mkasm(u, "["); 72 | 73 | if (u->pfx_seg) 74 | mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 75 | 76 | if (op->base) { 77 | mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 78 | op_f = 1; 79 | } 80 | 81 | if (op->index) { 82 | if (op_f) 83 | mkasm(u, "+"); 84 | mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]); 85 | op_f = 1; 86 | } 87 | 88 | if (op->scale) 89 | mkasm(u, "*%d", op->scale); 90 | 91 | if (op->offset == 8) { 92 | if (op->lval.sbyte < 0) 93 | mkasm(u, "-0x%x", -op->lval.sbyte); 94 | else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte); 95 | } 96 | else if (op->offset == 16) 97 | mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword); 98 | else if (op->offset == 32) { 99 | if (u->adr_mode == 64) { 100 | if (op->lval.sdword < 0) 101 | mkasm(u, "-0x%x", -op->lval.sdword); 102 | else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword); 103 | } 104 | else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", op->lval.udword); 105 | } 106 | else if (op->offset == 64) 107 | mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword); 108 | 109 | mkasm(u, "]"); 110 | break; 111 | } 112 | 113 | case UD_OP_IMM: 114 | if (syn_cast) opr_cast(u, op); 115 | switch (op->size) { 116 | case 8: mkasm(u, "0x%x", op->lval.ubyte); break; 117 | case 16: mkasm(u, "0x%x", op->lval.uword); break; 118 | case 32: mkasm(u, "0x%lx", op->lval.udword); break; 119 | case 64: mkasm(u, "0x" FMT64 "x", op->lval.uqword); break; 120 | default: break; 121 | } 122 | break; 123 | 124 | case UD_OP_JIMM: 125 | if (syn_cast) opr_cast(u, op); 126 | switch (op->size) { 127 | case 8: 128 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); 129 | break; 130 | case 16: 131 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); 132 | break; 133 | case 32: 134 | mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); 135 | break; 136 | default:break; 137 | } 138 | break; 139 | 140 | case UD_OP_PTR: 141 | switch (op->size) { 142 | case 32: 143 | mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg, 144 | op->lval.ptr.off & 0xFFFF); 145 | break; 146 | case 48: 147 | mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg, 148 | op->lval.ptr.off); 149 | break; 150 | } 151 | break; 152 | 153 | case UD_OP_CONST: 154 | if (syn_cast) opr_cast(u, op); 155 | mkasm(u, "%d", op->lval.udword); 156 | break; 157 | 158 | default: return; 159 | } 160 | } 161 | 162 | /* ============================================================================= 163 | * translates to intel syntax 164 | * ============================================================================= 165 | */ 166 | extern void ud_translate_intel(struct ud* u) 167 | { 168 | /* -- prefixes -- */ 169 | 170 | /* check if P_OSO prefix is used */ 171 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 172 | switch (u->dis_mode) { 173 | case 16: 174 | mkasm(u, "o32 "); 175 | break; 176 | case 32: 177 | case 64: 178 | mkasm(u, "o16 "); 179 | break; 180 | } 181 | } 182 | 183 | /* check if P_ASO prefix was used */ 184 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 185 | switch (u->dis_mode) { 186 | case 16: 187 | mkasm(u, "a32 "); 188 | break; 189 | case 32: 190 | mkasm(u, "a16 "); 191 | break; 192 | case 64: 193 | mkasm(u, "a32 "); 194 | break; 195 | } 196 | } 197 | 198 | if (u->pfx_lock) 199 | mkasm(u, "lock "); 200 | if (u->pfx_rep) 201 | mkasm(u, "rep "); 202 | if (u->pfx_repne) 203 | mkasm(u, "repne "); 204 | if (u->implicit_addr && u->pfx_seg) 205 | mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); 206 | 207 | /* print the instruction mnemonic */ 208 | mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic)); 209 | 210 | /* operand 1 */ 211 | if (u->operand[0].type != UD_NONE) { 212 | gen_operand(u, &u->operand[0], u->c1); 213 | } 214 | /* operand 2 */ 215 | if (u->operand[1].type != UD_NONE) { 216 | mkasm(u, ", "); 217 | gen_operand(u, &u->operand[1], u->c2); 218 | } 219 | 220 | /* operand 3 */ 221 | if (u->operand[2].type != UD_NONE) { 222 | mkasm(u, ", "); 223 | gen_operand(u, &u->operand[2], u->c3); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /ksplice-undo.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (C) 2007-2009 Ksplice, Inc. 4 | # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License, version 2. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 17 | # 02110-1301, USA. 18 | 19 | use strict; 20 | use warnings; 21 | use lib 'KSPLICE_DATA_DIR'; 22 | use Ksplice; 23 | my $have_usleep = eval { require Time::HiRes }; 24 | 25 | my $debug; 26 | my $debugon = 0; 27 | GetOptions(@common_options, 28 | "debug" => \$debugon, 29 | "debugfile=s" => \$debug) or pod2usage(1); 30 | 31 | pod2usage(1) if($help || scalar(@ARGV) != 1); 32 | $debugon = 1 if (defined($debug)); 33 | $debug = abs_path($debug) if (defined $debug); 34 | 35 | my $kid = $ARGV[0]; 36 | $kid =~ s/^ksplice[-_]//; 37 | $kid =~ s/[-_].*$//; 38 | my $update = "ksplice_$kid"; 39 | my $nounload = runstr("lsmod") =~ m/- $/m; 40 | 41 | chdir("/sys/module"); 42 | 43 | if (!update_loaded($kid) 44 | && !-e $update && !defined(glob("${update}_*_{o,n,old,new}"))) { 45 | print "Ksplice id $kid is not present in the kernel\n"; 46 | rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); 47 | exit(1); 48 | } 49 | 50 | set_debug_level($kid, $debugon); 51 | my $failed = 0; 52 | 53 | foreach my $module (glob("${update}_*_{o,old}")) { 54 | if (!$nounload && runval_raw('rmmod', $module) != 0) { 55 | child_error(); 56 | error_die(); 57 | } 58 | } 59 | 60 | my $have_sysfs = update_loaded($kid); 61 | my $stage = ($have_sysfs && get_stage($kid)); 62 | if ($stage ne 'applied') { 63 | print "Ksplice id $kid is not applied; just cleaning up\n"; 64 | } 65 | else { 66 | set_stage($kid, "reversed"); 67 | } 68 | $stage = ($have_sysfs && get_stage($kid)); 69 | ($stage eq 'reversed') or !$have_sysfs or error_die(); 70 | 71 | foreach my $module (glob("${update}_*_{n,new}")) { 72 | if (!$nounload && runval_raw('rmmod', $module) != 0) { 73 | child_error(); 74 | error_die(); 75 | } 76 | } 77 | 78 | set_stage($kid, "cleanup") if ($have_sysfs); 79 | if ($have_usleep) { 80 | my $count = 0; 81 | while (update_loaded($kid) && $count < 5) { 82 | Time::HiRes::usleep(100000); 83 | $count++; 84 | } 85 | } else { 86 | sleep(1) if (!update_loaded($kid)); 87 | } 88 | if (-e "/sys/module/$update") { 89 | if (!$nounload && runval_raw('rmmod', $update) != 0) { 90 | child_error(); 91 | error_die(); 92 | } 93 | } 94 | 95 | rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); 96 | 97 | exit(0); 98 | 99 | sub error_die { 100 | if (!update_loaded($kid)) { 101 | die("Error undoing Ksplice update $kid\n"); 102 | } 103 | print STDERR "Error undoing Ksplice update $kid:\n" unless $raw_errors; 104 | print_error($kid); 105 | if($debugon) { 106 | my $debugfile = get_debug_output($kid, $debug); 107 | print("Debugging output saved to $debugfile\n") if $debugfile; 108 | } 109 | exit(-1); 110 | } 111 | 112 | sub print_error { 113 | my ($kid) = @_; 114 | my %errors = ( 115 | "code_busy" => <<'END', 116 | Ksplice has aborted the undo operation because it appears that the code that 117 | you are trying to change is continuously in use by the system. More 118 | specifically, Ksplice has been unable to find a moment when one or more of the 119 | to-be-changed functions is not on a thread's kernel stack. 120 | END 121 | "module_busy" => <<'END', 122 | Ksplice has aborted the undo operation because it appears that the Ksplice 123 | update that you are trying to unload is in use by another module. You can find 124 | out what module is using the Ksplice update using the lsmod command. 125 | END 126 | "unexpected_running_task" => <<'END', 127 | Ksplice has aborted the undo operation because of an unexpected failure during 128 | the kernel stack check. Please consider reporting a bug to PACKAGE_BUGREPORT. 129 | END 130 | "out_of_memory" => <<'END', 131 | Ksplice has aborted the undo operation because the kernel ran out of memory. 132 | END 133 | "call_failed" => <<'END', 134 | Ksplice has aborted the undo operation at the request of a one of the 135 | pre-application hooks that were included as part of this Ksplice 136 | update. This is likely the result of a bug in the patch used to 137 | generate this update. 138 | END 139 | "cold_update_loaded" => <<'END', 140 | Ksplice has aborted the undo operation because the update was applied using the 141 | --partial option, and one of the modules that was changed by the update was loaded 142 | since the update was applied. You must first unload that (cold patched) module 143 | before you can undo this update. 144 | END 145 | "unexpected" => <<'END', 146 | Ksplice has aborted because of an unexpected error. 147 | Please consider reporting a bug to PACKAGE_BUGREPORT. 148 | END 149 | "UNKNOWN" => <<'END', 150 | The Ksplice kernel component has returned an error code that this version of 151 | ksplice-undo does not understand. 152 | END 153 | "ok" => <<'END', 154 | Ksplice has aborted the undo operation for unknown reasons. 155 | Please consider reporting a bug to PACKAGE_BUGREPORT. 156 | END 157 | ); 158 | print_abort_error($kid, %errors); 159 | } 160 | 161 | =head1 NAME 162 | 163 | ksplice-undo - Undo a Ksplice update that has been applied to the running kernel 164 | 165 | =head1 SYNOPSIS 166 | 167 | B [I] I 168 | 169 | =head1 DESCRIPTION 170 | 171 | B takes as input a Ksplice identification tag, as reported by 172 | L, and it reverses that update within the running binary kernel. 173 | 174 | =head1 OPTIONS 175 | 176 | =over 8 177 | 178 | =item B<--debug> 179 | 180 | Reverses the update with debugging output enabled. Recommended only for 181 | debugging. 182 | 183 | =item B<--debugfile=>I 184 | 185 | Sets the location where debugging output should be saved. Implies --debug. 186 | 187 | =item B<--raw-errors> 188 | 189 | Print only raw error information designed to be machine-readable on 190 | standard error (standard output is still intended to be 191 | human-readable). If B fails due to an error from the 192 | Ksplice kernel modules, the first line on standard error will be a 193 | Ksplice B (see the Ksplice source code for documentation 194 | on these codes). Further lines will vary depending on the abort code. 195 | If B fails for any other reason, it will output the line 196 | C<"OTHER\n">, followed by a human-readable failure message, to 197 | standard error. 198 | 199 | =back 200 | 201 | =head1 SEE ALSO 202 | 203 | L, L, L 204 | 205 | =head1 BUGS 206 | 207 | Please report bugs to . 208 | 209 | =head1 AUTHORS 210 | 211 | Jeff Arnold, Anders Kaseorg, and Tim Abbott 212 | 213 | =head1 COPYRIGHT 214 | 215 | Copyright (C) 2007-2009 Ksplice, Inc. 216 | 217 | This is free software and documentation. You can redistribute and/or modify it 218 | under the terms of the GNU General Public License, version 2. 219 | 220 | =cut 221 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/types.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/types.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_TYPES_H 27 | #define UD_TYPES_H 28 | 29 | #ifdef __KERNEL__ 30 | /* -D__KERNEL__ is automatically passed on the command line when 31 | building something as part of the Linux kernel */ 32 | # include 33 | # include 34 | # define __UD_STANDALONE__ 1 35 | #endif /* __KERNEL__ */ 36 | 37 | #ifndef __UD_STANDALONE__ 38 | # include 39 | #endif /* __UD_STANDALONE__ */ 40 | 41 | /* gcc specific extensions */ 42 | #ifdef __GNUC__ 43 | # define UD_ATTR_PACKED __attribute__((packed)) 44 | #else 45 | # define UD_ATTR_PACKED 46 | #endif /* UD_ATTR_PACKED */ 47 | 48 | #ifdef _MSC_VER 49 | # define FMT64 "%I64" 50 | typedef unsigned __int8 uint8_t; 51 | typedef unsigned __int16 uint16_t; 52 | typedef unsigned __int32 uint32_t; 53 | typedef unsigned __int64 uint64_t; 54 | typedef __int8 int8_t; 55 | typedef __int16 int16_t; 56 | typedef __int32 int32_t; 57 | typedef __int64 int64_t; 58 | #else 59 | # define FMT64 "%ll" 60 | # ifndef __UD_STANDALONE__ 61 | # include 62 | # endif /* __UD_STANDALONE__ */ 63 | #endif 64 | 65 | /* ----------------------------------------------------------------------------- 66 | * All possible "types" of objects in udis86. Order is Important! 67 | * ----------------------------------------------------------------------------- 68 | */ 69 | enum ud_type 70 | { 71 | UD_NONE, 72 | 73 | /* 8 bit GPRs */ 74 | UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, 75 | UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, 76 | UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, 77 | UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, 78 | UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, 79 | 80 | /* 16 bit GPRs */ 81 | UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, 82 | UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, 83 | UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, 84 | UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, 85 | 86 | /* 32 bit GPRs */ 87 | UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, 88 | UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, 89 | UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, 90 | UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, 91 | 92 | /* 64 bit GPRs */ 93 | UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, 94 | UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, 95 | UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, 96 | UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, 97 | 98 | /* segment registers */ 99 | UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, 100 | UD_R_FS, UD_R_GS, 101 | 102 | /* control registers*/ 103 | UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, 104 | UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, 105 | UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, 106 | UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, 107 | 108 | /* debug registers */ 109 | UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, 110 | UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, 111 | UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, 112 | UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, 113 | 114 | /* mmx registers */ 115 | UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, 116 | UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, 117 | 118 | /* x87 registers */ 119 | UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, 120 | UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, 121 | 122 | /* extended multimedia registers */ 123 | UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, 124 | UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, 125 | UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, 126 | UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, 127 | 128 | UD_R_RIP, 129 | 130 | /* Operand Types */ 131 | UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, 132 | UD_OP_JIMM, UD_OP_CONST 133 | }; 134 | 135 | #include "itab.h" 136 | 137 | /* ----------------------------------------------------------------------------- 138 | * struct ud_operand - Disassembled instruction Operand. 139 | * ----------------------------------------------------------------------------- 140 | */ 141 | struct ud_operand 142 | { 143 | enum ud_type type; 144 | uint8_t size; 145 | union { 146 | int8_t sbyte; 147 | uint8_t ubyte; 148 | int16_t sword; 149 | uint16_t uword; 150 | int32_t sdword; 151 | uint32_t udword; 152 | int64_t sqword; 153 | uint64_t uqword; 154 | 155 | struct { 156 | uint16_t seg; 157 | uint32_t off; 158 | } ptr; 159 | } lval; 160 | 161 | enum ud_type base; 162 | enum ud_type index; 163 | uint8_t offset; 164 | uint8_t scale; 165 | }; 166 | 167 | /* ----------------------------------------------------------------------------- 168 | * struct ud - The udis86 object. 169 | * ----------------------------------------------------------------------------- 170 | */ 171 | struct ud 172 | { 173 | int (*inp_hook) (struct ud*); 174 | uint8_t inp_curr; 175 | uint8_t inp_fill; 176 | #ifndef __UD_STANDALONE__ 177 | FILE* inp_file; 178 | #endif 179 | uint8_t inp_ctr; 180 | uint8_t* inp_buff; 181 | uint8_t* inp_buff_end; 182 | uint8_t inp_end; 183 | void (*translator)(struct ud*); 184 | uint64_t insn_offset; 185 | char insn_hexcode[32]; 186 | char insn_buffer[64]; 187 | unsigned int insn_fill; 188 | uint8_t dis_mode; 189 | uint64_t pc; 190 | uint8_t vendor; 191 | struct map_entry* mapen; 192 | enum ud_mnemonic_code mnemonic; 193 | struct ud_operand operand[3]; 194 | uint8_t error; 195 | uint8_t pfx_rex; 196 | uint8_t pfx_seg; 197 | uint8_t pfx_opr; 198 | uint8_t pfx_adr; 199 | uint8_t pfx_lock; 200 | uint8_t pfx_rep; 201 | uint8_t pfx_repe; 202 | uint8_t pfx_repne; 203 | uint8_t pfx_insn; 204 | uint8_t default64; 205 | uint8_t opr_mode; 206 | uint8_t adr_mode; 207 | uint8_t br_far; 208 | uint8_t br_near; 209 | uint8_t implicit_addr; 210 | uint8_t c1; 211 | uint8_t c2; 212 | uint8_t c3; 213 | uint8_t inp_cache[256]; 214 | uint8_t inp_sess[64]; 215 | void * user_opaque_data; 216 | struct ud_itab_entry * itab_entry; 217 | }; 218 | 219 | /* ----------------------------------------------------------------------------- 220 | * Type-definitions 221 | * ----------------------------------------------------------------------------- 222 | */ 223 | typedef enum ud_type ud_type_t; 224 | typedef enum ud_mnemonic_code ud_mnemonic_code_t; 225 | 226 | typedef struct ud ud_t; 227 | typedef struct ud_operand ud_operand_t; 228 | 229 | #define UD_SYN_INTEL ud_translate_intel 230 | #define UD_SYN_ATT ud_translate_att 231 | #define UD_EOI -1 232 | #define UD_INP_CACHE_SZ 32 233 | #define UD_VENDOR_AMD 0 234 | #define UD_VENDOR_INTEL 1 235 | #define UD_VENDOR_ANY 2 236 | 237 | #define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code ) 238 | #define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 ) 239 | #define catch_error() else 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /kmodsrc/x86/libudis86/input.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/input.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "extern.h" 27 | #include "types.h" 28 | #include "input.h" 29 | 30 | /* ----------------------------------------------------------------------------- 31 | * inp_buff_hook() - Hook for buffered inputs. 32 | * ----------------------------------------------------------------------------- 33 | */ 34 | static int 35 | inp_buff_hook(struct ud* u) 36 | { 37 | if (u->inp_buff < u->inp_buff_end) 38 | return *u->inp_buff++; 39 | else return -1; 40 | } 41 | 42 | #ifndef __UD_STANDALONE__ 43 | /* ----------------------------------------------------------------------------- 44 | * inp_file_hook() - Hook for FILE inputs. 45 | * ----------------------------------------------------------------------------- 46 | */ 47 | static int 48 | inp_file_hook(struct ud* u) 49 | { 50 | return fgetc(u->inp_file); 51 | } 52 | #endif /* __UD_STANDALONE__*/ 53 | 54 | /* ============================================================================= 55 | * ud_inp_set_hook() - Sets input hook. 56 | * ============================================================================= 57 | */ 58 | extern void 59 | ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 60 | { 61 | u->inp_hook = hook; 62 | inp_init(u); 63 | } 64 | 65 | extern void 66 | ud_set_user_opaque_data( struct ud * u, void * opaque ) 67 | { 68 | u->user_opaque_data = opaque; 69 | } 70 | 71 | extern void * 72 | ud_get_user_opaque_data( struct ud * u ) 73 | { 74 | return u->user_opaque_data; 75 | } 76 | 77 | /* ============================================================================= 78 | * ud_inp_set_buffer() - Set buffer as input. 79 | * ============================================================================= 80 | */ 81 | extern void 82 | ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len) 83 | { 84 | u->inp_hook = inp_buff_hook; 85 | u->inp_buff = buf; 86 | u->inp_buff_end = buf + len; 87 | inp_init(u); 88 | } 89 | 90 | #ifndef __UD_STANDALONE__ 91 | /* ============================================================================= 92 | * ud_input_set_file() - Set buffer as input. 93 | * ============================================================================= 94 | */ 95 | extern void 96 | ud_set_input_file(register struct ud* u, FILE* f) 97 | { 98 | u->inp_hook = inp_file_hook; 99 | u->inp_file = f; 100 | inp_init(u); 101 | } 102 | #endif /* __UD_STANDALONE__ */ 103 | 104 | /* ============================================================================= 105 | * ud_input_skip() - Skip n input bytes. 106 | * ============================================================================= 107 | */ 108 | extern void 109 | ud_input_skip(struct ud* u, size_t n) 110 | { 111 | while (n--) { 112 | u->inp_hook(u); 113 | } 114 | } 115 | 116 | /* ============================================================================= 117 | * ud_input_end() - Test for end of input. 118 | * ============================================================================= 119 | */ 120 | extern int 121 | ud_input_end(struct ud* u) 122 | { 123 | return (u->inp_curr == u->inp_fill) && u->inp_end; 124 | } 125 | 126 | /* ----------------------------------------------------------------------------- 127 | * inp_next() - Loads and returns the next byte from input. 128 | * 129 | * inp_curr and inp_fill are pointers to the cache. The program is written based 130 | * on the property that they are 8-bits in size, and will eventually wrap around 131 | * forming a circular buffer. So, the size of the cache is 256 in size, kind of 132 | * unnecessary yet optimized. 133 | * 134 | * A buffer inp_sess stores the bytes disassembled for a single session. 135 | * ----------------------------------------------------------------------------- 136 | */ 137 | extern uint8_t inp_next(struct ud* u) 138 | { 139 | int c = -1; 140 | /* if current pointer is not upto the fill point in the 141 | * input cache. 142 | */ 143 | if ( u->inp_curr != u->inp_fill ) { 144 | c = u->inp_cache[ ++u->inp_curr ]; 145 | /* if !end-of-input, call the input hook and get a byte */ 146 | } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) { 147 | /* end-of-input, mark it as an error, since the decoder, 148 | * expected a byte more. 149 | */ 150 | u->error = 1; 151 | /* flag end of input */ 152 | u->inp_end = 1; 153 | return 0; 154 | } else { 155 | /* increment pointers, we have a new byte. */ 156 | u->inp_curr = ++u->inp_fill; 157 | /* add the byte to the cache */ 158 | u->inp_cache[ u->inp_fill ] = c; 159 | } 160 | /* record bytes input per decode-session. */ 161 | u->inp_sess[ u->inp_ctr++ ] = c; 162 | /* return byte */ 163 | return ( uint8_t ) c; 164 | } 165 | 166 | /* ----------------------------------------------------------------------------- 167 | * inp_back() - Move back a single byte in the stream. 168 | * ----------------------------------------------------------------------------- 169 | */ 170 | extern void 171 | inp_back(struct ud* u) 172 | { 173 | if ( u->inp_ctr > 0 ) { 174 | --u->inp_curr; 175 | --u->inp_ctr; 176 | } 177 | } 178 | 179 | /* ----------------------------------------------------------------------------- 180 | * inp_peek() - Peek into the next byte in source. 181 | * ----------------------------------------------------------------------------- 182 | */ 183 | extern uint8_t 184 | inp_peek(struct ud* u) 185 | { 186 | uint8_t r = inp_next(u); 187 | if ( !u->error ) inp_back(u); /* Don't backup if there was an error */ 188 | return r; 189 | } 190 | 191 | /* ----------------------------------------------------------------------------- 192 | * inp_move() - Move ahead n input bytes. 193 | * ----------------------------------------------------------------------------- 194 | */ 195 | extern void 196 | inp_move(struct ud* u, size_t n) 197 | { 198 | while (n--) 199 | inp_next(u); 200 | } 201 | 202 | /*------------------------------------------------------------------------------ 203 | * inp_uintN() - return uintN from source. 204 | *------------------------------------------------------------------------------ 205 | */ 206 | extern uint8_t 207 | inp_uint8(struct ud* u) 208 | { 209 | return inp_next(u); 210 | } 211 | 212 | extern uint16_t 213 | inp_uint16(struct ud* u) 214 | { 215 | uint16_t r, ret; 216 | 217 | ret = inp_next(u); 218 | r = inp_next(u); 219 | return ret | (r << 8); 220 | } 221 | 222 | extern uint32_t 223 | inp_uint32(struct ud* u) 224 | { 225 | uint32_t r, ret; 226 | 227 | ret = inp_next(u); 228 | r = inp_next(u); 229 | ret = ret | (r << 8); 230 | r = inp_next(u); 231 | ret = ret | (r << 16); 232 | r = inp_next(u); 233 | return ret | (r << 24); 234 | } 235 | 236 | extern uint64_t 237 | inp_uint64(struct ud* u) 238 | { 239 | uint64_t r, ret; 240 | 241 | ret = inp_next(u); 242 | r = inp_next(u); 243 | ret = ret | (r << 8); 244 | r = inp_next(u); 245 | ret = ret | (r << 16); 246 | r = inp_next(u); 247 | ret = ret | (r << 24); 248 | r = inp_next(u); 249 | ret = ret | (r << 32); 250 | r = inp_next(u); 251 | ret = ret | (r << 40); 252 | r = inp_next(u); 253 | ret = ret | (r << 48); 254 | r = inp_next(u); 255 | return ret | (r << 56); 256 | } 257 | -------------------------------------------------------------------------------- /kmodsrc/ksplice.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * struct ksplice_symbol - Ksplice's analogue of an ELF symbol 5 | * @name: The ELF name of the symbol 6 | * @label: A unique Ksplice name for the symbol 7 | * @candidate_vals: A linked list of possible values for the symbol, or NULL 8 | * @value: The value of the symbol (valid when vals is NULL) 9 | **/ 10 | struct ksplice_symbol { 11 | const char *name; 12 | const char *label; 13 | /* private: */ 14 | struct list_head *candidate_vals; 15 | unsigned long value; 16 | }; 17 | 18 | /** 19 | * struct ksplice_reloc - Ksplice's analogue of an ELF relocation 20 | * @blank_addr: The address of the relocation's storage unit 21 | * @symbol: The ksplice_symbol associated with this relocation 22 | * @howto: The information regarding the relocation type 23 | * @insn_addend: The part of the ELF addend resulting from quirks of 24 | * the instruction one of whose operands is the relocation. 25 | * For example, this is -4 on x86 pc-relative jumps. 26 | * @target_addend: The rest of the ELF addend. This is equal to the offset 27 | * against the symbol that the relocation refers to. 28 | **/ 29 | struct ksplice_reloc { 30 | unsigned long blank_addr; 31 | struct ksplice_symbol *symbol; 32 | const struct ksplice_reloc_howto *howto; 33 | long insn_addend; 34 | long target_addend; 35 | }; 36 | 37 | enum ksplice_reloc_howto_type { 38 | KSPLICE_HOWTO_RELOC, 39 | KSPLICE_HOWTO_RELOC_PATCH, 40 | KSPLICE_HOWTO_DATE, 41 | KSPLICE_HOWTO_TIME, 42 | KSPLICE_HOWTO_BUG, 43 | KSPLICE_HOWTO_EXTABLE, 44 | KSPLICE_HOWTO_SYMBOL, 45 | }; 46 | 47 | /** 48 | * struct ksplice_reloc_howto - Ksplice's relocation type information 49 | * @type: The type of the relocation 50 | * @pcrel: Is the relocation PC relative? 51 | * @size: The size, in bytes, of the item to be relocated 52 | * @dst_mask: Bitmask for which parts of the instruction or data are 53 | * replaced with the relocated value 54 | * (based on dst_mask from GNU BFD's reloc_howto_struct) 55 | * @rightshift: The value the final relocation is shifted right by; 56 | * used to drop unwanted data from the relocation 57 | * (based on rightshift from GNU BFD's reloc_howto_struct) 58 | * @signed_addend: Should the addend be interpreted as a signed value? 59 | **/ 60 | struct ksplice_reloc_howto { 61 | enum ksplice_reloc_howto_type type; 62 | int pcrel; 63 | int size; 64 | long dst_mask; 65 | unsigned int rightshift; 66 | int signed_addend; 67 | }; 68 | 69 | #if BITS_PER_LONG == 32 70 | #define KSPLICE_CANARY 0x77777777UL 71 | #elif BITS_PER_LONG == 64 72 | #define KSPLICE_CANARY 0x7777777777777777UL 73 | #endif /* BITS_PER_LONG */ 74 | 75 | /** 76 | * struct ksplice_section - Ksplice's analogue of an ELF section 77 | * @symbol: The ksplice_symbol associated with this section 78 | * @size: The length, in bytes, of this section 79 | * @address: The address of the section 80 | * @flags: Flags indicating the type of the section, whether or 81 | * not it has been matched, etc. 82 | **/ 83 | struct ksplice_section { 84 | struct ksplice_symbol *symbol; 85 | unsigned long address; 86 | unsigned long size; 87 | unsigned int flags; 88 | const unsigned char **match_map; 89 | int unmatched; 90 | }; 91 | #define KSPLICE_SECTION_TEXT 0x00000001 92 | #define KSPLICE_SECTION_RODATA 0x00000002 93 | #define KSPLICE_SECTION_DATA 0x00000004 94 | #define KSPLICE_SECTION_STRING 0x00000008 95 | #define KSPLICE_SECTION_MATCH_DATA_EARLY 0x00000100 96 | #define KSPLICE_SECTION_MATCHED 0x10000000 97 | 98 | #define MAX_TRAMPOLINE_SIZE 5 99 | 100 | enum ksplice_patch_type { 101 | KSPLICE_PATCH_TEXT, 102 | KSPLICE_PATCH_DATA, 103 | KSPLICE_PATCH_EXPORT, 104 | }; 105 | 106 | /** 107 | * struct ksplice_patch - A replacement that Ksplice should perform 108 | * @oldaddr: The address of the obsolete function or structure 109 | * @repladdr: The address of the replacement function 110 | * @type: The type of the ksplice patch 111 | * @size: The size of the patch 112 | * @contents: The bytes to be installed at oldaddr 113 | * @vaddr The address of the page mapping used to write at oldaddr 114 | * @saved: The bytes originally at oldaddr which were 115 | * overwritten by the patch 116 | **/ 117 | struct ksplice_patch { 118 | unsigned long oldaddr; 119 | unsigned long repladdr; 120 | enum ksplice_patch_type type; 121 | unsigned int size; 122 | void *contents; 123 | /* private: */ 124 | void *vaddr; 125 | void *saved; 126 | }; 127 | 128 | #ifdef KSPLICE_STANDALONE 129 | struct ksplice_system_map { 130 | const char *label; 131 | unsigned long nr_candidates; 132 | const unsigned long *candidates; 133 | }; 134 | #endif /* KSPLICE_STANDALONE */ 135 | 136 | #ifdef __KERNEL__ 137 | #include 138 | #include 139 | #include 140 | 141 | #define _KS_PASTE(x, y) x##y 142 | #define KS_PASTE(x, y) _KS_PASTE(x, y) 143 | #define KSPLICE_UNIQ(s) KS_PASTE(s##_, KSPLICE_MID) 144 | #define KSPLICE_KID_UNIQ(s) KS_PASTE(s##_, KSPLICE_KID) 145 | #ifdef KSPLICE_STANDALONE 146 | #define init_ksplice_mod_change KSPLICE_KID_UNIQ(init_ksplice_mod_change) 147 | #define cleanup_ksplice_mod_change KSPLICE_KID_UNIQ(cleanup_ksplice_mod_change) 148 | #endif 149 | 150 | /** 151 | * struct ksplice_module_list_entry - A record of a ksplice_mod_change's target 152 | * @target_mod_name: The name of the ksplice_mod_change's target module 153 | * @new_code_mod_name: The name of the ksplice_mod_change's new_code module 154 | * @applied: Whether the ksplice_mod_change was applied or not (this 155 | * will be false for ksplice_mod_changes patching targets 156 | * that are not loaded when the partial flag is set) 157 | **/ 158 | struct ksplice_module_list_entry { 159 | const char *target_mod_name; 160 | const char *new_code_mod_name; 161 | const char *kid; 162 | bool applied; 163 | /* private: */ 164 | struct list_head update_list; /* list head for this is per-update */ 165 | struct list_head list; /* list head for this is global */ 166 | }; 167 | 168 | /* List of all ksplice modules and the module they patch */ 169 | extern struct list_head ksplice_modules; 170 | 171 | /* There are two actions, apply and reverse */ 172 | #define KS_ACTIONS 2 173 | enum ksplice_action { 174 | KS_APPLY, 175 | KS_REVERSE, 176 | }; 177 | 178 | /** 179 | * struct ksplice_hooks - Hooks to be run during an action (apply or reverse) 180 | * @pre: Runs before the action; 181 | * may return nonzero to abort the action 182 | * @check: Runs inside stop_machine before the action; 183 | * may return nonzero to abort the action 184 | * @intra: Runs inside stop_machine during the action 185 | * @post: Runs after the action is successfully performed 186 | * @fail: Runs if the action is aborted for any reason 187 | */ 188 | struct ksplice_hooks { 189 | const typeof(int (*)(void)) *pre, *pre_end, *check, *check_end; 190 | const typeof(void (*)(void)) *intra, *intra_end, *post, *post_end, 191 | *fail, *fail_end; 192 | }; 193 | 194 | /** 195 | * struct ksplice_code - Ksplice metadata for an object 196 | * @relocs: The Ksplice relocations for the object 197 | * @symbols: The Ksplice symbols for the object 198 | * @sections: The Ksplice sections for the object 199 | **/ 200 | struct ksplice_code { 201 | struct ksplice_reloc *relocs, *relocs_end; 202 | struct ksplice_section *sections, *sections_end; 203 | struct ksplice_symbol *symbols, *symbols_end; 204 | #ifdef KSPLICE_STANDALONE 205 | struct ksplice_system_map *system_map, *system_map_end; 206 | #endif /* KSPLICE_STANDALONE */ 207 | }; 208 | 209 | /** 210 | * struct ksplice_mod_change - Data for one module modified by a Ksplice update 211 | * @name: The name of the new_code module for the change 212 | * @kid: The Ksplice unique identifier for the change 213 | * @target_name: The name of the module modified by the change 214 | * @new_code_mod: The new_code module for the change 215 | * @old_code: The old code for run-pre matching 216 | * @new_code: The new code to switch to 217 | * @patches: The function replacements in the change 218 | * @patches_end: The end pointer for patches array 219 | * @hooks: Hooks to be run during apply and reverse 220 | * @update: The atomic update the change is part of 221 | * @target: The module modified by the change 222 | * @safety_records: The ranges of addresses that must not be on a 223 | * kernel stack for the patch to apply safely 224 | **/ 225 | struct ksplice_mod_change { 226 | const char *name; 227 | const char *kid; 228 | const char *target_name; 229 | #ifdef KSPLICE_STANDALONE 230 | unsigned long map_printk; 231 | #endif /* KSPLICE_STANDALONE */ 232 | struct module *new_code_mod; 233 | struct ksplice_code old_code, new_code; 234 | struct ksplice_patch *patches, *patches_end; 235 | struct ksplice_hooks hooks[KS_ACTIONS]; 236 | /* private: */ 237 | struct update *update; 238 | struct module *target; 239 | struct list_head temp_labelvals; 240 | struct list_head safety_records; 241 | struct list_head list; 242 | }; 243 | 244 | 245 | int init_ksplice_mod_change(struct ksplice_mod_change *change); 246 | 247 | void cleanup_ksplice_mod_change(struct ksplice_mod_change *change); 248 | 249 | #endif /* __KERNEL__ */ 250 | -------------------------------------------------------------------------------- /Ksplice.pm.in: -------------------------------------------------------------------------------- 1 | package Ksplice; 2 | use Cwd qw(abs_path getcwd); 3 | use Getopt::Long qw(:config bundling); 4 | use File::Basename; 5 | use File::Copy; 6 | use File::Path; 7 | use File::Spec::Functions qw(tmpdir); 8 | use File::Temp qw(tempfile tempdir); 9 | use Fatal qw(:void copy rename move chdir mkdir rmdir unlink rmtree); 10 | use IPC::Open2; 11 | use IPC::Open3; 12 | use Pod::Usage; 13 | use Text::ParseWords; 14 | use strict; 15 | use warnings; 16 | use Verbose qw(:2 copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir); 17 | require Exporter; 18 | our @ISA = qw(Exporter); 19 | our @EXPORT = qw( 20 | Verbose GetOptions pod2usage shellwords 21 | $datadir $libexecdir @common_options $help $raw_errors 22 | child_error runval runval_raw runstr runstr_err runval_in runval_infile runval_outfile 23 | unpack_update 24 | get_stage set_stage set_debug_level set_partial get_abort_cause get_patch update_loaded 25 | get_debug_output get_conflicts get_raw_conflicts get_short_description 26 | read_file write_file 27 | abs_path getcwd basename dirname tmpdir 28 | copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir 29 | print_abort_error print_abort_code 30 | ); 31 | 32 | our ($datadir, $libexecdir) = qw(KSPLICE_DATA_DIR KSPLICE_LIBEXEC_DIR); 33 | 34 | our $help = 0; 35 | our $raw_errors = 0; 36 | our $printed_abort_code; 37 | 38 | our @common_options = ( 39 | "help|?" => \$help, 40 | "raw-errors" => \$raw_errors, 41 | "version" => sub { print "Ksplice version PACKAGE_VERSION\n"; exit(0); }, 42 | "api-version" => sub { print "KSPLICE_API_VERSION\n"; exit(0); }, 43 | "verbose|v:+" => \$Verbose::level, 44 | "quiet|q:+" => sub { $Verbose::level -= $_[1]; }, 45 | ); 46 | 47 | $SIG{__DIE__} = sub { 48 | die @_ if $^S || !$raw_errors; 49 | my ($msg) = @_; 50 | if(!$printed_abort_code) { 51 | print STDERR "OTHER\n$msg"; 52 | } 53 | exit(-1); 54 | }; 55 | 56 | sub child_error { 57 | if($raw_errors) { 58 | return ($? != 0); 59 | } 60 | if($? == -1) { 61 | print STDERR "Failed to exec child\n"; 62 | } elsif(($? & 127) != 0) { 63 | print STDERR "Child exited with signal ", ($? & 127), ($? & 128) ? " (core dumped)\n" : "\n"; 64 | } elsif($? >> 8 != 0) { 65 | print STDERR "Child exited with status ", $? >> 8, "\n"; 66 | } else { 67 | return 0; 68 | } 69 | return 1; 70 | } 71 | 72 | sub runval { 73 | my (@cmd) = @_; 74 | if(runval_raw(@cmd) != 0) { 75 | child_error(); 76 | die "Failed during: @cmd\n"; 77 | } 78 | } 79 | 80 | sub runval_raw { 81 | my (@cmd) = @_; 82 | my ($out, $err); 83 | print "+ @cmd\n" if($Verbose::level >= 1); 84 | if($raw_errors) { 85 | my $pid = open3(fileno STDIN, ">&STDOUT", ">/dev/null", @cmd); 86 | waitpid($pid, 0); 87 | return $?; 88 | } else { 89 | return system(@cmd); 90 | } 91 | } 92 | 93 | sub runstr { 94 | my @cmd = @_; 95 | print "+ @cmd\n" if($Verbose::level >= 1); 96 | local $/; 97 | local (*PIPE); 98 | if($raw_errors) { 99 | open3(fileno STDIN, \*PIPE, ">/dev/null", @cmd); 100 | } else { 101 | open PIPE, '-|', @cmd or die "Can't run @cmd: $!"; 102 | } 103 | my $output = ; 104 | close PIPE or $! == 0 or die "Can't run @cmd: $!"; 105 | return $output; 106 | } 107 | 108 | sub runstr_err { 109 | my @cmd = @_; 110 | print "+ @cmd\n" if($Verbose::level >= 1); 111 | local (*ERROR); 112 | my $pid = open3(fileno STDIN, '>&STDOUT', \*ERROR, @cmd); 113 | local $/; 114 | my $error = ; 115 | waitpid($pid, 0); 116 | print STDERR $error unless $raw_errors; 117 | return $error; 118 | } 119 | 120 | sub runval_in { 121 | my ($in, @cmd) = @_; 122 | print "+ @cmd <<'EOF'\n${in}EOF\n" if($Verbose::level >= 1); 123 | local (*WRITE); 124 | if($raw_errors) { 125 | open3(\*WRITE, ">&STDOUT", ">/dev/null", @cmd); 126 | } else { 127 | open(WRITE, '|-', @cmd) or die "Can't run @cmd: $!"; 128 | } 129 | print WRITE $in; 130 | close(WRITE) or $! == 0 or die "Can't run @cmd: $!"; 131 | if(child_error()) { 132 | die "Failed during: @cmd"; 133 | } 134 | } 135 | 136 | sub runval_infile { 137 | my ($infile, @cmd) = @_; 138 | print "+ @cmd < $infile\n" if($Verbose::level >= 1); 139 | local (*INFILE); 140 | open(INFILE, '<', $infile) or die "Can't open $infile: $!"; 141 | my $pid; 142 | if($raw_errors) { 143 | $pid = open3('<&INFILE', '>&STDOUT', ">/dev/null", @cmd); 144 | } else { 145 | $pid = open2('>&STDOUT', '<&INFILE', @cmd); 146 | } 147 | waitpid($pid, 0); 148 | if(child_error()) { 149 | die "Failed during: @cmd"; 150 | } 151 | } 152 | 153 | sub runval_outfile { 154 | my ($outfile, @cmd) = @_; 155 | print "+ @cmd > $outfile\n" if($Verbose::level >= 1); 156 | local (*OUTFILE); 157 | open(OUTFILE, '>', $outfile) or die "Can't open $outfile: $!"; 158 | my $pid; 159 | if($raw_errors) { 160 | $pid = open3('&OUTFILE', ">/dev/null", @cmd); 161 | } else { 162 | $pid = open2('>&OUTFILE', ' 1, CLEANUP => 1); 176 | runval("tar", "-C", $tmpdir, "--force-local", "-zxf", $file); 177 | my ($ksplice) = glob("$tmpdir/*/"); 178 | chop($ksplice); # remove the trailing slash 179 | return $ksplice; 180 | } 181 | 182 | sub get_sysfs { 183 | my ($kid) = @_; 184 | if(! -d "/sys/module") { 185 | die "/sys not mounted?\n"; 186 | } 187 | my $update = "ksplice_$kid"; 188 | if (-d "/sys/kernel/ksplice/$kid") { 189 | return "/sys/kernel/ksplice/$kid"; 190 | } 191 | if (-d "/sys/module/$update/ksplice") { 192 | return "/sys/module/$update/ksplice"; 193 | } 194 | return undef; 195 | } 196 | 197 | sub update_loaded { 198 | my ($kid) = @_; 199 | return defined(get_sysfs($kid)); 200 | } 201 | 202 | sub read_file { 203 | my ($file) = @_; 204 | local (*INPUT, $/); 205 | open(INPUT, "<", $file) or die $!; 206 | return ; 207 | } 208 | 209 | sub write_file { 210 | my ($file, $string) = @_; 211 | local *INPUT; 212 | open(INPUT, ">", $file) or die $!; 213 | print INPUT $string; 214 | } 215 | 216 | sub read_sysfs { 217 | my ($kid, $attr) = @_; 218 | my $sysfs = get_sysfs($kid); 219 | return undef if (!defined($sysfs)); 220 | return read_file("$sysfs/$attr"); 221 | } 222 | 223 | sub write_sysfs { 224 | my ($kid, $attr, $string) = @_; 225 | my $sysfs = get_sysfs($kid); 226 | return undef if (!defined($sysfs)); 227 | write_file("$sysfs/$attr", $string); 228 | } 229 | 230 | sub get_debug_output { 231 | my ($kid, $debugfs_out) = @_; 232 | my $update = "ksplice_$kid"; 233 | if (!$debugfs_out) { 234 | (undef, $debugfs_out) = tempfile('ksplice-debug-XXXXXX', DIR => tmpdir()); 235 | } 236 | if (runval_raw("grep", "-qFx", "nodev\tdebugfs", "/proc/filesystems") == 0) { 237 | my $debugfsdir = tempdir('ksplice-debugfs-XXXXXX', TMPDIR => 1); 238 | runval(qw(mount -t debugfs debugfs), $debugfsdir); 239 | if (-e "$debugfsdir/$update") { 240 | copy("$debugfsdir/$update", $debugfs_out); 241 | } 242 | runval(qw(umount), $debugfsdir); 243 | rmdir($debugfsdir); 244 | return $debugfs_out; 245 | } elsif ($? >> 8 == 1) { 246 | return (); 247 | } else { 248 | child_error(); 249 | exit(-1); 250 | } 251 | } 252 | 253 | sub get_stage { 254 | my ($kid) = @_; 255 | chomp(my $result = read_sysfs($kid, "stage")); 256 | return $result; 257 | } 258 | 259 | sub get_abort_cause { 260 | my ($kid) = @_; 261 | chomp(my $result = read_sysfs($kid, "abort_cause")); 262 | return $result; 263 | } 264 | 265 | sub get_conflicts { 266 | my ($kid) = @_; 267 | chomp(my $conflicts = read_sysfs($kid, "conflicts")); 268 | my @conflicts = split('\n', $conflicts); 269 | my $out = ''; 270 | foreach my $conflict (@conflicts) { 271 | my ($name, $pid, @symbols) = split(' ', $conflict); 272 | next if (!@symbols); 273 | $out .= "Process $name(pid $pid) is using the following symbols changed by update $kid:\n"; 274 | foreach my $symbol (@symbols) { 275 | $out .= " $symbol\n"; 276 | } 277 | } 278 | return $out; 279 | } 280 | 281 | sub get_raw_conflicts { 282 | my ($kid) = @_; 283 | my $conflicts = read_sysfs($kid, "conflicts"); 284 | return $conflicts; 285 | } 286 | 287 | sub get_patch { 288 | my ($kid) = @_; 289 | my $result = read_file("/var/run/ksplice/updates/$kid/patch"); 290 | return $result; 291 | } 292 | 293 | sub get_short_description { 294 | my ($kid) = @_; 295 | open(INPUT, "<", "/var/run/ksplice/updates/$kid/description") or return undef; 296 | my $result = ; 297 | close(INPUT); 298 | return $result; 299 | } 300 | 301 | sub set_stage { 302 | my ($kid, $string) = @_; 303 | write_sysfs($kid, "stage", "$string\n"); 304 | } 305 | 306 | sub set_debug_level { 307 | my ($kid, $string) = @_; 308 | write_sysfs($kid, "debug", "$string\n"); 309 | } 310 | 311 | sub set_partial { 312 | my ($kid, $string) = @_; 313 | write_sysfs($kid, "partial", "$string\n"); 314 | } 315 | 316 | sub print_abort_error { 317 | my ($kid, %errors) = @_; 318 | my $error = get_abort_cause($kid); 319 | 320 | print_abort_code($error, %errors); 321 | if ($error eq 'code_busy') { 322 | if($raw_errors) { 323 | print STDERR get_raw_conflicts($kid); 324 | } else { 325 | print STDERR get_conflicts($kid); 326 | } 327 | } 328 | $printed_abort_code = 1; 329 | } 330 | 331 | sub print_abort_code { 332 | my ($error, %errors) = @_; 333 | if($raw_errors) { 334 | print STDERR "$error\n"; 335 | } else { 336 | $error = "UNKNOWN" if (!exists $errors{$error}); 337 | print STDERR "\n$errors{$error}\n"; 338 | } 339 | $printed_abort_code = 1; 340 | } 341 | 342 | END { 343 | $Verbose::level = 0; 344 | chdir("/"); 345 | } 346 | 347 | 1; 348 | -------------------------------------------------------------------------------- /objcommon.h: -------------------------------------------------------------------------------- 1 | /* workaround for bfd crap check. WTF were they thinking? */ 2 | #ifndef PACKAGE 3 | #define PACKAGE "ksplice" 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define BITS_PER_LONG LONG_BIT 16 | #define _PASTE(x, y) x##y 17 | #define PASTE(x, y) _PASTE(x, y) 18 | 19 | #define DIE do { fprintf(stderr, "ksplice: died at %s:%d\n", __FILE__, __LINE__); abort(); } while(0) 20 | #define assert(x) do { if(!(x)) DIE; } while(0) 21 | #define align(x, n) ((((x)+(n)-1)/(n))*(n)) 22 | 23 | #define container_of(ptr, type, member) ({ \ 24 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 25 | (type *)( (char *)__mptr - offsetof(type,member) );}) 26 | 27 | #define DECLARE_VEC_TYPE(elt_t, vectype) \ 28 | struct vectype { \ 29 | elt_t *data; \ 30 | size_t size; \ 31 | size_t mem_size; \ 32 | } 33 | 34 | /* void vec_init(struct vectype *vec); */ 35 | #define vec_init(vec) *(vec) = (typeof(*(vec))) { NULL, 0, 0 } 36 | 37 | /* void vec_move(struct vectype *dstvec, struct vectype *srcvec); */ 38 | #define vec_move(dstvec, srcvec) do { \ 39 | typeof(srcvec) _srcvec = (srcvec); \ 40 | *(dstvec) = *(_srcvec); \ 41 | vec_init(_srcvec); \ 42 | } while (0) 43 | 44 | /* void vec_free(struct vectype *vec); */ 45 | #define vec_free(vec) do { \ 46 | typeof(vec) _vec1 = (vec); \ 47 | free(_vec1->data); \ 48 | vec_init(_vec1); \ 49 | } while (0) 50 | 51 | void vec_do_reserve(void **data, size_t *mem_size, size_t newsize); 52 | 53 | /* void vec_reserve(struct vectype *vec, size_t new_mem_size); */ 54 | #define vec_reserve(vec, new_mem_size) do { \ 55 | typeof(vec) _vec2 = (vec); \ 56 | vec_do_reserve((void **)&_vec2->data, &_vec2->mem_size, \ 57 | (new_mem_size)); \ 58 | } while (0) 59 | 60 | /* void vec_resize(struct vectype *vec, size_t new_size); */ 61 | #define vec_resize(vec, new_size) do { \ 62 | typeof(vec) _vec3 = (vec); \ 63 | _vec3->size = (new_size); \ 64 | vec_reserve(_vec3, _vec3->size * sizeof(*_vec3->data)); \ 65 | } while (0) 66 | 67 | /* elt_t *vec_grow(struct vectype *vec, size_t n); */ 68 | #define vec_grow(vec, n) ({ \ 69 | typeof(vec) _vec4 = (vec); \ 70 | size_t _n = (n); \ 71 | vec_resize(_vec4, _vec4->size + _n); \ 72 | _vec4->data + (_vec4->size - _n); \ 73 | }) 74 | 75 | DECLARE_VEC_TYPE(void, void_vec); 76 | DECLARE_VEC_TYPE(arelent *, arelentp_vec); 77 | DECLARE_VEC_TYPE(asymbol *, asymbolp_vec); 78 | DECLARE_VEC_TYPE(asymbol **, asymbolpp_vec); 79 | 80 | #define DECLARE_HASH_TYPE(elt_t, hashtype, \ 81 | hashtype_init, hashtype_free, \ 82 | hashtype_lookup) \ 83 | struct hashtype { \ 84 | struct bfd_hash_table root; \ 85 | }; \ 86 | \ 87 | void hashtype_init(struct hashtype *table); \ 88 | void hashtype_free(struct hashtype *table); \ 89 | typeof(elt_t) *hashtype_lookup(struct hashtype *table, \ 90 | const char *string, \ 91 | bfd_boolean create) 92 | 93 | #ifndef BFD_HASH_TABLE_HAS_ENTSIZE 94 | #define bfd_hash_table_init(table, newfunc, entry) \ 95 | bfd_hash_table_init(table, newfunc) 96 | #endif 97 | 98 | #define IMPLEMENT_HASH_TYPE(elt_t, hashtype, \ 99 | hashtype_init, hashtype_free, \ 100 | hashtype_lookup, \ 101 | elt_construct) \ 102 | \ 103 | struct hashtype##_entry { \ 104 | struct bfd_hash_entry root; \ 105 | typeof(elt_t) val; \ 106 | }; \ 107 | \ 108 | static struct bfd_hash_entry *hashtype##_newfunc( \ 109 | struct bfd_hash_entry *entry, \ 110 | struct bfd_hash_table *table, \ 111 | const char *string) \ 112 | { \ 113 | if (entry == NULL) { \ 114 | entry = bfd_hash_allocate(table, \ 115 | sizeof(struct hashtype##_entry)); \ 116 | if (entry == NULL) \ 117 | return entry; \ 118 | } \ 119 | entry = bfd_hash_newfunc(entry, table, string); \ 120 | typeof(elt_t) *v = \ 121 | &container_of(entry, struct hashtype##_entry, \ 122 | root)->val; \ 123 | elt_construct(v); \ 124 | return entry; \ 125 | }; \ 126 | \ 127 | void hashtype_init(struct hashtype *table) \ 128 | { \ 129 | bfd_hash_table_init(&table->root, hashtype##_newfunc, \ 130 | sizeof(struct hashtype##_entry)); \ 131 | } \ 132 | \ 133 | void hashtype_free(struct hashtype *table) \ 134 | { \ 135 | bfd_hash_table_free(&table->root); \ 136 | } \ 137 | \ 138 | typeof(elt_t) *hashtype_lookup(struct hashtype *table, \ 139 | const char *string, \ 140 | bfd_boolean create) \ 141 | { \ 142 | struct bfd_hash_entry *e = \ 143 | bfd_hash_lookup(&table->root, string, create, \ 144 | TRUE); \ 145 | if (create) \ 146 | assert(e != NULL); \ 147 | else if (e == NULL) \ 148 | return NULL; \ 149 | return &container_of(e, struct hashtype##_entry, \ 150 | root)->val; \ 151 | } \ 152 | \ 153 | struct eat_trailing_semicolon 154 | 155 | #define DEFINE_HASH_TYPE(elt_t, hashtype, \ 156 | hashtype_init, hashtype_free, \ 157 | hashtype_lookup, \ 158 | elt_construct) \ 159 | DECLARE_HASH_TYPE(elt_t, hashtype, hashtype_init, \ 160 | hashtype_free, hashtype_lookup); \ 161 | IMPLEMENT_HASH_TYPE(elt_t, hashtype, hashtype_init, \ 162 | hashtype_free, hashtype_lookup, \ 163 | elt_construct); 164 | 165 | 166 | #ifndef bfd_get_section_size 167 | #define bfd_get_section_size(x) ((x)->_cooked_size) 168 | #endif 169 | 170 | DECLARE_HASH_TYPE(arelent *, arelentp_hash, arelentp_hash_init, 171 | arelentp_hash_free, arelentp_hash_lookup); 172 | DECLARE_HASH_TYPE(asymbol **, asymbolpp_hash, asymbolpp_hash_init, 173 | asymbolpp_hash_free, asymbolpp_hash_lookup); 174 | DECLARE_HASH_TYPE(const char *, string_hash, string_hash_init, 175 | string_hash_free, string_hash_lookup); 176 | 177 | struct label_map { 178 | asymbol *csym; 179 | const char *orig_label; 180 | const char *label; 181 | int count; 182 | }; 183 | DECLARE_VEC_TYPE(struct label_map, label_map_vec); 184 | DECLARE_HASH_TYPE(struct label_map *, label_mapp_hash, label_mapp_hash_init, 185 | label_mapp_hash_free, label_mapp_hash_lookup); 186 | 187 | struct entry_point { 188 | const char *label; 189 | const char *name; 190 | long offset; 191 | asymbol *symbol; 192 | }; 193 | DECLARE_VEC_TYPE(struct entry_point, entry_point_vec); 194 | 195 | struct span { 196 | struct supersect *ss; 197 | asymbol *symbol; 198 | const char *orig_label; 199 | const char *label; 200 | bfd_vma start; 201 | bfd_vma size; 202 | bfd_vma contents_size; 203 | bool keep; 204 | bool new; 205 | bool patch; 206 | bool bugpatch; 207 | bool datapatch; 208 | bool precallable; 209 | struct span *match; 210 | struct entry_point_vec entry_points; 211 | struct entry_point_vec pre_entry_points; 212 | bfd_size_type shift; 213 | }; 214 | DECLARE_VEC_TYPE(struct span, span_vec); 215 | 216 | struct superbfd { 217 | bfd *abfd; 218 | struct asymbolp_vec syms; 219 | struct supersect *new_supersects; 220 | struct label_map_vec maps; 221 | struct label_mapp_hash maps_hash; 222 | struct asymbolpp_vec new_syms; 223 | struct asymbolpp_hash csyms; 224 | struct string_hash callers; 225 | }; 226 | 227 | enum supersect_type { 228 | SS_TYPE_TEXT, SS_TYPE_DATA, SS_TYPE_RODATA, SS_TYPE_STRING, 229 | SS_TYPE_SPECIAL, SS_TYPE_IGNORED, SS_TYPE_KSPLICE, SS_TYPE_EXPORT, 230 | SS_TYPE_EXIT, SS_TYPE_KSPLICE_CALL, SS_TYPE_KSPLICE_EXTRACT, 231 | SS_TYPE_BUGTABLE, SS_TYPE_UNKNOWN 232 | }; 233 | 234 | struct supersect { 235 | struct superbfd *parent; 236 | const char *name; 237 | flagword flags; 238 | struct void_vec contents; 239 | int alignment; 240 | unsigned int entsize; 241 | struct arelentp_vec relocs; 242 | struct arelentp_vec new_relocs; 243 | struct supersect *next; 244 | struct asymbolp_vec syms; 245 | struct span_vec spans; 246 | struct arelentp_hash reloc_hash; 247 | asymbol *symbol; 248 | bool keep; 249 | enum supersect_type type; 250 | enum supersect_type orig_type; 251 | bool match_data_early; 252 | }; 253 | 254 | struct superbfd *fetch_superbfd(bfd *abfd); 255 | struct supersect *fetch_supersect(struct superbfd *sbfd, asection *sect); 256 | struct supersect *new_supersect(struct superbfd *sbfd, const char *name); 257 | void supersect_move(struct supersect *dest_ss, struct supersect *src_ss); 258 | 259 | #define sect_grow(ss, n, type) \ 260 | ((type *)sect_do_grow(ss, n, sizeof(type), __alignof__(type))) 261 | void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment); 262 | 263 | #define sect_copy(dest_ss, dest, src_ss, src, n) \ 264 | sect_do_copy(dest_ss, dest, src_ss, src, (n) * sizeof(*(src))) 265 | void sect_do_copy(struct supersect *dest_ss, void *dest, 266 | struct supersect *src_ss, const void *src, size_t n); 267 | 268 | #define strstarts(str, prefix) \ 269 | (strncmp(str, prefix, strlen(prefix)) == 0) 270 | #define ends_with(str, suffix) \ 271 | (strlen(str) >= strlen(suffix) && \ 272 | strcmp(&str[strlen(str) - strlen(suffix)], suffix) == 0) 273 | 274 | bfd_vma addr_offset(struct supersect *ss, const void *addr); 275 | bfd_vma reloc_offset(struct supersect *ss, arelent *reloc); 276 | arelent *find_reloc(struct supersect *ss, const void *addr); 277 | bfd_vma read_reloc(struct supersect *ss, const void *addr, size_t size, 278 | asymbol **symp); 279 | const void *read_pointer(struct supersect *ss, void *const *addr, 280 | struct supersect **ssp); 281 | const char *read_string(struct supersect *ss, const char *const *addr); 282 | 283 | #define read_num(ss, addr) ((typeof(*(addr))) \ 284 | read_reloc(ss, addr, sizeof(*(addr)), NULL)) 285 | 286 | static inline char *vstrprintf(const char *fmt, va_list ap) 287 | { 288 | char *str; 289 | assert(vasprintf(&str, fmt, ap) >= 0); 290 | return str; 291 | } 292 | 293 | static inline char * __attribute__((format (printf, 1, 2))) 294 | strprintf(const char *fmt, ...) 295 | { 296 | va_list ap; 297 | va_start(ap, fmt); 298 | char *str = vstrprintf(fmt, ap); 299 | va_end(ap); 300 | return str; 301 | } 302 | -------------------------------------------------------------------------------- /Makefile.ksplice: -------------------------------------------------------------------------------- 1 | ksplice-makefile := $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST)) 2 | ksplice-script = $(dir $(ksplice-makefile))ksplice-obj.pl 3 | 4 | KSPLICE_MODE ?= diff 5 | $(if $(filter_out snap diff revert modinst,$(KSPLICE_MODE)), \ 6 | $(error Invalid KSPLICE_MODE $(KSPLICE_MODE).)) 7 | 8 | KSPLICE_ONLY_TARGETS ?= % 9 | 10 | PHONY := 11 | 12 | __ksplice: 13 | 14 | ksplice-extra = $(filter-out $(KSPLICE_EXCLUDE_MATCH),$(filter $(KSPLICE_EXTRA_MATCH),$(lib-y) $(real-objs-m) $(real-objs-y))) 15 | ksplice-objs = $(foreach o,$(1),$(o:=.KSPLICE) $(addsuffix .KSPLICE_old_code,$(filter $(ksplice-extra),$(o)))) 16 | 17 | escsq ?= $(subst ','\'',$(1)) 18 | echo-cmd ?= $(if $($(quiet)cmd_$(1)),echo ' $(call escsq,$($(quiet)cmd_$(1)))';) 19 | 20 | quiet_cmd_ksplice-combine = COMBINE $(@:.KSPLICE=) 21 | cmd_ksplice-combine = $(ksplice-script) combine $@ $(filter $(call ksplice-objs,$(ksplice-link-deps)) $(@:.KSPLICE=),$^ $|) 22 | quiet_cmd_ksplice-snap = SNAP $(@:.KSPLICE=) 23 | cmd_ksplice-snap = $(ksplice-script) snap $@ 24 | quiet_cmd_ksplice-diff = DIFF $(@:.KSPLICE=) 25 | cmd_ksplice-diff = $(ksplice-script) diff $@ 26 | quiet_cmd_ksplice-ignore = IGNORE $(@:.KSPLICE=) 27 | cmd_ksplice-ignore = touch $@ 28 | quiet_cmd_ksplice-cow = COW $@ 29 | cmd_ksplice-cow = cp -a $@ $@.KSPLICE_pre 30 | quiet_cmd_ksplice-mod = MOD $(@:$(KSPLICE_KMODSRC)/%.mod.KSPLICE=%) 31 | cmd_ksplice-mod = echo $(<:.o.KSPLICE=) > $@; cp -a $< $(<:.KSPLICE=.KSPLICE_new_code) $(<:.KSPLICE=.KSPLICE_old_code) $(KSPLICE_KMODSRC)/ 32 | rule_ksplice-mod = if [ -s $< ]; then $(echo-cmd) $(cmd_$(1)); fi 33 | quiet_cmd_ksplice-old-code = OLDCODE $(@:.KSPLICE_old_code=) 34 | cmd_ksplice-old-code = $(ksplice-script) old_code $@ 35 | quiet_cmd_ksplice-freeze = FREEZE $(@:_ksplice-revert_%.KSPLICE_pre=%) 36 | cmd_ksplice-freeze = rm -f $(@:_ksplice-revert_%=%) 37 | quiet_cmd_ksplice-revert = REVERT $(@:_ksplice-revert_%.KSPLICE_pre=%) 38 | cmd_ksplice-revert = touch -r ksplice-revert-stamp $(@:_ksplice-revert_%=%); mv $(@:_ksplice-revert_%=%) $(@:_ksplice-revert_%.KSPLICE_pre=%) 39 | quiet_cmd_ksplice-revert-snap = SNAP $(@:_ksplice-revert-snap_%.KSPLICE=%) 40 | cmd_ksplice-revert-snap = $(ksplice-script) snap $(@:_ksplice-revert-snap_%=%) 41 | quiet_cmd_ksplice-clean = CLEAN $(@:_ksplice-clean_%=%) 42 | cmd_ksplice-clean = rm -f $(@:_ksplice-clean_%=%) 43 | 44 | ifeq ($(obj),) 45 | 46 | ifneq ($(wildcard include/linux/compile.h),) 47 | MAKE += --old-file=include/linux/compile.h 48 | endif 49 | ifneq ($(filter snap diff,$(KSPLICE_MODE)),) 50 | # Makefile.lib must be included before Makefile because they contain 51 | # different filechk definitions in 2.6.12. 52 | include $(if $(KBUILD_SRC),$(KBUILD_SRC)/)scripts/Makefile.lib 53 | endif 54 | include $(if $(KBUILD_SRC),$(KBUILD_SRC)/)Makefile 55 | 56 | ifneq ($(skip-makefile),) 57 | 58 | PHONY += __ksplice 59 | __ksplice: FORCE 60 | $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ 61 | KBUILD_SRC=$(CURDIR) \ 62 | KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(ksplice-makefile) \ 63 | $(if $(wildcard $(KBUILD_OUTPUT)/include/config/kernel.release),--old-file=include/config/kernel.release) 64 | 65 | else # skip-makefile 66 | 67 | CC := ksplice-cc.pl $(CC) 68 | CFLAGS_KSPLICE = -ffunction-sections -fdata-sections -ksplice-cflags-api=1 69 | CFLAGS_KERNEL += $(CFLAGS_KSPLICE) 70 | CFLAGS_MODULE += $(CFLAGS_KSPLICE) 71 | 72 | ifeq ($(KSPLICE_MODE),revert) 73 | 74 | ksplice-revert-dirs = $(vmlinux-alldirs:%=_ksplice_%) 75 | ksplice-dirs += $(ksplice-revert-dirs) 76 | 77 | .INTERMEDIATE $(ksplice-revert-dirs): ksplice-revert-stamp 78 | ksplice-revert-stamp: FORCE 79 | $(Q)touch $@ 80 | 81 | endif # KSPLICE_MODE 82 | 83 | ifneq ($(filter snap diff,$(KSPLICE_MODE)),) 84 | 85 | ksplice-mods += vmlinux 86 | ifdef KSPLICE_BUILD_MODULES 87 | ksplice-deps += ksplice_modpost 88 | endif 89 | ksplice-deps += $(vmlinux-dirs) 90 | 91 | ksplice-vmlinux-objs = $(if $(vmlinux-deps),$(vmlinux-deps),$(if $(vmlinux-all),$(vmlinux-all),$(vmlinux-objs))) 92 | $(obj)/vmlinux.o.KSPLICE: ksplice-link-deps = $(ksplice-vmlinux-objs) 93 | $(obj)/vmlinux.o.KSPLICE: $(call ksplice-objs,$(ksplice-vmlinux-objs)) FORCE 94 | $(call if_changed,ksplice-combine) 95 | ksplice-targets += $(obj)/vmlinux.o.KSPLICE 96 | $(ksplice-vmlinux-objs:=.KSPLICE): $(vmlinux-dirs) ; 97 | 98 | PHONY += ksplice_modpost 99 | ksplice_modpost: $(vmlinux-dirs) vmlinux 100 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost 101 | 102 | endif # KSPLICE_MODE 103 | 104 | ifeq ($(KSPLICE_MODE),modinst) 105 | 106 | ksplice-deps += ksplice_modinst 107 | PHONY += ksplice_modinst 108 | ksplice_modinst: 109 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst 110 | 111 | endif # KSPLICE_MODE 112 | 113 | endif # skip-makefile 114 | 115 | else # obj 116 | 117 | ifeq ($(KSPLICE_MODE),revert) 118 | 119 | -include .config # workaround for missing obj- = subdir/ declarations 120 | include $(srctree)/scripts/Makefile.clean 121 | ksplice-dirs += $(subdir-ymn:%=_ksplice_%) 122 | 123 | endif # KSPLICE_MODE 124 | 125 | ifneq ($(filter snap diff,$(KSPLICE_MODE)),) 126 | 127 | ifdef KSPLICE_BUILD_MODULES 128 | KBUILD_MODULES = 1 129 | endif 130 | 131 | include $(srctree)/scripts/Makefile.build 132 | ksplice-mods += $(obj-m:.o=) 133 | ksplice-deps += $(if $(filter $(KSPLICE_ONLY_TARGETS),vmlinux),$(builtin-target:=.KSPLICE) $(lib-target:=.KSPLICE)) 134 | ifdef KSPLICE_BUILD_MODULES 135 | ksplice-deps += __build 136 | endif 137 | ksplice-deps += $(subdir-ym) $(always) 138 | 139 | ifdef builtin-target 140 | $(builtin-target:=.KSPLICE): ksplice-link-deps = $(obj-y) 141 | $(builtin-target:=.KSPLICE): $(call ksplice-objs,$(obj-y)) FORCE | $(builtin-target) 142 | $(call if_changed,ksplice-combine) 143 | ksplice-targets += $(builtin-target:=.KSPLICE) 144 | endif 145 | 146 | ifdef lib-target 147 | $(lib-target:=.KSPLICE): ksplice-link-deps = $(lib-y) 148 | $(lib-target:=.KSPLICE): $(call ksplice-objs,$(lib-y)) FORCE | $(lib-target) 149 | $(call if_changed,ksplice-combine) 150 | ksplice-targets += $(lib-target:=.KSPLICE) 151 | endif 152 | 153 | $(sort $(multi-used-y:=.KSPLICE) $(multi-used-m:=.KSPLICE)): ksplice-link-deps = $($(@:$(obj)/%.o.KSPLICE=%-objs):%=$(obj)/%) $($(@:$(obj)/%.o.KSPLICE=%-y):%=$(obj)/%) 154 | $(sort $(multi-used-y:=.KSPLICE)): $(obj)/%.o.KSPLICE: $(call ksplice-objs,$(multi-objs-y)) FORCE | $(obj)/%.o 155 | $(call if_changed,ksplice-combine) 156 | $(sort $(multi-used-m:=.KSPLICE)): $(obj)/%.o.KSPLICE: $(call ksplice-objs,$(multi-objs-m)) FORCE | $(obj)/%.o 157 | $(call if_changed,ksplice-combine) 158 | ksplice-targets += $(sort $(multi-used-y:=.KSPLICE) $(multi-used-m:=.KSPLICE)) 159 | 160 | ifeq ($(KSPLICE_MODE),snap) 161 | $(obj)/%.o.KSPLICE: $(obj)/%.o FORCE 162 | $(if $(strip $(wildcard $<.KSPLICE_pre) $(filter $<,$?)), \ 163 | $(call cmd,ksplice-snap)) 164 | else 165 | $(obj)/%.o.KSPLICE: $(obj)/%.o 166 | $(call cmd,ksplice-diff) 167 | endif 168 | 169 | $(obj)/%.lds.KSPLICE: 170 | $(call cmd,ksplice-ignore) 171 | 172 | $(sort $(subdir-obj-y:=.KSPLICE)): $(subdir-ym) ; 173 | 174 | ifeq ($(MAKECMDGOALS),missing-syscalls) 175 | cmd = @: 176 | endif 177 | 178 | endif # KSPLICE_MODE 179 | 180 | endif # obj 181 | 182 | ifeq ($(skip-makefile),) 183 | 184 | ifeq ($(KSPLICE_MODE),revert) 185 | 186 | ksplice-revert-obj := $(wildcard $(obj)/*.KSPLICE_pre) 187 | ksplice-revert-files := $(ksplice-revert-obj) 188 | ifneq ($(obj),$(src)) 189 | ksplice-revert-files += $(wildcard $(src)/*.KSPLICE_pre) 190 | endif 191 | ksplice-revert-deps := $(ksplice-revert-files:%=_ksplice-revert_%) 192 | ksplice-deps += $(ksplice-revert-deps) 193 | PHONY += $(ksplice-revert-deps) 194 | $(ksplice-revert-deps): FORCE 195 | ifdef KSPLICE_SERIES 196 | $(call cmd,ksplice-freeze) 197 | else 198 | $(call cmd,ksplice-revert) 199 | endif 200 | 201 | ksplice-revert-snap-files := $(wildcard $(ksplice-revert-obj:.KSPLICE_pre=.KSPLICE)) 202 | ksplice-revert-snap-deps := $(ksplice-revert-snap-files:%=_ksplice-revert-snap_%) 203 | ksplice-deps += $(ksplice-revert-snap-deps) 204 | PHONY += $(ksplice-revert-snap-deps) 205 | $(ksplice-revert-snap-deps): $(ksplice-revert-snap-files:%.KSPLICE=_ksplice-revert_%.KSPLICE_pre) FORCE 206 | $(call cmd,ksplice-revert-snap) 207 | 208 | ksplice-clean-files := $(filter-out $(ksplice-revert-snap-files:.KSPLICE_pre=.KSPLICE_new_code) $(ksplice-revert-snap-files:.KSPLICE_pre=.KSPLICE_old_code),$(wildcard $(obj)/*.KSPLICE_new_code $(obj)/*.KSPLICE_old_code)) 209 | ksplice-clean-deps = $(ksplice-clean-files:%=_ksplice-clean_%) 210 | ksplice-deps += $(ksplice-clean-deps) 211 | PHONY += $(ksplice-clean-deps) 212 | $(ksplice-clean-deps): FORCE 213 | $(call cmd,ksplice-clean) 214 | 215 | endif # KSPLICE_MODE 216 | 217 | ifneq ($(filter snap diff,$(KSPLICE_MODE)),) 218 | 219 | ksplice-modnames = $(filter $(KSPLICE_ONLY_TARGETS),$(notdir $(ksplice-mods))) 220 | ifdef KSPLICE_KMODSRC 221 | ksplice-deps += $(ksplice-modnames:%=$(KSPLICE_KMODSRC)/%.mod.KSPLICE) 222 | $(KSPLICE_KMODSRC)/%.mod.KSPLICE: $(obj)/%.o.KSPLICE 223 | $(Q)$(call rule_ksplice-mod,ksplice-mod) 224 | else 225 | ksplice-deps += $(ksplice-modnames:%=$(obj)/%.o.KSPLICE) 226 | endif 227 | .SECONDARY: $(obj)/%.o.KSPLICE 228 | 229 | $(obj)/%.o.KSPLICE_old_code: $(obj)/%.o.KSPLICE 230 | $(call cmd,ksplice-old-code) 231 | 232 | ifeq ($(KSPLICE_MODE),diff) 233 | 234 | define ksplice-cow-check 235 | $(if $(strip $(1)),$(if $(filter-out %.KSPLICE,$@),$(if $(wildcard $@),$(if $(wildcard $@.KSPLICE_pre),,$(call cmd,ksplice-cow) 236 | ))))$(1) 237 | endef 238 | 239 | define ksplice-add-cow-check 240 | $(v) = $$(call ksplice-cow-check,$(value $(v))) 241 | 242 | endef 243 | 244 | ksplice-cow-eval += $(foreach v,if_changed if_changed_dep if_changed_rule,$(ksplice-add-cow-check)) 245 | 246 | endif # KSPLICE_MODE 247 | 248 | ksplice-cmd-files := $(wildcard $(foreach f,$(sort $(ksplice-targets)),$(dir $(f)).$(notdir $(f)).cmd)) 249 | ifneq ($(ksplice-cmd-files),) 250 | $(ksplice-cmd-files): ; 251 | include $(ksplice-cmd-files) 252 | endif 253 | 254 | endif # KSPLICE_MODE 255 | 256 | PHONY += __ksplice 257 | __ksplice: $(ksplice-deps) $(ksplice-dirs) 258 | @: 259 | 260 | build := -f $(ksplice-makefile) obj 261 | descend =$(Q)$(MAKE) $(build)=$(1) $(2) 262 | 263 | PHONY += $(ksplice-dirs) 264 | $(ksplice-dirs): 265 | $(Q)$(MAKE) $(build)=$(@:_ksplice_%=%) 266 | 267 | endif # skip-makefile 268 | 269 | $(eval $(ksplice-cow-eval)) 270 | 271 | PHONY += FORCE 272 | FORCE: 273 | 274 | .PHONY: $(PHONY) 275 | -------------------------------------------------------------------------------- /objcommon.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2009 Ksplice, Inc. 2 | * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | #define _GNU_SOURCE 19 | #include "objcommon.h" 20 | #include 21 | 22 | #define arelentp_init(x) *(x) = NULL 23 | IMPLEMENT_HASH_TYPE(arelent *, arelentp_hash, arelentp_hash_init, 24 | arelentp_hash_free, arelentp_hash_lookup, arelentp_init); 25 | 26 | #define label_mapp_init(map) *(map) = NULL 27 | IMPLEMENT_HASH_TYPE(struct label_map *, label_mapp_hash, label_mapp_hash_init, 28 | label_mapp_hash_free, label_mapp_hash_lookup, 29 | label_mapp_init); 30 | 31 | #define asymbolpp_init(symp) *(symp) = NULL 32 | IMPLEMENT_HASH_TYPE(asymbol **, asymbolpp_hash, asymbolpp_hash_init, 33 | asymbolpp_hash_free, asymbolpp_hash_lookup, asymbolpp_init); 34 | 35 | #define string_init(str) *(str) = NULL 36 | IMPLEMENT_HASH_TYPE(const char *, string_hash, string_hash_init, 37 | string_hash_free, string_hash_lookup, string_init); 38 | 39 | void vec_do_reserve(void **data, size_t *mem_size, size_t new_size) 40 | { 41 | if (new_size > *mem_size || new_size * 2 < *mem_size) { 42 | if (new_size < *mem_size * 2) 43 | new_size = *mem_size * 2; 44 | *data = realloc(*data, new_size); 45 | assert(new_size == 0 || *data != NULL); 46 | *mem_size = new_size; 47 | } 48 | } 49 | 50 | void get_syms(bfd *abfd, struct asymbolp_vec *syms) 51 | { 52 | long storage_needed = bfd_get_symtab_upper_bound(abfd); 53 | if (storage_needed == 0) 54 | return; 55 | assert(storage_needed >= 0); 56 | 57 | vec_init(syms); 58 | vec_reserve(syms, storage_needed); 59 | vec_resize(syms, bfd_canonicalize_symtab(abfd, syms->data)); 60 | assert(syms->size >= 0); 61 | } 62 | 63 | struct superbfd *fetch_superbfd(bfd *abfd) 64 | { 65 | assert(abfd != NULL); 66 | if (abfd->usrdata != NULL) 67 | return abfd->usrdata; 68 | 69 | struct superbfd *sbfd = malloc(sizeof(*sbfd)); 70 | assert(sbfd != NULL); 71 | 72 | abfd->usrdata = sbfd; 73 | sbfd->abfd = abfd; 74 | get_syms(abfd, &sbfd->syms); 75 | vec_init(&sbfd->new_syms); 76 | sbfd->new_supersects = NULL; 77 | return sbfd; 78 | } 79 | 80 | struct supersect *fetch_supersect(struct superbfd *sbfd, asection *sect) 81 | { 82 | assert(sect != NULL); 83 | assert(!bfd_is_const_section(sect)); 84 | if (sect->userdata != NULL) 85 | return sect->userdata; 86 | 87 | struct supersect *new = malloc(sizeof(*new)); 88 | assert(new != NULL); 89 | 90 | sect->userdata = new; 91 | new->parent = sbfd; 92 | new->name = sect->name; 93 | new->flags = bfd_get_section_flags(sbfd->abfd, sect); 94 | new->keep = true; 95 | new->match_data_early = false; 96 | new->symbol = sect->symbol; 97 | 98 | vec_init(&new->contents); 99 | vec_resize(&new->contents, bfd_get_section_size(sect)); 100 | assert(bfd_get_section_contents 101 | (sbfd->abfd, sect, new->contents.data, 0, new->contents.size)); 102 | new->alignment = bfd_get_section_alignment(sbfd->abfd, sect); 103 | new->entsize = sect->entsize; 104 | 105 | vec_init(&new->relocs); 106 | vec_reserve(&new->relocs, bfd_get_reloc_upper_bound(sbfd->abfd, sect)); 107 | vec_resize(&new->relocs, 108 | bfd_canonicalize_reloc(sbfd->abfd, sect, new->relocs.data, 109 | sbfd->syms.data)); 110 | assert(new->relocs.size >= 0); 111 | vec_init(&new->new_relocs); 112 | 113 | vec_init(&new->syms); 114 | asymbol **symp; 115 | for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; 116 | symp++) { 117 | asymbol *sym = *symp; 118 | if (sym->section == sect && (sym->flags & BSF_SECTION_SYM) == 0) 119 | *vec_grow(&new->syms, 1) = sym; 120 | } 121 | 122 | vec_init(&new->spans); 123 | 124 | arelentp_hash_init(&new->reloc_hash); 125 | arelent **relocp; 126 | for (relocp = new->relocs.data; 127 | relocp < new->relocs.data + new->relocs.size; relocp++) { 128 | arelent *reloc = *relocp; 129 | char *key = strprintf("%lx", (unsigned long)reloc->address); 130 | arelent **hash_relocp = arelentp_hash_lookup(&new->reloc_hash, 131 | key, TRUE); 132 | free(key); 133 | *hash_relocp = reloc; 134 | } 135 | 136 | return new; 137 | } 138 | 139 | struct supersect *new_supersect(struct superbfd *sbfd, const char *name) 140 | { 141 | struct supersect *ss; 142 | for (ss = sbfd->new_supersects; ss != NULL; ss = ss->next) { 143 | if (strcmp(name, ss->name) == 0) 144 | return ss; 145 | } 146 | 147 | struct supersect *new = malloc(sizeof(*new)); 148 | new->parent = sbfd; 149 | new->name = name; 150 | new->next = sbfd->new_supersects; 151 | sbfd->new_supersects = new; 152 | new->flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_RELOC; 153 | new->keep = true; 154 | 155 | vec_init(&new->contents); 156 | new->alignment = 0; 157 | new->entsize = 0; 158 | vec_init(&new->relocs); 159 | vec_init(&new->new_relocs); 160 | 161 | new->type = SS_TYPE_KSPLICE; 162 | return new; 163 | } 164 | 165 | void supersect_move(struct supersect *dest_ss, struct supersect *src_ss) 166 | { 167 | *dest_ss = *src_ss; 168 | vec_init(&src_ss->contents); 169 | vec_init(&src_ss->relocs); 170 | vec_init(&src_ss->new_relocs); 171 | vec_init(&src_ss->syms); 172 | } 173 | 174 | void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment) 175 | { 176 | if (ss->alignment < ffs(alignment) - 1) 177 | ss->alignment = ffs(alignment) - 1; 178 | int pad = align(ss->contents.size, alignment) - ss->contents.size; 179 | void *out = vec_grow(&ss->contents, pad + n * size); 180 | memset(out, 0, pad + n * size); 181 | return out + pad; 182 | } 183 | 184 | static void mod_relocs(struct arelentp_vec *dest_relocs, 185 | struct arelentp_vec *src_relocs, 186 | bfd_size_type start, bfd_size_type end, 187 | bfd_size_type mod) 188 | { 189 | arelent **relocp; 190 | for (relocp = src_relocs->data; 191 | relocp < src_relocs->data + src_relocs->size; relocp++) { 192 | if ((*relocp)->address >= start && (*relocp)->address < end) { 193 | arelent *reloc = malloc(sizeof(*reloc)); 194 | assert(reloc != NULL); 195 | *reloc = **relocp; 196 | reloc->address += mod; 197 | *vec_grow(dest_relocs, 1) = reloc; 198 | } 199 | } 200 | } 201 | 202 | static void mod_symbols(struct asymbolp_vec *dest_syms, 203 | struct asymbolp_vec *src_syms, 204 | bfd_size_type start, bfd_size_type end, 205 | bfd_size_type mod) 206 | { 207 | asymbol **symp; 208 | for (symp = src_syms->data; 209 | symp < src_syms->data + src_syms->size; symp++) { 210 | /* must mutate symbols in-place since there are pointers 211 | to them in relocations elsewhere */ 212 | asymbol *sym = *symp; 213 | if (sym->value >= start && sym->value < end) { 214 | sym->value += mod; 215 | *vec_grow(dest_syms, 1) = sym; 216 | } 217 | } 218 | } 219 | 220 | void sect_do_copy(struct supersect *dest_ss, void *dest, 221 | struct supersect *src_ss, const void *src, size_t n) 222 | { 223 | memcpy(dest, src, n); 224 | bfd_size_type start = addr_offset(src_ss, src); 225 | bfd_size_type end = start + n; 226 | bfd_size_type mod = addr_offset(dest_ss, dest) - start; 227 | mod_relocs(&dest_ss->relocs, &src_ss->relocs, start, end, mod); 228 | mod_relocs(&dest_ss->new_relocs, &src_ss->new_relocs, start, end, mod); 229 | mod_symbols(&dest_ss->syms, &src_ss->syms, start, end, mod); 230 | } 231 | 232 | bfd_vma addr_offset(struct supersect *ss, const void *addr) 233 | { 234 | return (void *)addr - ss->contents.data; 235 | } 236 | 237 | bfd_vma reloc_offset(struct supersect *ss, arelent *reloc) 238 | { 239 | int size = bfd_get_reloc_size(reloc->howto); 240 | 241 | bfd_vma x = bfd_get(size * 8, ss->parent->abfd, 242 | ss->contents.data + reloc->address); 243 | x &= reloc->howto->src_mask; 244 | x >>= reloc->howto->bitpos; 245 | bfd_vma signbit = reloc->howto->dst_mask >> reloc->howto->bitpos; 246 | signbit &= ~(signbit >> 1); 247 | switch (reloc->howto->complain_on_overflow) { 248 | case complain_overflow_signed: 249 | case complain_overflow_bitfield: 250 | x |= -(x & signbit); 251 | break; 252 | case complain_overflow_unsigned: 253 | break; 254 | default: 255 | DIE; 256 | } 257 | x <<= reloc->howto->rightshift; 258 | 259 | bfd_vma add = reloc->addend; 260 | if (reloc->howto->pc_relative) { 261 | if (!reloc->howto->pcrel_offset) 262 | add += reloc->address; 263 | } 264 | return x + add; 265 | } 266 | 267 | arelent *find_reloc(struct supersect *ss, const void *addr) 268 | { 269 | bfd_vma address = addr_offset(ss, addr); 270 | char *key = strprintf("%lx", (unsigned long)address); 271 | arelent **relocp = arelentp_hash_lookup(&ss->reloc_hash, key, FALSE); 272 | free(key); 273 | return relocp != NULL ? *relocp : NULL; 274 | } 275 | 276 | bfd_vma read_reloc(struct supersect *ss, const void *addr, size_t size, 277 | asymbol **symp) 278 | { 279 | bfd_vma val = bfd_get(size * 8, ss->parent->abfd, addr); 280 | arelent *reloc = find_reloc(ss, addr); 281 | if (reloc == NULL) { 282 | if (symp != NULL) 283 | *symp = *bfd_abs_section_ptr->symbol_ptr_ptr; 284 | return val; 285 | } 286 | 287 | if (symp != NULL) 288 | *symp = *reloc->sym_ptr_ptr; 289 | else if (*reloc->sym_ptr_ptr != bfd_abs_section_ptr->symbol) 290 | fprintf(stderr, "warning: unexpected " 291 | "non-absolute relocation at %s+%lx\n", 292 | ss->name, (unsigned long)addr_offset(ss, addr)); 293 | return reloc_offset(ss, reloc); 294 | } 295 | 296 | const void *read_pointer(struct supersect *ss, void *const *addr, 297 | struct supersect **data_ssp) 298 | { 299 | asymbol *sym; 300 | bfd_vma offset = read_reloc(ss, addr, sizeof(*addr), &sym); 301 | if (bfd_is_abs_section(sym->section) && sym->value + offset == 0) 302 | return NULL; 303 | if (bfd_is_const_section(sym->section)) { 304 | fprintf(stderr, "warning: unexpected relocation to const " 305 | "section at %s+%lx\n", ss->name, 306 | (unsigned long)addr_offset(ss, addr)); 307 | return NULL; 308 | } 309 | struct supersect *data_ss = fetch_supersect(ss->parent, sym->section); 310 | if (data_ssp != NULL) 311 | *data_ssp = data_ss; 312 | return data_ss->contents.data + sym->value + offset; 313 | } 314 | 315 | const char *read_string(struct supersect *ss, const char *const *addr) 316 | { 317 | return read_pointer(ss, (void *const *)addr, NULL); 318 | } 319 | -------------------------------------------------------------------------------- /ksplice-apply.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (C) 2007-2009 Ksplice, Inc. 4 | # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License, version 2. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 17 | # 02110-1301, USA. 18 | 19 | use strict; 20 | use warnings; 21 | use sigtrap 'handler', \&handler, qw(normal-signals error-signals); 22 | use lib 'KSPLICE_DATA_DIR'; 23 | use Ksplice; 24 | 25 | our %apply_errors; 26 | initialize_abort_code_table(); 27 | 28 | my $debug; 29 | my $debugon = 0; 30 | my $partial = 0; 31 | GetOptions(@common_options, 32 | "partial" => \$partial, 33 | "debug" => \$debugon, 34 | "debugfile=s" => \$debug) or pod2usage(1); 35 | 36 | pod2usage(1) if($help || scalar(@ARGV) != 1); 37 | 38 | my $file = $ARGV[0]; 39 | $debugon = 1 if(defined $debug); 40 | $debug = abs_path($debug) if (defined $debug); 41 | 42 | chdir(unpack_update($file)); 43 | 44 | die "No contents file in $file\n" if (!-e "contents"); 45 | open(CONTENTS, '<', "contents"); 46 | my $core; 47 | my @changes; 48 | my $kid; 49 | while () { 50 | my ($type, @args) = split(' ', $_); 51 | if ($type eq 'core') { 52 | die "Multiple core modules in $file!" if (defined $core); 53 | $core = {}; 54 | @$core{qw(module file)} = @args; 55 | } elsif ($type eq 'change') { 56 | my $change = {}; 57 | @$change{qw(target new_code new_code_file old_code old_code_file)} = @args; 58 | push @changes, $change; 59 | my ($ckid) = $change->{'new_code'} =~ m/^ksplice_([^-_]+)_/ or die "Bad new_code $change->{'new_code'}"; 60 | !$kid or $kid eq $ckid or die "Multiple kids"; 61 | $kid = $ckid; 62 | } 63 | } 64 | $kid or die "No kid"; 65 | close(CONTENTS); 66 | 67 | die "Update was built using an old version of Ksplice" if (@changes == 0); 68 | 69 | my $nounload = runstr("lsmod") =~ m/- $/m; 70 | 71 | my $update = "ksplice_$kid"; 72 | if(update_loaded($kid)) { 73 | my $stage = get_stage($kid); 74 | if ($stage eq "applied") { 75 | print STDERR "Ksplice update $kid already applied.\n" unless $raw_errors; 76 | exit(0); 77 | } 78 | die "Reversed Ksplice module $update already loaded!" if ($stage eq "reversed"); 79 | } 80 | 81 | runstr_err(qw(modprobe -q ksplice)) eq "" or die("Error loading Ksplice module.\n"); 82 | if (defined $core) { 83 | die "Could not find Ksplice core module $core->{file}\n" if (!-e $core->{file}); 84 | if (runstr("lsmod") =~ m/^\Q$core->{module}\E\s+/) { 85 | die "Ksplice core module $core already loaded."; 86 | } 87 | if (!load_module($core->{file}, "debug=$debugon")) { 88 | die "Error loading Ksplice core module $core->{module} for update $kid"; 89 | } 90 | } 91 | 92 | foreach my $change (@changes) { 93 | die unless (-e $change->{old_code_file} && -e $change->{new_code_file}); 94 | if ($change->{'target'} ne 'vmlinux' && 95 | runstr("lsmod") !~ m/^\Q$change->{target}\E\s+/m) { 96 | if (!$partial) { 97 | cleanup_modules(); 98 | print_abort_code("target_not_loaded", %apply_errors); 99 | die "Module $change->{target} to be patched not loaded"; 100 | } 101 | } 102 | } 103 | 104 | foreach my $change (@changes) { 105 | if(!load_module($change->{new_code_file})) { 106 | die "Error loading new code module $change->{new_code}"; 107 | } 108 | if(!load_module($change->{old_code_file})) { 109 | if($debugon) { 110 | my $debugfile = get_debug_output("init_$kid", $debug); 111 | print("Debugging output saved to $debugfile\n") if $debugfile; 112 | } 113 | cleanup_modules(); 114 | die("Error loading old code module $change->{old_code}\n"); 115 | } 116 | } 117 | 118 | mkpath("/var/run/ksplice/updates/$kid"); 119 | copy("patch", "/var/run/ksplice/updates/$kid/patch") if (-e "patch"); 120 | copy("description", "/var/run/ksplice/updates/$kid/description") if (-e "description"); 121 | 122 | set_debug_level($kid, $debugon); 123 | set_partial($kid, $partial); 124 | set_stage($kid, "applied"); 125 | my $stage = get_stage($kid); 126 | if($stage ne 'applied') { 127 | print STDERR "Error applying Ksplice update $kid:\n" unless $raw_errors; 128 | print_error($kid); 129 | 130 | if ($debugon) { 131 | my $debugfile = get_debug_output($kid, $debug); 132 | print("Debugging output saved to $debugfile\n") if $debugfile; 133 | } 134 | 135 | rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); 136 | cleanup_modules(); 137 | 138 | exit(-1); 139 | } 140 | 141 | if (!$nounload) { 142 | foreach my $change (@changes) { 143 | runval('rmmod', $change->{old_code}); 144 | runval('rmmod', $change->{new_code}) if ($partial && refcount($change->{new_code}) == 0); 145 | } 146 | } 147 | 148 | print "Done!\n"; 149 | exit(0); 150 | 151 | my @modules_loaded = qw(); 152 | 153 | sub handler { 154 | my ($sig) = @_; 155 | die "caught SIG$sig, abort\n" if (!defined($kid)); 156 | die "caught SIG$sig after finished\n" 157 | if (update_loaded($kid) && (get_stage($kid) eq 'applied')); 158 | print STDERR "caught SIG$sig, aborting\n"; 159 | rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); 160 | cleanup_modules(); 161 | exit(1); 162 | } 163 | 164 | sub load_module { 165 | my ($module, @params) = @_; 166 | push @modules_loaded, ($module =~ m/^(.*)\.ko$/); 167 | if (runval_raw("insmod", $module, @params) != 0) { 168 | pop @modules_loaded; 169 | child_error(); 170 | return 0; 171 | } 172 | return 1; 173 | } 174 | 175 | sub refcount { 176 | my ($module) = @_; 177 | $module =~ s/-/_/g; 178 | foreach(split(/\n/, runstr("lsmod"))) { 179 | if (m/^(\S+)\s+[0-9]+\s+([0-9])+\s/) { 180 | return $2 if ($1 eq $module); 181 | } 182 | } 183 | return -1; 184 | } 185 | 186 | sub cleanup_modules { 187 | foreach my $module (reverse(@modules_loaded)) { 188 | runval_raw("rmmod", $module) if(!$nounload); 189 | } 190 | } 191 | 192 | sub initialize_abort_code_table { 193 | %apply_errors = ( 194 | "no_match" => <<'END', 195 | Ksplice has aborted the upgrade because Ksplice has been unable to match the 196 | object code produced by your current compiler and assembler against the running 197 | kernel's object code. If you provided the exact kernel source to the running 198 | kernel, then it appears that your current compiler and/or assembler are 199 | behaving differently from the compiler and assembler used to build the running 200 | kernel. If possible, please use the exact compiler and assembler that were 201 | used to build the running kernel. If you are using exactly the same compiler 202 | and assembler, consider reporting a bug to PACKAGE_BUGREPORT. 203 | END 204 | "code_busy" => <<'END', 205 | Ksplice has aborted the upgrade because it appears that the code that you are 206 | trying to patch is continuously in use by the system. More specifically, 207 | Ksplice has been unable to find a moment when one or more of the to-be-patched 208 | functions is not on a thread's kernel stack. 209 | END 210 | "bad_system_map" => <<'END', 211 | Ksplice has aborted the upgrade because it appears that the System.map file 212 | provided to ksplice-create does not match the running kernel. 213 | END 214 | "failed_to_find" => <<'END', 215 | Ksplice has aborted the upgrade because it was unable to resolve some of the 216 | symbols used in the update. 217 | END 218 | "already_reversed" => <<'END', 219 | The Ksplice update that you are attempting to apply has already been applied 220 | and reversed. You need to unload the Ksplice modules associated with this 221 | update before you can apply this update again. 222 | END 223 | "missing_export" => <<'END', 224 | Ksplice has aborted the upgrade because the symbols exported by the kernel 225 | did not match Ksplice's expectations. 226 | END 227 | "unexpected_running_task" => <<'END', 228 | Ksplice has aborted the upgrade because of an unexpected failure during the 229 | kernel stack check. Please consider reporting a bug to PACKAGE_BUGREPORT. 230 | END 231 | "target_not_loaded" => <<'END', 232 | Ksplice has aborted the upgrade because one of the modules to be 233 | patched by the update was not loaded. If you want to apply this 234 | update only to those modules that are loaded, then you should use the 235 | --partial option. 236 | END 237 | "out_of_memory" => <<'END', 238 | Ksplice has aborted the upgrade because the kernel ran out of memory. 239 | END 240 | "call_failed" => <<'END', 241 | Ksplice has aborted the upgrade at the request of a one of the 242 | pre-application hooks that were included as part of this Ksplice 243 | update. This is likely the result of a bug in the patch used to 244 | generate this update. 245 | END 246 | "unexpected" => <<'END', 247 | Ksplice has aborted because of an unexpected error. 248 | Please consider reporting a bug to PACKAGE_BUGREPORT. 249 | END 250 | "UNKNOWN" => <<'END', 251 | The Ksplice kernel component has returned an error code that this version of 252 | ksplice-apply does not understand. 253 | END 254 | "ok" => <<'END', 255 | Ksplice has aborted the upgrade for unknown reasons. 256 | Please consider reporting a bug to PACKAGE_BUGREPORT. 257 | END 258 | ); 259 | } 260 | 261 | sub print_error { 262 | my ($kid) = @_; 263 | print_abort_error($kid, %apply_errors); 264 | } 265 | 266 | =head1 NAME 267 | 268 | ksplice-apply - Apply an on-disk Ksplice update to the running kernel 269 | 270 | =head1 SYNOPSIS 271 | 272 | B [I] {I | I} 273 | 274 | =head1 DESCRIPTION 275 | 276 | B takes as input a Ksplice update, as generated by 277 | L, and it applies the update to the running binary kernel. 278 | The update may be supplied in the form of a tarball or an unpacked tree. 279 | 280 | The update is required to have been generated for the running kernel's 281 | version. 282 | 283 | =head1 OPTIONS 284 | 285 | =over 8 286 | 287 | =item B<--debug> 288 | 289 | Applies the update with debugging output enabled. Recommended only for 290 | debugging. 291 | 292 | =item B<--debugfile=>I 293 | 294 | Sets the location where debugging output should be saved. Implies --debug. 295 | 296 | =item B<--partial> 297 | 298 | Applies the update only to those modules which are loaded. Any 299 | modules patched by the update that are not loaded are ignored (without 300 | this option, Ksplice aborts if any modules patched by the update are 301 | not loaded). 302 | 303 | =item B<--raw-errors> 304 | 305 | Print only raw error information designed to be machine-readable on 306 | standard error (standard output is still intended to be 307 | human-readable). If B fails due to an error from the 308 | Ksplice kernel modules, the first line on standard error will be a 309 | Ksplice B (see the Ksplice source code for documentation 310 | on these codes). Further lines will vary depending on the abort code. 311 | If B fails for any other reason, it will output the 312 | line C<"OTHER\n">, followed by a human-readable failure message, to 313 | standard error. 314 | 315 | =back 316 | 317 | =head1 SEE ALSO 318 | 319 | L, L, L 320 | 321 | =head1 BUGS 322 | 323 | Please report bugs to . 324 | 325 | =head1 AUTHORS 326 | 327 | Jeff Arnold, Anders Kaseorg, and Tim Abbott 328 | 329 | =head1 COPYRIGHT 330 | 331 | Copyright (C) 2007-2009 Ksplice, Inc. 332 | 333 | This is free software and documentation. You can redistribute and/or modify it 334 | under the terms of the GNU General Public License, version 2. 335 | 336 | =cut 337 | -------------------------------------------------------------------------------- /inspect.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2008-2009 Ksplice, Inc. 2 | * Authors: Anders Kaseorg, Tim Abbott, Jeff Arnold 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License, version 2. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 15 | * 02110-1301, USA. 16 | */ 17 | 18 | /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice. 19 | inspect won't compile without it. */ 20 | #define KSPLICE_STANDALONE 21 | 22 | #define _GNU_SOURCE 23 | #include "objcommon.h" 24 | #include "kmodsrc/ksplice.h" 25 | #include 26 | 27 | char *str_pointer(struct supersect *ss, void *const *addr); 28 | 29 | struct kreloc_section { 30 | struct supersect *ss; 31 | const struct ksplice_reloc *reloc; 32 | }; 33 | 34 | #define kreloc_section_init(ks) *(ks) = NULL 35 | DEFINE_HASH_TYPE(struct kreloc_section *, kreloc_section_hash, 36 | kreloc_section_hash_init, kreloc_section_hash_free, 37 | kreloc_section_hash_lookup, kreloc_section_init); 38 | struct kreloc_section_hash ksplice_relocs; 39 | 40 | char *str_ulong_vec(struct supersect *ss, const unsigned long *const *datap, 41 | const unsigned long *sizep) 42 | { 43 | struct supersect *data_ss; 44 | const unsigned long *data = 45 | read_pointer(ss, (void *const *)datap, &data_ss); 46 | unsigned long size = read_num(ss, sizep); 47 | 48 | char *buf = NULL; 49 | size_t bufsize = 0; 50 | FILE *fp = open_memstream(&buf, &bufsize); 51 | fprintf(fp, "[ "); 52 | size_t i; 53 | for (i = 0; i < size; ++i) 54 | fprintf(fp, "%lx ", read_num(data_ss, &data[i])); 55 | fprintf(fp, "]"); 56 | fclose(fp); 57 | return buf; 58 | } 59 | 60 | static const struct ksplice_reloc * 61 | find_ksplice_reloc(struct supersect *ss, void *const *addr, 62 | struct supersect **reloc_ss) 63 | { 64 | char *key = strprintf("%p", addr); 65 | struct kreloc_section **ksp = 66 | kreloc_section_hash_lookup(&ksplice_relocs, key, FALSE); 67 | free(key); 68 | if (ksp == NULL) 69 | return NULL; 70 | *reloc_ss = (*ksp)->ss; 71 | return (*ksp)->reloc; 72 | } 73 | 74 | char *str_ksplice_symbol(struct supersect *ss, 75 | const struct ksplice_symbol *ksymbol) 76 | { 77 | return strprintf("%s (%s)", 78 | read_string(ss, &ksymbol->label), 79 | read_string(ss, &ksymbol->name)); 80 | } 81 | 82 | char *str_ksplice_symbolp(struct supersect *ptr_ss, 83 | struct ksplice_symbol *const *ksymbolp) 84 | { 85 | asymbol *sym; 86 | bfd_vma offset = read_reloc(ptr_ss, ksymbolp, sizeof(*ksymbolp), &sym); 87 | if (bfd_is_const_section(sym->section)) 88 | return strprintf("*(%s)", 89 | str_pointer(ptr_ss, (void *const *)ksymbolp)); 90 | struct supersect *ksymbol_ss = fetch_supersect(ptr_ss->parent, 91 | sym->section); 92 | return str_ksplice_symbol(ksymbol_ss, ksymbol_ss->contents.data + 93 | sym->value + offset); 94 | } 95 | 96 | char *str_pointer(struct supersect *ss, void *const *addr) 97 | { 98 | asymbol *sym; 99 | struct supersect *kreloc_ss; 100 | const struct ksplice_reloc *kreloc = 101 | find_ksplice_reloc(ss, addr, &kreloc_ss); 102 | if (kreloc == NULL) { 103 | bfd_vma offset = read_reloc(ss, addr, sizeof(*addr), &sym); 104 | return strprintf("%s+%lx", sym->name, (unsigned long)offset); 105 | } else { 106 | return strprintf("[%s]+%lx", 107 | str_ksplice_symbolp(kreloc_ss, 108 | &kreloc->symbol), 109 | kreloc->target_addend); 110 | } 111 | } 112 | 113 | static const char *str_howto_type(const struct ksplice_reloc_howto *howto) 114 | { 115 | switch (howto->type) { 116 | case KSPLICE_HOWTO_RELOC: 117 | return "reloc"; 118 | case KSPLICE_HOWTO_RELOC_PATCH: 119 | return "reloc(patch)"; 120 | case KSPLICE_HOWTO_TIME: 121 | return "time"; 122 | case KSPLICE_HOWTO_DATE: 123 | return "date"; 124 | case KSPLICE_HOWTO_BUG: 125 | return "bug"; 126 | case KSPLICE_HOWTO_EXTABLE: 127 | return "extable"; 128 | case KSPLICE_HOWTO_SYMBOL: 129 | return "symbol"; 130 | default: 131 | return "unknown"; 132 | } 133 | } 134 | 135 | void show_ksplice_reloc(struct supersect *ss, 136 | const struct ksplice_reloc *kreloc) 137 | { 138 | struct supersect *khowto_ss; 139 | const struct ksplice_reloc_howto *khowto = 140 | read_pointer(ss, (void *const *)&kreloc->howto, &khowto_ss); 141 | printf(" blank_addr: %s size: %x\n" 142 | " type: %s\n" 143 | " symbol: %s\n" 144 | " insn_addend: %lx\n" 145 | " target_addend: %lx\n" 146 | " pcrel: %x dst_mask: %lx rightshift: %x signed_addend: %x\n" 147 | "\n", 148 | str_pointer(ss, (void *const *)&kreloc->blank_addr), 149 | read_num(khowto_ss, &khowto->size), 150 | str_howto_type(khowto), 151 | str_ksplice_symbolp(ss, &kreloc->symbol), 152 | read_num(ss, &kreloc->insn_addend), 153 | read_num(ss, &kreloc->target_addend), 154 | read_num(khowto_ss, &khowto->pcrel), 155 | read_num(khowto_ss, &khowto->dst_mask), 156 | read_num(khowto_ss, &khowto->rightshift), 157 | read_num(khowto_ss, &khowto->signed_addend)); 158 | } 159 | 160 | void show_ksplice_relocs(struct supersect *kreloc_ss) 161 | { 162 | const struct ksplice_reloc *kreloc; 163 | for (kreloc = kreloc_ss->contents.data; (void *)kreloc < 164 | kreloc_ss->contents.data + kreloc_ss->contents.size; kreloc++) 165 | show_ksplice_reloc(kreloc_ss, kreloc); 166 | } 167 | 168 | void show_ksplice_section_flags(const struct ksplice_section *ksect) 169 | { 170 | printf(" flags:"); 171 | if (ksect->flags & KSPLICE_SECTION_RODATA) 172 | printf(" rodata"); 173 | if (ksect->flags & KSPLICE_SECTION_TEXT) 174 | printf(" text"); 175 | if (ksect->flags & KSPLICE_SECTION_DATA) 176 | printf(" data"); 177 | if (ksect->flags & KSPLICE_SECTION_MATCH_DATA_EARLY) 178 | printf(" match_early"); 179 | printf("\n"); 180 | } 181 | 182 | void show_ksplice_section(struct supersect *ss, 183 | const struct ksplice_section *ksect) 184 | { 185 | printf(" symbol: %s\n" 186 | " address: %s size: %lx\n", 187 | str_ksplice_symbolp(ss, &ksect->symbol), 188 | str_pointer(ss, (void *const *)&ksect->address), 189 | read_num(ss, &ksect->size)); 190 | show_ksplice_section_flags(ksect); 191 | printf("\n"); 192 | } 193 | 194 | void show_ksplice_sections(struct supersect *ksect_ss) 195 | { 196 | struct ksplice_section *ksect; 197 | for (ksect = ksect_ss->contents.data; (void *)ksect < 198 | ksect_ss->contents.data + ksect_ss->contents.size; ksect++) 199 | show_ksplice_section(ksect_ss, ksect); 200 | } 201 | 202 | const char *str_ksplice_patch_type(struct supersect *ss, 203 | const struct ksplice_patch *kpatch) 204 | { 205 | const char *const *strp; 206 | struct supersect *data_ss; 207 | switch(kpatch->type) { 208 | case KSPLICE_PATCH_TEXT: 209 | return strprintf("text\n repladdr: %s", str_pointer 210 | (ss, (void *const *)&kpatch->repladdr)); 211 | case KSPLICE_PATCH_DATA: 212 | return strprintf("data\n size: %x", kpatch->size); 213 | case KSPLICE_PATCH_EXPORT: 214 | strp = read_pointer(ss, &kpatch->contents, &data_ss); 215 | return strprintf("export\n newname: %s", 216 | read_string(data_ss, strp)); 217 | default: 218 | return "unknown"; 219 | } 220 | } 221 | 222 | void show_ksplice_patch(struct supersect *ss, 223 | const struct ksplice_patch *kpatch) 224 | { 225 | printf(" type: %s\n" 226 | " oldaddr: %s\n\n", 227 | str_ksplice_patch_type(ss, kpatch), 228 | str_pointer(ss, (void *const *)&kpatch->oldaddr)); 229 | } 230 | 231 | void show_ksplice_patches(struct supersect *kpatch_ss) 232 | { 233 | const struct ksplice_patch *kpatch; 234 | for (kpatch = kpatch_ss->contents.data; (void *)kpatch < 235 | kpatch_ss->contents.data + kpatch_ss->contents.size; kpatch++) 236 | show_ksplice_patch(kpatch_ss, kpatch); 237 | } 238 | 239 | void show_ksplice_call(struct supersect *ss, void *const *kcall) 240 | { 241 | printf("%s\n", str_pointer(ss, kcall)); 242 | } 243 | 244 | void show_ksplice_calls(struct supersect *kcall_ss) 245 | { 246 | void *const *kcall; 247 | for (kcall = kcall_ss->contents.data; (void *)kcall < 248 | kcall_ss->contents.data + kcall_ss->contents.size; kcall++) 249 | show_ksplice_call(kcall_ss, kcall); 250 | } 251 | 252 | void show_ksplice_system_map(struct supersect *ss, 253 | const struct ksplice_system_map *smap) 254 | { 255 | printf("%s %s\n", 256 | read_string(ss, &smap->label), 257 | str_ulong_vec(ss, &smap->candidates, &smap->nr_candidates)); 258 | } 259 | 260 | void show_ksplice_system_maps(struct supersect *smap_ss) 261 | { 262 | const struct ksplice_system_map *smap; 263 | for (smap = smap_ss->contents.data; 264 | (void *)smap < smap_ss->contents.data + smap_ss->contents.size; 265 | smap++) 266 | show_ksplice_system_map(smap_ss, smap); 267 | } 268 | 269 | struct inspect_section { 270 | const char *prefix; 271 | const char *header; 272 | const char *notfound; 273 | void (*show)(struct supersect *ss); 274 | }; 275 | 276 | const struct inspect_section inspect_sections[] = { 277 | { 278 | .prefix = ".ksplice_init_relocs", 279 | .header = "KSPLICE INIT RELOCATIONS", 280 | .notfound = "No ksplice init relocations.\n", 281 | .show = show_ksplice_relocs, 282 | }, 283 | { 284 | .prefix = ".ksplice_relocs", 285 | .header = "KSPLICE RELOCATIONS", 286 | .notfound = "No ksplice relocations.\n", 287 | .show = show_ksplice_relocs, 288 | }, 289 | { 290 | .prefix = ".ksplice_sections", 291 | .header = "KSPLICE SECTIONS", 292 | .notfound = "No ksplice sections.\n", 293 | .show = show_ksplice_sections, 294 | }, 295 | { 296 | .prefix = ".ksplice_patches", 297 | .header = "KSPLICE PATCHES", 298 | .notfound = "No ksplice patches.\n", 299 | .show = show_ksplice_patches, 300 | }, 301 | { 302 | .prefix = ".ksplice_call", 303 | .header = "KSPLICE CALLS", 304 | .notfound = "No ksplice calls.\n", 305 | .show = show_ksplice_calls, 306 | }, 307 | { 308 | .prefix = ".ksplice_system_map", 309 | .header = "KSPLICE SYSTEM.MAP", 310 | .notfound = "No ksplice System.map.\n", 311 | .show = show_ksplice_system_maps, 312 | }, 313 | }, *const inspect_sections_end = *(&inspect_sections + 1); 314 | 315 | static void load_ksplice_reloc_offsets(struct superbfd *sbfd) 316 | { 317 | kreloc_section_hash_init(&ksplice_relocs); 318 | 319 | asection *sect; 320 | for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { 321 | struct supersect *ss = fetch_supersect(sbfd, sect); 322 | if (!strstarts(ss->name, ".ksplice_relocs") && 323 | !strstarts(ss->name, ".ksplice_init_relocs")) 324 | continue; 325 | struct ksplice_reloc *kreloc; 326 | for (kreloc = ss->contents.data; 327 | (void *)kreloc < ss->contents.data + ss->contents.size; 328 | kreloc++) { 329 | const struct ksplice_reloc_howto *khowto = 330 | read_pointer(ss, (void *const *)&kreloc->howto, 331 | NULL); 332 | if (khowto->size == 0) 333 | continue; 334 | 335 | struct supersect *sym_ss; 336 | const void *ptr = 337 | read_pointer(ss, (void *const *)&kreloc->blank_addr, 338 | &sym_ss); 339 | char *key = strprintf("%p", ptr); 340 | struct kreloc_section *ks, **ksp = 341 | kreloc_section_hash_lookup(&ksplice_relocs, key, 342 | TRUE); 343 | free(key); 344 | assert(*ksp == NULL); 345 | ks = malloc(sizeof(*ks)); 346 | *ksp = ks; 347 | ks->reloc = kreloc; 348 | ks->ss = ss; 349 | } 350 | } 351 | } 352 | 353 | static void show_inspect_section(struct superbfd *sbfd, 354 | const struct inspect_section *isect) 355 | { 356 | bool found = false; 357 | asection *sect; 358 | for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { 359 | struct supersect *ss = fetch_supersect(sbfd, sect); 360 | if (strstarts(ss->name, isect->prefix) && 361 | ss->contents.size != 0) { 362 | printf("%s IN [%s]:\n", isect->header, sect->name); 363 | found = true; 364 | isect->show(ss); 365 | } 366 | } 367 | if (!found) 368 | printf("%s", isect->notfound); 369 | printf("\n"); 370 | } 371 | 372 | int main(int argc, char *argv[]) 373 | { 374 | bfd *ibfd; 375 | 376 | assert(argc >= 1); 377 | bfd_init(); 378 | ibfd = bfd_openr(argv[1], NULL); 379 | assert(ibfd); 380 | 381 | char **matching; 382 | assert(bfd_check_format_matches(ibfd, bfd_object, &matching)); 383 | 384 | struct superbfd *sbfd = fetch_superbfd(ibfd); 385 | load_ksplice_reloc_offsets(sbfd); 386 | const struct inspect_section *isect; 387 | for (isect = inspect_sections; isect < inspect_sections_end; isect++) 388 | show_inspect_section(sbfd, isect); 389 | 390 | return 0; 391 | } 392 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------