#!/usr/bin/perl
# test_x86dis.pl
# ... actually this is a general test utility for libdisasm; however, it
# is also useful for comparing the AT&T syntax output of x86dis (which is
# generated by libdisasm) against what GNU as(1) expects.
# NOTE: this script expects to be run from $LIBDISASM/libdisasm/test
# and uses the instructions in ia32_test_insn.S to test disassembly.
use warnings;
use strict;
# assembler settings
my $asm_file = 'ia32_test_insn.S';
my $obj_file = '/tmp/ia32.o';
my $text_off = 0x34; # hopefully this won't change :)
my $text_size = 1986; # same
my $as = `which as`;
# relative path, ld_library_path for running x86dis from compile dir
my $x86dis = '../x86dis/x86dis';
# path is not needed now that libtool is being used
#my $ldpath = 'LD_LIBRARY_PATH="../libdisasm"';
my $ldpath = '';
my $x86dis_opt_str = "-f $obj_file -s att -r %d %d";
# uninitialized stuff
my ($line, @asm_lines, $x86dis_opts, $output, @disasm_lines, @bytes, $i);
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$jnk);
my ($a_mnem, $d_mnem, $a_op, $d_op);
print "## open asm file \n";
open ASMFILE, $asm_file || die "Cannot open $asm_file : $!\n";
foreach (<ASMFILE>) {
chomp;
next if /^#/; # skip comment lines
$line = $_;
$line =~ s/\s+/ /g;
$line =~ s/\s+$//;
$line =~ s/#.*//;
$line = lc $line;
push @asm_lines, $line;
}
$as =~ s/\n//g;
print "## assemble asm file: $as -o $obj_file $asm_file\n";
system "$as -o $obj_file $asm_file";
exit(1) if ($? != 0);
print "## stat obj file $obj_file\n";
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$jnk) = stat $obj_file;
#$x86dis_opts = sprintf $x86dis_opt_str, $text_off, $size;
$x86dis_opts = sprintf $x86dis_opt_str, $text_off, $text_size;
print "## disasm obj file: $ldpath $x86dis $x86dis_opts\n";
$output = `$ldpath $x86dis $x86dis_opts`;
exit(1) if ($? != 0);
foreach ( split /\n/, $output ) {
chomp;
next if /^#/; # skip comment lines
$line = $_;
$line =~ s/\s+/ /g;
$line =~ s/\s+$//;
$line =~ s/#.*//;
$line = lc $line;
$line =~ s/^[0-9][0-9a-f]+\s+(([0-9a-f]{2} )+)//;
push @bytes, $1;
push @disasm_lines, $line;
}
my $status = 0;
for ( $i = 0; $i <= $#disasm_lines and $i <= $#asm_lines; $i = $i + 1 ) {
if ( $disasm_lines[$i] ne $asm_lines[$i] ) {
# check if this is a jump or call, in which case
# the targets will be different addresses
($a_mnem, $a_op, $jnk) = split / /, $asm_lines[$i];
($d_mnem, $d_op, $jnk) = split / /, $disasm_lines[$i];
if ( $a_mnem eq $d_mnem and
($d_mnem =~ /^j/ or $d_mnem =~/call/ or
$d_mnem =~ /loop/ ) and $a_op =~ /^[-0-9]+/ ){
next;
}
print "ERROR: orig '$asm_lines[$i]'\n";
print " dis '$disasm_lines[$i]' BYTES $bytes[$i]\n";
$status = 1;
}
}
exit($status);
syntax highlighted by Code2HTML, v. 0.9.1