Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133017779
D34677.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D34677.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D34677: Add support for both big and little endian hints files to ldconfig
Attached
Detach File
Event Timeline
Log In to Comment