summaryrefslogtreecommitdiffstats
path: root/c6x/incore6x
diff options
context:
space:
mode:
Diffstat (limited to 'c6x/incore6x')
-rw-r--r--c6x/incore6x241
1 files changed, 241 insertions, 0 deletions
diff --git a/c6x/incore6x b/c6x/incore6x
new file mode 100644
index 0000000000..be73aca2d9
--- /dev/null
+++ b/c6x/incore6x
@@ -0,0 +1,241 @@
+#!/usr/bin/env perl
+#
+# Copyright (c) 2011 The OpenSSL Project.
+#
+# The script embeds fingerprint into TI-COFF executable object.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+
+unshift(@INC,$dir);
+require "hmac_sha1.pl";
+
+######################################################################
+#
+# COFF symbol table parser by <appro@openssl.org>. The table entries
+# are extended with offset within executable file...
+#
+{ package COFF;
+ use FileHandle;
+
+ sub dup { my %copy=map {$_} @_; return \%copy; }
+
+ sub Load {
+ my $class = shift;
+ my $self = {};
+ my $FD = FileHandle->new(); # autoclose
+
+ bless $self,$class;
+
+ sysopen($FD,shift,0) or die "$!";
+ binmode($FD);
+
+ #################################################
+ # read and parse COFF header...
+ #
+ read($FD,my $coff,22) or die "$!";
+
+ my %coff_header;
+ @coff_header{version,nsects,date,syms_off,nsyms,opt,flags,magic}=
+ unpack("v2V3v3",$coff);
+
+ $!=42; # signal fipsld to revert to two-step link
+ die "not TI-COFF file" if ($coff_header{version} != 0xC2);
+
+ my $big_endian = ($coff_header{flags}>>9)&1; # 0 or 1
+
+ my $strings;
+ my $symsize;
+
+ #################################################
+ # load strings table
+ #
+ seek($FD,$coff_header{syms_off}+18*$coff_header{nsyms},0) or die "$!";
+ read($FD,$strings,4) or die "$!";
+ $symsize = unpack("V",$strings);
+ read($FD,$strings,$symsize,4) or die "$!";
+
+ #################################################
+ # read sections
+ #
+ my $i;
+ my @sections;
+
+ # seek to section headers
+ seek($FD,22+@coff_header{opt},0) or die "$!";
+ for ($i=0;$i<$coff_header{nsects};$i++) {
+ my %coff_shdr;
+ my $name;
+
+ read($FD,my $section,48) or die "$!";
+
+ @coff_shdr{sh_name,sh_phaddr,sh_vaddr,
+ sh_size,sh_offset,sh_relocs,sh_reserved,
+ sh_relocoff,sh_lines,sh_flags} =
+ unpack("a8V9",$section);
+
+ $name = $coff_shdr{sh_name};
+ # see if sh_name is a an offset in $strings
+ my ($hi,$lo) = unpack("V2",$name);
+ if ($hi==0 && $lo<$symsize) {
+ $name = substr($strings,$lo,64);
+ }
+ $coff_shdr{sh_name} = (split(chr(0),$name))[0];
+
+ push(@sections,dup(%coff_shdr));
+ }
+
+ #################################################
+ # load symbols table
+ #
+ seek($FD,$coff_header{syms_off},0) or die "$!";
+ for ($i=0;$i<$coff_header{nsyms};$i++) {
+ my %coff_sym;
+ my $name;
+
+ read($FD,my $blob,18) or die "$!";
+
+ @coff_sym{st_name,st_value,st_shndx,reserved,class,aux} =
+ unpack("a8Vv2C2",$blob);
+
+ # skip aux entries
+ if ($coff_sym{aux}) {
+ seek($FD,18*$coff_sym{aux},1) or die "$!";
+ $i+=$coff_sym{aux};
+ }
+
+ $name = $coff_sym{st_name};
+ # see if st_name is a an offset in $strings
+ my ($hi,$lo) = unpack("V2",$name);
+ if ($hi==0 && $lo<$symsize) {
+ $name = substr($strings,$lo,64);
+ }
+ $coff_sym{st_name} = $name = (split(chr(0),$name))[0];
+
+ my $st_secn = $coff_sym{st_shndx}-1;
+ if ($st_secn>=0 && $st_secn<=$#sections
+ && @sections[$st_secn]->{sh_offset}
+ && $name =~ m/^_[a-z]+/i) {
+ # synthesize st_offset, ...
+ $coff_sym{st_offset} = $coff_sym{st_value}
+ - @sections[$st_secn]->{sh_vaddr}
+ + @sections[$st_secn]->{sh_offset};
+ $coff_sym{st_section} = @sections[$st_secn]->{sh_name};
+ # ... and add to lookup table
+ $self->{symbols}{$name} = dup(%coff_sym);
+ }
+ }
+
+ return $self;
+ }
+
+ sub Lookup {
+ my $self = shift;
+ my $name = shift;
+ return $self->{symbols}{"_$name"};
+ }
+
+ sub Traverse {
+ my $self = shift;
+ my $code = shift;
+
+ if (ref($code) eq 'CODE') {
+ for (keys(%{$self->{symbols}})) { &$code($self->{symbols}{$_}); }
+ }
+ }
+}
+
+######################################################################
+#
+# main()
+#
+my $legacy_mode;
+
+if ($#ARGV<0 || ($#ARGV>0 && !($legacy_mode=(@ARGV[0] =~ /^\-(dso|exe)$/)))) {
+ print STDERR "usage: $0 [-dso|-exe] ti-coff-binary\n";
+ exit(1);
+}
+
+$exe = COFF->Load(@ARGV[$#ARGV]);
+
+$FIPS_text_start = $exe->Lookup("FIPS_text_start") or die;
+$FIPS_text_end = $exe->Lookup("FIPS_text_end") or die;
+$FIPS_rodata_start = $exe->Lookup("FIPS_rodata_start") or die;
+$FIPS_rodata_end = $exe->Lookup("FIPS_rodata_end") or die;
+$FIPS_signature = $exe->Lookup("FIPS_signature") or die;
+
+# new cross-compile support
+$FIPS_text_startX = $exe->Lookup("FIPS_text_startX");
+$FIPS_text_endX = $exe->Lookup("FIPS_text_endX");
+
+if (!$legacy_mode) {
+ if (!$FIPS_text_startX || !$FIPS_text_endX) {
+ print STDERR "@ARGV[$#ARGV] is not cross-compiler aware.\n";
+ exit(42); # signal fipsld to revert to two-step link
+ }
+
+ $FINGERPRINT_ascii_value
+ = $exe->Lookup("FINGERPRINT_ascii_value");
+}
+if ($FIPS_text_startX && $FIPS_text_endX) {
+ $FIPS_text_start = $FIPS_text_startX;
+ $FIPS_text_end = $FIPS_text_endX;
+}
+
+sysopen(FD,@ARGV[$#ARGV],$legacy_mode?0:2) or die "$!"; # 2 is read/write
+binmode(FD);
+
+sub HMAC_Update {
+ my ($hmac,$off,$len) = @_;
+ my $blob;
+
+ seek(FD,$off,0) or die "$!";
+ read(FD,$blob,$len) or die "$!";
+ $$hmac->Update($blob);
+}
+
+# fips/fips.c:FIPS_incore_fingerprint's Perl twin
+#
+sub FIPS_incore_fingerprint {
+ my $p1 = $FIPS_text_start->{st_offset};
+ my $p2 = $FIPS_text_end->{st_offset};
+ my $p3 = $FIPS_rodata_start->{st_offset};
+ my $p4 = $FIPS_rodata_end->{st_offset};
+ my $sig = $FIPS_signature->{st_offset};
+ my $ctx = HMAC->Init("etaonrishdlcupfm");
+
+ # detect overlapping regions
+ if ($p1<=$p3 && $p2>=$p3) {
+ $p3 = $p1; $p4 = $p2>$p4?$p2:$p4; $p1 = 0; $p2 = 0;
+ } elsif ($p3<=$p1 && $p4>=$p1) {
+ $p3 = $p3; $p4 = $p2>$p4?$p2:$p4; $p1 = 0; $p2 = 0;
+ }
+
+ if ($p1) {
+ HMAC_Update (\$ctx,$p1,$p2-$p1);
+ }
+
+ if ($sig>=$p3 && $sig<$p4) {
+ # "punch" hole
+ HMAC_Update(\$ctx,$p3,$sig-$p3);
+ $p3 = $sig+20;
+ HMAC_Update(\$ctx,$p3,$p4-$p3);
+ } else {
+ HMAC_Update(\$ctx,$p3,$p4-$p3);
+ }
+
+ return $ctx->Final();
+}
+
+$fingerprint = FIPS_incore_fingerprint();
+
+if ($legacy_mode) {
+ print unpack("H*",$fingerprint);
+} elsif ($FINGERPRINT_ascii_value) {
+ seek(FD,$FINGERPRINT_ascii_value->{st_offset},0) or die "$!";
+ print FD unpack("H*",$fingerprint) or die "$!";
+} else {
+ seek(FD,$FIPS_signature->{st_offset},0) or die "$!";
+ print FD $fingerprint or die "$!";
+}
+
+close (FD);