| #!/usr/bin/env perl |
| |
| my $quiet = 1; |
| |
| unpack("L",pack("N",1))!=1 || die "only little-endian hosts are supported"; |
| |
| # first argument can specify custom suffix... |
| $suffix=(@ARGV[0]=~/^\$/) ? shift(@ARGV) : "\$m"; |
| ################################################################# |
| # rename segments in COFF modules according to %map table below # |
| %map=( ".text" => "fipstx$suffix", # |
| ".text\$"=> "fipstx$suffix", # |
| ".rdata"=> "fipsrd$suffix", # |
| ".data" => "fipsda$suffix" ); # |
| ################################################################# |
| |
| # collect file list |
| foreach (@ARGV) { |
| if (/\*/) { push(@files,glob($_)); } |
| else { push(@files,$_); } |
| } |
| |
| use Fcntl; |
| use Fcntl ":seek"; |
| |
| foreach (@files) { |
| $file=$_; |
| print "processing $file\n" unless $quiet; |
| |
| sysopen(FD,$file,O_RDWR|O_BINARY) || die "sysopen($file): $!"; |
| |
| # read IMAGE_DOS_HEADER |
| sysread(FD,$mz,64)==64 || die "$file is too short"; |
| @dos_header=unpack("a2C58I",$mz); |
| if (@dos_header[0] eq "MZ") { |
| $e_lfanew=pop(@dos_header); |
| sysseek(FD,$e_lfanew,SEEK_SET) || die "$file is too short"; |
| sysread(FD,$Magic,4)==4 || die "$file is too short"; |
| unpack("I",$Magic)==0x4550 || die "$file is not COFF image"; |
| } elsif ($file =~ /\.obj$/i) { |
| # .obj files have no IMAGE_DOS_HEADER |
| sysseek(FD,0,SEEK_SET) || die "unable to rewind $file"; |
| } else { next; } |
| |
| # read IMAGE_FILE_HEADER |
| sysread(FD,$coff,20)==20 || die "$file is too short"; |
| ($Machine,$NumberOfSections,$TimeDateStamp, |
| $PointerToSymbolTable,$NumberOfSysmbols, |
| $SizeOfOptionalHeader,$Characteristics)=unpack("SSIIISS",$coff); |
| |
| # skip over IMAGE_OPTIONAL_HEADER |
| sysseek(FD,$SizeOfOptionalHeader,SEEK_CUR) || die "$file is too short"; |
| |
| # traverse IMAGE_SECTION_HEADER table |
| for($i=0;$i<$NumberOfSections;$i++) { |
| sysread(FD,$SectionHeader,40)==40 || die "$file is too short"; |
| ($Name,@opaque)=unpack("Z8C*",$SectionHeader); |
| if ($map{$Name}) { |
| sysseek(FD,-40,SEEK_CUR) || die "unable to rewind $file"; |
| syswrite(FD,pack("a8C*",$map{$Name},@opaque))==40 || die "syswrite failed: $!"; |
| printf " %-8s -> %.8s\n",$Name,$map{$Name} unless $quiet; |
| } |
| } |
| close(FD); |
| } |