The branch stable/14 has been updated by se:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fa7b31166ddb93eddead4c814c5f5e4c0bd38dd7

commit fa7b31166ddb93eddead4c814c5f5e4c0bd38dd7
Author:     Stefan Eßer <s...@freebsd.org>
AuthorDate: 2024-02-28 17:49:29 +0000
Commit:     Stefan Eßer <s...@freebsd.org>
CommitDate: 2024-03-29 06:49:02 +0000

    ldconfig: support hints files of either byte-order
    
    Make the ldconfig program accept hints files in little-endian and
    big-endian format on all architectures.
    
    The default format is the native byte-order of the respective host.
    This is expected to change when a version of the pkg command is
    available that implements support for either byte-order in its
    internal ldconfig function. (Already committed in the development
    tree of the pkg utility, a release is expected at the end of Q1/2024).
    
    This update adds the -B option to the ldconfig program. It enforces
    the creation of a big-endian hints file on a little-endian host.
    The main purpose to is support of tests with non-native byte-order
    files on little-endian hosts. It will be removed when all supported
    FreeBSD releases use little-endian hints files by default.
    
    When little-endian hints files are generally used, support of
    either byte-order in libexec/rtld can also be removed.
    
    When support for big-endian hints files is no longer required,
    the COND_SWAP macro in ldconfig and rtld shall be replaced by
    le32toh(), which just return their argument on little-endian
    architectures.
    
    Approved by:    kib
    Relnotes:       yes
    Differential Revision:  https://reviews.freebsd.org/D44093
    
    (cherry picked from commit e0dfecadf5946b6a8ad423be4eb1c14017b3a8a7)
---
 sbin/ldconfig/elfhints.c | 46 ++++++++++++++++++++++++++++++++--------------
 sbin/ldconfig/ldconfig.8 | 11 ++++++++---
 sbin/ldconfig/ldconfig.c | 13 ++++++++-----
 sbin/ldconfig/ldconfig.h |  2 +-
 4 files changed, 49 insertions(+), 23 deletions(-)

diff --git a/sbin/ldconfig/elfhints.c b/sbin/ldconfig/elfhints.c
index 72b9273ab93a..d6ee5e0918d6 100644
--- a/sbin/ldconfig/elfhints.c
+++ b/sbin/ldconfig/elfhints.c
@@ -27,6 +27,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/endian.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
@@ -48,11 +49,12 @@
 
 static void    add_dir(const char *, const char *, bool);
 static void    read_dirs_from_file(const char *, const char *);
-static void    read_elf_hints(const char *, bool);
+static void    read_elf_hints(const char *, bool, bool);
 static void    write_elf_hints(const char *);
 
 static const char      *dirs[MAXDIRS];
 static int              ndirs;
+static bool             is_be;
 bool                    insecure;
 
 static void
@@ -95,7 +97,7 @@ list_elf_hints(const char *hintsfile)
        int     i;
        int     nlibs;
 
-       read_elf_hints(hintsfile, 1);
+       read_elf_hints(hintsfile, true, false);
        printf("%s:\n", hintsfile);
        printf("\tsearch directories:");
        for (i = 0;  i < ndirs;  i++)
@@ -183,8 +185,11 @@ read_dirs_from_file(const char *hintsfile, const char 
*listfile)
        fclose(fp);
 }
 
+/* Convert between native byte order and forced little resp. big endian. */
+#define COND_SWAP(n) (is_be ? be32toh(n) : le32toh(n))
+
 static void
-read_elf_hints(const char *hintsfile, bool must_exist)
+read_elf_hints(const char *hintsfile, bool must_exist, bool force_be)
 {
        int                      fd;
        struct stat              s;
@@ -193,6 +198,7 @@ read_elf_hints(const char *hintsfile, bool must_exist)
        char                    *strtab;
        char                    *dirlist;
        char                    *p;
+       int                      hdr_version;
 
        if ((fd = open(hintsfile, O_RDONLY)) == -1) {
                if (errno == ENOENT && !must_exist)
@@ -214,14 +220,18 @@ read_elf_hints(const char *hintsfile, bool must_exist)
        close(fd);
 
        hdr = (struct elfhints_hdr *)mapbase;
-       if (hdr->magic != ELFHINTS_MAGIC)
+       is_be = be32toh(hdr->magic) == ELFHINTS_MAGIC;
+       if (COND_SWAP(hdr->magic) != ELFHINTS_MAGIC)
                errx(1, "\"%s\": invalid file format", hintsfile);
-       if (hdr->version != 1)
+       if (force_be && !is_be)
+               errx(1, "\"%s\": incompatible endianness requested", hintsfile);
+       hdr_version = COND_SWAP(hdr->version);
+       if (hdr_version != 1)
                errx(1, "\"%s\": unrecognized file version (%d)", hintsfile,
-                   hdr->version);
+                   hdr_version);
 
-       strtab = (char *)mapbase + hdr->strtab;
-       dirlist = strtab + hdr->dirlist;
+       strtab = (char *)mapbase + COND_SWAP(hdr->strtab);
+       dirlist = strtab + COND_SWAP(hdr->dirlist);
 
        if (*dirlist != '\0')
                while ((p = strsep(&dirlist, ":")) != NULL)
@@ -229,13 +239,19 @@ read_elf_hints(const char *hintsfile, bool must_exist)
 }
 
 void
