]>
git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-hwcaps.c
1 /* Hardware capability support for run-time dynamic loader.
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
26 #include <dl-procinfo.h>
27 #include <dl-hwcaps.h>
29 /* Return an array of useful/necessary hardware capability names. */
30 const struct r_strlenpair
*
31 _dl_important_hwcaps (size_t *sz
, size_t *max_capstrlen
)
33 uint64_t hwcap_mask
= GET_HWCAP_MASK();
34 /* Determine how many important bits are set. */
35 uint64_t masked
= GLRO(dl_hwcap
) & hwcap_mask
;
36 size_t cnt
= GLRO (dl_platform
) != NULL
;
39 struct r_strlenpair
*result
;
40 struct r_strlenpair
*rp
;
43 /* Count the number of bits set in the masked value. */
44 for (n
= 0; (~((1ULL << n
) - 1) & masked
) != 0; ++n
)
45 if ((masked
& (1ULL << n
)) != 0)
48 /* For TLS enabled builds always add 'tls'. */
51 /* Create temporary data structure to generate result table. */
52 struct r_strlenpair temp
[cnt
];
54 for (n
= 0; masked
!= 0; ++n
)
55 if ((masked
& (1ULL << n
)) != 0)
57 temp
[m
].str
= _dl_hwcap_string (n
);
58 temp
[m
].len
= strlen (temp
[m
].str
);
62 if (GLRO (dl_platform
) != NULL
)
64 temp
[m
].str
= GLRO (dl_platform
);
65 temp
[m
].len
= GLRO (dl_platformlen
);
75 /* Determine the total size of all strings together. */
77 total
= temp
[0].len
+ 1;
80 total
= temp
[0].len
+ temp
[cnt
- 1].len
+ 2;
84 for (n
= 1; n
+ 1 < cnt
; ++n
)
85 total
+= temp
[n
].len
+ 1;
87 && (cnt
>= sizeof (size_t) * 8
88 || total
+ (sizeof (*result
) << 3)
89 >= (1UL << (sizeof (size_t) * 8 - cnt
+ 3))))
90 _dl_signal_error (ENOMEM
, NULL
, NULL
,
91 N_("cannot create capability list"));
97 /* The result structure: we use a very compressed way to store the
98 various combinations of capability names. */
100 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
102 _dl_signal_error (ENOMEM
, NULL
, NULL
,
103 N_("cannot create capability list"));
107 result
[0].str
= (char *) (result
+ *sz
);
108 result
[0].len
= temp
[0].len
+ 1;
109 result
[1].str
= (char *) (result
+ *sz
);
111 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
114 *max_capstrlen
= result
[0].len
;
119 /* Fill in the information. This follows the following scheme
120 (indices from TEMP for four strings):
121 entry #0: 0, 1, 2, 3 binary: 1111
125 This allows the representation of all possible combinations of
126 capability names in the string. First generate the strings. */
127 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
129 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
142 /* We always add the last string. */
145 /* Add the strings which have the bit set in N. */
146 for (m
= cnt
- 2; m
> 0; --m
)
147 if ((n
& (1 << m
)) != 0)
150 /* Always add the first string. */
157 /* Now we are ready to install the string pointers and length. */
158 for (n
= 0; n
< (1UL << cnt
); ++n
)
163 size_t mask
= 1 << --n
;
166 for (m
= 1 << cnt
; m
> 0; ++rp
)
167 if ((--m
& mask
) != 0)
168 rp
->len
+= temp
[n
].len
+ 1;
172 /* The first half of the strings all include the first string. */
175 while (n
!= (1UL << (cnt
- 1)))
178 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
180 rp
[0].str
= rp
[-1].str
;
184 /* The second half starts right after the first part of the string of
185 the corresponding entry in the first half. */
188 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
193 /* The maximum string length. */
194 *max_capstrlen
= result
[0].len
;