]> git.ipfire.org Git - thirdparty/openssl.git/blame - util/mkdef.pl
Don't complain about documented symbols with find-doc-nits -d -o
[thirdparty/openssl.git] / util / mkdef.pl
CommitLineData
e0a65194 1#! /usr/bin/env perl
8effd8fa 2# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
e0a65194 3#
9059ab42 4# Licensed under the Apache License 2.0 (the "License"). You may not use
e0a65194
RS
5# this file except in compliance with the License. You can obtain a copy
6# in the file LICENSE in the source distribution or at
7# https://www.openssl.org/source/license.html
8
8effd8fa
RL
9# Generate a linker version script suitable for the given platform
10# from a given ordinals file.
d02b48c6 11
8effd8fa
RL
12use strict;
13use warnings;
14
15use Getopt::Long;
8d2214c0
RL
16use FindBin;
17use lib "$FindBin::Bin/perl";
8effd8fa
RL
18
19use OpenSSL::Ordinals;
20
21use lib '.';
22use configdata;
23
9afc2b92
RL
24use File::Spec::Functions;
25use lib catdir($config{sourcedir}, 'Configurations');
26use platform;
27
8effd8fa
RL
28my $name = undef; # internal library/module name
29my $ordinals_file = undef; # the ordinals file to use
97624638 30my $version = undef; # the version to use for the library
8effd8fa
RL
31my $OS = undef; # the operating system family
32my $verbose = 0;
33my $ctest = 0;
34
36d3acb9
RL
35# For VMS, some modules may have case insensitive names
36my $case_insensitive = 0;
37
8effd8fa
RL
38GetOptions('name=s' => \$name,
39 'ordinals=s' => \$ordinals_file,
97624638 40 'version=s' => \$version,
8effd8fa
RL
41 'OS=s' => \$OS,
42 'ctest' => \$ctest,
36d3acb9
RL
43 'verbose' => \$verbose,
44 # For VMS
45 'case-insensitive' => \$case_insensitive)
8effd8fa
RL
46 or die "Error in command line arguments\n";
47
48die "Please supply arguments\n"
49 unless $name && $ordinals_file && $OS;
3fa04f0d 50
822b5e26
VD
51# When building a "variant" shared library, with a custom SONAME, also customize
52# all the symbol versions. This produces a shared object that can coexist
53# without conflict in the same address space as a default build, or an object
54# with a different variant tag.
55#
56# For example, with a target definition that includes:
57#
58# shlib_variant => "-opt",
59#
60# we build the following objects:
61#
62# $ perl -le '
63# for (@ARGV) {
64# if ($l = readlink) {
65# printf "%s -> %s\n", $_, $l
66# } else {
67# print
68# }
69# }' *.so*
70# libcrypto-opt.so.1.1
71# libcrypto.so -> libcrypto-opt.so.1.1
72# libssl-opt.so.1.1
73# libssl.so -> libssl-opt.so.1.1
74#
75# whose SONAMEs and dependencies are:
76#
77# $ for l in *.so; do
78# echo $l
79# readelf -d $l | egrep 'SONAME|NEEDED.*(ssl|crypto)'
80# done
81# libcrypto.so
82# 0x000000000000000e (SONAME) Library soname: [libcrypto-opt.so.1.1]
83# libssl.so
84# 0x0000000000000001 (NEEDED) Shared library: [libcrypto-opt.so.1.1]
85# 0x000000000000000e (SONAME) Library soname: [libssl-opt.so.1.1]
86#
87# We case-fold the variant tag to upper case and replace all non-alnum
88# characters with "_". This yields the following symbol versions:
89#
90# $ nm libcrypto.so | grep -w A
91# 0000000000000000 A OPENSSL_OPT_1_1_0
92# 0000000000000000 A OPENSSL_OPT_1_1_0a
93# 0000000000000000 A OPENSSL_OPT_1_1_0c
94# 0000000000000000 A OPENSSL_OPT_1_1_0d
95# 0000000000000000 A OPENSSL_OPT_1_1_0f
96# 0000000000000000 A OPENSSL_OPT_1_1_0g
97# $ nm libssl.so | grep -w A
98# 0000000000000000 A OPENSSL_OPT_1_1_0
99# 0000000000000000 A OPENSSL_OPT_1_1_0d
100#
8effd8fa
RL
101(my $SO_VARIANT = uc($target{"shlib_variant"} // '')) =~ s/\W/_/g;
102
9afc2b92 103my $libname = platform->sharedname($name);
8effd8fa
RL
104
105my %OS_data = (
106 solaris => { writer => \&writer_linux,
107 sort => sorter_linux(),
211da00b 108 platforms => { UNIX => 1 } },
8effd8fa 109 linux => 'solaris', # alias
a5fcce6b 110 "bsd-gcc" => 'solaris', # alias
8effd8fa
RL
111 aix => { writer => \&writer_aix,
112 sort => sorter_unix(),
211da00b 113 platforms => { UNIX => 1 } },
8effd8fa
RL
114 VMS => { writer => \&writer_VMS,
115 sort => OpenSSL::Ordinals::by_number(),
211da00b 116 platforms => { VMS => 1 } },
8effd8fa
RL
117 vms => 'VMS', # alias
118 WINDOWS => { writer => \&writer_windows,
119 sort => OpenSSL::Ordinals::by_name(),
120 platforms => { WIN32 => 1,
211da00b 121 _WIN32 => 1 } },
8effd8fa
RL
122 windows => 'WINDOWS', # alias
123 WIN32 => 'WINDOWS', # alias
124 win32 => 'WIN32', # alias
125 32 => 'WIN32', # alias
126 NT => 'WIN32', # alias
127 nt => 'WIN32', # alias
128 mingw => 'WINDOWS', # alias
129 );
130
131do {
132 die "Unknown operating system family $OS\n"
133 unless exists $OS_data{$OS};
134 $OS = $OS_data{$OS};
135} while(ref($OS) eq '');
136
137my %disabled_uc = map { my $x = uc $_; $x =~ s|-|_|g; $x => 1 } keys %disabled;
138
139my %ordinal_opts = ();
140$ordinal_opts{sort} = $OS->{sort} if $OS->{sort};
141$ordinal_opts{filter} =
142 sub {
143 my $item = shift;
144 return
145 $item->exists()
146 && platform_filter($item)
147 && feature_filter($item);
148 };
149my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file);
150
151my $writer = $OS->{writer};
152$writer = \&writer_ctest if $ctest;
153
154$writer->($ordinals->items(%ordinal_opts));
155
156exit 0;
157
158sub platform_filter {
159 my $item = shift;
160 my %platforms = ( $item->platforms() );
161
162 # True if no platforms are defined
163 return 1 if scalar keys %platforms == 0;
164
165 # For any item platform tag, return the equivalence with the
166 # current platform settings if it exists there, return 0 otherwise
167 # if the item platform tag is true
168 for (keys %platforms) {
169 if (exists $OS->{platforms}->{$_}) {
170 return $platforms{$_} == $OS->{platforms}->{$_};
171 }
172 if ($platforms{$_}) {
173 return 0;
174 }
175 }
948d0125 176
8effd8fa
RL
177 # Found no match? Then it's a go
178 return 1;
948d0125
RL
179}
180
8effd8fa
RL
181sub feature_filter {
182 my $item = shift;
8effd8fa 183 my @features = ( $item->features() );
d02b48c6 184
8effd8fa 185 # True if no features are defined
ab1e5495 186 return 1 if scalar @features == 0;
62dc5aad 187
ab1e5495 188 my $verdict = ! grep { $disabled_uc{$_} } @features;
62dc5aad 189
a6a4d0ac 190 if ($disabled{deprecated}) {
8effd8fa 191 foreach (@features) {
a6a4d0ac
RL
192 next unless /^DEPRECATEDIN_(\d+)_(\d+)(?:_(\d+))?$/;
193 my $symdep = $1 * 10000 + $2 * 100 + ($3 // 0);
194 $verdict = 0 if $config{api} >= $symdep;
195 print STDERR "DEBUG: \$symdep = $symdep, \$verdict = $verdict\n"
196 if $1 == 0;
8effd8fa
RL
197 }
198 }
d02b48c6 199
8effd8fa 200 return $verdict;
948d0125
RL
201}
202
8effd8fa
RL
203sub sorter_unix {
204 my $by_name = OpenSSL::Ordinals::by_name();
205 my %weight = (
206 'FUNCTION' => 1,
207 'VARIABLE' => 2
208 );
948d0125 209
8effd8fa
RL
210 return sub {
211 my $item1 = shift;
212 my $item2 = shift;
451e60e9 213
8effd8fa
RL
214 my $verdict = $weight{$item1->type()} <=> $weight{$item2->type()};
215 if ($verdict == 0) {
216 $verdict = $by_name->($item1, $item2);
217 }
218 return $verdict;
219 };
47339f61 220}
d02b48c6 221
8effd8fa
RL
222sub sorter_linux {
223 my $by_version = OpenSSL::Ordinals::by_version();
224 my $by_unix = sorter_unix();
62dc5aad 225
8effd8fa
RL
226 return sub {
227 my $item1 = shift;
228 my $item2 = shift;
62dc5aad 229
8effd8fa
RL
230 my $verdict = $by_version->($item1, $item2);
231 if ($verdict == 0) {
232 $verdict = $by_unix->($item1, $item2);
233 }
234 return $verdict;
235 };
62dc5aad
RL
236}
237
8effd8fa
RL
238sub writer_linux {
239 my $thisversion = '';
97624638
RL
240 my $currversion_s = '';
241 my $prevversion_s = '';
242 my $indent = 0;
8effd8fa
RL
243
244 for (@_) {
245 if ($thisversion && $_->version() ne $thisversion) {
97624638
RL
246 die "$ordinals_file: It doesn't make sense to have both versioned ",
247 "and unversioned symbols"
248 if $thisversion eq '*';
8effd8fa 249 print <<"_____";
97624638 250}${prevversion_s};
8effd8fa 251_____
97624638 252 $prevversion_s = " OPENSSL${SO_VARIANT}_$thisversion";
8effd8fa
RL
253 $thisversion = ''; # Trigger start of next section
254 }
255 unless ($thisversion) {
97624638 256 $indent = 0;
8effd8fa 257 $thisversion = $_->version();
97624638
RL
258 $currversion_s = '';
259 $currversion_s = "OPENSSL${SO_VARIANT}_$thisversion "
260 if $thisversion ne '*';
8effd8fa 261 print <<"_____";
97624638 262${currversion_s}{
8effd8fa
RL
263 global:
264_____
265 }
266 print ' ', $_->name(), ";\n";
267 }
62dc5aad 268
8effd8fa
RL
269 print <<"_____";
270 local: *;
97624638 271}${prevversion_s};
8effd8fa 272_____
12aefe78
DSH
273}
274
8effd8fa
RL
275sub writer_aix {
276 for (@_) {
277 print $_->name(),"\n";
278 }
0b352c58
RL
279}
280
8effd8fa
RL
281sub writer_windows {
282 print <<"_____";
d02b48c6 283;
8effd8fa 284; Definition file for the DLL version of the $libname library from OpenSSL
d02b48c6
RE
285;
286
8effd8fa 287LIBRARY $libname
d02b48c6 288
8effd8fa
RL
289EXPORTS
290_____
291 for (@_) {
292 print " ",$_->name(),"\n";
293 }
294}
d02b48c6 295
36d3acb9
RL
296sub collect_VMS_mixedcase {
297 return [ 'SPARE', 'SPARE' ] unless @_;
298
299 my $s = shift;
300 my $s_uc = uc($s);
301 my $type = shift;
302
303 return [ "$s=$type", 'SPARE' ] if $s_uc eq $s;
304 return [ "$s_uc/$s=$type", "$s=$type" ];
305}
306
307sub collect_VMS_uppercase {
308 return [ 'SPARE' ] unless @_;
309
310 my $s = shift;
311 my $s_uc = uc($s);
312 my $type = shift;
313
314 return [ "$s_uc=$type" ];
315}
316
8effd8fa
RL
317sub writer_VMS {
318 my @slot_collection = ();
36d3acb9
RL
319 my $collector =
320 $case_insensitive ? \&collect_VMS_uppercase : \&collect_VMS_mixedcase;
8effd8fa
RL
321
322 my $last_num = 0;
323 foreach (@_) {
e4f2d539
RL
324 my $this_num = $_->number();
325 $this_num = $last_num + 1 if $this_num =~ m|^\?|;
326
327 while (++$last_num < $this_num) {
36d3acb9 328 push @slot_collection, $collector->(); # Just occupy a slot
8effd8fa
RL
329 }
330 my $type = {
331 FUNCTION => 'PROCEDURE',
332 VARIABLE => 'DATA'
333 } -> {$_->type()};
36d3acb9 334 push @slot_collection, $collector->($_->name(), $type);
8effd8fa 335 }
d02b48c6 336
97624638
RL
337 print <<"_____" if defined $version;
338IDENTIFICATION=$version
339_____
36d3acb9 340 print <<"_____" unless $case_insensitive;
8effd8fa 341CASE_SENSITIVE=YES
36d3acb9
RL
342_____
343 print <<"_____";
8effd8fa
RL
344SYMBOL_VECTOR=(-
345_____
346 # It's uncertain how long aggregated lines the linker can handle,
347 # but it has been observed that at least 1024 characters is ok.
348 # Either way, this means that we need to keep track of the total
349 # line length of each "SYMBOL_VECTOR" statement. Fortunately, we
350 # can have more than one of those...
351 my $symvtextcount = 16; # The length of "SYMBOL_VECTOR=("
352 while (@slot_collection) {
36d3acb9
RL
353 my $set = shift @slot_collection;
354 my $settextlength = 0;
355 foreach (@$set) {
356 $settextlength +=
357 + 3 # two space indentation and comma
358 + length($_)
359 + 1 # postdent
360 ;
361 }
362 $settextlength--; # only one space indentation on the first one
8effd8fa
RL
363 my $firstcomma = ',';
364
36d3acb9 365 if ($symvtextcount + $settextlength > 1024) {
8effd8fa
RL
366 print <<"_____";
367)
368SYMBOL_VECTOR=(-
369_____
370 $symvtextcount = 16; # The length of "SYMBOL_VECTOR=("
a388633d 371 }
8effd8fa
RL
372 if ($symvtextcount == 16) {
373 $firstcomma = '';
374 }
36d3acb9
RL
375
376 my $indent = ' '.$firstcomma;
377 foreach (@$set) {
378 print <<"_____";
379$indent$_ -
8effd8fa 380_____
36d3acb9
RL
381 $symvtextcount += length($indent) + length($_) + 1;
382 $indent = ' ,';
383 }
8effd8fa
RL
384 }
385 print <<"_____";
386)
387_____
388
97624638 389 if (defined $version) {
d1c87578
RL
390 $version =~ /^(\d+)\.(\d+)\.(\d+)/;
391 my $libvmajor = $1;
392 my $libvminor = $2 * 100 + $3;
97624638 393 print <<"_____";
72818ef0 394GSMATCH=LEQUAL,$libvmajor,$libvminor
8effd8fa 395_____
97624638 396 }
e863d920
MC
397}
398
8effd8fa
RL
399sub writer_ctest {
400 print <<'_____';
401/*
402 * Test file to check all DEF file symbols are present by trying
403 * to link to all of them. This is *not* intended to be run!
404 */
e863d920 405
8effd8fa 406int main()
e863d920 407{
8effd8fa 408_____
e863d920 409
e4f2d539 410 my $last_num = 0;
8effd8fa 411 for (@_) {
e4f2d539
RL
412 my $this_num = $_->number();
413 $this_num = $last_num + 1 if $this_num =~ m|^\?|;
414
8effd8fa 415 if ($_->type() eq 'VARIABLE') {
e4f2d539
RL
416 print "\textern int ", $_->name(), '; /* type unknown */ /* ',
417 $this_num, ' ', $_->version(), " */\n";
8effd8fa 418 } else {
e4f2d539
RL
419 print "\textern int ", $_->name(), '(); /* type unknown */ /* ',
420 $this_num, ' ', $_->version(), " */\n";
8effd8fa 421 }
e4f2d539
RL
422
423 $last_num = $this_num;
8effd8fa
RL
424 }
425 print <<'_____';
e863d920 426}
8effd8fa 427_____
7a556fb6 428}