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