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