git: 7572ddd1671e - stable/13 - usr.bin/elfctl: Allow for cross-endian operations.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 12 Dec 2021 18:59:51 UTC
The branch stable/13 has been updated by emaste:
URL: https://cgit.FreeBSD.org/src/commit/?id=7572ddd1671e13844a470bdfbbfbe15a4b4fbfa2
commit 7572ddd1671e13844a470bdfbbfbe15a4b4fbfa2
Author: Marcin Wojtas <mw@FreeBSD.org>
AuthorDate: 2021-05-21 09:19:31 +0000
Commit: Ed Maste <emaste@FreeBSD.org>
CommitDate: 2021-12-12 18:59:30 +0000
usr.bin/elfctl: Allow for cross-endian operations.
Detect if host endian is different than target endian and swap
byte order of ELF note fields instead of failing.
Submitted by: Dawid Gorecki <dgr@semihalf.com>
Reviewed by: imp
Obtained from: Semihalf
Sponsored by: Stormshield
Differential Revision: https://reviews.freebsd.org/D29550
(cherry picked from commit 4a27bf128b108d90412190c06a54ebac36a8ca2e)
---
usr.bin/elfctl/elfctl.c | 55 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 19 deletions(-)
diff --git a/usr.bin/elfctl/elfctl.c b/usr.bin/elfctl/elfctl.c
index 04719b487613..ef7f915ded30 100644
--- a/usr.bin/elfctl/elfctl.c
+++ b/usr.bin/elfctl/elfctl.c
@@ -52,10 +52,10 @@
__FBSDID("$FreeBSD$");
static bool convert_to_feature_val(char *, uint32_t *);
-static bool edit_file_features(Elf *, int, int, char *);
-static bool get_file_features(Elf *, int, int, uint32_t *, uint64_t *);
+static bool edit_file_features(Elf *, int, int, char *, bool);
+static bool get_file_features(Elf *, int, int, uint32_t *, uint64_t *, bool);
static void print_features(void);
-static bool print_file_features(Elf *, int, int, char *);
+static bool print_file_features(Elf *, int, int, char *, bool);
static void usage(void);
struct ControlFeatures {
@@ -81,9 +81,11 @@ static struct option long_opts[] = {
};
#if BYTE_ORDER == LITTLE_ENDIAN
-#define SUPPORTED_ENDIAN ELFDATA2LSB
+#define HOST_ENDIAN ELFDATA2LSB
+#define SWAP_ENDIAN ELFDATA2MSB
#else
-#define SUPPORTED_ENDIAN ELFDATA2MSB
+#define HOST_ENDIAN ELFDATA2MSB
+#define SWAP_ENDIAN ELFDATA2LSB
#endif
static bool iflag;
@@ -96,7 +98,7 @@ main(int argc, char **argv)
Elf_Kind kind;
int ch, fd, retval;
char *features;
- bool editfeatures, lflag;
+ bool editfeatures, lflag, endian_swap;
lflag = 0;
editfeatures = false;
@@ -165,24 +167,25 @@ main(int argc, char **argv)
retval = 1;
goto fail;
}
- /*
- * XXX need to support cross-endian operation, but for now
- * exit on error rather than misbehaving.
- */
- if (ehdr.e_ident[EI_DATA] != SUPPORTED_ENDIAN) {
- warnx("file endianness must match host");
+
+ if (ehdr.e_ident[EI_DATA] == HOST_ENDIAN) {
+ endian_swap = false;
+ } else if (ehdr.e_ident[EI_DATA] == SWAP_ENDIAN) {
+ endian_swap = true;
+ } else {
+ warnx("file endianness unknown");
retval = 1;
goto fail;
}
if (!editfeatures) {
if (!print_file_features(elf, ehdr.e_phnum, fd,
- argv[0])) {
+ argv[0], endian_swap)) {
retval = 1;
goto fail;
}
} else if (!edit_file_features(elf, ehdr.e_phnum, fd,
- features)) {
+ features, endian_swap)) {
retval = 1;
goto fail;
}
@@ -286,12 +289,13 @@ convert_to_feature_val(char *feature_str, uint32_t *feature_val)
}
static bool
-edit_file_features(Elf *elf, int phcount, int fd, char *val)
+edit_file_features(Elf *elf, int phcount, int fd, char *val, bool endian_swap)
{
uint32_t features, prev_features;
uint64_t off;
- if (!get_file_features(elf, phcount, fd, &features, &off)) {
+ if (!get_file_features(elf, phcount, fd, &features, &off,
+ endian_swap)) {
warnx("NT_FREEBSD_FEATURE_CTL note not found");
return (false);
}
@@ -303,6 +307,9 @@ edit_file_features(Elf *elf, int phcount, int fd, char *val)
if (features == prev_features)
return (true);
+ if (endian_swap)
+ features = bswap32(features);
+
if (lseek(fd, off, SEEK_SET) == -1 ||
write(fd, &features, sizeof(features)) <
(ssize_t)sizeof(features)) {
@@ -324,12 +331,14 @@ print_features(void)
}
static bool
-print_file_features(Elf *elf, int phcount, int fd, char *filename)
+print_file_features(Elf *elf, int phcount, int fd, char *filename,
+ bool endian_swap)
{
uint32_t features;
unsigned long i;
- if (!get_file_features(elf, phcount, fd, &features, NULL)) {
+ if (!get_file_features(elf, phcount, fd, &features, NULL,
+ endian_swap)) {
return (false);
}
@@ -348,7 +357,7 @@ print_file_features(Elf *elf, int phcount, int fd, char *filename)
static bool
get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
- uint64_t *off)
+ uint64_t *off, bool endian_swap)
{
GElf_Phdr phdr;
Elf_Note note;
@@ -383,6 +392,12 @@ get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
}
read_total += sizeof(note);
+ if (endian_swap) {
+ note.n_namesz = bswap32(note.n_namesz);
+ note.n_descsz = bswap32(note.n_descsz);
+ note.n_type = bswap32(note.n_type);
+ }
+
/*
* XXX: Name and descriptor are 4 byte aligned, however,
* the size given doesn't include the padding.
@@ -434,6 +449,8 @@ get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
free(name);
return (false);
}
+ if (endian_swap)
+ *features = bswap32(*features);
if (off != NULL)
*off = phdr.p_offset + read_total;
free(name);