Monday 9 February 2009

perl hexdump function (substr and x operator)

I can't quite believe I'm still writing hexdump functions.
I needed one again in perl and I had a basic one but fixed it up a bit more.

Interesting things: perl substr returns a warning/error if you request a substr outside range of the string. You should be able to persuade it to not produce warning. But I failed. perl v5.8.4 on solaris intel. From `perldoc -f substr`:
my $name = 'fred';
my $null = substr $name, 6, 2; # returns '' (no warning)

For padding make use of the `x` operator. `perldoc -q pad` `perldoc perlop`
http://perldoc.perl.org/perlfaq4.html#How-do-I-pad-a-string-with-blanks-or-pad-a-number-with-zeroes%3f
my $pad = " " x $padl;

Function hexdump is to be used in a file dumping different sections and in seperate calls hence possibility to pass in address. And generic pass in n - chars per line.


#!/usr/bin/perl -w

# n chars per line
sub hexdump {
my $text = shift;
my $addroffset = shift || 0; # optional
my $n = shift || 20;
my $pstr = "hack";
my $addr = 0;

# the extra awkward checks are to avoid warnings from substr
until ($pstr eq "" || $addr>length($text) || !defined($pstr)) {
$pstr = substr($text,$addr,$n);
if (defined($pstr) && $pstr) {
my $textaddr = sprintf "%08x", $addr + $addroffset;
my $padl = 2 * ($n - length($pstr));
my $texthex = join("", map { sprintf "%02x", $_ } unpack("C*",$pstr));
my $pad = " " x $padl;
$pstr =~ s/[\x00-\x1f]/./g;
$pstr =~ s/[\x7f-\xff]/./g;
print "$textaddr: $texthex $pad $pstr\n";
}
$addr += $n;
}
}

# one should check values of n (chars per line) 16, 20, others
# one should check hexdump(""); and 1 char, 2 chars up to n*2 + 1 chars at least
hexdump("1234567");
hexdump("MMMMMMMMMMMMOOOOOOOOOOOOOOORRRRRRR\nRRRRRRRRGGGGGGG\nGGGGGGEB1234567");
hexdump("MMMMMMMMMMMMOOOOOOOOOOOOOOORRRRRRR\nRRRRRRRRGGGGGGG\nGGGGGGEB1234567",2345);
hexdump("\x00\x02\x34MMMMMMMMMMMMOOOOOOOOOOOOOOORRRRRRR\nRRRRRRRRGGGGGGG\nGGGGGGEB1234567");
hexdump("\x78\x79\x7e\x7f\x80\x81\x82\xfe\xff\x00\x02\x34MMMMMMMMMMMMOOOOOOOOOOOOOOORRRRRRR\nRRRRRRRRGGGGGGG\nGGGGGGEB1234567");

my $file = shift;

if ( !open( FILE, "<$file" )) {
warn "$file: $!";
exit;
} else {
print "Data from $file\n";
}

# read - text mode returns short lines
#while ( ) {
# hexdump $_;
#}

while ( read(FILE,$_,20)) {
hexdump $_;
}


e.g. output:

$ ~/bin/hexdump.pl ~/bin/hexdump.pl
00000000: 31323334353637 1234567
00000000: 4d4d4d4d4d4d4d4d4d4d4d4d4f4f4f4f4f4f4f4f MMMMMMMMMMMMOOOOOOOO
00000014: 4f4f4f4f4f4f4f525252525252520a5252525252 OOOOOOORRRRRRR.RRRRR
00000028: 525252474747474747470a474747474747454231 RRRGGGGGGG.GGGGGGEB1
0000003c: 323334353637 234567
00000929: 4d4d4d4d4d4d4d4d4d4d4d4d4f4f4f4f4f4f4f4f MMMMMMMMMMMMOOOOOOOO
0000093d: 4f4f4f4f4f4f4f525252525252520a5252525252 OOOOOOORRRRRRR.RRRRR
00000951: 525252474747474747470a474747474747454231 RRRGGGGGGG.GGGGGGEB1
00000965: 323334353637 234567
00000000: 0002344d4d4d4d4d4d4d4d4d4d4d4d4f4f4f4f4f ..4MMMMMMMMMMMMOOOOO
00000014: 4f4f4f4f4f4f4f4f4f4f525252525252520a5252 OOOOOOOOOORRRRRRR.RR
00000028: 525252525252474747474747470a474747474747 RRRRRRGGGGGGG.GGGGGG
0000003c: 454231323334353637 EB1234567
00000000: 78797e7f808182feff0002344d4d4d4d4d4d4d4d xy~........4MMMMMMMM
00000014: 4d4d4d4d4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f52 MMMMOOOOOOOOOOOOOOOR
00000028: 5252525252520a52525252525252524747474747 RRRRRR.RRRRRRRRGGGGG
0000003c: 47470a474747474747454231323334353637 GG.GGGGGGEB1234567
Data from /home/james_coleman/bin/hexdump.pl
00000000: 23212f7573722f62696e2f7065726c202d770a0a #!/usr/bin/perl -w..
00000000: 23206e206279206e0a7375622068657864756d70 # n by n.sub hexdump
00000000: 207b0a202020206d79202474657874203d207368 {. my $text = sh
00000000: 6966743b0a202020206d792024616464726f6666 ift;. my $addroff
00000000: 736574203d207368696674207c7c20303b202320 set = shift || 0; #
00000000: 6f7074696f6e616c0a202020206d7920246e203d optional. my $n =
00000000: 207368696674207c7c2032303b0a202020206d79 shift || 20;. my
00000000: 202470737472203d20226861636b223b0a202020 $pstr = "hack";.
...
00000000: 3c46494c453e29207b0a23202020206865786475 ) {.# hexdu
00000000: 6d7020245f3b0a237d0a0a7768696c6520282072 mp $_;.#}..while ( r
00000000: 6561642846494c452c245f2c32302929207b0a20 ead(FILE,$_,20)) {.
00000000: 20202068657864756d7020245f3b0a7d0a hexdump $_;.}.

No comments: