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
This commit is contained in:
parent
4eac63af23
commit
4a27bf128b
@ -52,10 +52,10 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
static bool convert_to_feature_val(char *, uint32_t *);
|
static bool convert_to_feature_val(char *, uint32_t *);
|
||||||
static bool edit_file_features(Elf *, int, int, char *);
|
static bool edit_file_features(Elf *, int, int, char *, bool);
|
||||||
static bool get_file_features(Elf *, int, int, uint32_t *, uint64_t *);
|
static bool get_file_features(Elf *, int, int, uint32_t *, uint64_t *, bool);
|
||||||
static void print_features(void);
|
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);
|
static void usage(void);
|
||||||
|
|
||||||
struct ControlFeatures {
|
struct ControlFeatures {
|
||||||
@ -81,9 +81,11 @@ static struct option long_opts[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
#define SUPPORTED_ENDIAN ELFDATA2LSB
|
#define HOST_ENDIAN ELFDATA2LSB
|
||||||
|
#define SWAP_ENDIAN ELFDATA2MSB
|
||||||
#else
|
#else
|
||||||
#define SUPPORTED_ENDIAN ELFDATA2MSB
|
#define HOST_ENDIAN ELFDATA2MSB
|
||||||
|
#define SWAP_ENDIAN ELFDATA2LSB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool iflag;
|
static bool iflag;
|
||||||
@ -96,7 +98,7 @@ main(int argc, char **argv)
|
|||||||
Elf_Kind kind;
|
Elf_Kind kind;
|
||||||
int ch, fd, retval;
|
int ch, fd, retval;
|
||||||
char *features;
|
char *features;
|
||||||
bool editfeatures, lflag;
|
bool editfeatures, lflag, endian_swap;
|
||||||
|
|
||||||
lflag = 0;
|
lflag = 0;
|
||||||
editfeatures = false;
|
editfeatures = false;
|
||||||
@ -165,24 +167,25 @@ main(int argc, char **argv)
|
|||||||
retval = 1;
|
retval = 1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* XXX need to support cross-endian operation, but for now
|
if (ehdr.e_ident[EI_DATA] == HOST_ENDIAN) {
|
||||||
* exit on error rather than misbehaving.
|
endian_swap = false;
|
||||||
*/
|
} else if (ehdr.e_ident[EI_DATA] == SWAP_ENDIAN) {
|
||||||
if (ehdr.e_ident[EI_DATA] != SUPPORTED_ENDIAN) {
|
endian_swap = true;
|
||||||
warnx("file endianness must match host");
|
} else {
|
||||||
|
warnx("file endianness unknown");
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!editfeatures) {
|
if (!editfeatures) {
|
||||||
if (!print_file_features(elf, ehdr.e_phnum, fd,
|
if (!print_file_features(elf, ehdr.e_phnum, fd,
|
||||||
argv[0])) {
|
argv[0], endian_swap)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else if (!edit_file_features(elf, ehdr.e_phnum, fd,
|
} else if (!edit_file_features(elf, ehdr.e_phnum, fd,
|
||||||
features)) {
|
features, endian_swap)) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -286,12 +289,13 @@ convert_to_feature_val(char *feature_str, uint32_t *feature_val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
uint32_t features;
|
||||||
uint64_t off;
|
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");
|
warnx("NT_FREEBSD_FEATURE_CTL note not found");
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
@ -299,6 +303,9 @@ edit_file_features(Elf *elf, int phcount, int fd, char *val)
|
|||||||
if (!convert_to_feature_val(val, &features))
|
if (!convert_to_feature_val(val, &features))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
if (endian_swap)
|
||||||
|
features = bswap32(features);
|
||||||
|
|
||||||
if (lseek(fd, off, SEEK_SET) == -1 ||
|
if (lseek(fd, off, SEEK_SET) == -1 ||
|
||||||
write(fd, &features, sizeof(features)) <
|
write(fd, &features, sizeof(features)) <
|
||||||
(ssize_t)sizeof(features)) {
|
(ssize_t)sizeof(features)) {
|
||||||
@ -320,12 +327,14 @@ print_features(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
uint32_t features;
|
||||||
unsigned long i;
|
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);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +353,7 @@ print_file_features(Elf *elf, int phcount, int fd, char *filename)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
|
get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
|
||||||
uint64_t *off)
|
uint64_t *off, bool endian_swap)
|
||||||
{
|
{
|
||||||
GElf_Phdr phdr;
|
GElf_Phdr phdr;
|
||||||
Elf_Note note;
|
Elf_Note note;
|
||||||
@ -379,6 +388,12 @@ get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
|
|||||||
}
|
}
|
||||||
read_total += sizeof(note);
|
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,
|
* XXX: Name and descriptor are 4 byte aligned, however,
|
||||||
* the size given doesn't include the padding.
|
* the size given doesn't include the padding.
|
||||||
@ -430,6 +445,8 @@ get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
|
|||||||
free(name);
|
free(name);
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
if (endian_swap)
|
||||||
|
*features = bswap32(*features);
|
||||||
if (off != NULL)
|
if (off != NULL)
|
||||||
*off = phdr.p_offset + read_total;
|
*off = phdr.p_offset + read_total;
|
||||||
free(name);
|
free(name);
|
||||||
|
Loading…
Reference in New Issue
Block a user