Only use COW hooks in diff mode.
[ksplice.git] / ksplice-obj.pl.in
blob6cf79f3a1a93d81e724088c7381bd61616372a69
1 #!/usr/bin/perl
3 # Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
4 # Jeffrey Brian Arnold <jbarnold@mit.edu>,
5 # Tim Abbott <tabbott@mit.edu>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License, version 2.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 # 02110-1301, USA.
20 use strict;
21 use warnings;
22 use lib 'KSPLICE_DATA_DIR';
23 use Ksplice;
25 $Verbose::level = $ENV{KSPLICE_VERBOSE} if (defined $ENV{KSPLICE_VERBOSE});
27 sub empty_diff {
28 my ($out) = @_;
29 my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die;
30 unlink "$obj.KSPLICE_primary" if (-e "$obj.KSPLICE_primary");
31 unlink "$obj.KSPLICE_helper" if (-e "$obj.KSPLICE_helper");
32 open OUT, '>', "$out.tmp";
33 close OUT;
34 rename "$out.tmp", $out;
37 sub do_snap {
38 my ($out) = @_;
39 my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die;
40 die if (!-e $obj);
41 unlink "$obj.KSPLICE_pre" if (-e "$obj.KSPLICE_pre");
42 empty_diff($out);
45 sub do_diff {
46 my ($out) = @_;
47 my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die;
48 my $obj_old = "$obj.KSPLICE_pre";
49 die if (!-e $obj);
50 die "Patch creates new object $obj" if (!-e $obj_old);
51 if (system('cmp', '-s', '--', $obj_old, $obj) == 0) {
52 unlink $obj_old;
53 return empty_diff($out);
56 runval("$libexecdir/ksplice-objmanip", $obj, "$obj.KSPLICE_primary", "keep-primary", "$obj.KSPLICE_pre", $ENV{KSPLICE_KID});
57 return empty_diff($out) if (!-e "$obj.KSPLICE_primary");
59 open OUT, '>', "$out.tmp";
60 print OUT "1\n";
61 close OUT;
62 rename "$out.tmp", $out;
64 runval("$libexecdir/ksplice-objmanip", $obj_old, "$obj.KSPLICE_helper", "keep-helper");
67 sub do_helper {
68 my ($out) = @_;
69 my ($obj) = $out =~ /^(.*)\.KSPLICE_helper$/ or die;
70 my $obj_old = "$obj.KSPLICE_pre";
71 -e $obj_old or $obj_old = $obj;
72 runval("$libexecdir/ksplice-objmanip", $obj_old, "$obj.KSPLICE_helper", "keep-helper");
75 sub link_objs {
76 my ($out, @ins) = @_;
77 if (@ins == 0) {
78 runval(shellwords($ENV{AR}), "rcs", $out);
79 } elsif (@ins == 1) {
80 copy @ins, $out;
81 } else {
82 runval(shellwords($ENV{LD}), "-r", "-o", $out, @ins);
86 sub do_combine {
87 my ($out, @ins) = @_;
88 my @primaries;
89 my @helpers;
90 foreach my $in (@ins) {
91 if (my ($obj) = $in =~ /^(.*)\.KSPLICE$/) {
92 next if (!-s $in);
93 push @primaries, "$obj.KSPLICE_primary";
94 push @helpers, "$obj.KSPLICE_helper";
95 } elsif (($obj) = $in =~ /^(.*)\.KSPLICE_helper$/) {
96 push @helpers, "$obj.KSPLICE_helper"
97 unless (@helpers && $helpers[$#helpers] eq "$obj.KSPLICE_helper");
98 } else {
99 die;
103 return empty_diff($out) unless (@helpers);
105 my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die;
106 link_objs("$obj.KSPLICE_primary", @primaries);
107 link_objs("$obj.KSPLICE_helper", @helpers);
109 open OUT, '>', "$out.tmp";
110 print OUT "1\n";
111 close OUT;
112 rename "$out.tmp", $out;
115 sub do_finalize {
116 my ($in, $out, $target) = @_;
117 runval("$libexecdir/ksplice-objmanip", $in, $out, "finalize", $target);
120 sub do_rmsyms {
121 my ($in, $out, @rmsyms) = @_;
122 runval_in("@rmsyms\n", "$libexecdir/ksplice-objmanip", $in, $out, "rmsyms");
125 sub do_system_map_lookup {
126 my ($symarg) = @_;
127 open(SYMS, "<", "$ENV{KSPLICE_CONFIG_DIR}/System.map") or die;
128 my $line;
129 while (defined($line = <SYMS>)) {
130 my ($addr, $type, $sym, $mod) = split(/\s+/, $line);
131 if ($sym eq $symarg) { print $addr; last; }
133 close(SYMS);
136 my %handlers = (
137 'snap' => \&do_snap,
138 'diff' => \&do_diff,
139 'helper' => \&do_helper,
140 'combine' => \&do_combine,
141 'finalize' => \&do_finalize,
142 'rmsyms' => \&do_rmsyms,
143 'system_map_lookup' => \&do_system_map_lookup,
146 my ($cmd, @args) = @ARGV;
147 if (exists $handlers{$cmd}) {
148 my $handler = $handlers{$cmd};
149 &$handler(@args);
150 } else {
151 print "Usage: ksplice-obj.pl ", join('|', keys %handlers), " ...\n";
152 exit(1);