Fwd: Updating PAR executables
[email protected] (Roderich Schupp)
| Newsgroups | perl.par |
|---|---|
| Message-ID | <CAC9r9zYfoRKxMy4TTpBUoET52Avf8j+MHSpufLAsT9eDKqdjsQ@mail.gmail.com> |
On Tue, Mar 14, 2017 at 12:49 PM, Johan Vromans <[email protected]> wrote: > I have a perl application that consists of pure perl modules only. Are you sure that your pure perl modules don't require (directly or transitively) something platform dependent, e.g. IO.pm (which is an XS module)? Check by pp'ing it into foo.exe and look at its contents with "unzip -l foo.exe". If that's the case, the following might work (haven't actually tried this). For reference, see "man par.pl", "Stand-alone executable format". 1. Get any packed executable (e.g. pp a hello-world one liner) from your target platform. 2. Run the attached script on it (repurposed from contrib/extract-embedded/extract-embedded.pl). This will print something like embedded FILEs start at offset 2119320 zip starts at offset 3143323 size of FILEs section is 1024003 3. Chop off the executable after the start of the zip. 4. Pack your application into a .par file ("pp -p -o my.par ...") 5. Append my.par to the executable stub. 6. Compute the SHA1 of the file so far and append it in hex (40 bytes) 7. Append "\0CACHE" 8. Append pack('N', size of FILEs section + size of my.par) 9. Append "\012PAR.pm\012" 10. Ta-da, new executable for the target platform Cheers, Roderich
analyze-pp.pl
(application/x-perl, 1.6 KB)
#!/usr/bin/perl
use File::Spec;
use File::Basename;
use File::Path;
use strict;
use warnings;
@ARGV == 1 || die "usage: $0 executable\n";
{
my ($exe) = @ARGV;
open my $fh, '<', $exe or die qq[failed to open "$exe": $!];
binmode $fh;
# search for the "\nPAR.pm\n signature backward from the end of the file
my $buf;
my $size = -s $exe;
my $offset = 512;
my $idx = -1;
while (1)
{
$offset = $size if $offset > $size;
seek $fh, -$offset, 2 or die qq[seek failed on "$exe": $!];
my $nread = read $fh, $buf, $offset;
die qq[read failed on "$exe": $!] unless $nread == $offset;
$idx = rindex($buf, "\nPAR.pm\n");
last if $idx >= 0 || $offset == $size || $offset > 128 * 1024;
$offset *= 2;
}
die qq[no PAR signature found in "$exe"] unless $idx >= 0;
# seek 4 bytes backward from the signature to get the offset of the
# first embedded FILE, then seek to it
$offset -= $idx - 4;
seek $fh, -$offset, 2;
read $fh, $buf, 4;
seek $fh, -$offset - unpack("N", $buf), 2;
my $FILES_offset = tell $fh;
printf qq[embedded FILEs start at offset %d\n], $FILES_offset;
read $fh, $buf, 4;
while ($buf eq "FILE")
{
read $fh, $buf, 4;
seek $fh, unpack("N", $buf), 1;
read $fh, $buf, 4;
seek $fh, unpack("N", $buf), 1;
read $fh, $buf, 4;
}
die qq[no zip found after FILEs in "$exe"] unless $buf eq "PK\003\004";
my $ZIP_offset = tell($fh) - 4;
printf qq[zip starts at offset %d\n], $ZIP_offset;
printf qq[size of FILEs section is %d\n], $ZIP_offset - $FILES_offset;
close $fh;
}