b520e4b1d5
required for FIPS.
268 lines
7.5 KiB
Perl
268 lines
7.5 KiB
Perl
#!/bin/env perl
|
|
#
|
|
# Quick and dirty utility to help assemble the mandated (but otherwise
|
|
# useless) API documentation. We get the list of external function
|
|
# symbols from fipscanister.o, pair those with the source file names
|
|
# (from ./fips/fipssyms.h), and map to the object file name containing
|
|
# them.
|
|
#
|
|
# Requires the "nm" and "find" utilities.
|
|
# Execure from the root of the FIPS module source code workarea
|
|
|
|
use HTML::Entities;
|
|
use File::Basename;
|
|
|
|
$here = dirname($0);
|
|
require "$here/api_fns.pm";
|
|
|
|
$_direction_question = ''; # Set to '?' to show "<-?", "<->?" for uncertain directions
|
|
|
|
print STDERR "Info: finding FIPS renames and reimplementations of OpenSSL symbols\n";
|
|
# Get mapping of old (source code) to new (live as renamed) symbols
|
|
foreach $file ("./fips/fipssyms.h") {
|
|
open(IN, $file) || die "Error opening $file";
|
|
# grab pairs until assembler symbols
|
|
my $buf = '';
|
|
my $reimplementations = 1; # When 1, we're looking at reimplementations
|
|
# (not renames) of OpenSSL functions. They
|
|
# still have to be saved to get the API.
|
|
while (<IN>) {
|
|
$reimplementations = 0 if m|^\s*/\*\sRename\ssymbols\s|;
|
|
|
|
if ($buf) {
|
|
$_ = $buf . $_;
|
|
$buf = '';
|
|
}
|
|
if (s/\\\n$//) {
|
|
$buf = $_;
|
|
next;
|
|
}
|
|
if (m/\(/) {
|
|
($oldname, $newname) = m/#define\s+(\S+)\(.*\)\s+(\S+)\(.*\)/;
|
|
} else {
|
|
($oldname, $newname) = m/#define\s+(\S+)\s+(\S+)/;
|
|
}
|
|
|
|
$oldname || next;
|
|
if (!$reimplementations) {
|
|
$oldname{$newname} = $oldname;
|
|
}
|
|
$oldimpl{$newname} = $oldname;
|
|
last if (/assembler/)
|
|
}
|
|
close(IN);
|
|
# %oldname is the mapping of new function names to old
|
|
print "<!-- Total of ", scalar(keys %oldname), " mapped symbols in $file -->\n";
|
|
}
|
|
|
|
print STDERR "Info: finding FIPS symbols in object files\n";
|
|
# generate list of external function names in fipscanister.o
|
|
$file = "./fips/fipscanister.o";
|
|
for (`nm -g --defined-only -p -o $file`) {
|
|
chomp;
|
|
s/^\S+ T // || next;
|
|
m/^fips_/ && next;
|
|
$fipssyms{$_}++;
|
|
$objname =~ s/\.o$/\.\[o\|c\]/;
|
|
$objname{$symname} = $objname;
|
|
}
|
|
# keys %fipssyms is the list of module functions
|
|
print "<!-- Total of ", scalar(keys %fipssyms), " functions in $file -->\n";
|
|
|
|
# grab filename to symbol name mapping, each line is of the format
|
|
# ./fips/sha/fips_sha1_selftest.o:00000000 T FIPS_selftest_sha1
|
|
# discard the offset and type ":00000000 T".
|
|
for (`find . -name '*.o' \\! -name 'fipscanister.o' -exec nm -g --defined-only -p -o {} \\;`) {
|
|
($objname, $symname) = m/^(\S+):\S+\s+T+\s+(\S+)/;
|
|
$objname || next;
|
|
# $fipssyms{$symname} || next;
|
|
$objname =~ s/\.o$/\.\[o\|c\]/;
|
|
$objname{$symname} = $objname;
|
|
}
|
|
# %objname is the mapping of new symbol name to (source/object) file name
|
|
print "<!-- Total of ", scalar(keys %objname), " functions found in files -->\n";
|
|
|
|
print STDERR "Info: finding declarations in header files\n";
|
|
|
|
# grab filenames in include/openssl, run each of them through
|
|
# get_function_declarations_from_file (defined in api_fns.pl)
|
|
# and collect the result.
|
|
%declarations = ();
|
|
while (<include/openssl/*.h ./crypto/cryptlib.h>) {
|
|
my %decls = api_data::get_function_declaration_strings_from_file($_);
|
|
map { $declarations{$_} = $decls{$_} } keys %decls;
|
|
}
|
|
# %declarations is the mapping of old symbol name to their declaration
|
|
print "<!-- Total of ", scalar(keys %declarations), " declarations found in header files -->\n";
|
|
|
|
# Add the markers FIPS_text_start and FIPS_text_end
|
|
$declarations{FIPS_text_start} = "void *FIPS_text_start()";
|
|
$declarations{FIPS_text_end} = "void *FIPS_text_end()";
|
|
|
|
|
|
# Read list of API names obtained from edited "nm -g fipscanister.o"
|
|
$spill = 0;
|
|
sub printer {
|
|
foreach (@_) {
|
|
if ($_->{kind} >= 0) {
|
|
if ($spill) {
|
|
print " " x $indent;
|
|
print "kind: ",$_->{kind} ? "function" : "variable","\n";
|
|
print " " x $indent;
|
|
print "sym: ",$_->{sym},"\n";
|
|
print " " x $indent;
|
|
print "type: ",$_->{type},"\n";
|
|
}
|
|
if ($_->{kind}) {
|
|
$c = 0;
|
|
map {
|
|
if ($spill) {
|
|
print " " x $indent;
|
|
printf "param %d:\n", ++$c;
|
|
}
|
|
$indent += 2;
|
|
printer($_);
|
|
my $direction = $_->{direction};
|
|
if (!$_direction_question) {
|
|
$direction =~ s/<-\? <->\?/<->/;
|
|
$direction =~ s/\?//g;
|
|
}
|
|
print " " x $indent,$direction," ",$_->{sym},"\n";
|
|
$indent -= 2;
|
|
} @{$_->{params}};
|
|
if ($_->{type} !~ m/^\s*void\s*$/) {
|
|
print " " x $indent;
|
|
print "<- Return\n";
|
|
}
|
|
}
|
|
} else {
|
|
if ($spill) {
|
|
print " " x $indent;
|
|
print "decl: ",$_->{decl},"\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub html_printer {
|
|
my $print_mode = shift; # 0 = print declaration with symbol in bold,
|
|
# call recursively with 1 for each parameter,
|
|
# call recursively with 2 for each parameter
|
|
# 1 = print declaration with sym grey background,
|
|
# call recursivelt with 3 for each parameter
|
|
# 2 = just print declaration
|
|
my $d = shift; # Parsed declaration
|
|
my $s = '';
|
|
|
|
if ($print_mode == 0) {
|
|
$d->{sym} || return $s;
|
|
my $h = "<hr><br />\n";
|
|
$h .= $d->{sym} . ($d->{symcomment} ? " " . $d->{symcomment} : "");
|
|
$h .= " in file " . $d->{objfile} . "<br />\n<br />\n";
|
|
|
|
$s .= '<b>' . $d->{sym} . '</b>';
|
|
if ($d->{kind} == 1) {
|
|
$s .= '(';
|
|
$s .= join(', ',
|
|
map {
|
|
html_printer(1,$_);
|
|
} @{$d->{params}});
|
|
$s .= ')';
|
|
}
|
|
my $t = $d->{type};
|
|
$t =~ s/\?/$s/;
|
|
$s = $t;
|
|
if ($d->{kind} == 1) {
|
|
map {
|
|
my $direction = $_->{direction};
|
|
if (!$_direction_question) {
|
|
$direction =~ s/<-\? <->\?/<->/;
|
|
$direction =~ s/\?//g;
|
|
}
|
|
$s .= "<br />\n";
|
|
$s .= encode_entities($direction
|
|
. "\xA0" x (9 - length($direction)));
|
|
$s .= $_->{sym};
|
|
} @{$d->{params}};
|
|
}
|
|
if ($d->{type} !~ m/^\s*void\s*\?$/) {
|
|
$s .= "<br />\n";
|
|
$s .= encode_entities('<-'.("\xA0" x 7).'Return');
|
|
}
|
|
$s = $h . $s;
|
|
} elsif ($print_mode == 1) {
|
|
$s .= '<span style="background: #c0c0c0">' . $d->{sym} . '</span>';
|
|
if ($d->{kind} == 1) {
|
|
$s .= '(';
|
|
$s .= join(', ',
|
|
map {
|
|
html_printer(3,$_);
|
|
} @{$d->{params}});
|
|
$s .= ')';
|
|
}
|
|
my $t = $d->{type};
|
|
$t =~ s/\?/$s/;
|
|
$s = $t;
|
|
} elsif ($print_mode == 2) {
|
|
$s .= $d->{sym};
|
|
if ($d->{kind} == 1) {
|
|
$s .= '(';
|
|
$s .= join(', ',
|
|
map {
|
|
html_printer(2,$_);
|
|
} @{$d->{params}});
|
|
$s .= ')';
|
|
}
|
|
my $t = $d->{type};
|
|
$t =~ s/\?/$s/;
|
|
$s = $t;
|
|
}
|
|
return $s;
|
|
}
|
|
|
|
print STDERR "Info: building/updating symbol information database\n";
|
|
|
|
$d = api_data->new();
|
|
if (-s "$here/declarations.dat") {
|
|
$d->read_declaration_db("$here/declarations.dat");
|
|
} else {
|
|
print STDERR "Warning: there was no file '$here/declarations.dat'. A new one will be created\n";
|
|
}
|
|
|
|
for (sort keys %fipssyms) {
|
|
$newname = $_;
|
|
$namecomment = undef;
|
|
if ($oldname{$newname}) {
|
|
$oldname = $oldname{$newname};
|
|
$objname = $objname{$oldname} ? $objname{$oldname} : $objname{$newname};
|
|
$namecomment = "(renames $oldname)";
|
|
} else {
|
|
$objname = $objname{$newname};
|
|
}
|
|
if ($oldimpl{$newname}) {
|
|
$apisym = $oldimpl{$newname};
|
|
$namecomment = "(reimplements $apisym)" if !$namecomment;
|
|
} else {
|
|
$apisym = $newname;
|
|
}
|
|
$declaration = $declarations{$apisym};
|
|
print "<!--\n";
|
|
print "$newname\t\t$namecomment\tin file $objname:\n";
|
|
print " ",$declaration,"\n ";
|
|
$d->add_declaration($declaration,$newname,$objname,$namecomment);
|
|
print "-->\n";
|
|
}
|
|
|
|
$d->complete_directions();
|
|
$d->write_declaration_db("$here/declarations.dat");
|
|
|
|
print STDERR "Info: printing output\n";
|
|
|
|
$d->on_all_declarations(
|
|
sub {
|
|
my $decl = shift;
|
|
#$indent = 2;
|
|
#print printer($decl);
|
|
print "<p>",html_printer(0,$decl),"</p>\n";
|
|
});
|