#!/usr/sbin/perl # # Usage example: # findoff.perl 0x400000 a.out # # Given an elf file, and a virtual address, find the # offset in the elf file corresponding to that address # Using elfdump -o (or elfdump -h if it must) # to find virtual addresses # and file offsets. # # Stops as soon as it sees a program header with the right virtual # address. # # If the file has no program headers (a .o has none ) this # looks for all matches and also prints the section info so # you can decide if you really want this section as the one. # Prints all section header matches. # # elfdump -o output format example: # Type Offset Vaddr Paddr # Filesz Memsz Flags Align # # LOAD 0xf000 0x1000f000 0x1000f000 # 0x1000 0x1000 rw- 0x1000 $_ = $ARGV[0]; shift; sub getvalue { my $vin = $_[0]; my $v = 0; $v = oct($vin); return $v; } $y = $_; $v = getvalue($y,"2"); $file = $ARGV[0]; if ( ! -e $file ) {die "$file does not exist";} $waspt = 0; open MYF, "elfdump -o $file |" or die "elfdump on $file failed: $!"; while() { if(/PT_.*/) { @lin1 = split(" ",$_); $waspt = 1; next; } if($waspt == 1 ) { @lin2 = split(" ",$_); $waspt = 0; $lo = getvalue($lin1[2]); $high = $lo + getvalue($lin2[0]); $offbase = getvalue($lin1[1]); if(($v >= $lo) && ($v < $high)) { $off = $offbase + ($v - $lo); printf "0x%lx ( %ld decimal) in %s\n", $off, $off, $file; exit(0); } } next; } close MYF or die "bad elfdump completion on $file: $! $?"; # # We found nothing # so lets try -h # **** SECTION HEADER TABLE **** #[No] Type Addr Offset Size Name # Link Info Adralgn Entsize Flags # #[1] SHT_SYMTAB 0 0x34 0xd0 .symtab # 3 0x5 0x4 0x10 # $waspt = 0; $linec = 1; $lineh1 = "\n"; $lineh2 = "\n"; open MYF, "elfdump -h $file |" or die "elfdump on $file failed: $!"; while() { if($linec == 5) { $lineh1 = $_; } if($linec == 6) { $lineh2 = $_; } $linec = $linec + 1; if(/SHT.*/) { @lin1 = split(" ",$_); $waspt = 1; $line1entire = $_; next; } if($waspt == 1 ) { @lin2 = split(" ",$_); $line2entire = $_; $waspt = 0; $lo = getvalue($lin1[2]); $high = $lo + getvalue($lin2[3]); $offbase = getvalue($lin1[3]); if(($v >= $lo) && ($v < $high)) { $off = $offbase + ($v - $lo); printf "0x%lx ( %ld decimal) in %s section %s\n", $off, $off, $file, $lin1[5]; print $lineh1; print $lineh2; print $line1entire; print $line2entire; printf "\n"; } } next; } close MYF or die "bad elfdump completion on $file: $! $?"; exit(0);