Page MenuHomeFreeBSD

D34677.diff
No OneTemporary

D34677.diff

diff --git a/sbin/ldconfig/elfhints.c b/sbin/ldconfig/elfhints.c
--- a/sbin/ldconfig/elfhints.c
+++ b/sbin/ldconfig/elfhints.c
@@ -29,6 +29,7 @@
*/
#include <sys/param.h>
+#include <sys/endian.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -50,8 +51,8 @@
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 write_elf_hints(const char *);
+static bool read_elf_hints(const char *, bool, bool, bool);
+static void write_elf_hints(const char *, bool);
static const char *dirs[MAXDIRS];
static int ndirs;
@@ -97,7 +98,7 @@
int i;
int nlibs;
- read_elf_hints(hintsfile, 1);
+ (void)read_elf_hints(hintsfile, 1, false, false);
printf("%s:\n", hintsfile);
printf("\tsearch directories:");
for (i = 0; i < ndirs; i++)
@@ -185,8 +186,12 @@
fclose(fp);
}
-static void
-read_elf_hints(const char *hintsfile, bool must_exist)
+/* Convert between native byte order and forced little resp. big endian. */
+#define COND_SWAP(n) (is_le ? le32toh(n) : be32toh(n))
+
+static bool
+read_elf_hints(const char *hintsfile, bool must_exist, bool force_be,
+ bool force_le)
{
int fd;
struct stat s;
@@ -195,10 +200,11 @@
char *strtab;
char *dirlist;
char *p;
+ bool is_le;
if ((fd = open(hintsfile, O_RDONLY)) == -1) {
if (errno == ENOENT && !must_exist)
- return;
+ return (((htole32(1) == 1) || force_le) && !force_be);
err(1, "Cannot open \"%s\"", hintsfile);
}
if (fstat(fd, &s) == -1)
@@ -216,28 +222,36 @@
close(fd);
hdr = (struct elfhints_hdr *)mapbase;
- if (hdr->magic != ELFHINTS_MAGIC)
+ is_le = (le32toh(hdr->magic) == ELFHINTS_MAGIC);
+ if (!is_le && be32toh(hdr->magic) != ELFHINTS_MAGIC)
errx(1, "\"%s\": invalid file format", hintsfile);
- if (hdr->version != 1)
+ if ((force_be && is_le) || (force_le && !is_le))
+ errx(1, "\"%s\": incompatible endianness requested", hintsfile);
+ if (COND_SWAP(hdr->version) != 1)
errx(1, "\"%s\": unrecognized file version (%d)", hintsfile,
- hdr->version);
+ COND_SWAP(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)
add_dir(hintsfile, p, 1);
+ return (is_le);
}
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, bool force_le)
{
struct stat s;
int i;
+ bool is_le;
if (merge)
- read_elf_hints(hintsfile, false);
+ is_le = read_elf_hints(hintsfile, false, force_be, force_le);
+ else
+ is_le = ((htole32(1) == 1) || force_le) && !force_be;
for (i = 0; i < argc; i++) {
if (stat(argv[i], &s) == -1)
warn("warning: %s", argv[i]);
@@ -246,11 +260,11 @@
else
add_dir(hintsfile, argv[i], 0);
}
- write_elf_hints(hintsfile);
+ write_elf_hints(hintsfile, is_le);
}
static void
-write_elf_hints(const char *hintsfile)
+write_elf_hints(const char *hintsfile, bool is_le)
{
struct elfhints_hdr hdr;
char *tempname;
@@ -267,9 +281,9 @@
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);
@@ -280,8 +294,10 @@
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.h b/sbin/ldconfig/ldconfig.h
--- a/sbin/ldconfig/ldconfig.h
+++ b/sbin/ldconfig/ldconfig.h
@@ -38,7 +38,7 @@
__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, bool);
__END_DECLS
#endif
diff --git a/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8
--- a/sbin/ldconfig/ldconfig.8
+++ b/sbin/ldconfig/ldconfig.8
@@ -105,16 +105,29 @@
.It Fl 32
Generate the hints for 32-bit ABI shared libraries
on 64-bit systems that support running 32-bit binaries.
+.It Fl 32b
+Generate the hints for 32-bit ABI shared libraries
+on 64-bit systems that support running 32-bit binaries
+for use by a big-endian CPU.
+.It Fl 32l
+Generate the hints for 32-bit ABI shared libraries
+on 64-bit systems that support running 32-bit binaries
+for use by a little-endian CPU.
+.It Fl 64b
+Generate the hints for for use by a big-endian 64-bit CPU.
+.It Fl 64l
+Generate the hints for for use by a little-endian 64-bit CPU.
.It Fl elf
Ignored for backwards compatibility.
.It Fl R
Appends pathnames on the command line to the directory list from
the hints file.
.Pp
-This is the default action when no options are given.
+This is the default action when no file or directory arguments are given.
.It Fl f Ar hints_file
Read and/or update the specified hints file, instead of the standard file.
-This option is provided primarily for testing.
+This option is provided for testing and to e.g. allow updating a hints
+file in a file system prepared for a CPU with different endianness.
.It Fl i
Run in insecure mode.
The security checks will not be performed.
diff --git a/sbin/ldconfig/ldconfig.c b/sbin/ldconfig/ldconfig.c
--- a/sbin/ldconfig/ldconfig.c
+++ b/sbin/ldconfig/ldconfig.c
@@ -57,7 +57,7 @@
{
const char *hints_file;
int c;
- bool is_32, justread, merge, rescan, verbose;
+ bool is_32, justread, merge, rescan, verbose, force_be, force_le;
is_32 = justread = merge = rescan = verbose = false;
@@ -67,8 +67,16 @@
} else if (strcmp(argv[1], "-elf") == 0) {
argc--;
argv++;
- } else if (strcmp(argv[1], "-32") == 0) {
+ } else if (strncmp(argv[1], "-32", 3) == 0) {
is_32 = true;
+ force_be = (argv[1][3] == 'b');
+ force_le = (argv[1][3] == 'l');
+ argc--;
+ argv++;
+ } else if (strncmp(argv[1], "-64", 3) == 0) {
+ is_32 = false;
+ force_be = (argv[1][3] == 'b');
+ force_le = (argv[1][3] == 'l');
argc--;
argv++;
} else {
@@ -115,7 +123,7 @@
if (argc == optind)
rescan = true;
update_elf_hints(hints_file, argc - optind,
- argv + optind, merge || rescan);
+ argv + optind, merge || rescan, force_be, force_le);
}
exit(0);
}
@@ -124,7 +132,7 @@
usage(void)
{
fprintf(stderr,
- "usage: ldconfig [-32] [-elf] [-Rimrv] [-f hints_file] "
- "[directory | file ...]\n");
+ "usage: ldconfig [-32|-32b|-32l|-64b|-64l] [-elf] [-Rimrv] "
+ "[-f hints_file] [directory | file ...]\n");
exit(1);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 23, 2:55 AM (9 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24079490
Default Alt Text
D34677.diff (6 KB)

Event Timeline