From 6462d8a4cf0c283549e13a7436bac6f25b934836 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 9 Dec 2024 21:38:09 +0000 Subject: [PATCH] libpkg: make shlib handling portable All shared objects NEEDED by an ELF file are added to shlibs_required by pkg-create rather than filtering them based on the host system ELF hints file and installed libraries. The ALLOW_BASE_SHLIBS option is deprecated and ignored. Before running the solver, pkg now scans /lib and /usr/lib (taking --rootdir into account) and builds a list of system-provided shlibs that is used as an input to the solver. If pkg detects that it is targeting a pkgbase system this scan for system shlibs is skipped as the base packages will provide all necessary shlibs. The detection of a pkgbase system is implemented by checking if /usr/bin/uname is tracked in the pkg database. The main user-facing change is that pkg-create now adds *all* shared objects listed as NEEDED by an ELF file to shlibs_required. In general this should not cause issues due to the solver taking the shlibs provided by the base system into account but there may be exceptions. An option to filter these entries will be added in the next commit. References: https://github.com/freebsd/pkg/issues/2331 Sponsored by: The FreeBSD Foundation --- libpkg/Makefile.autosetup | 3 +- libpkg/elfhints.c | 559 -------------------------- libpkg/pkg_abi.c | 3 +- libpkg/pkg_abi_macho.c | 92 ++--- libpkg/pkg_config.c | 5 - libpkg/pkg_elf.c | 162 +------- libpkg/pkg_jobs.c | 16 +- libpkg/pkg_solve.c | 5 + libpkg/private/binfmt.h | 7 + libpkg/private/ldconfig.h | 81 ---- libpkg/private/pkg.h | 2 + libpkg/private/pkg_jobs.h | 1 + libpkg/system_shlibs.c | 92 +++++ scripts/completion/_pkg.in | 1 - tests/frontend/create-parsebin.sh | 45 +-- tests/frontend/test_environment.sh.in | 41 +- tests/lib/pkg_elf.c | 11 +- 17 files changed, 205 insertions(+), 921 deletions(-) delete mode 100644 libpkg/elfhints.c delete mode 100644 libpkg/private/ldconfig.h create mode 100644 libpkg/system_shlibs.c diff --git a/libpkg/Makefile.autosetup b/libpkg/Makefile.autosetup index 95764b2cf7..4e4606d5f6 100644 --- a/libpkg/Makefile.autosetup +++ b/libpkg/Makefile.autosetup @@ -36,7 +36,8 @@ SRCS= backup_lib.c \ pkg_elf.c \ pkg_abi_macho.c \ binfmt_macho.c \ - ssh.c elfhints.c \ + ssh.c \ + system_shlibs.c \ pkg_arch.c \ pkg_cudf.c \ pkg_jobs_universe.c pkg_printf.c \ diff --git a/libpkg/elfhints.c b/libpkg/elfhints.c deleted file mode 100644 index ce61ffb93c..0000000000 --- a/libpkg/elfhints.c +++ /dev/null @@ -1,559 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra - * Copyright (c) 2012 Matthew Seaman - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: stable/8/sbin/ldconfig/elfhints.c 76224 2001-05-02 23:56:21Z obrien $ - */ - -#include -#include "private/pkg_abi.h" -#include -#include -#ifdef HAVE_SYS_ENDIAN_H -#include -#elif HAVE_ENDIAN_H -#include -#elif HAVE_MACHINE_ENDIAN_H -#include -#endif - -#ifdef __APPLE__ -#include -#define be32toh(n) OSSwapBigToHostInt32(n) -#define le32toh(n) OSSwapLittleToHostInt32(n) -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pkg.h" -#include "private/pkg.h" -#include "private/ldconfig.h" - -#define MAXDIRS 1024 /* Maximum directories in path */ -#define MAXFILESIZE (16*1024) /* Maximum hints file size */ - -struct shlib { - const char *name; - char path[]; -}; - -static int shlib_list_add(pkghash **shlib_list, - const char *dir, const char *shlib_file); -static int scan_dirs_for_shlibs(pkghash **shlib_list, - int numdirs, const char **dirlist, - bool strictnames); -static void add_dir(const char *, const char *, int); -static void read_dirs_from_file(const char *, const char *); -static void read_elf_hints(const char *, int); -static void write_elf_hints(const char *); - -static const char *dirs[MAXDIRS]; -static int ndirs; -static int is_be; -int insecure; - -#define COND_SWAP(n) (is_be ? be32toh(n) : le32toh(n)) - -/* Known shlibs on the standard system search path. Persistent, - common to all applications */ -static pkghash *shlibs = NULL; - -/* Known shlibs on the specific RPATH or RUNPATH of one binary. - Evanescent. */ -static pkghash *rpath = NULL; - -void -shlib_list_init(void) -{ - assert(pkghash_count(shlibs) == 0); -} - -void -rpath_list_init(void) -{ - assert(pkghash_count(rpath) == 0); -} - -static int -shlib_list_add(pkghash **shlib_list, const char *dir, - const char *shlib_file) -{ - struct shlib *sl; - size_t path_len, dir_len; - - /* If shlib_file is already in the shlib_list table, don't try - * and add it again */ - if (pkghash_get(*shlib_list, shlib_file) != NULL) - return (EPKG_OK); - - path_len = strlen(dir) + strlen(shlib_file) + 2; - - sl = xcalloc(1, sizeof(struct shlib) + path_len); - - strlcpy(sl->path, dir, path_len); - dir_len = strlcat(sl->path, "/", path_len); - strlcat(sl->path, shlib_file, path_len); - - sl->name = sl->path + dir_len; - - pkghash_safe_add(*shlib_list, sl->name, sl, free); - - return (EPKG_OK); -} - -const char * -shlib_list_find_by_name(const char *shlib_file) -{ - struct shlib *sl; - - sl = pkghash_get_value(rpath, shlib_file); - if (sl != NULL) - return (sl->path); - - sl = pkghash_get_value(shlibs, shlib_file); - if (sl != NULL) - return (sl->path); - - return (NULL); -} - -void -shlib_list_free(void) -{ - - pkghash_destroy(shlibs); - shlibs = NULL; -} - -void -rpath_list_free(void) -{ - - pkghash_destroy(rpath); - rpath = NULL; -} - -static void -add_dir(const char *hintsfile, const char *name, int trusted) -{ - struct stat stbuf; - int i; - - /* Do some security checks */ - if (!trusted && !insecure) { - if (stat(name, &stbuf) == -1) { - warn("%s", name); - return; - } - if (stbuf.st_uid != 0) { - warnx("%s: ignoring directory not owned by root", name); - return; - } - if ((stbuf.st_mode & S_IWOTH) != 0) { - warnx("%s: ignoring world-writable directory", name); - return; - } - if ((stbuf.st_mode & S_IWGRP) != 0) { - warnx("%s: ignoring group-writable directory", name); - return; - } - } - - for (i = 0; i < ndirs; i++) - if (STREQ(dirs[i], name)) - return; - if (ndirs >= MAXDIRS) - errx(1, "\"%s\": Too many directories in path", hintsfile); - dirs[ndirs++] = name; -} - -static int -scan_dirs_for_shlibs(pkghash **shlib_list, int numdirs, - const char **dirlist, bool strictnames) -{ - int i; - - /* Expect shlibs to follow the name pattern libfoo.so.N if - strictnames is true -- ie. when searching the default - library search path. - - Otherwise, allow any name ending in .so or .so.N -- - ie. when searching RPATH or RUNPATH and assuming it - contains private shared libraries which can follow just - about any naming convention */ - - for (i = 0; i < numdirs; i++) { - DIR *dirp; - struct dirent *dp; - - if ((dirp = opendir(dirlist[i])) == NULL) - continue; - while ((dp = readdir(dirp)) != NULL) { - int len; - int ret; - const char *vers; - - /* Only regular files and sym-links. On some - filesystems d_type is not set, on these the d_type - field will be DT_UNKNOWN. */ - if (dp->d_type != DT_REG && dp->d_type != DT_LNK && - dp->d_type != DT_UNKNOWN) - continue; - - len = strlen(dp->d_name); - if (strictnames) { - /* Name can't be shorter than "libx.so" */ - if (len < 7 || - strncmp(dp->d_name, "lib", 3) != 0) - continue; - } - - vers = dp->d_name + len; - while (vers > dp->d_name && - (isdigit(*(vers-1)) || *(vers-1) == '.')) - vers--; - if (vers == dp->d_name + len) { - if (strncmp(vers - 3, ".so", 3) != 0) - continue; - } else if (vers < dp->d_name + 3 || - strncmp(vers - 3, ".so.", 4) != 0) - continue; - - /* We have a valid shared library name. */ - ret = shlib_list_add(shlib_list, dirlist[i], - dp->d_name); - if (ret != EPKG_OK) { - closedir(dirp); - return ret; - } - } - closedir(dirp); - } - return 0; -} - -#define ORIGIN "$ORIGIN" - -int shlib_list_from_rpath(const char *rpath_str, const char *dirpath) -{ - const char **dirlist; - char *buf; - size_t buflen; - int i, numdirs; - int ret; - const char *c, *cstart; - - /* The special token $ORIGIN should be replaced by the - dirpath: adjust buflen calculation to account for this */ - - numdirs = 1; - for (c = rpath_str; *c != '\0'; c++) - if (*c == ':') - numdirs++; - buflen = numdirs * sizeof(char *) + strlen(rpath_str) + 1; - i = strlen(dirpath) - strlen(ORIGIN); - if (i > 0) - buflen += i * numdirs; - - dirlist = xcalloc(1, buflen); - buf = (char *)dirlist + numdirs * sizeof(char *); - - buf[0] = '\0'; - cstart = rpath_str; - while ( (c = strstr(cstart, ORIGIN)) != NULL ) { - strncat(buf, cstart, c - cstart); - strlcat(buf, dirpath, buflen); - cstart = c + strlen(ORIGIN); - } - strlcat(buf, cstart, buflen); - - i = 0; - while ((c = strsep(&buf, ":")) != NULL) { - if (strlen(c) > 0) - dirlist[i++] = c; - } - - assert(i <= numdirs); - - ret = scan_dirs_for_shlibs(&rpath, i, dirlist, false); - - free(dirlist); - - return (ret); -} - -int -shlib_list_from_elf_hints(const char *hintsfile) -{ - if (ctx.abi.os == PKG_OS_FREEBSD || ctx.abi.os == PKG_OS_DRAGONFLY) - read_elf_hints(hintsfile, false); - - return (scan_dirs_for_shlibs(&shlibs, ndirs, dirs, true)); -} - -static const char *stage_dirs[] = { - "/lib", - "/usr/lib", -}; - -void -shlib_list_from_stage(const char *stage) -{ - int i; - char *dir; - - if (stage == NULL) - return; - - for (i = 0; i < NELEM(stage_dirs); i++) { - xasprintf(&dir, "%s%s", stage, stage_dirs[i]); - scan_dirs_for_shlibs(&shlibs, 1, (const char **)&dir, true); - free(dir); - } -} - -void -list_elf_hints(const char *hintsfile) -{ - int i; - int nlibs; - - read_elf_hints(hintsfile, 1); - printf("%s:\n", hintsfile); - printf("\tsearch directories:"); - for (i = 0; i < ndirs; i++) - printf("%c%s", i == 0 ? ' ' : ':', dirs[i]); - putchar('\n'); - - nlibs = 0; - for (i = 0; i < ndirs; i++) { - DIR *dirp; - struct dirent *dp; - - if ((dirp = opendir(dirs[i])) == NULL) - continue; - while ((dp = readdir(dirp)) != NULL) { - int len; - int namelen; - const char *name; - const char *vers; - - /* Name can't be shorter than "libx.so.0" */ - if ((len = strlen(dp->d_name)) < 9 || - strncmp(dp->d_name, "lib", 3) != 0) - continue; - name = dp->d_name + 3; - vers = dp->d_name + len; - while (vers > dp->d_name && isdigit(*(vers-1))) - vers--; - if (vers == dp->d_name + len) - continue; - if (vers < dp->d_name + 4 || - strncmp(vers - 4, ".so.", 4) != 0) - continue; - - /* We have a valid shared library name. */ - namelen = (vers - 4) - name; - printf("\t%d:-l%.*s.%s => %s/%s\n", nlibs, - namelen, name, vers, dirs[i], dp->d_name); - nlibs++; - } - closedir(dirp); - } -} - -static void -read_dirs_from_file(const char *hintsfile, const char *listfile) -{ - FILE *fp; - char buf[MAXPATHLEN]; - int linenum; - - if ((fp = fopen(listfile, "re")) == NULL) - err(1, "%s", listfile); - - linenum = 0; - while (fgets(buf, sizeof buf, fp) != NULL) { - char *cp, *sp; - - linenum++; - cp = buf; - /* Skip leading white space. */ - while (isspace(*cp)) - cp++; - if (*cp == '#' || *cp == '\0') - continue; - sp = cp; - /* Advance over the directory name. */ - while (!isspace(*cp) && *cp != '\0') - cp++; - /* Terminate the string and skip trailing white space. */ - if (*cp != '\0') { - *cp++ = '\0'; - while (isspace(*cp)) - cp++; - } - /* Now we had better be at the end of the line. */ - if (*cp != '\0') - warnx("%s:%d: trailing characters ignored", - listfile, linenum); - - sp = xstrdup(sp); - add_dir(hintsfile, sp, 0); - } - - fclose(fp); -} - -static void -read_elf_hints(const char *hintsfile, int must_exist) -{ - int fd; - struct stat s; - void *mapbase; - struct elfhints_hdr *hdr; - char *strtab; - char *dirlist; - char *p; - - if ((fd = open(hintsfile, O_RDONLY)) == -1) { - if (errno == ENOENT && !must_exist) - return; - err(1, "Cannot open \"%s\"", hintsfile); - } - if (fstat(fd, &s) == -1) - err(1, "Cannot stat \"%s\"", hintsfile); - if (s.st_size > MAXFILESIZE) - errx(1, "\"%s\" is unreasonably large", hintsfile); - /* - * We use a read-write, private mapping so that we can null-terminate - * some strings in it without affecting the underlying file. - */ - mapbase = mmap(NULL, s.st_size, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fd, 0); - if (mapbase == MAP_FAILED) - err(1, "Cannot mmap \"%s\"", hintsfile); - close(fd); - - hdr = (struct elfhints_hdr *)mapbase; - is_be = be32toh(hdr->magic) == ELFHINTS_MAGIC; - if (COND_SWAP(hdr->magic) != ELFHINTS_MAGIC) - errx(1, "\"%s\": invalid file format", hintsfile); - if (COND_SWAP(hdr->version) != 1) - errx(1, "\"%s\": unrecognized file version (%d)", hintsfile, - COND_SWAP(hdr->version)); - - strtab = (char *)mapbase + COND_SWAP(hdr->strtab); - dirlist = strtab + COND_SWAP(hdr->dirlist); - - if (*dirlist != '\0') - while ((p = strsep(&dirlist, ":")) != NULL) - add_dir(hintsfile, p, 1); -} - -void -update_elf_hints(const char *hintsfile, int argc, char **argv, int merge) -{ - int i; - - if (merge) - read_elf_hints(hintsfile, 0); - else - // remove when FreeBSD switches to LE for all architectures - is_be = be32toh(1) == 1; - for (i = 0; i < argc; i++) { - struct stat s; - - if (stat(argv[i], &s) == -1) - warn("warning: %s", argv[i]); - else if (S_ISREG(s.st_mode)) - read_dirs_from_file(hintsfile, argv[i]); - else - add_dir(hintsfile, argv[i], 0); - } - write_elf_hints(hintsfile); -} - -static void -write_elf_hints(const char *hintsfile) -{ - struct elfhints_hdr hdr; - char *tempname; - int fd; - FILE *fp; - int i; - - xasprintf(&tempname, "%s.XXXXXX", hintsfile); - if ((fd = mkstemp(tempname)) == -1) - err(1, "mkstemp(%s)", tempname); - if (fchmod(fd, 0444) == -1) - err(1, "fchmod(%s)", tempname); - if ((fp = fdopen(fd, "wb")) == NULL) - err(1, "fdopen(%s)", tempname); - - hdr.magic = COND_SWAP(ELFHINTS_MAGIC); - hdr.version = COND_SWAP(1); - hdr.strtab = COND_SWAP(sizeof hdr); - hdr.strsize = 0; - hdr.dirlist = 0; - memset(hdr.spare, 0, sizeof hdr.spare); - - /* Count up the size of the string table. */ - if (ndirs > 0) { - hdr.strsize += strlen(dirs[0]); - for (i = 1; i < ndirs; i++) - hdr.strsize += 1 + strlen(dirs[i]); - } - hdr.dirlistlen = COND_SWAP(hdr.strsize); - hdr.strsize++; /* For the null terminator */ - hdr.strsize = COND_SWAP(hdr.strsize); - - /* Write the header. */ - if (fwrite(&hdr, 1, sizeof hdr, fp) != sizeof hdr) - err(1, "%s: write error", tempname); - /* Write the strings. */ - if (ndirs > 0) { - if (fputs(dirs[0], fp) == EOF) - err(1, "%s: write error", tempname); - for (i = 1; i < ndirs; i++) - if (fprintf(fp, ":%s", dirs[i]) < 0) - err(1, "%s: write error", tempname); - } - if (putc('\0', fp) == EOF || fclose(fp) == EOF) - err(1, "%s: write error", tempname); - - if (rename(tempname, hintsfile) == -1) - err(1, "rename %s to %s", tempname, hintsfile); - free(tempname); -} diff --git a/libpkg/pkg_abi.c b/libpkg/pkg_abi.c index aba7db2932..f7c672eeab 100644 --- a/libpkg/pkg_abi.c +++ b/libpkg/pkg_abi.c @@ -448,8 +448,7 @@ pkg_analyse_files(struct pkgdb *db __unused, struct pkg *pkg, const char *stage) bool failures = false; int (*pkg_analyse_init)(const char *stage); - int (*pkg_analyse)(const bool developer_mode, struct pkg *pkg, - const char *fpath); + int (*pkg_analyse)(const bool developer_mode, struct pkg *pkg, const char *fpath); int (*pkg_analyse_close)(); if (0 == strncmp(pkg->abi, "Darwin", 6)) { diff --git a/libpkg/pkg_abi_macho.c b/libpkg/pkg_abi_macho.c index bd2ca1842d..bb3548cb7c 100644 --- a/libpkg/pkg_abi_macho.c +++ b/libpkg/pkg_abi_macho.c @@ -6,6 +6,7 @@ #include +#include "private/binfmt.h" #include "private/binfmt_macho.h" #include "private/pkg.h" #include "private/event.h" @@ -13,7 +14,7 @@ /** * Routines to support pkg_abi.c functions when dealing with Mach-O files. - * Supports getting struct pkg_abi from the binary's load commands. + * Supports getting struct pkg_abi from the binary's load commands. * Supports getting shared libary information (needed, provided & loader). * Picks right binary in Universal binary based on ABI. */ @@ -299,28 +300,8 @@ pkg_macho_abi_from_fd(int fd, struct pkg_abi *abi, enum pkg_arch arch_hint) return ret; } -static const char * const system_dylib_prefixes[] = { - "/System/", - "/usr/lib/", - "/lib/", -}; - -static bool -system_dylib(const char *libname) -{ - const char * const *p = system_dylib_prefixes; - const char * const *p_end = p + NELEM(system_dylib_prefixes); - while (p < p_end) { - if (strncmp(libname, *p, strlen(*p)) == 0) { - return true; - } - p++; - } - return false; -} - static int -analyse_macho(int fd, struct pkg *pkg, const bool baselibs) +analyse_macho(int fd, struct pkg *pkg) { ssize_t x; pkg_error_t ret = EPKG_END; @@ -378,45 +359,33 @@ analyse_macho(int fd, struct pkg *pkg, const bool baselibs) goto cleanup; } n += x; - if (!baselibs && system_dylib(dylib->path)) { - pkg_debug(3, - "Skipping System dynamic library path: %s ts %"PRIu32" current(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16") compat(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16")\n", - dylib->path, dylib->timestamp, - dylib->current_version.major, - dylib->current_version.minor, - dylib->current_version.patch, - dylib->compatibility_version.major, - dylib->compatibility_version.minor, - dylib->compatibility_version.patch); + // while under Darwin full path references are recommended and ubiquitous, + // we align with pkg native environment and use only the basename + // this also strips off any @executable_path, @loader_path, @rpath components + const char * basename = strrchr(dylib->path, '/'); + basename = basename ? basename + 1 : dylib->path; + pkg_debug(3, + "Adding dynamic library path: %s ts %"PRIu32" current(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16") compat(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16")\n", + dylib->path, dylib->timestamp, + dylib->current_version.major, + dylib->current_version.minor, + dylib->current_version.patch, + dylib->compatibility_version.major, + dylib->compatibility_version.minor, + dylib->compatibility_version.patch); + + char *lib_with_version; + if (dylib->current_version.patch) { + xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor, dylib->current_version.patch); } else { - // while under Darwin full path references are recommended and ubiquitous, - // we align with pkg native environment and use only the basename - // this also strips off any @executable_path, @loader_path, @rpath components - const char * basename = strrchr(dylib->path, '/'); - basename = basename ? basename + 1 : dylib->path; - pkg_debug(3, - "Adding dynamic library path: %s ts %"PRIu32" current(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16") compat(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16")\n", - dylib->path, dylib->timestamp, - dylib->current_version.major, - dylib->current_version.minor, - dylib->current_version.patch, - dylib->compatibility_version.major, - dylib->compatibility_version.minor, - dylib->compatibility_version.patch); - - char *lib_with_version; - if (dylib->current_version.patch) { - xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor, dylib->current_version.patch); - } else { - xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor); - } - if (LC_ID_DYLIB == loadcmd) { - pkg_addshlib_provided(pkg, lib_with_version); - } else { - pkg_addshlib_required(pkg, lib_with_version); - } - free(lib_with_version); + xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor); + } + if (LC_ID_DYLIB == loadcmd) { + pkg_addshlib_provided(pkg, lib_with_version); + } else { + pkg_addshlib_required(pkg, lib_with_version); } + free(lib_with_version); free(dylib); break; default: @@ -450,8 +419,7 @@ int pkg_analyse_macho(const bool developer_mode, struct pkg *pkg, const char *fpath) { int ret = EPKG_OK; - bool baselibs = pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS")); - pkg_debug(1, "Analysing Mach-O %s %d", fpath, baselibs); + pkg_debug(1, "Analysing Mach-O %s", fpath); int fd = open(fpath, O_RDONLY); if (-1 == fd) { @@ -460,7 +428,7 @@ pkg_analyse_macho(const bool developer_mode, struct pkg *pkg, const char *fpath) // Be consistent with analyse_elf and return no error if fpath cannot be opened return ret; } else { - ret = analyse_macho(fd, pkg, baselibs); + ret = analyse_macho(fd, pkg); if (-1 == close(fd)) { pkg_emit_errno("close_pkg_analyse_macho", fpath); ret = EPKG_FATAL; diff --git a/libpkg/pkg_config.c b/libpkg/pkg_config.c index c6ea23b06e..cd808a3b38 100644 --- a/libpkg/pkg_config.c +++ b/libpkg/pkg_config.c @@ -352,11 +352,6 @@ static struct config_entry c[] = { "VALID_URL_SCHEME", "pkg+http,pkg+https,https,http,file,ssh,tcp", }, - { - PKG_BOOL, - "ALLOW_BASE_SHLIBS", - "NO", - }, { PKG_INT, "WARN_SIZE_LIMIT", diff --git a/libpkg/pkg_elf.c b/libpkg/pkg_elf.c index 6f2a8e864b..166cd59a23 100644 --- a/libpkg/pkg_elf.c +++ b/libpkg/pkg_elf.c @@ -44,7 +44,6 @@ #include "private/pkg.h" #include "private/pkg_abi.h" #include "private/event.h" -#include "private/ldconfig.h" #include "private/binfmt.h" #ifndef NT_ABI_TAG @@ -55,82 +54,12 @@ #define NT_ARCH 2 #define NT_GNU_ABI_TAG 1 -/* FFR: when we support installing a 32bit package on a 64bit host */ -#define _PATH_ELF32_HINTS "/var/run/ld-elf32.so.hints" - #ifndef roundup2 #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ #endif static enum pkg_arch elf_parse_arch(Elf *elf, GElf_Ehdr *ehdr); -static int -filter_system_shlibs(const char *name, char *path, size_t pathlen) -{ - const char *shlib_path; - - shlib_path = shlib_list_find_by_name(name); - if (shlib_path == NULL) { - /* dynamic linker could not resolve */ - return (EPKG_FATAL); - } - - if (pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) { - if (strstr(shlib_path, "/lib32/") != NULL) - return (EPKG_END); - } else { - /* match /lib, /lib32, /usr/lib and /usr/lib32 */ - if (strncmp(shlib_path, "/lib", 4) == 0 || - strncmp(shlib_path, "/usr/lib", 8) == 0) - return (EPKG_END); /* ignore libs from base */ - } - - if (path != NULL) - strncpy(path, shlib_path, pathlen); - - return (EPKG_OK); -} - -/* ARGSUSED */ -static int -add_shlibs_to_pkg(struct pkg *pkg, const char *fpath, const char *name, - bool is_shlib) -{ - struct pkg_file *file = NULL; - const char *filepath; - size_t fsz, nsz; - - switch(filter_system_shlibs(name, NULL, 0)) { - case EPKG_OK: /* A non-system library */ - pkg_addshlib_required(pkg, name); - return (EPKG_OK); - case EPKG_END: /* A system library */ - return (EPKG_OK); - default: - /* Ignore link resolution errors if we're analysing a - shared library. */ - if (is_shlib) - return (EPKG_OK); - - while (pkg_files(pkg, &file) == EPKG_OK) { - filepath = file->path; - fsz = strlen(filepath); - nsz = strlen(name); - - if (fsz >= nsz && - STREQ(&filepath[fsz - nsz], name)) { - pkg_addshlib_required(pkg, name); - return (EPKG_OK); - } - } - - pkg_emit_notice("(%s-%s) %s - required shared library %s not " - "found", pkg->name, pkg->version, fpath, name); - - return (EPKG_FATAL); - } -} - #ifdef __FreeBSD__ static bool is_old_freebsd_armheader(const GElf_Ehdr *e) @@ -173,10 +102,6 @@ analyse_elf(struct pkg *pkg, const char *fpath) size_t numdyn = 0; size_t sh_link = 0; size_t dynidx; - const char *shlib; - char *rpath = NULL; - - bool is_shlib = false; int fd; @@ -289,19 +214,6 @@ analyse_elf(struct pkg *pkg, const char *fpath) goto cleanup; } - /* First, scan through the data from the .dynamic section to - find any RPATH or RUNPATH settings. These are colon - separated paths to prepend to the ld.so search paths from - the ELF hints file. These always seem to come right after - the NEEDED shared library entries. - - NEEDED entries should resolve to a filename for installed - executables, but need not resolve for installed shared - libraries -- additional info from the apps that link - against them would be required. Shared libraries are - distinguished by a DT_SONAME tag */ - - rpath_list_init(); for (dynidx = 0; dynidx < numdyn; dynidx++) { if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) { ret = EPKG_FATAL; @@ -310,48 +222,19 @@ analyse_elf(struct pkg *pkg, const char *fpath) goto cleanup; } - if (dyn->d_tag == DT_SONAME) { - is_shlib = true; - - /* The file being scanned is a shared library - *provided* by the package. Record this if - appropriate */ - shlib = elf_strptr(e, sh_link, dyn->d_un.d_val); - if (shlib != NULL && *shlib != '\0') - pkg_addshlib_provided(pkg, shlib); + const char *shlib = elf_strptr(e, sh_link, dyn->d_un.d_val); + if (shlib == NULL || *shlib == '\0') { + continue; } - if ((dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) && - rpath == NULL) - rpath = elf_strptr(e, sh_link, dyn->d_un.d_val); - } - if (rpath != NULL) { - char *p = xstrdup(fpath); - shlib_list_from_rpath(rpath, get_dirname(p)); - free(p); - } - - /* Now find all of the NEEDED shared libraries. */ - - for (dynidx = 0; dynidx < numdyn; dynidx++) { - if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) { - ret = EPKG_FATAL; - pkg_emit_error("getdyn() failed for %s: %s", fpath, - elf_errmsg(-1)); - goto cleanup; + if (dyn->d_tag == DT_SONAME) { + pkg_addshlib_provided(pkg, shlib); + } else if (dyn->d_tag == DT_NEEDED) { + pkg_addshlib_required(pkg, shlib); } - - if (dyn->d_tag != DT_NEEDED) - continue; - - shlib = elf_strptr(e, sh_link, dyn->d_un.d_val); - - add_shlibs_to_pkg(pkg, fpath, shlib, is_shlib); } cleanup: - rpath_list_free(); - if (e != NULL) elf_end(e); close(fd); @@ -753,33 +636,24 @@ pkg_elf_abi_from_fd(int fd, struct pkg_abi *abi) return (ret); } -int pkg_analyse_init_elf(const char* stage) { +int pkg_analyse_init_elf(__unused const char* stage) { if (elf_version(EV_CURRENT) == EV_NONE) return (EPKG_FATAL); - - shlib_list_init(); - - if (stage != NULL && pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) { - /* Do not check the return */ - shlib_list_from_stage(stage); - } - - int ret = shlib_list_from_elf_hints(_PATH_ELF_HINTS); - return ret; + return (EPKG_OK); } -int pkg_analyse_elf(const bool developer_mode, struct pkg *pkg, const char *fpath) { - int ret = analyse_elf(pkg, fpath); - if (developer_mode) { - if (ret != EPKG_OK && ret != EPKG_END) { - return EPKG_WARN; - } - analyse_fpath(pkg, fpath); +int pkg_analyse_elf(const bool developer_mode, struct pkg *pkg, const char *fpath) +{ + int ret = analyse_elf(pkg, fpath); + if (developer_mode) { + if (ret != EPKG_OK && ret != EPKG_END) { + return EPKG_WARN; } - return ret; + analyse_fpath(pkg, fpath); + } + return ret; } int pkg_analyse_close_elf() { - shlib_list_free(); return EPKG_OK; } diff --git a/libpkg/pkg_jobs.c b/libpkg/pkg_jobs.c index d5cee05fae..bbc459b315 100644 --- a/libpkg/pkg_jobs.c +++ b/libpkg/pkg_jobs.c @@ -219,6 +219,7 @@ pkg_jobs_free(struct pkg_jobs *j) ucl_object_unref(j->triggers.schema); pkghash_destroy(j->orphaned); pkghash_destroy(j->notorphaned); + pkghash_destroy(j->system_shlibs); free(j); } @@ -1915,8 +1916,21 @@ pkg_jobs_check_and_solve_conflicts(struct pkg_jobs *j, bool *found_conflicts) int pkg_jobs_solve(struct pkg_jobs *j) { - int ret = pkg_jobs_run_solver(j); + int ret; + + assert(j->system_shlibs == NULL); + + /* If /usr/bin/uname is in the pkg database, we are targeting + * a pkgbase system and should rely on the pkgbase packages to + * provide system shlibs. */ + if (!pkgdb_file_exists(j->db, "/usr/bin/uname")) { + ret = scan_system_shlibs(&j->system_shlibs, ctx.pkg_rootdir); + if (ret != EPKG_OK) { + return (ret); + } + } + ret = pkg_jobs_run_solver(j); if (ret != EPKG_OK) return (ret); diff --git a/libpkg/pkg_solve.c b/libpkg/pkg_solve.c index 0b7668c43a..cb3c43f83f 100644 --- a/libpkg/pkg_solve.c +++ b/libpkg/pkg_solve.c @@ -40,6 +40,7 @@ #include #include "pkg.h" +#include "pkghash.h" #include "private/event.h" #include "private/pkg.h" #include "private/pkgdb.h" @@ -671,6 +672,10 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem, /* Shlibs */ tll_foreach(pkg->shlibs_required, s) { + if (pkghash_get(j->system_shlibs, s->item) != NULL) { + /* The shlib is provided by the system */ + continue; + } if (pkg_solve_add_require_rule(problem, cur_var, s->item, cur_var->assumed_reponame) != EPKG_OK) { continue; diff --git a/libpkg/private/binfmt.h b/libpkg/private/binfmt.h index fda509a3e3..91b5444cfe 100644 --- a/libpkg/private/binfmt.h +++ b/libpkg/private/binfmt.h @@ -8,6 +8,13 @@ #include "private/pkg.h" +/* In the future this will be extended to include + e.g. PKG_PROVIDE_SHLIB_COMPAT_32 */ +enum pkg_provide_flags { + PKG_PROVIDE_NONE = 0, + PKG_PROVIDE_SHLIB_NATIVE = 1 << 0, +}; + int pkg_elf_abi_from_fd(int fd, struct pkg_abi *abi); int pkg_analyse_init_elf(const char* stage); int pkg_analyse_elf(const bool developer_mode, struct pkg *pkg, const char *fpath); diff --git a/libpkg/private/ldconfig.h b/libpkg/private/ldconfig.h deleted file mode 100644 index bbcbc7238f..0000000000 --- a/libpkg/private/ldconfig.h +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: stable/8/sbin/ldconfig/ldconfig.h 92882 2002-03-21 13:14:21Z imp $ - */ - -#ifndef LDCONFIG_H -#define LDCONFIG_H 1 - -#ifdef HAVE_CONFIG_H -#include "pkg_config.h" -#endif - -#include - -#ifdef HAVE_ELF_HINTS_H -#include -#else -/* - * Hints file produced by ldconfig. - */ -struct elfhints_hdr -{ - u_int32_t magic; /* Magic number */ - u_int32_t version; /* File version (1) */ - u_int32_t strtab; /* Offset of string table in file */ - u_int32_t strsize; /* Size of string table */ - u_int32_t dirlist; /* Offset of directory list in - string table */ - u_int32_t dirlistlen; /* strlen(dirlist) */ - u_int32_t spare[26]; /* Room for expansion */ -}; - -#define ELFHINTS_MAGIC 0x746e6845 - -# ifdef __NetBSD__ -#define _PATH_ELF_HINTS "/var/run/ld.so.hints" -# else -#define _PATH_ELF_HINTS "/var/run/ld-elf.so.hints" -# endif -#endif - -extern int insecure; /* -i flag, needed here for elfhints.c */ - -__BEGIN_DECLS -void shlib_list_init(void); -void rpath_list_init(void); -const char *shlib_list_find_by_name(const char *); -void shlib_list_free(void); -void rpath_list_free(void); -int shlib_list_from_elf_hints(const char *); -int shlib_list_from_rpath(const char *, const char *); -void shlib_list_from_stage(const char *); - -void list_elf_hints(const char *); -void update_elf_hints(const char *, int, char **, int); -__END_DECLS - -#endif diff --git a/libpkg/private/pkg.h b/libpkg/private/pkg.h index 1b53eb51a0..79db5c1da6 100644 --- a/libpkg/private/pkg.h +++ b/libpkg/private/pkg.h @@ -844,4 +844,6 @@ int pkg_parse_manifest_ucl(struct pkg *pkg, ucl_object_t *o); int pkg_get_reposdirfd(void); char * expand_plist_variables(const char *in, kvlist_t *vars); +int scan_system_shlibs(pkghash **system_shlibs, const char *rootdir); + #endif diff --git a/libpkg/private/pkg_jobs.h b/libpkg/private/pkg_jobs.h index 5cfda59309..e67d8d1791 100644 --- a/libpkg/private/pkg_jobs.h +++ b/libpkg/private/pkg_jobs.h @@ -142,6 +142,7 @@ struct pkg_jobs { struct triggers triggers; struct pkghash *orphaned; struct pkghash *notorphaned; + struct pkghash *system_shlibs; }; #define PKG_PATTERN_FLAG_FILE (1 << 0) diff --git a/libpkg/system_shlibs.c b/libpkg/system_shlibs.c new file mode 100644 index 0000000000..31f3c0180c --- /dev/null +++ b/libpkg/system_shlibs.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 1998 John D. Polstra + * Copyright (c) 2012 Matthew Seaman + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed in part by Isaac Freund + * under sponsorship from the FreeBSD Foundation. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +#include "pkg.h" +#include "pkghash.h" +#include "private/event.h" +#include "xmalloc.h" + +static int +scan_dir_for_shlibs(pkghash **shlib_list, const char *dir) +{ + DIR *dirp= opendir(dir); + if (dirp == NULL) { + if (errno == ENOENT) { + return (EPKG_OK); + } + pkg_errno("Failed to open '%s' to scan for shared libraries", dir); + return (EPKG_FATAL); + } + + struct dirent *dp; + while ((dp = readdir(dirp)) != NULL) { + /* Only regular files and sym-links. On some + filesystems d_type is not set, on these the d_type + field will be DT_UNKNOWN. */ + if (dp->d_type != DT_REG && dp->d_type != DT_LNK && + dp->d_type != DT_UNKNOWN) + continue; + + int len = strlen(dp->d_name); + /* Name can't be shorter than "libx.so" */ + if (len < 7 || strncmp(dp->d_name, "lib", 3) != 0) + continue; + + const char *vers = dp->d_name + len; + while (vers > dp->d_name && + (isdigit(*(vers-1)) || *(vers-1) == '.')) + vers--; + if (vers == dp->d_name + len) { + if (strncmp(vers - 3, ".so", 3) != 0) + continue; + } else if (vers < dp->d_name + 3 || + strncmp(vers - 3, ".so.", 4) != 0) + continue; + + /* We have a valid shared library name. */ + pkghash_safe_add(*shlib_list, dp->d_name, NULL, NULL); + } + + closedir(dirp); + + return (EPKG_OK); +} + +static const char *system_shlib_dirs[] = { + "/lib", + "/usr/lib", +}; + +int +scan_system_shlibs(pkghash **system_shlibs, const char *rootdir) +{ + for (int i = 0; i < NELEM(system_shlib_dirs); i++) { + char *dir; + if (rootdir != NULL) { + xasprintf(&dir, "%s%s", rootdir, system_shlib_dirs[i]); + } else { + dir = xstrdup(system_shlib_dirs[i]); + } + int ret = scan_dir_for_shlibs(system_shlibs, dir); + free(dir); + if (ret != EPKG_OK) { + return (ret); + } + } + + return (EPKG_OK); +} diff --git a/scripts/completion/_pkg.in b/scripts/completion/_pkg.in index 6a13055440..af16962c57 100644 --- a/scripts/completion/_pkg.in +++ b/scripts/completion/_pkg.in @@ -108,7 +108,6 @@ _pkg_config_opts() { _values 'configuration option' \ 'ABI[ABI of package you want to install]:string' \ 'ALIAS[define local aliases for various pkg(8) standard command lines]:key/value list' \ - 'ALLOW_BASE_SHLIBS[enable base libraries analysis]:boolean:(yes no)' \ 'AUTOCLEAN[cleanout content of cache directory after upgrades or installations]:boolean:(yes no)' \ 'AUTOMERGE[automatically merge configuration files]:boolean:(yes no)' \ 'DEFAULT_ALWAYS_YES[default to "yes" for all questions requiring user confirmation]:boolean:(yes no)' \ diff --git a/tests/frontend/create-parsebin.sh b/tests/frontend/create-parsebin.sh index d46e6ae359..264dc28808 100644 --- a/tests/frontend/create-parsebin.sh +++ b/tests/frontend/create-parsebin.sh @@ -3,9 +3,7 @@ . $(atf_get_srcdir)/test_environment.sh tests_init \ - create_from_bin \ - create_from_machobinbase \ - create_from_elfbinbase + create_from_bin genmanifest() { local PKG_NAME="$1" @@ -64,9 +62,6 @@ categories [ "test", ] EOF - if [ x"${ALLOW_BASE_SHLIBS}" = xyes ]; then - Xshlibs_required="${Xshlibs_required_base}" - fi if [ -n "${Xshlibs_required}" ]; then echo "shlibs_required [" >> ${PKG_NAME}.expected for i in ${Xshlibs_required}; do @@ -97,22 +92,17 @@ EOF } do_check() { - ALLOW_BASE_SHLIBS=$1 - local PKG_NAME=$2 - local file1=$(atf_get_srcdir)/$3 + local PKG_NAME=$1 + local file1=$(atf_get_srcdir)/$2 genmanifest ${PKG_NAME} ${file1} - atf_check \ - -o inline:"${ALLOW_BASE_SHLIBS}\n" \ - pkg -o IGNORE_OSMAJOR=1 -o ABI_FILE=${file1} -o ALLOW_BASE_SHLIBS=${ALLOW_BASE_SHLIBS} config allow_base_shlibs - # cat ${PKG_NAME}.manifest atf_check \ -o empty \ -e empty \ -s exit:0 \ - pkg -o IGNORE_OSMAJOR=1 -o ABI_FILE=${file1} -o ALLOW_BASE_SHLIBS=${ALLOW_BASE_SHLIBS} create -M ./${PKG_NAME}.manifest -r ${TMPDIR} + pkg -o IGNORE_OSMAJOR=1 -o ABI_FILE=${file1} create -M ./${PKG_NAME}.manifest -r ${TMPDIR} # cat ${PKG_NAME}.expected atf_check \ @@ -131,31 +121,6 @@ create_from_bin_body() { macosfat.bin "macosfat.bin#x86_64" "macosfat.bin#aarch64" \ macosfatlib.bin "macosfatlib.bin#x86_64" "macosfatlib.bin#aarch64" do - do_check no testbin $bin + do_check testbin $bin done } - -create_from_machobinbase_body() { - for bin in \ - macos.bin macos106.bin macos150.bin \ - macosfat.bin "macosfat.bin#x86_64" "macosfat.bin#aarch64" \ - macosfatlib.bin "macosfatlib.bin#x86_64" "macosfatlib.bin#aarch64" - do - do_check yes machobinbase $bin - done -} - -create_from_elfbinbase_body() { - atf_skip_on Linux Test fails on Linux - atf_skip_on Darwin Test fails on Darwin - - # FIXME: All ELF readers are failing on non-native runs. - for bin in \ - freebsd-aarch64.bin freebsd-amd64.bin freebsd-armv6.bin freebsd-armv7.bin \ - freebsd-i386.bin freebsd-powerpc.bin freebsd-powerpc64.bin freebsd-powerpc64le.bin \ - freebsd-riscv64.bin \ - linux.bin dfly.bin - do - do_check yes elfbinbase $bin - done -} \ No newline at end of file diff --git a/tests/frontend/test_environment.sh.in b/tests/frontend/test_environment.sh.in index fe97ff1422..f02a5e0419 100755 --- a/tests/frontend/test_environment.sh.in +++ b/tests/frontend/test_environment.sh.in @@ -58,103 +58,102 @@ bin_meta() { XFreeBSD_version="" Xshlibs_provided="" Xshlibs_required="" - Xshlibs_required_base="" case "${file}" in *freebsd-aarch64.bin) XABI=FreeBSD:14:aarch64 XALTABI=freebsd:14:aarch64:64 XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-amd64.bin) XABI=FreeBSD:14:amd64 XALTABI=freebsd:14:x86:64 XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-armv6.bin) XABI=FreeBSD:13:armv6 XALTABI=freebsd:13:armv6:32:el:eabi:hardfp XFreeBSD_version=1304000 - Xshlibs_required_base="libgcc_s.so.1 libc.so.7" + Xshlibs_required="libgcc_s.so.1 libc.so.7" ;; *freebsd-armv7.bin) XABI=FreeBSD:14:armv7 XALTABI=freebsd:14:armv7:32:el:eabi:hardfp XFreeBSD_version=1401000 - Xshlibs_required_base="libgcc_s.so.1 libc.so.7" + Xshlibs_required="libgcc_s.so.1 libc.so.7" ;; *freebsd-i386.bin) XABI=FreeBSD:14:i386 XALTABI=freebsd:14:x86:32 XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-powerpc.bin) XABI=FreeBSD:14:powerpc XALTABI=freebsd:14:powerpc:32:eb XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-powerpc64.bin) XABI=FreeBSD:14:powerpc64 XALTABI=freebsd:14:powerpc:64:eb XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-powerpc64le.bin) XABI=FreeBSD:14:powerpc64le XALTABI=freebsd:14:powerpc:64:el XFreeBSD_version=1401000 - Xshlibs_required_base="libc.so.7" + Xshlibs_required="libc.so.7" ;; *freebsd-riscv64.bin) XABI=FreeBSD:14:riscv64 XALTABI=freebsd:14:riscv:64:hf XFreeBSD_version=1401000 -# Xshlibs_required_base="libc.so.7" +# This riscv64 binary does not have the OS set to FreeBSD in its ELF header +# TODO: handle this in pkg_elf.c +# Xshlibs_required="libc.so.7" ;; *dfly.bin) XABI=dragonfly:5.10:x86:64 XALTABI=dragonfly:5.10:x86:64 -# Xshlibs_required_base="libc.so.8" + Xshlibs_required="libc.so.8" ;; *linux.bin) XABI=Linux:3.2:x86_64 XALTABI=linux:3.2:x86_64 -# Xshlibs_required_base="libc.so.6" + Xshlibs_required="libc.so.6" ;; *macos.bin) XABI=Darwin:24:aarch64 XALTABI=darwin:24:aarch64:64 - Xshlibs_required_base="libSystem.B.dylib-1351.0" + Xshlibs_required="libSystem.B.dylib-1351.0" ;; *macos106.bin) XABI=Darwin:10:x86_64 XALTABI=darwin:10:x86_64 - Xshlibs_required_base="libSystem.B.dylib-125.2.11" + Xshlibs_required="libSystem.B.dylib-125.2.11" ;; *macos150.bin) XABI=Darwin:24:x86_64 XALTABI=darwin:24:x86_64 - Xshlibs_required_base="libSystem.B.dylib-1351.0" + Xshlibs_required="libSystem.B.dylib-1351.0" ;; # macosfat.bin has x86_64 as its first entry *macosfat.bin|*macosfat.bin#x86_64) XABI=Darwin:17:x86_64 XALTABI=darwin:17:x86_64 - Xshlibs_required="libAnswer.A.dylib-1.2" - Xshlibs_required_base="libAnswer.A.dylib-1.2 libSystem.B.dylib-1319.0" + Xshlibs_required="libAnswer.A.dylib-1.2 libSystem.B.dylib-1319.0" ;; # macosfat also has an aarch64 entry *macosfat.bin#aarch64) XABI=Darwin:20:aarch64 XALTABI=darwin:20:aarch64:64 - Xshlibs_required="libAnswer.A.dylib-1.1" - Xshlibs_required_base="libAnswer.A.dylib-1.1 libSystem.B.dylib-1319.0" + Xshlibs_required="libAnswer.A.dylib-1.1 libSystem.B.dylib-1319.0" ;; # macosfatlib.bin has x86_64 as its first entry @@ -162,14 +161,14 @@ bin_meta() { XABI=Darwin:17:x86_64 XALTABI=darwin:17:x86_64 Xshlibs_provided="libAnswer.A.dylib-1.2" - Xshlibs_required_base="libSystem.B.dylib-1319.0" + Xshlibs_required="libSystem.B.dylib-1319.0" ;; *macosfatlib.bin#aarch64) XABI=Darwin:20:aarch64 XALTABI=darwin:20:aarch64:64 Xshlibs_provided="libAnswer.A.dylib-1.1" - Xshlibs_required_base="libSystem.B.dylib-1319.0" + Xshlibs_required="libSystem.B.dylib-1319.0" ;; *) diff --git a/tests/lib/pkg_elf.c b/tests/lib/pkg_elf.c index c26b4b03fc..6af751f667 100644 --- a/tests/lib/pkg_elf.c +++ b/tests/lib/pkg_elf.c @@ -61,22 +61,25 @@ ATF_TC_BODY(analyse_elf, tc) ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath), EPKG_OK); ATF_REQUIRE_EQ(tll_length(p->shlibs_provided), 1); ATF_REQUIRE_STREQ(tll_front(p->shlibs_provided), "libtestfbsd.so.1"); + ATF_REQUIRE_EQ(tll_length(p->shlibs_required), 1); + ATF_REQUIRE_STREQ(tll_front(p->shlibs_required), "libc.so.7"); free(binpath); xasprintf(&binpath, "%s/Makefile", atf_tc_get_config_var(tc, "srcdir")); ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath), EPKG_END); ATF_REQUIRE_EQ(tll_length(p->shlibs_provided), 1); + ATF_REQUIRE_EQ(tll_length(p->shlibs_required), 1); free(binpath); - ATF_REQUIRE_EQ(tll_length(p->shlibs_required), 0); xasprintf(&binpath, "%s/frontend/libtest2fbsd.so.1", atf_tc_get_config_var(tc, "srcdir")); ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath), EPKG_OK); ATF_REQUIRE_EQ(tll_length(p->shlibs_provided), 2); ATF_REQUIRE_STREQ(tll_back(p->shlibs_provided), "libtest2fbsd.so.1"); - ATF_REQUIRE_EQ(tll_length(p->shlibs_required), 1); - ATF_REQUIRE_STREQ(tll_front(p->shlibs_required), "libfoo.so.1"); + ATF_REQUIRE_EQ(tll_length(p->shlibs_required), 2); + ATF_REQUIRE_STREQ(tll_front(p->shlibs_required), "libc.so.7"); + ATF_REQUIRE_STREQ(tll_back(p->shlibs_required), "libfoo.so.1"); free(binpath); - + pkg_free(p); }