xref: /freebsd/crypto/openssl/util/mknum.pl (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1*e0c4386eSCy Schubert
2*e0c4386eSCy Schubert#! /usr/bin/env perl
3*e0c4386eSCy Schubert# Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
4*e0c4386eSCy Schubert#
5*e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License").  You may not use
6*e0c4386eSCy Schubert# this file except in compliance with the License.  You can obtain a copy
7*e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at
8*e0c4386eSCy Schubert# https://www.openssl.org/source/license.html
9*e0c4386eSCy Schubert
10*e0c4386eSCy Schubertuse strict;
11*e0c4386eSCy Schubertuse warnings;
12*e0c4386eSCy Schubert
13*e0c4386eSCy Schubertuse Getopt::Long;
14*e0c4386eSCy Schubertuse FindBin;
15*e0c4386eSCy Schubertuse lib "$FindBin::Bin/perl";
16*e0c4386eSCy Schubert
17*e0c4386eSCy Schubertuse OpenSSL::Ordinals;
18*e0c4386eSCy Schubertuse OpenSSL::ParseC;
19*e0c4386eSCy Schubert
20*e0c4386eSCy Schubertmy $ordinals_file = undef;      # the ordinals file to use
21*e0c4386eSCy Schubertmy $symhacks_file = undef;      # a symbol hacking file (optional)
22*e0c4386eSCy Schubertmy $version = undef;            # the version to use for added symbols
23*e0c4386eSCy Schubertmy $checkexist = 0;             # (unsure yet)
24*e0c4386eSCy Schubertmy $warnings = 1;
25*e0c4386eSCy Schubertmy $renumber = 0;
26*e0c4386eSCy Schubertmy $verbose = 0;
27*e0c4386eSCy Schubertmy $debug = 0;
28*e0c4386eSCy Schubert
29*e0c4386eSCy SchubertGetOptions('ordinals=s' => \$ordinals_file,
30*e0c4386eSCy Schubert           'symhacks=s' => \$symhacks_file,
31*e0c4386eSCy Schubert           'version=s'  => \$version,
32*e0c4386eSCy Schubert           'exist'      => \$checkexist,
33*e0c4386eSCy Schubert           'renumber'   => \$renumber,
34*e0c4386eSCy Schubert           'warnings!'  => \$warnings,
35*e0c4386eSCy Schubert           'verbose'    => \$verbose,
36*e0c4386eSCy Schubert           'debug'      => \$debug)
37*e0c4386eSCy Schubert    or die "Error in command line arguments\n";
38*e0c4386eSCy Schubert
39*e0c4386eSCy Schubertdie "Please supply ordinals file\n"
40*e0c4386eSCy Schubert    unless $ordinals_file;
41*e0c4386eSCy Schubert
42*e0c4386eSCy Schubertmy $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file,
43*e0c4386eSCy Schubert                                      warnings => $warnings,
44*e0c4386eSCy Schubert                                      verbose => $verbose,
45*e0c4386eSCy Schubert                                      debug => $debug);
46*e0c4386eSCy Schubert$ordinals->set_version($version);
47*e0c4386eSCy Schubert
48*e0c4386eSCy Schubertmy %orig_names = ();
49*e0c4386eSCy Schubert%orig_names = map { $_->name() => 1 }
50*e0c4386eSCy Schubert    $ordinals->items(comparator => sub { $_[0] cmp $_[1] },
51*e0c4386eSCy Schubert                     filter => sub { $_->exists() })
52*e0c4386eSCy Schubert    if $checkexist;
53*e0c4386eSCy Schubert
54*e0c4386eSCy Schubert# Invalidate all entries, they get revalidated when we re-check below
55*e0c4386eSCy Schubert$ordinals->invalidate();
56*e0c4386eSCy Schubert
57*e0c4386eSCy Schubertforeach my $f (($symhacks_file // (), @ARGV)) {
58*e0c4386eSCy Schubert    print STDERR $f," ","-" x (69 - length($f)),"\n" if $verbose;
59*e0c4386eSCy Schubert    open IN, $f or die "Couldn't open $f: $!\n";
60*e0c4386eSCy Schubert    foreach (parse(<IN>, { filename => $f,
61*e0c4386eSCy Schubert                           warnings => $warnings,
62*e0c4386eSCy Schubert                           verbose => $verbose,
63*e0c4386eSCy Schubert                           debug => $debug })) {
64*e0c4386eSCy Schubert        $_->{value} = $_->{value}||"";
65*e0c4386eSCy Schubert        next if grep { $_ eq 'CONST_STRICT' } @{$_->{conds}};
66*e0c4386eSCy Schubert        printf STDERR "%s> %s%s : %s\n",
67*e0c4386eSCy Schubert            $_->{type},
68*e0c4386eSCy Schubert            $_->{name},
69*e0c4386eSCy Schubert            ($_->{type} eq 'M' && defined $symhacks_file && $f eq $symhacks_file
70*e0c4386eSCy Schubert             ? ' = ' . $_->{value}
71*e0c4386eSCy Schubert             : ''),
72*e0c4386eSCy Schubert            join(', ', @{$_->{conds}})
73*e0c4386eSCy Schubert            if $verbose;
74*e0c4386eSCy Schubert        if ($_->{type} eq 'M'
75*e0c4386eSCy Schubert                && defined $symhacks_file
76*e0c4386eSCy Schubert                && $f eq $symhacks_file
77*e0c4386eSCy Schubert                && $_->{value} =~ /^\w(?:\w|\d)*/) {
78*e0c4386eSCy Schubert            $ordinals->add_alias($f, $_->{value}, $_->{name}, @{$_->{conds}});
79*e0c4386eSCy Schubert        } else {
80*e0c4386eSCy Schubert            next if $_->{returntype} =~ /\b(?:ossl_)inline/;
81*e0c4386eSCy Schubert            my $type = {
82*e0c4386eSCy Schubert                F => 'FUNCTION',
83*e0c4386eSCy Schubert                V => 'VARIABLE',
84*e0c4386eSCy Schubert            } -> {$_->{type}};
85*e0c4386eSCy Schubert            if ($type) {
86*e0c4386eSCy Schubert                $ordinals->add($f, $_->{name}, $type, @{$_->{conds}});
87*e0c4386eSCy Schubert            }
88*e0c4386eSCy Schubert        }
89*e0c4386eSCy Schubert    }
90*e0c4386eSCy Schubert    close IN;
91*e0c4386eSCy Schubert}
92*e0c4386eSCy Schubert
93*e0c4386eSCy Schubert$ordinals->renumber() if $renumber;
94*e0c4386eSCy Schubert
95*e0c4386eSCy Schubertif ($checkexist) {
96*e0c4386eSCy Schubert    my %new_names = map { $_->name() => 1 }
97*e0c4386eSCy Schubert        $ordinals->items(comparator => sub { $_[0] cmp $_[1] },
98*e0c4386eSCy Schubert                         filter => sub { $_->exists() });
99*e0c4386eSCy Schubert    # Eliminate common names
100*e0c4386eSCy Schubert    foreach (keys %orig_names) {
101*e0c4386eSCy Schubert        next unless exists $new_names{$_};
102*e0c4386eSCy Schubert        delete $orig_names{$_};
103*e0c4386eSCy Schubert        delete $new_names{$_};
104*e0c4386eSCy Schubert    }
105*e0c4386eSCy Schubert    if (%orig_names) {
106*e0c4386eSCy Schubert        print "The following symbols do not seem to exist in code:\n";
107*e0c4386eSCy Schubert        foreach (sort keys %orig_names) {
108*e0c4386eSCy Schubert            print "\t$_\n";
109*e0c4386eSCy Schubert        }
110*e0c4386eSCy Schubert    }
111*e0c4386eSCy Schubert    if (%new_names) {
112*e0c4386eSCy Schubert        print "The following existing symbols are not in ordinals file:\n";
113*e0c4386eSCy Schubert        foreach (sort keys %new_names) {
114*e0c4386eSCy Schubert            print "\t$_\n";
115*e0c4386eSCy Schubert        }
116*e0c4386eSCy Schubert    }
117*e0c4386eSCy Schubert} else {
118*e0c4386eSCy Schubert    my $dropped = 0;
119*e0c4386eSCy Schubert    my $unassigned;
120*e0c4386eSCy Schubert    my $filter = sub {
121*e0c4386eSCy Schubert        my $item = shift;
122*e0c4386eSCy Schubert        my $result = $item->number() ne '?' || $item->exists();
123*e0c4386eSCy Schubert        $dropped++ unless $result;
124*e0c4386eSCy Schubert        return $result;
125*e0c4386eSCy Schubert    };
126*e0c4386eSCy Schubert    $ordinals->rewrite(filter => $filter);
127*e0c4386eSCy Schubert    my %stats = $ordinals->stats();
128*e0c4386eSCy Schubert    print STDERR
129*e0c4386eSCy Schubert        "${ordinals_file}: $stats{modified} old symbols have updated info\n"
130*e0c4386eSCy Schubert        if $stats{modified};
131*e0c4386eSCy Schubert    if ($stats{new}) {
132*e0c4386eSCy Schubert        print STDERR "${ordinals_file}: Added $stats{new} new symbols\n";
133*e0c4386eSCy Schubert    } else {
134*e0c4386eSCy Schubert        print STDERR "${ordinals_file}: No new symbols added\n";
135*e0c4386eSCy Schubert    }
136*e0c4386eSCy Schubert    if ($dropped) {
137*e0c4386eSCy Schubert        print STDERR "${ordinals_file}: Dropped $dropped new symbols\n";
138*e0c4386eSCy Schubert    }
139*e0c4386eSCy Schubert    $stats{unassigned} = 0 unless defined $stats{unassigned};
140*e0c4386eSCy Schubert    $unassigned = $stats{unassigned} - $dropped;
141*e0c4386eSCy Schubert    if ($unassigned) {
142*e0c4386eSCy Schubert        my $symbol = $unassigned == 1 ? "symbol" : "symbols";
143*e0c4386eSCy Schubert        my $is = $unassigned == 1 ? "is" : "are";
144*e0c4386eSCy Schubert        print STDERR "${ordinals_file}: $unassigned $symbol $is without ordinal number\n";
145*e0c4386eSCy Schubert    }
146*e0c4386eSCy Schubert}
147