Perl script to rename sections in MS COFF binaries.
authorDr. Stephen Henson <steve@openssl.org>
Tue, 27 Mar 2007 00:04:55 +0000 (00:04 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 27 Mar 2007 00:04:55 +0000 (00:04 +0000)
Submitted by: Andy Polyakov

ms/segrenam.pl [new file with mode: 0644]

diff --git a/ms/segrenam.pl b/ms/segrenam.pl
new file mode 100644 (file)
index 0000000..8be9888
--- /dev/null
@@ -0,0 +1,64 @@
+#!/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",                             #
+       ".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);
+}