1 # Combine version map fragments into version scripts for our shared objects.
2 # Copyright (C) 1998-2024 Free Software Foundation, Inc.
4 # This script expects the following variables to be defined:
5 # defsfile name of Versions.def file
6 # buildroot name of build directory with trailing slash
7 # move_if_change move-if-change command
9 # Read definitions for the versions.
14 while (getline < defsfile
) {
15 if (/^
[a
-zA
-Z0
-9_.
]+ \
{/) {
18 while (getline < defsfile
&& !
/^
}/) {
20 renamed
[curlib
"::" $
1] = $
3;
23 versions
[curlib
"::" $
1] =
1;
29 tmpfile = buildroot
"Versions.tmp";
31 sort =
"sort -t. -k 1,1 -k 2n,2n -k 3 > " tmpfile
;
34 # GNU awk does not implement the ord and chr functions.
35 # <https://www.gnu.org/software/gawk/manual/html_node/Ordinal-Functions.html>
36 # says that they are "written very nicely", using code similar to what
39 return sprintf("%c", c
)
43 for (c =
1; c
< 127; c
++) {
44 ord_table
[chr
(c
)] = c
;
52 printf("Invalid character reference: '%c'\n", c
) > "/dev/stderr";
57 # Remove comment lines.
62 # This matches the beginning of the version information for a new library.
66 printf("no versions defined for %s\n", $
1) > "/dev/stderr";
72 # This matches the beginning of a new version for the current library.
74 if (renamed
[actlib
"::" $
1])
75 actver = renamed
[actlib
"::" $
1];
76 else if (!versions
[actlib
"::" $
1] && $
1 != "GLIBC_PRIVATE") {
77 printf("version %s not defined for %s\n", $
1, actlib
) > "/dev/stderr";
85 # This matches lines with names to be added to the current version in the
86 # current library. This is the only place where we print something to
87 # the intermediate file.
90 # Ensure GLIBC_ versions come always first
91 sub(/^GLIBC_
/," GLIBC_",sortver
)
92 printf("%s %s %s\n", actlib
, sortver
, $
0) | sort
;
95 # Some targets do not set the ABI baseline for libdl. As a result,
96 # symbols originally in libdl need to be moved under historic symbol
97 # versions, without altering the baseline version for libc itself.
98 /^
*!libc_pre_versions
/ {
99 libc_pre_versions_active =
1;
102 function libc_pre_versions
() {
103 # No local: * here, so that we do not have to update this script
104 # if symbols are moved into libc. The abilist files and the other
105 # targets (with a real GLIBC_2.0 baseline) provide testing
116 function closeversion
(name
, oldname
) {
117 printf(" local:\n *;\n") > outfile
;
118 # This version inherits from the last one only if they
119 # have the same nonnumeric prefix, i.e. GLIBC_x.y and GLIBC_x.z
120 # or FOO_x and FOO_y but not GLIBC_x and FOO_y.
122 sub(/[0-9.
]+/,".+",pfx
);
123 if (oldname ==
"" || name !~ pfx
) print "};" > outfile
;
124 else printf("} %s;\n", oldname
) > outfile
;
127 function close_and_move
(name
, real_name
) {
129 system(move_if_change
" " name
" " real_name
" >&2");
132 # ELF hash, for use with symbol versions.
133 function elf_hash
(s
, i
, acc
) {
135 for (i =
1; i
<=
length(s
); ++i
) {
136 acc = and
(lshift
(acc
, 4) + ord
(substr(s
, i
, 1)), 0xffffffff);
137 top = and
(acc
, 0xf0000000);
138 acc = and
(xor
(acc
, rshift
(top
, 24)), compl
(top
));
143 # Now print the accumulated information.
148 system("rm -f " tmpfile
);
154 real_first_ver_header = buildroot
"first-versions.h"
155 first_ver_header = real_first_ver_header
"T"
156 printf("#ifndef _FIRST_VERSIONS_H\n") > first_ver_header
;
157 printf("#define _FIRST_VERSIONS_H\n") > first_ver_header
;
158 real_ldbl_compat_header = buildroot
"ldbl-compat-choose.h"
159 ldbl_compat_header = real_ldbl_compat_header
"T"
160 printf("#ifndef _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header
;
161 printf("#define _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header
;
162 printf("#ifndef LONG_DOUBLE_COMPAT\n") > ldbl_compat_header
;
163 printf("# error LONG_DOUBLE_COMPAT not defined\n") > ldbl_compat_header
;
164 printf("#endif\n") > ldbl_compat_header
;
165 printf("version-maps =");
166 while (getline < tmpfile
) {
169 closeversion
(oldver
, veryoldver
);
171 close_and_move
(outfile
, real_outfile
);
174 real_outfile = buildroot oldlib
".map";
175 outfile = real_outfile
"T";
176 if ($
1 ==
"libc" && libc_pre_versions_active
) {
177 veryoldver = libc_pre_versions
();
181 printf(" %s.map", oldlib
);
185 closeversion
(oldver
, veryoldver
);
189 # Skip the placeholder symbol used only for empty version map.
190 if ($
3 ==
"__placeholder_only_for_empty_version_map;") {
191 printf("%s {\n", $
2) > outfile
;
194 printf("%s {\n global:\n", $
2) > outfile
;
196 printf(" ") > outfile
;
197 for (n =
3; n
<=
NF; ++n
) {
198 printf(" %s", $n
) > outfile
;
201 first_ver_macro =
"FIRST_VERSION_" oldlib
"_" sym
;
202 if (!
(first_ver_macro in first_ver_seen
) \
203 && oldver ~
"^GLIBC_[0-9]" \
204 && sym ~
"^[A-Za-z0-9_]*$") {
206 printf("#define %s_STRING \"%s\"\n", first_ver_macro
, ver_val
) > first_ver_header
;
207 printf("#define %s_HASH 0x%x\n", first_ver_macro
, elf_hash
(ver_val
)) > first_ver_header
;
208 gsub("\\.", "_", ver_val
);
209 printf("#define %s %s\n", first_ver_macro
, ver_val
) > first_ver_header
;
210 first_ver_seen
[first_ver_macro
] =
1;
211 if (oldlib ==
"libc" || oldlib ==
"libm") {
212 printf("#if LONG_DOUBLE_COMPAT (%s, %s)\n",
213 oldlib
, ver_val
) > ldbl_compat_header
;
214 printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) a\n",
215 oldlib
, sym
) > ldbl_compat_header
;
216 printf("#else\n") > ldbl_compat_header
;
217 printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) b\n",
218 oldlib
, sym
) > ldbl_compat_header
;
219 printf("#endif\n") > ldbl_compat_header
;
223 printf("\n") > outfile
;
226 printf("#endif /* first-versions.h */\n") > first_ver_header
;
227 printf("#endif /* ldbl-compat-choose.h */\n") > ldbl_compat_header
;
228 closeversion
(oldver
, veryoldver
);
229 close_and_move
(outfile
, real_outfile
);
230 close_and_move
(first_ver_header
, real_first_ver_header
);
231 close_and_move
(ldbl_compat_header
, real_ldbl_compat_header
);
232 #system("rm -f " tmpfile);