Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
libpkg: make shlib handling portable
Isaac Freund committed 1 year ago
commit 6462d8a4cf0c283549e13a7436bac6f25b934836
parent cb54627
17 files changed +205 -921
modified 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 \
deleted libpkg/elfhints.c
@@ -1,559 +0,0 @@
-
/*-
-
 * Copyright (c) 1998 John D. Polstra
-
 * Copyright (c) 2012 Matthew Seaman <matthew@FreeBSD.org>
-
 * 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 <bsd_compat.h>
-
#include "private/pkg_abi.h"
-
#include <sys/mman.h>
-
#include <sys/stat.h>
-
#ifdef HAVE_SYS_ENDIAN_H
-
#include <sys/endian.h>
-
#elif HAVE_ENDIAN_H
-
#include <endian.h>
-
#elif HAVE_MACHINE_ENDIAN_H
-
#include <machine/endian.h>
-
#endif
-

-
#ifdef __APPLE__
-
#include <libkern/OSByteOrder.h>
-
#define be32toh(n) OSSwapBigToHostInt32(n)
-
#define le32toh(n) OSSwapLittleToHostInt32(n)
-
#endif
-

-
#include <assert.h>
-
#include <ctype.h>
-
#include <dirent.h>
-
#include <err.h>
-
#include <errno.h>
-
#include <fcntl.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <unistd.h>
-

-
#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);
-
}
modified 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)) {
modified libpkg/pkg_abi_macho.c
@@ -6,6 +6,7 @@

#include <errno.h>

+
#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 @@ cleanup:
	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;
modified libpkg/pkg_config.c
@@ -353,11 +353,6 @@ static struct config_entry c[] = {
		"pkg+http,pkg+https,https,http,file,ssh,tcp",
	},
	{
-
		PKG_BOOL,
-
		"ALLOW_BASE_SHLIBS",
-
		"NO",
-
	},
-
	{
		PKG_INT,
		"WARN_SIZE_LIMIT",
		"1048576", /* 1 meg */
modified 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 @@ cleanup:
	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;
}
modified 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);

modified libpkg/pkg_solve.c
@@ -40,6 +40,7 @@
#include <tllist.h>

#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;
modified 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);
deleted libpkg/private/ldconfig.h
@@ -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 <sys/cdefs.h>
-

-
#ifdef HAVE_ELF_HINTS_H
-
#include <elf-hints.h>
-
#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
modified 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
modified 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)
added libpkg/system_shlibs.c
@@ -0,0 +1,92 @@
+
/*-
+
 * Copyright (c) 1998 John D. Polstra
+
 * Copyright (c) 2012 Matthew Seaman <matthew@FreeBSD.org>
+
 * Copyright (c) 2024 The FreeBSD Foundation
+
 *
+
 * This software was developed in part by Isaac Freund <ifreund@freebsdfoundation.org>
+
 * under sponsorship from the FreeBSD Foundation.
+
 *
+
 * SPDX-License-Identifier: BSD-2-Clause
+
 */
+

+
#include <assert.h>
+
#include <ctype.h>
+
#include <dirent.h>
+
#include <errno.h>
+
#include <string.h>
+

+
#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);
+
}
modified 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)' \
modified 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
modified 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"
			;;

		*)
modified 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);
}