-update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge)
+update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge,
+    bool force_be)
 {
        struct stat s;
        int i;
 
+       /*
+        * Remove "be32toh(1) == 1" from this condition to create
+        * little-endian hints files on all architectures by default.
+        */
+       is_be = be32toh(1) == 1 || force_be;
        if (merge)
-               read_elf_hints(hintsfile, false);
+               read_elf_hints(hintsfile, false, force_be);
        for (i = 0;  i < argc;  i++) {
                if (stat(argv[i], &s) == -1)
                        warn("warning: %s", argv[i]);
@@ -265,9 +281,9 @@ write_elf_hints(const char *hintsfile)
        if ((fp = fdopen(fd, "wb")) == NULL)
                err(1, "fdopen(%s)", tempname);
 
-       hdr.magic = ELFHINTS_MAGIC;
-       hdr.version = 1;
-       hdr.strtab = sizeof hdr;
+       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);
@@ -278,8 +294,10 @@ write_elf_hints(const char *hintsfile)
                for (i = 1;  i < ndirs;  i++)
                        hdr.strsize += 1 + strlen(dirs[i]);
        }
-       hdr.dirlistlen = hdr.strsize;
+       hdr.dirlistlen = COND_SWAP(hdr.strsize);
        hdr.strsize++;  /* For the null terminator */
+       /* convert in-place from native to target endianness */
+       hdr.strsize = COND_SWAP(hdr.strsize);
 
        /* Write the header. */
        if (fwrite(&hdr, 1, sizeof hdr, fp) != sizeof hdr)
diff --git a/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8
index 47e0dfa99b50..88d99567912e 100644
--- a/sbin/ldconfig/ldconfig.8
+++ b/sbin/ldconfig/ldconfig.8
@@ -32,7 +32,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 15, 2021
+.Dd February 28, 2024
 .Dt LDCONFIG 8
 .Os
 .Sh NAME
@@ -41,7 +41,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl 32
-.Op Fl Rimrv
+.Op Fl BRimrv
 .Op Fl f Ar hints_file
 .Op Ar directory | Ar
 .Sh DESCRIPTION
@@ -105,6 +105,11 @@ Generate the hints for 32-bit ABI shared libraries
 on 64-bit systems that support running 32-bit binaries.
 .It Fl elf
 Ignored for backwards compatibility.
+.It Fl B
+Force writing big-endian binary data´to the hints file.
+The default is to create little-endian hints files on all architectures.
+Reading of and merging into hints files preserves the endianness of the
+existing hints file.
 .It Fl R
 Appends pathnames on the command line to the directory list from
 the hints file.
@@ -159,7 +164,7 @@ invocations with
 .El
 .Sh SEE ALSO
 .Xr ld 1 ,
-.Xr ld-elf.so.1 ,
+.Xr ld-elf.so.1 1 ,
 .Xr link 5
 .Sh HISTORY
 A
diff --git a/sbin/ldconfig/ldconfig.c b/sbin/ldconfig/ldconfig.c
index 2f5cdbd6505e..0eb9cb801ac2 100644
--- a/sbin/ldconfig/ldconfig.c
+++ b/sbin/ldconfig/ldconfig.c
@@ -57,9 +57,9 @@ main(int argc, char **argv)
 {
        const char *hints_file;
        int c;
-       bool is_32, justread, merge, rescan, verbose;
+       bool is_32, justread, merge, rescan, force_be, verbose;
 
-       is_32 = justread = merge = rescan = verbose = false;
+       force_be = is_32 = justread = merge = rescan = verbose = false;
 
        while (argc > 1) {
                if (strcmp(argv[1], "-aout") == 0) {
@@ -80,8 +80,11 @@ main(int argc, char **argv)
                hints_file = __PATH_ELF_HINTS("32");
        else
                hints_file = _PATH_ELF_HINTS;
-       while((c = getopt(argc, argv, "Rf:imrsv")) != -1) {
+       while((c = getopt(argc, argv, "BRf:imrsv")) != -1) {
                switch (c) {
+               case 'B':
+                       force_be = true;
+                       break;
                case 'R':
                        rescan = true;
                        break;
@@ -115,7 +118,7 @@ main(int argc, char **argv)
                if (argc == optind)
                        rescan = true;
                update_elf_hints(hints_file, argc - optind,
-                   argv + optind, merge || rescan);
+                   argv + optind, merge || rescan, force_be);
        }
        exit(0);
 }
@@ -124,7 +127,7 @@ static void
 usage(void)
 {
        fprintf(stderr,
-           "usage: ldconfig [-32] [-elf] [-Rimrv] [-f hints_file] "
+           "usage: ldconfig [-32] [-elf] [-BRimrv] [-f hints_file]"
            "[directory | file ...]\n");
        exit(1);
 }
diff --git a/sbin/ldconfig/ldconfig.h b/sbin/ldconfig/ldconfig.h
index e03ba928be7d..aa7ad810bacd 100644
--- a/sbin/ldconfig/ldconfig.h
+++ b/sbin/ldconfig/ldconfig.h
@@ -36,7 +36,7 @@ extern bool insecure;         /* -i flag, needed here for 
elfhints.c */
 
 __BEGIN_DECLS
 void   list_elf_hints(const char *);
-void   update_elf_hints(const char *, int, char **, bool);
+void   update_elf_hints(const char *, int, char **, bool, bool);
 __END_DECLS
 
 #endif

Reply via email to