Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer
11 : : * in this position and unchanged.
12 : : * 2. Redistributions in binary form must reproduce the above copyright
13 : : * notice, this list of conditions and the following disclaimer in the
14 : : * documentation and/or other materials provided with the distribution.
15 : : *
16 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : : */
27 : :
28 : : #ifdef HAVE_CONFIG_H
29 : : #include "pkg_config.h"
30 : : #endif
31 : :
32 : : #ifdef HAVE_SYS_ENDIAN_H
33 : : #include <sys/endian.h>
34 : : #elif HAVE_ENDIAN_H
35 : : #include <endian.h>
36 : : #elif HAVE_MACHINE_ENDIAN_H
37 : : #include <machine/endian.h>
38 : : #endif
39 : : #include <sys/types.h>
40 : : #if defined(HAVE_SYS_ELF_COMMON_H) && !defined(__DragonFly__)
41 : : #include <sys/elf_common.h>
42 : : #endif
43 : : #include <sys/stat.h>
44 : :
45 : : #include <assert.h>
46 : : #include <ctype.h>
47 : : #include <dlfcn.h>
48 : : #include <fcntl.h>
49 : : #include <gelf.h>
50 : : #include <libgen.h>
51 : : #if defined(HAVE_LINK_H) && !defined(__DragonFly__) && defined(HAVE_LIBELF)
52 : : #include <link.h>
53 : : #endif
54 : : #include <paths.h>
55 : : #include <stdbool.h>
56 : : #include <string.h>
57 : : #include <unistd.h>
58 : : #ifdef HAVE_LIBELF
59 : : #include <libelf.h>
60 : : #endif
61 : :
62 : : #include <bsd_compat.h>
63 : :
64 : : #include "pkg.h"
65 : : #include "private/pkg.h"
66 : : #include "private/event.h"
67 : : #include "private/elf_tables.h"
68 : : #include "private/ldconfig.h"
69 : :
70 : : #ifndef NT_ABI_TAG
71 : : #define NT_ABI_TAG 1
72 : : #endif
73 : :
74 : : #define _PATH_UNAME "/usr/bin/uname"
75 : :
76 : : /* FFR: when we support installing a 32bit package on a 64bit host */
77 : : #define _PATH_ELF32_HINTS "/var/run/ld-elf32.so.hints"
78 : :
79 : : #ifndef roundup2
80 : : #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
81 : : #endif
82 : :
83 : : static const char * elf_corres_to_string(const struct _elf_corres* m, int e);
84 : : static int elf_string_to_corres(const struct _elf_corres* m, const char *s);
85 : :
86 : : static int
87 : 64 : filter_system_shlibs(const char *name, char *path, size_t pathlen)
88 : : {
89 : : const char *shlib_path;
90 : :
91 : 64 : shlib_path = shlib_list_find_by_name(name);
92 [ + - ]: 64 : if (shlib_path == NULL) {
93 : : /* dynamic linker could not resolve */
94 : 0 : return (EPKG_FATAL);
95 : : }
96 : :
97 [ - + ]: 64 : if (pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) {
98 [ # # ]: 0 : if (strstr(shlib_path, "/lib32/") != NULL)
99 : 0 : return (EPKG_END);
100 : 0 : } else {
101 : : /* match /lib, /lib32, /usr/lib and /usr/lib32 */
102 [ + + - + ]: 64 : if (strncmp(shlib_path, "/lib", 4) == 0 ||
103 : 16 : strncmp(shlib_path, "/usr/lib", 8) == 0)
104 : 48 : return (EPKG_END); /* ignore libs from base */
105 : : }
106 : :
107 [ + - ]: 16 : if (path != NULL)
108 : 0 : strncpy(path, shlib_path, pathlen);
109 : :
110 : 16 : return (EPKG_OK);
111 : 64 : }
112 : :
113 : : /* ARGSUSED */
114 : : static int
115 : 64 : add_shlibs_to_pkg(struct pkg *pkg, const char *fpath, const char *name,
116 : : bool is_shlib)
117 : : {
118 : 64 : struct pkg_file *file = NULL;
119 : : const char *filepath;
120 : :
121 [ + - + ]: 64 : switch(filter_system_shlibs(name, NULL, 0)) {
122 : : case EPKG_OK: /* A non-system library */
123 : 16 : pkg_addshlib_required(pkg, name);
124 : 16 : return (EPKG_OK);
125 : : case EPKG_END: /* A system library */
126 : 48 : return (EPKG_OK);
127 : : default:
128 : : /* Ignore link resolution errors if we're analysing a
129 : : shared library. */
130 [ # # ]: 0 : if (is_shlib)
131 : 0 : return (EPKG_OK);
132 : :
133 [ # # ]: 0 : while (pkg_files(pkg, &file) == EPKG_OK) {
134 : 0 : filepath = file->path;
135 [ # # # # ]: 0 : if (strlen(filepath) >= strlen(name) &&
136 : 0 : strcmp(&filepath[strlen(filepath) - strlen(name)], name) == 0) {
137 : 0 : pkg_addshlib_required(pkg, name);
138 : 0 : return (EPKG_OK);
139 : : }
140 : : }
141 : :
142 : 0 : pkg_emit_notice("(%s-%s) %s - required shared library %s not "
143 : 0 : "found", pkg->name, pkg->version, fpath, name);
144 : :
145 : 0 : return (EPKG_FATAL);
146 : : }
147 : 64 : }
148 : :
149 : : static bool
150 : 48 : shlib_valid_abi(const char *fpath, GElf_Ehdr *hdr, const char *abi)
151 : : {
152 : : int semicolon;
153 : : const char *p, *t;
154 : : char arch[64], wordsize[64];
155 : : int wclass;
156 : : const char *shlib_arch;
157 : :
158 : : /*
159 : : * ABI string is in format:
160 : : * <osname>:<osversion>:<arch>:<wordsize>[.other]
161 : : * We need here arch and wordsize only
162 : : */
163 : 48 : arch[0] = '\0';
164 : 48 : wordsize[0] = '\0';
165 : 48 : p = abi;
166 [ - + + - ]: 96 : for(semicolon = 0; semicolon < 3 && p != NULL; semicolon ++, p ++) {
167 : 96 : p = strchr(p, ':');
168 [ - + ]: 96 : if (p != NULL) {
169 [ + + - ]: 96 : switch(semicolon) {
170 : : case 1:
171 : : /* We have arch here */
172 : 48 : t = strchr(p + 1, ':');
173 : : /* Abi line is likely invalid */
174 [ - + ]: 48 : if (t == NULL)
175 : 48 : return (true);
176 [ # # ]: 0 : strlcpy(arch, p + 1, MIN((long)sizeof(arch), t - p));
177 : 0 : break;
178 : : case 2:
179 : 0 : t = strchr(p + 1, ':');
180 [ # # ]: 0 : if (t == NULL)
181 : 0 : strlcpy(wordsize, p + 1, sizeof(wordsize));
182 : : else
183 [ # # ]: 0 : strlcpy(wordsize, p + 1, MIN((long)sizeof(wordsize), t - p));
184 : 0 : break;
185 : : }
186 : 48 : }
187 : 48 : }
188 : : /* Invalid ABI line */
189 [ # # # # ]: 0 : if (arch[0] == '\0' || wordsize[0] == '\0')
190 : 0 : return (true);
191 : :
192 : 0 : shlib_arch = elf_corres_to_string(mach_corres, (int)hdr->e_machine);
193 [ # # ]: 0 : if (shlib_arch == NULL)
194 : 0 : return (true);
195 : :
196 : 0 : wclass = elf_string_to_corres(wordsize_corres, wordsize);
197 [ # # ]: 0 : if (wclass == -1)
198 : 0 : return (true);
199 : :
200 : :
201 : : /*
202 : : * Compare wordsize first as the arch for amd64/i386 is an abmiguous
203 : : * 'x86'
204 : : */
205 [ # # ]: 0 : if ((int)hdr->e_ident[EI_CLASS] != wclass) {
206 : 0 : pkg_debug(1, "not valid elf class for shlib: %s: %s",
207 : 0 : elf_corres_to_string(wordsize_corres,
208 : 0 : (int)hdr->e_ident[EI_CLASS]),
209 : 0 : fpath);
210 : 0 : return (false);
211 : : }
212 : :
213 [ # # ]: 0 : if (strcmp(shlib_arch, arch) != 0) {
214 : 0 : pkg_debug(1, "not valid abi for shlib: %s: %s", shlib_arch,
215 : 0 : fpath);
216 : 0 : return (false);
217 : : }
218 : :
219 : 0 : return (true);
220 : 48 : }
221 : :
222 : : #ifdef __FreeBSD__
223 : : static bool
224 : 0 : is_old_freebsd_armheader(const GElf_Ehdr *e)
225 : : {
226 : : GElf_Word eabi;
227 : :
228 : : /*
229 : : * Old FreeBSD arm EABI binaries were created with zeroes in [EI_OSABI].
230 : : * Attempt to identify them by the little bit of valid info that is
231 : : * present: 32-bit ARM with EABI version 4 or 5 in the flags. OABI
232 : : * binaries (prior to freebsd 10) have the correct [EI_OSABI] value.
233 : : */
234 [ # # # # ]: 0 : if (e->e_machine == EM_ARM && e->e_ident[EI_CLASS] == ELFCLASS32) {
235 : 0 : eabi = e->e_flags & 0xff000000;
236 [ # # # # ]: 0 : if (eabi == 0x04000000 || eabi == 0x05000000)
237 : 0 : return (true);
238 : 0 : }
239 : 0 : return (false);
240 : 0 : }
241 : : #endif
242 : :
243 : : #ifndef HAVE_ELF_NOTE
244 : : typedef Elf32_Nhdr Elf_Note;
245 : : #endif
246 : :
247 : : static int
248 : 969 : analyse_elf(struct pkg *pkg, const char *fpath)
249 : : {
250 : 969 : Elf *e = NULL;
251 : : GElf_Ehdr elfhdr;
252 : 969 : Elf_Scn *scn = NULL;
253 : 969 : Elf_Scn *note = NULL;
254 : 969 : Elf_Scn *dynamic = NULL;
255 : : GElf_Shdr shdr;
256 : : Elf_Data *data;
257 : : GElf_Dyn *dyn, dyn_mem;
258 : : struct stat sb;
259 : 969 : int ret = EPKG_OK;
260 : :
261 : 969 : size_t numdyn = 0;
262 : 969 : size_t sh_link = 0;
263 : : size_t dynidx;
264 : : const char *myarch;
265 : : const char *shlib;
266 : 969 : char *rpath = NULL;
267 : :
268 : 969 : bool is_shlib = false;
269 : :
270 : 969 : myarch = pkg_object_string(pkg_config_get("ABI"));
271 : :
272 : : int fd;
273 : :
274 : 969 : pkg_debug(1, "analysing elf %s", fpath);
275 [ + - ]: 969 : if (lstat(fpath, &sb) != 0)
276 : 0 : pkg_emit_errno("fstat() failed for", fpath);
277 : : /* ignore empty files and non regular files */
278 [ + + + + ]: 969 : if (sb.st_size == 0 || !S_ISREG(sb.st_mode))
279 : 689 : return (EPKG_END); /* Empty file or sym-link: no results */
280 : :
281 [ - + ]: 280 : if ((fd = open(fpath, O_RDONLY, 0)) < 0) {
282 : 0 : return (EPKG_FATAL);
283 : : }
284 : :
285 [ - + ]: 280 : if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
286 : 0 : ret = EPKG_FATAL;
287 : 0 : pkg_debug(1, "elf_begin() for %s failed: %s", fpath,
288 : 0 : elf_errmsg(-1));
289 : 0 : goto cleanup;
290 : : }
291 : :
292 [ + + ]: 280 : if (elf_kind(e) != ELF_K_ELF) {
293 : : /* Not an elf file: no results */
294 : 232 : ret = EPKG_END;
295 : 232 : pkg_debug(1, "not an elf");
296 : 232 : goto cleanup;
297 : : }
298 : :
299 [ + - ]: 48 : if (ctx.developer_mode)
300 : 0 : pkg->flags |= PKG_CONTAINS_ELF_OBJECTS;
301 : :
302 [ + - ]: 48 : if (gelf_getehdr(e, &elfhdr) == NULL) {
303 : 0 : ret = EPKG_FATAL;
304 : 0 : pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
305 : 0 : goto cleanup;
306 : : }
307 : :
308 [ - + # # : 48 : if (elfhdr.e_type != ET_DYN && elfhdr.e_type != ET_EXEC &&
# # ]
309 : 0 : elfhdr.e_type != ET_REL) {
310 : 0 : pkg_debug(1, "not an elf");
311 : 0 : ret = EPKG_END;
312 : 0 : goto cleanup;
313 : : }
314 : :
315 : : /* Elf file has sections header */
316 [ - + ]: 864 : while ((scn = elf_nextscn(e, scn)) != NULL) {
317 [ + - ]: 864 : if (gelf_getshdr(scn, &shdr) != &shdr) {
318 : 0 : ret = EPKG_FATAL;
319 : 0 : pkg_emit_error("getshdr() for %s failed: %s", fpath,
320 : 0 : elf_errmsg(-1));
321 : 0 : goto cleanup;
322 : : }
323 [ + + + ]: 864 : switch (shdr.sh_type) {
324 : : case SHT_NOTE:
325 [ + - ]: 48 : if ((data = elf_getdata(scn, NULL)) == NULL) {
326 : 0 : ret = EPKG_END; /* Some error occurred, ignore this file */
327 : 0 : goto cleanup;
328 : : }
329 [ + - ]: 48 : else if (data->d_buf != NULL) {
330 : 48 : Elf_Note *en = (Elf_Note *)data->d_buf;
331 [ - + ]: 48 : if (en->n_type == NT_ABI_TAG)
332 : 48 : note = scn;
333 : 48 : }
334 : 48 : break;
335 : : case SHT_DYNAMIC:
336 : 48 : dynamic = scn;
337 : 48 : sh_link = shdr.sh_link;
338 [ + - ]: 48 : if (shdr.sh_entsize == 0) {
339 : 0 : ret = EPKG_END;
340 : 0 : goto cleanup;
341 : : }
342 : 48 : numdyn = shdr.sh_size / shdr.sh_entsize;
343 : 48 : break;
344 : : }
345 : :
346 [ + - + + ]: 864 : if (note != NULL && dynamic != NULL)
347 : 48 : break;
348 : : }
349 : :
350 : : /*
351 : : * note == NULL usually means a shared object for use with dlopen(3)
352 : : * dynamic == NULL means not a dynamically linked elf
353 : : */
354 [ + - ]: 48 : if (dynamic == NULL) {
355 : 0 : ret = EPKG_END;
356 : 0 : goto cleanup; /* not a dynamically linked elf: no results */
357 : : }
358 : :
359 [ + - ]: 48 : if (!shlib_valid_abi(fpath, &elfhdr, myarch)) {
360 : 0 : ret = EPKG_END;
361 : 0 : goto cleanup; /* Invalid ABI */
362 : : }
363 : :
364 : : #ifdef __FreeBSD__
365 [ - + # # ]: 48 : if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD &&
366 : 0 : !is_old_freebsd_armheader(&elfhdr)) {
367 : 0 : ret = EPKG_END;
368 : 0 : goto cleanup;
369 : : }
370 : : #endif
371 : :
372 [ + - ]: 48 : if ((data = elf_getdata(dynamic, NULL)) == NULL) {
373 : 0 : ret = EPKG_END; /* Some error occurred, ignore this file */
374 : 0 : goto cleanup;
375 : : }
376 : :
377 : : /* First, scan through the data from the .dynamic section to
378 : : find any RPATH or RUNPATH settings. These are colon
379 : : separated paths to prepend to the ld.so search paths from
380 : : the ELF hints file. These always seem to come right after
381 : : the NEEDED shared library entries.
382 : :
383 : : NEEDED entries should resolve to a filename for installed
384 : : executables, but need not resolve for installed shared
385 : : libraries -- additional info from the apps that link
386 : : against them would be required. Shared libraries are
387 : : distinguished by a DT_SONAME tag */
388 : :
389 : 48 : rpath_list_init();
390 [ + + ]: 1216 : for (dynidx = 0; dynidx < numdyn; dynidx++) {
391 [ + - ]: 1168 : if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
392 : 0 : ret = EPKG_FATAL;
393 : 0 : pkg_emit_error("getdyn() failed for %s: %s", fpath,
394 : 0 : elf_errmsg(-1));
395 : 0 : goto cleanup;
396 : : }
397 : :
398 [ + + ]: 1168 : if (dyn->d_tag == DT_SONAME) {
399 : 32 : is_shlib = true;
400 : :
401 : : /* The file being scanned is a shared library
402 : : *provided* by the package. Record this if
403 : : appropriate */
404 : 32 : shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);
405 [ + - - + ]: 32 : if (shlib != NULL && *shlib != '\0')
406 : 32 : pkg_addshlib_provided(pkg, shlib);
407 : 32 : }
408 : :
409 [ + - + + ]: 1168 : if ((dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) &&
410 : 1168 : rpath == NULL)
411 : 16 : rpath = elf_strptr(e, sh_link, dyn->d_un.d_val);
412 : 1168 : }
413 [ + + ]: 48 : if (rpath != NULL) {
414 : 16 : char *p = xstrdup(fpath);
415 : 16 : shlib_list_from_rpath(rpath, get_dirname(p));
416 : 16 : free(p);
417 : 16 : }
418 : :
419 : : /* Now find all of the NEEDED shared libraries. */
420 : :
421 [ + + ]: 1216 : for (dynidx = 0; dynidx < numdyn; dynidx++) {
422 [ - + ]: 1168 : if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
423 : 0 : ret = EPKG_FATAL;
424 : 0 : pkg_emit_error("getdyn() failed for %s: %s", fpath,
425 : 0 : elf_errmsg(-1));
426 : 0 : goto cleanup;
427 : : }
428 : :
429 [ + + ]: 1168 : if (dyn->d_tag != DT_NEEDED)
430 : 1104 : continue;
431 : :
432 : 64 : shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);
433 : :
434 : 64 : add_shlibs_to_pkg(pkg, fpath, shlib, is_shlib);
435 : 112 : }
436 : :
437 : : cleanup:
438 : 280 : rpath_list_free();
439 : :
440 [ - + ]: 280 : if (e != NULL)
441 : 280 : elf_end(e);
442 : 280 : close(fd);
443 : :
444 : 280 : return (ret);
445 : 969 : }
446 : :
447 : : static int
448 : 0 : analyse_fpath(struct pkg *pkg, const char *fpath)
449 : : {
450 : : const char *dot;
451 : :
452 : 0 : dot = strrchr(fpath, '.');
453 : :
454 [ # # ]: 0 : if (dot == NULL) /* No extension */
455 : 0 : return (EPKG_OK);
456 : :
457 [ # # # # ]: 0 : if (dot[1] == 'a' && dot[2] == '\0')
458 : 0 : pkg->flags |= PKG_CONTAINS_STATIC_LIBS;
459 : :
460 [ # # # # : 0 : if ((dot[1] == 'l' && dot[2] == 'a' && dot[3] == '\0'))
# # ]
461 : 0 : pkg->flags |= PKG_CONTAINS_LA;
462 : :
463 : 0 : return (EPKG_OK);
464 : 0 : }
465 : :
466 : : int
467 : 1330 : pkg_analyse_files(struct pkgdb *db __unused, struct pkg *pkg, const char *stage)
468 : : {
469 : 1330 : struct pkg_file *file = NULL;
470 : 1330 : int ret = EPKG_OK;
471 : : char fpath[MAXPATHLEN +1];
472 : : const char *lib;
473 : 1330 : bool failures = false;
474 : :
475 [ + + ]: 1330 : if (pkghash_count(pkg->shlibs_required) != 0) {
476 : 8 : pkghash_destroy(pkg->shlibs_required);
477 : 8 : pkg->shlibs_required = NULL;
478 : 8 : }
479 : :
480 [ + + ]: 1330 : if (pkghash_count(pkg->shlibs_provided) != 0) {
481 : 20 : pkghash_destroy(pkg->shlibs_provided);
482 : 20 : pkg->shlibs_provided = NULL;
483 : 20 : }
484 : :
485 [ + - ]: 1330 : if (elf_version(EV_CURRENT) == EV_NONE)
486 : 0 : return (EPKG_FATAL);
487 : :
488 : 1330 : shlib_list_init();
489 : :
490 [ + + + - ]: 1330 : if (stage != NULL && pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) {
491 : : /* Do not check the return */
492 : 0 : shlib_list_from_stage(stage);
493 : 0 : }
494 : :
495 : 1330 : ret = shlib_list_from_elf_hints(_PATH_ELF_HINTS);
496 [ - + ]: 1330 : if (ret != EPKG_OK)
497 : 0 : goto cleanup;
498 : :
499 : : /* Assume no architecture dependence, for contradiction */
500 [ + - ]: 1330 : if (ctx.developer_mode)
501 : 0 : pkg->flags &= ~(PKG_CONTAINS_ELF_OBJECTS |
502 : : PKG_CONTAINS_STATIC_LIBS |
503 : : PKG_CONTAINS_LA);
504 : :
505 [ + + ]: 2299 : while (pkg_files(pkg, &file) == EPKG_OK) {
506 [ + + ]: 969 : if (stage != NULL)
507 : 178 : snprintf(fpath, sizeof(fpath), "%s/%s", stage, file->path);
508 : : else
509 : 791 : strlcpy(fpath, file->path, sizeof(fpath));
510 : :
511 : 969 : ret = analyse_elf(pkg, fpath);
512 [ + - ]: 969 : if (ctx.developer_mode) {
513 [ # # # # ]: 0 : if (ret != EPKG_OK && ret != EPKG_END) {
514 : 0 : failures = true;
515 : 0 : continue;
516 : : }
517 : 0 : analyse_fpath(pkg, fpath);
518 : 0 : }
519 : : }
520 : :
521 : : /*
522 : : * Do not depend on libraries that a package provides itself
523 : : */
524 : 1330 : pkghash_it it = pkghash_iterator(pkg->shlibs_required);
525 [ + + ]: 1346 : while (pkghash_next(&it)) {
526 [ - + ]: 16 : if (pkghash_get(pkg->shlibs_provided, it.key)) {
527 : 0 : pkg_debug(2, "remove %s from required shlibs as the "
528 : : "package %s provides this library itself",
529 : 0 : it.key, pkg->name);
530 : 0 : pkghash_del(pkg->shlibs_required, it.key);
531 : 0 : continue;
532 : : }
533 : 16 : file = NULL;
534 [ + + ]: 32 : while (pkg_files(pkg, &file) == EPKG_OK) {
535 [ - + # # ]: 16 : if ((lib = strstr(file->path, it.key)) != NULL &&
536 [ # # ]: 0 : strlen(lib) == strlen(it.key) && lib[-1] == '/') {
537 : 0 : pkg_debug(2, "remove %s from required shlibs as "
538 : : "the package %s provides this file itself",
539 : 0 : it.key, pkg->name);
540 : :
541 : 0 : pkghash_del(pkg->shlibs_required, it.key);
542 : 0 : break;
543 : : }
544 : : }
545 : : }
546 : :
547 : : /*
548 : : * if the package is not supposed to provide share libraries then
549 : : * drop the provided one
550 : : */
551 [ + - ]: 1330 : if (pkg_kv_get(&pkg->annotations, "no_provide_shlib") != NULL) {
552 : 0 : pkghash_destroy(pkg->shlibs_provided);
553 : 0 : pkg->shlibs_provided = NULL;
554 : 0 : }
555 : :
556 [ - + ]: 1330 : if (failures)
557 : 0 : goto cleanup;
558 : :
559 : 1330 : ret = EPKG_OK;
560 : :
561 : : cleanup:
562 : 1330 : shlib_list_free();
563 : :
564 : 1330 : return (ret);
565 : 1330 : }
566 : :
567 : : static const char *
568 : 13988 : elf_corres_to_string(const struct _elf_corres* m, int e)
569 : : {
570 : 13988 : int i = 0;
571 : :
572 [ + - ]: 27976 : for (i = 0; m[i].string != NULL; i++)
573 [ + + ]: 27976 : if (m[i].elf_nb == e)
574 : 13988 : return (m[i].string);
575 : :
576 : 0 : return ("unknown");
577 : 13988 : }
578 : :
579 : : static int
580 : 0 : elf_string_to_corres(const struct _elf_corres* m, const char *s)
581 : : {
582 : 0 : int i = 0;
583 : :
584 [ # # ]: 0 : for (i = 0; m[i].string != NULL; i++)
585 [ # # ]: 0 : if (strcmp(m[i].string, s) == 0)
586 : 0 : return (m[i].elf_nb);
587 : :
588 : 0 : return (-1);
589 : 0 : }
590 : :
591 : : static const char *
592 : 0 : aeabi_parse_arm_attributes(void *data, size_t length)
593 : : {
594 : : uint32_t sect_len;
595 : 0 : uint8_t *section = data;
596 : :
597 : : #define MOVE(len) do { \
598 : : assert(length >= (len)); \
599 : : section += (len); \
600 : : length -= (len); \
601 : : } while (0)
602 : :
603 [ # # # # ]: 0 : if (length == 0 || *section != 'A')
604 : 0 : return (NULL);
605 [ # # ]: 0 : MOVE(1);
606 : :
607 : : /* Read the section length */
608 [ # # ]: 0 : if (length < sizeof(sect_len))
609 : 0 : return (NULL);
610 : 0 : memcpy(§_len, section, sizeof(sect_len));
611 : :
612 : : /*
613 : : * The section length should be no longer than the section it is within
614 : : */
615 [ # # ]: 0 : if (sect_len > length)
616 : 0 : return (NULL);
617 : :
618 [ # # ]: 0 : MOVE(sizeof(sect_len));
619 : :
620 : : /* Skip the vendor name */
621 [ # # ]: 0 : while (length != 0) {
622 [ # # ]: 0 : if (*section == '\0')
623 : 0 : break;
624 [ # # ]: 0 : MOVE(1);
625 : : }
626 [ # # ]: 0 : if (length == 0)
627 : 0 : return (NULL);
628 [ # # ]: 0 : MOVE(1);
629 : :
630 [ # # ]: 0 : while (length != 0) {
631 : : uint32_t tag_length;
632 : :
633 [ # # # ]: 0 : switch(*section) {
634 : : case 1: /* Tag_File */
635 [ # # ]: 0 : MOVE(1);
636 [ # # ]: 0 : if (length < sizeof(tag_length))
637 : 0 : return (NULL);
638 : 0 : memcpy(&tag_length, section, sizeof(tag_length));
639 : 0 : break;
640 : : case 2: /* Tag_Section */
641 : : case 3: /* Tag_Symbol */
642 : : default:
643 : 0 : return (NULL);
644 : : }
645 : : /* At least space for the tag and size */
646 [ # # ]: 0 : if (tag_length <= 5)
647 : 0 : return (NULL);
648 : 0 : tag_length--;
649 : : /* Check the tag fits */
650 [ # # ]: 0 : if (tag_length > length)
651 : 0 : return (NULL);
652 : :
653 : : #define MOVE_TAG(len) do { \
654 : : assert(tag_length >= (len)); \
655 : : MOVE(len); \
656 : : tag_length -= (len); \
657 : : } while(0)
658 : :
659 [ # # ]: 0 : MOVE(sizeof(tag_length));
660 : 0 : tag_length -= sizeof(tag_length);
661 : :
662 [ # # ]: 0 : while (tag_length != 0) {
663 : : uint8_t tag;
664 : :
665 [ # # ]: 0 : assert(tag_length >= length);
666 : :
667 : 0 : tag = *section;
668 [ # # # # ]: 0 : MOVE_TAG(1);
669 : :
670 : : /*
671 : : * These tag values come from:
672 : : *
673 : : * Addenda to, and Errata in, the ABI for the
674 : : * ARM Architecture. Release 2.08, section 2.3.
675 : : */
676 [ # # ]: 0 : if (tag == 6) { /* == Tag_CPU_arch */
677 : : uint8_t val;
678 : :
679 : 0 : val = *section;
680 : : /*
681 : : * We don't support values that require
682 : : * more than one byte.
683 : : */
684 [ # # ]: 0 : if (val & (1 << 7))
685 : 0 : return (NULL);
686 : :
687 : : /* We have an ARMv4 or ARMv5 */
688 [ # # ]: 0 : if (val <= 5)
689 : 0 : return ("arm");
690 [ # # ]: 0 : else if (val == 6) /* We have an ARMv6 */
691 : 0 : return ("armv6");
692 : : else /* We have an ARMv7+ */
693 : 0 : return ("armv7");
694 [ # # # # : 0 : } else if (tag == 4 || tag == 5 || tag == 32 ||
# # # # ]
695 [ # # ]: 0 : tag == 65 || tag == 67) {
696 [ # # # # ]: 0 : while (*section != '\0' && length != 0)
697 [ # # # # ]: 0 : MOVE_TAG(1);
698 [ # # ]: 0 : if (tag_length == 0)
699 : 0 : return (NULL);
700 : : /* Skip the last byte */
701 [ # # # # ]: 0 : MOVE_TAG(1);
702 [ # # # # : 0 : } else if ((tag >= 7 && tag <= 31) || tag == 34 ||
# # ]
703 [ # # # # : 0 : tag == 36 || tag == 38 || tag == 42 || tag == 44 ||
# # # # ]
704 [ # # # # : 0 : tag == 64 || tag == 66 || tag == 68 || tag == 70) {
# # ]
705 : : /* Skip the uleb128 data */
706 [ # # # # ]: 0 : while (*section & (1 << 7) && length != 0)
707 [ # # # # ]: 0 : MOVE_TAG(1);
708 [ # # ]: 0 : if (tag_length == 0)
709 : 0 : return (NULL);
710 : : /* Skip the last byte */
711 [ # # # # ]: 0 : MOVE_TAG(1);
712 : 0 : } else
713 : 0 : return (NULL);
714 : : #undef MOVE_TAG
715 : : }
716 : :
717 : 0 : break;
718 : : }
719 : 0 : return (NULL);
720 : : #undef MOVE
721 : 0 : }
722 : :
723 : : static bool
724 : 6994 : elf_note_analyse(Elf_Data *data, GElf_Ehdr *elfhdr, struct os_info *oi)
725 : : {
726 : : Elf_Note note;
727 : : char *src;
728 : : uint32_t gnu_abi_tag[4];
729 : 6994 : char *note_os[6] = {"Linux", "GNU", "Solaris", "FreeBSD", "NetBSD", "Syllable"};
730 : 6994 : char *(*pnote_os)[6] = ¬e_os;
731 : 6994 : char invalid_osname[] = "Unknown";
732 : 6994 : uint32_t version = 0;
733 : 6994 : int version_style = 1;
734 : :
735 : 6994 : src = data->d_buf;
736 : :
737 [ - + ]: 6994 : while ((uintptr_t)src < ((uintptr_t)data->d_buf + data->d_size)) {
738 : 6994 : memcpy(¬e, src, sizeof(Elf_Note));
739 : 6994 : src += sizeof(Elf_Note);
740 [ - + # # ]: 6994 : if ((strncmp ((const char *) src, "FreeBSD", note.n_namesz) == 0) ||
741 [ # # ]: 0 : (strncmp ((const char *) src, "DragonFly", note.n_namesz) == 0) ||
742 [ # # ]: 0 : (strncmp ((const char *) src, "NetBSD", note.n_namesz) == 0) ||
743 : 0 : (note.n_namesz == 0)) {
744 [ - + ]: 6994 : if (note.n_type == NT_VERSION) {
745 : 6994 : version_style = 1;
746 : 6994 : break;
747 : : }
748 : 0 : }
749 [ # # ]: 0 : if (strncmp ((const char *) src, "GNU", note.n_namesz) == 0) {
750 [ # # ]: 0 : if (note.n_type == NT_GNU_ABI_TAG) {
751 : 0 : version_style = 2;
752 : 0 : break;
753 : : }
754 : 0 : }
755 : 0 : src += roundup2(note.n_namesz + note.n_descsz, 4);
756 : : }
757 [ - + ]: 6994 : if ((uintptr_t)src >= ((uintptr_t)data->d_buf + data->d_size)) {
758 : 0 : return (false);
759 : : }
760 : 6994 : free(oi->name);
761 [ - + ]: 6994 : if (version_style == 2) {
762 : : /*
763 : : * NT_GNU_ABI_TAG
764 : : * Operating system (OS) ABI information. The
765 : : * desc field contains 4 words:
766 : : * word 0: OS descriptor (ELF_NOTE_OS_LINUX, ELF_NOTE_OS_GNU, etc)
767 : : * word 1: major version of the ABI
768 : : * word 2: minor version of the ABI
769 : : * word 3: subminor version of the ABI
770 : : */
771 : 0 : src += roundup2(note.n_namesz, 4);
772 [ # # ]: 0 : if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB) {
773 [ # # ]: 0 : for (int wdndx = 0; wdndx < 4; wdndx++) {
774 : 0 : gnu_abi_tag[wdndx] = be32dec(src);
775 : 0 : src += 4;
776 : 0 : }
777 : 0 : } else {
778 [ # # ]: 0 : for (int wdndx = 0; wdndx < 4; wdndx++) {
779 : 0 : gnu_abi_tag[wdndx] = le32dec(src);
780 : 0 : src += 4;
781 : 0 : }
782 : : }
783 [ # # ]: 0 : if (gnu_abi_tag[0] < 6)
784 : 0 : oi->name = xstrdup((*pnote_os)[gnu_abi_tag[0]]);
785 : : else
786 : 0 : oi->name = xstrdup(invalid_osname);
787 : 0 : } else {
788 [ - + ]: 6994 : if (note.n_namesz == 0)
789 : 0 : oi->name = xstrdup(invalid_osname);
790 : : else
791 : 6994 : oi->name = xstrdup(src);
792 : 6994 : src += roundup2(note.n_namesz, 4);
793 [ - + ]: 6994 : if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB)
794 : 0 : version = be32dec(src);
795 : : else
796 : 6994 : version = le32dec(src);
797 : : }
798 : :
799 : 6994 : free(oi->version);
800 [ - + ]: 6994 : if (version_style == 2) {
801 : 0 : xasprintf(&oi->version, "%d.%d.%d", gnu_abi_tag[1],
802 : 0 : gnu_abi_tag[2], gnu_abi_tag[3]);
803 : 0 : } else {
804 [ + - ]: 6994 : if (oi->osversion == 0)
805 : 6994 : oi->osversion = version;
806 : : #ifdef __DragonFly__
807 : : xasprintf(&oi->version, "%d.%d", version / 100000, (((version / 100 % 1000)+1)/2)*2);
808 : : #endif
809 : : #ifdef __NetBSD__
810 : : xasprintf(&oi->version, "%d", (version + 1000000) / 100000000);
811 : : #endif
812 : 6994 : xasprintf(&oi->version_major, "%d", version / 100000);
813 : 6994 : xasprintf(&oi->version_minor, "%d", (version / 1000 % 100));
814 : 6994 : xasprintf(&oi->version, "%d", version / 100000);
815 : : }
816 : :
817 : 6994 : return (true);
818 : 6994 : }
819 : :
820 : :
821 : : static int
822 : 6994 : pkg_get_myarch_elfparse(char *dest, size_t sz, struct os_info *oi)
823 : : {
824 : : char rooted_abi_file[PATH_MAX];
825 : 6994 : Elf *elf = NULL;
826 : : GElf_Ehdr elfhdr;
827 : : GElf_Shdr shdr;
828 : : Elf_Data *data;
829 : 6994 : Elf_Scn *scn = NULL;
830 : : int fd, i;
831 : 6994 : int ret = EPKG_OK;
832 : : const char *arch, *abi, *endian_corres_str, *wordsize_corres_str, *fpu;
833 : : bool checkroot;
834 : : struct os_info loi;
835 : :
836 : 13988 : const char *abi_files[] = {
837 : 6994 : getenv("ABI_FILE"),
838 : : _PATH_UNAME,
839 : : _PATH_BSHELL,
840 : : };
841 : :
842 : 6994 : arch = NULL;
843 : :
844 [ + + ]: 6994 : if (oi == NULL) {
845 : 3497 : memset(&loi, 0, sizeof(loi));
846 : 3497 : oi = &loi;
847 : 3497 : }
848 : :
849 [ + - ]: 6994 : if (elf_version(EV_CURRENT) == EV_NONE) {
850 : 0 : pkg_emit_error("ELF library initialization failed: %s",
851 : 0 : elf_errmsg(-1));
852 : 0 : return (EPKG_FATAL);
853 : : }
854 : :
855 : : /*
856 : : * Perhaps not yet needed, but it may be in the future that there's no
857 : : * need to check root under some conditions where there is a rootdir.
858 : : * This also helps alleviate some excessive wrapping later.
859 : : */
860 : 6994 : checkroot = ctx.pkg_rootdir != NULL;
861 [ - + ]: 13980 : for (fd = -1, i = 0; i < nitems(abi_files); i++) {
862 [ + + ]: 13980 : if (abi_files[i] == NULL)
863 : 6986 : continue;
864 : : /*
865 : : * Try prepending rootdir and using that if it exists. If
866 : : * ABI_FILE is specified, assume that the consumer didn't want
867 : : * it mangled by rootdir.
868 : : */
869 [ + + + + : 6994 : if (i > 0 && checkroot && snprintf(rooted_abi_file, PATH_MAX,
- + - + -
+ ]
870 : 1208 : "%s/%s", ctx.pkg_rootdir, abi_files[i]) < PATH_MAX) {
871 [ + - ]: 604 : if ((fd = open(rooted_abi_file, O_RDONLY)) >= 0)
872 : 0 : break;
873 : 604 : }
874 [ - + ]: 6994 : if ((fd = open(abi_files[i], O_RDONLY)) >= 0)
875 : 6994 : break;
876 : : /* if the ABI_FILE was provided we only care about it */
877 [ # # ]: 0 : if (i == 0)
878 : 0 : break;
879 : 0 : }
880 [ + - ]: 6994 : if (fd == -1) {
881 : 0 : pkg_emit_error("Unable to determine the ABI\n");
882 : 0 : return (EPKG_FATAL);
883 : : }
884 : :
885 [ + - ]: 6994 : if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
886 : 0 : ret = EPKG_FATAL;
887 : 0 : pkg_emit_error("elf_begin() failed: %s.", elf_errmsg(-1));
888 : 0 : goto cleanup;
889 : : }
890 : :
891 [ + - ]: 6994 : if (gelf_getehdr(elf, &elfhdr) == NULL) {
892 : 0 : ret = EPKG_FATAL;
893 : 0 : pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
894 : 0 : goto cleanup;
895 : : }
896 : :
897 : :
898 [ + + ]: 209884 : while ((scn = elf_nextscn(elf, scn)) != NULL) {
899 [ + - ]: 202890 : if (gelf_getshdr(scn, &shdr) != &shdr) {
900 : 0 : ret = EPKG_FATAL;
901 : 0 : pkg_emit_error("getshdr() failed: %s.", elf_errmsg(-1));
902 : 0 : goto cleanup;
903 : : }
904 : :
905 [ + + ]: 202890 : if (shdr.sh_type == SHT_NOTE) {
906 : 6994 : data = elf_getdata(scn, NULL);
907 : : /*
908 : : * loop over all the note section and override what
909 : : * should be overridden if any
910 : : */
911 : 6994 : elf_note_analyse(data, &elfhdr, oi);
912 : 6994 : }
913 : : }
914 : :
915 [ + - ]: 6994 : if (oi->name == NULL) {
916 : 0 : ret = EPKG_FATAL;
917 : 0 : pkg_emit_error("failed to get the note section");
918 : 0 : goto cleanup;
919 : : }
920 : :
921 : 6994 : snprintf(dest, sz, "%s:%s", oi->name, oi->version);
922 : :
923 : 6994 : wordsize_corres_str = elf_corres_to_string(wordsize_corres,
924 : 6994 : (int)elfhdr.e_ident[EI_CLASS]);
925 : :
926 : 6994 : arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
927 : :
928 [ - + - - : 6994 : switch (elfhdr.e_machine) {
- ]
929 : : case EM_ARM:
930 : 0 : endian_corres_str = elf_corres_to_string(endian_corres,
931 : 0 : (int)elfhdr.e_ident[EI_DATA]);
932 : :
933 [ # # ]: 0 : if (elfhdr.e_flags & EF_ARM_VFP_FLOAT)
934 : 0 : fpu = "hardfp";
935 : : else
936 : 0 : fpu = "softfp";
937 : :
938 [ # # ]: 0 : if ((elfhdr.e_flags & 0xFF000000) != 0) {
939 : 0 : const char *sh_name = NULL;
940 : : size_t shstrndx;
941 : :
942 : : /* This is an EABI file, the conformance level is set */
943 : 0 : abi = "eabi";
944 : :
945 : : /* Find which TARGET_ARCH we are building for. */
946 : 0 : elf_getshdrstrndx(elf, &shstrndx);
947 [ # # ]: 0 : while ((scn = elf_nextscn(elf, scn)) != NULL) {
948 : 0 : sh_name = NULL;
949 [ # # ]: 0 : if (gelf_getshdr(scn, &shdr) != &shdr) {
950 : 0 : scn = NULL;
951 : 0 : break;
952 : : }
953 : :
954 : 0 : sh_name = elf_strptr(elf, shstrndx,
955 : 0 : shdr.sh_name);
956 [ # # ]: 0 : if (sh_name == NULL)
957 : 0 : continue;
958 [ # # ]: 0 : if (strcmp(".ARM.attributes", sh_name) == 0)
959 : 0 : break;
960 : : }
961 [ # # # # ]: 0 : if (scn != NULL && sh_name != NULL) {
962 : 0 : data = elf_getdata(scn, NULL);
963 : : /*
964 : : * Prior to FreeBSD 10.0 libelf would return
965 : : * NULL from elf_getdata on the .ARM.attributes
966 : : * section. As this was the first release to
967 : : * get armv6 support assume a NULL value means
968 : : * arm.
969 : : *
970 : : * This assumption can be removed when 9.x
971 : : * is unsupported.
972 : : */
973 [ # # ]: 0 : if (data != NULL) {
974 : 0 : arch = aeabi_parse_arm_attributes(
975 : 0 : data->d_buf, data->d_size);
976 [ # # ]: 0 : if (arch == NULL) {
977 : 0 : ret = EPKG_FATAL;
978 : 0 : pkg_emit_error(
979 : : "unknown ARM ARCH");
980 : 0 : goto cleanup;
981 : : }
982 : 0 : }
983 : 0 : } else {
984 : 0 : ret = EPKG_FATAL;
985 : 0 : pkg_emit_error("Unable to find the "
986 : : ".ARM.attributes section");
987 : 0 : goto cleanup;
988 : : }
989 : :
990 [ # # ]: 0 : } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) {
991 : : /*
992 : : * EABI executables all have this field set to
993 : : * ELFOSABI_NONE, therefore it must be an oabi file.
994 : : */
995 : 0 : abi = "oabi";
996 : 0 : } else {
997 : : /*
998 : : * We may have failed to positively detect the ABI,
999 : : * set the ABI to unknown. If we end up here one of
1000 : : * the above cases should be fixed for the binary.
1001 : : */
1002 : 0 : ret = EPKG_FATAL;
1003 : 0 : pkg_emit_error("unknown ARM ABI");
1004 : 0 : goto cleanup;
1005 : : }
1006 : 0 : snprintf(dest + strlen(dest), sz - strlen(dest),
1007 : 0 : ":%s:%s:%s:%s:%s", arch, wordsize_corres_str,
1008 : 0 : endian_corres_str, abi, fpu);
1009 : 0 : break;
1010 : : case EM_MIPS:
1011 : : /*
1012 : : * this is taken from binutils sources:
1013 : : * include/elf/mips.h
1014 : : * mapping is figured out from binutils:
1015 : : * gas/config/tc-mips.c
1016 : : */
1017 [ # # # ]: 0 : switch (elfhdr.e_flags & EF_MIPS_ABI) {
1018 : : case E_MIPS_ABI_O32:
1019 : 0 : abi = "o32";
1020 : 0 : break;
1021 : : case E_MIPS_ABI_N32:
1022 : 0 : abi = "n32";
1023 : 0 : break;
1024 : : default:
1025 [ # # ]: 0 : if (elfhdr.e_ident[EI_DATA] == ELFCLASS32)
1026 : 0 : abi = "o32";
1027 [ # # ]: 0 : else if (elfhdr.e_ident[EI_DATA] == ELFCLASS64)
1028 : 0 : abi = "n64";
1029 : : else
1030 : 0 : abi = "unknown";
1031 : 0 : break;
1032 : : }
1033 : 0 : endian_corres_str = elf_corres_to_string(endian_corres,
1034 : 0 : (int)elfhdr.e_ident[EI_DATA]);
1035 : :
1036 : 0 : snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s",
1037 : 0 : arch, wordsize_corres_str, endian_corres_str, abi);
1038 : 0 : break;
1039 : : #if defined(EM_RISCV) && defined(EF_RISCV_FLOAT_ABI_MASK)
1040 : : case EM_RISCV:
1041 [ # # # ]: 0 : switch (elfhdr.e_flags & EF_RISCV_FLOAT_ABI_MASK) {
1042 : : case EF_RISCV_FLOAT_ABI_SOFT:
1043 : 0 : abi = "sf";
1044 : 0 : break;
1045 : : case EF_RISCV_FLOAT_ABI_DOUBLE:
1046 : 0 : abi = "hf";
1047 : 0 : break;
1048 : : default:
1049 : 0 : abi = "unknown";
1050 : 0 : break;
1051 : : }
1052 : 0 : snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s",
1053 : 0 : arch, wordsize_corres_str, abi);
1054 : 0 : break;
1055 : : #endif
1056 : : case EM_PPC:
1057 : : case EM_PPC64:
1058 : 0 : endian_corres_str = elf_corres_to_string(endian_corres,
1059 : 0 : (int)elfhdr.e_ident[EI_DATA]);
1060 : :
1061 : 0 : snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s",
1062 : 0 : arch, wordsize_corres_str, endian_corres_str);
1063 : 0 : break;
1064 : : default:
1065 : 13988 : snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s",
1066 : 6994 : arch, wordsize_corres_str);
1067 : 6994 : break;
1068 : 6994 : }
1069 : :
1070 : : cleanup:
1071 [ - + ]: 6994 : if (elf != NULL)
1072 : 6994 : elf_end(elf);
1073 [ + + ]: 6994 : if (oi == &loi) {
1074 : 3497 : free(oi->name);
1075 : 3497 : free(oi->version);
1076 : 3497 : free(oi->version_major);
1077 : 3497 : free(oi->version_minor);
1078 : 3497 : free(oi->arch);
1079 : 3497 : }
1080 : 6994 : close(fd);
1081 : 6994 : return (ret);
1082 : 6994 : }
1083 : :
1084 : : int
1085 : 5415 : pkg_arch_to_legacy(const char *arch, char *dest, size_t sz)
1086 : : {
1087 : 5415 : int i = 0;
1088 : : struct arch_trans *arch_trans;
1089 : :
1090 : 5415 : bzero(dest, sz);
1091 : : /* Lower case the OS */
1092 [ + + + + ]: 35112 : while (arch[i] != ':' && arch[i] != '\0') {
1093 : 29697 : dest[i] = tolower(arch[i]);
1094 : 29697 : i++;
1095 : : }
1096 [ + + ]: 5415 : if (arch[i] == '\0')
1097 : 1368 : return (0);
1098 : :
1099 : 4047 : dest[i++] = ':';
1100 : :
1101 : : /* Copy the version */
1102 [ + + + + ]: 12141 : while (arch[i] != ':' && arch[i] != '\0') {
1103 : 8094 : dest[i] = arch[i];
1104 : 8094 : i++;
1105 : : }
1106 [ + - ]: 4047 : if (arch[i] == '\0')
1107 : 0 : return (0);
1108 : :
1109 : 4047 : dest[i++] = ':';
1110 : :
1111 [ + - ]: 8094 : for (arch_trans = machine_arch_translation; arch_trans->elftype != NULL;
1112 : 4047 : arch_trans++) {
1113 [ + + ]: 8094 : if (strcmp(arch + i, arch_trans->archid) == 0) {
1114 : 8094 : strlcpy(dest + i, arch_trans->elftype,
1115 : 4047 : sz - (arch + i - dest));
1116 : 4047 : return (0);
1117 : : }
1118 : 4047 : }
1119 : 0 : strlcpy(dest + i, arch + i, sz - (arch + i - dest));
1120 : :
1121 : 0 : return (0);
1122 : 5415 : }
1123 : :
1124 : : int
1125 : 3497 : pkg_get_myarch_legacy(char *dest, size_t sz)
1126 : : {
1127 : : int i, err;
1128 : :
1129 : 3497 : err = pkg_get_myarch_elfparse(dest, sz, NULL);
1130 [ - + ]: 3497 : if (err)
1131 : 0 : return (err);
1132 : :
1133 [ + + ]: 62946 : for (i = 0; i < strlen(dest); i++)
1134 : 59449 : dest[i] = tolower(dest[i]);
1135 : :
1136 : 3497 : return (0);
1137 : 3497 : }
1138 : :
1139 : : int
1140 : 3497 : pkg_get_myarch(char *dest, size_t sz, struct os_info *oi)
1141 : : {
1142 : : struct arch_trans *arch_trans;
1143 : : char *arch_tweak;
1144 : : int err;
1145 : 3497 : err = pkg_get_myarch_elfparse(dest, sz, oi);
1146 [ - + ]: 3497 : if (err) {
1147 [ # # ]: 0 : if (oi) {
1148 : 0 : free(oi->name);
1149 : 0 : }
1150 : 0 : return (err);
1151 : : }
1152 : :
1153 : : #ifdef __DragonFly__
1154 : : if (strncasecmp(dest, "DragonFly", 9) == 0) {
1155 : : for (int i = 0; i < strlen(dest); i++)
1156 : : dest[i] = tolower(dest[i]);
1157 : : return (0);
1158 : : }
1159 : : #endif
1160 : :
1161 : : /* Translate architecture string back to regular OS one */
1162 : 3497 : arch_tweak = strchr(dest, ':');
1163 [ + - ]: 3497 : if (arch_tweak == NULL)
1164 : 0 : return (0);
1165 : 3497 : arch_tweak++;
1166 : 3497 : arch_tweak = strchr(arch_tweak, ':');
1167 [ + - ]: 3497 : if (arch_tweak == NULL)
1168 : 0 : return (0);
1169 : 3497 : arch_tweak++;
1170 [ - + ]: 6994 : for (arch_trans = machine_arch_translation; arch_trans->elftype != NULL;
1171 : 3497 : arch_trans++) {
1172 [ + + ]: 6994 : if (strcmp(arch_tweak, arch_trans->elftype) == 0) {
1173 : 6994 : strlcpy(arch_tweak, arch_trans->archid,
1174 : 3497 : sz - (arch_tweak - dest));
1175 : 3497 : oi->arch = xstrdup(arch_tweak);
1176 : 3497 : break;
1177 : : }
1178 : 3497 : }
1179 : :
1180 : 3497 : return (0);
1181 : 3497 : }
1182 : :
|