File Coverage

blib/lib/Games/Hack/Patch/x86_64.pm
Criterion Covered Total %
statement 16 16 100.0
branch 12 12 100.0
condition n/a
subroutine 1 1 100.0
pod 1 1 100.0
total 30 30 100.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             # vim: set sw=2 expandtab : #
3             # Master version is at https://developer.berlios.de/projects/games-hack/
4              
5             package Games::Hack::Patch::x86_64;
6              
7             $VERSION=0.13;
8              
9             require Exporter;
10             @ISA = qw(Exporter);
11             @EXPORT = qw(GetNOP);
12              
13              
14              
15             sub GetNOP
16             {
17 8     8 1 2719 my($adr_start, $adr_end, $disass)=@_;
18 8         12 my($binary, $diff);
19              
20 8         21 $binary="";
21              
22             ### Floating point store? Stores always %ST(0).
23 8 100       57 if ($disass =~ m#^f[bi]?st(p)?s? #)
    100          
    100          
24             {
25 3 100       11 if ($1)
26             {
27             # If the "Pop" flag is given in the "fst" ("floating point store")
28             # operation, we need to clean the floating point stack.
29             # We use the "ffreep st(0)" instruction, .
30 2         4 $binary .= "\xdf\xc0";
31              
32 2         3 $adr_start += 2;
33             }
34             # Rest gets done by jump.
35             }
36             # Popping values from the stack
37             elsif ($disass =~ m#^pop#)
38             {
39             # increment esp; rest done by jump.
40             # is there a 64bit pop?
41 1         2 $binary .= "\x83\xc4\x04";
42 1         1 $adr_start += 3;
43             }
44             ### Integer move or direct modification
45             elsif ($disass =~ m#^(mov|or|and|add|sub|xor)#)
46             {
47             # done by jump.
48             }
49             else
50             {
51 2         19 warn "Unknown instruction '" . $disass . "', patching unsafe!";
52 2         10 return undef;
53             }
54              
55              
56             ### short jump
57 6 100       16 if (($diff=$adr_end-$adr_start) >= 2)
58             {
59             # The opcode needs two bytes; these are already consumed, and so the jump
60             # distance has to be reduced.
61 4         12 $binary .= "\xeb" . pack("C", $diff-2);
62 4         7 $adr_end=$adr_start;
63             }
64              
65             ### NOP.
66             # That should never be needed ... all instructions involving memory access
67             # (even via a register) have at least 2 bytes.
68             # (If some value would be persistently stored in a register, we wouldn't
69             # find it by looking at the memory contents.)
70 6 100       15 $binary .= "\x90" x $diff
71             if ($diff=$adr_end-$adr_start) >= 1;
72              
73 6         17 return $binary;
74             }
75              
76             __END__