modpost: detect endianness on run-time
Endianness is currently detected on compile-time, but we can defer this until run-time. This change avoids re-executing scripts/mod/mk_elfconfig even if modpost in the linux-headers package needs to be rebuilt for a foreign architecture. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>pull/963/head
parent
4f32f799a9
commit
a660deb0f1
|
|
@ -8,7 +8,6 @@ int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
unsigned char ei[EI_NIDENT];
|
unsigned char ei[EI_NIDENT];
|
||||||
union { short s; char c[2]; } endian_test;
|
|
||||||
|
|
||||||
if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
|
if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
|
||||||
fprintf(stderr, "Error: input truncated\n");
|
fprintf(stderr, "Error: input truncated\n");
|
||||||
|
|
@ -28,24 +27,6 @@ main(int argc, char **argv)
|
||||||
default:
|
default:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
switch (ei[EI_DATA]) {
|
|
||||||
case ELFDATA2LSB:
|
|
||||||
printf("#define KERNEL_ELFDATA ELFDATA2LSB\n");
|
|
||||||
break;
|
|
||||||
case ELFDATA2MSB:
|
|
||||||
printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
endian_test.s = 0x0102;
|
|
||||||
if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
|
|
||||||
printf("#define HOST_ELFDATA ELFDATA2MSB\n");
|
|
||||||
else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
|
|
||||||
printf("#define HOST_ELFDATA ELFDATA2LSB\n");
|
|
||||||
else
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ static bool error_occurred;
|
||||||
|
|
||||||
static bool extra_warn;
|
static bool extra_warn;
|
||||||
|
|
||||||
|
bool target_is_big_endian;
|
||||||
|
bool host_is_big_endian;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cut off the warnings when there are too many. This typically occurs when
|
* Cut off the warnings when there are too many. This typically occurs when
|
||||||
* vmlinux is missing. ('make modules' without building vmlinux.)
|
* vmlinux is missing. ('make modules' without building vmlinux.)
|
||||||
|
|
@ -438,6 +441,18 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
||||||
/* Not an ELF file - silently ignore it */
|
/* Not an ELF file - silently ignore it */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (hdr->e_ident[EI_DATA]) {
|
||||||
|
case ELFDATA2LSB:
|
||||||
|
target_is_big_endian = false;
|
||||||
|
break;
|
||||||
|
case ELFDATA2MSB:
|
||||||
|
target_is_big_endian = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("target endian is unknown\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix endianness in ELF header */
|
/* Fix endianness in ELF header */
|
||||||
hdr->e_type = TO_NATIVE(hdr->e_type);
|
hdr->e_type = TO_NATIVE(hdr->e_type);
|
||||||
hdr->e_machine = TO_NATIVE(hdr->e_machine);
|
hdr->e_machine = TO_NATIVE(hdr->e_machine);
|
||||||
|
|
@ -2117,6 +2132,25 @@ struct dump_list {
|
||||||
const char *file;
|
const char *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void check_host_endian(void)
|
||||||
|
{
|
||||||
|
static const union {
|
||||||
|
short s;
|
||||||
|
char c[2];
|
||||||
|
} endian_test = { .c = {0x01, 0x02} };
|
||||||
|
|
||||||
|
switch (endian_test.s) {
|
||||||
|
case 0x0102:
|
||||||
|
host_is_big_endian = true;
|
||||||
|
break;
|
||||||
|
case 0x0201:
|
||||||
|
host_is_big_endian = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("Unknown host endian\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct module *mod;
|
struct module *mod;
|
||||||
|
|
@ -2181,6 +2215,8 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_host_endian();
|
||||||
|
|
||||||
list_for_each_entry_safe(dl, dl2, &dump_lists, list) {
|
list_for_each_entry_safe(dl, dl2, &dump_lists, list) {
|
||||||
read_dump(dl->file);
|
read_dump(dl->file);
|
||||||
list_del(&dl->list);
|
list_del(&dl->list);
|
||||||
|
|
|
||||||
|
|
@ -62,15 +62,8 @@
|
||||||
x); \
|
x); \
|
||||||
})
|
})
|
||||||
|
|
||||||
#if KERNEL_ELFDATA != HOST_ELFDATA
|
#define TO_NATIVE(x) \
|
||||||
|
(target_is_big_endian == host_is_big_endian ? x : bswap(x))
|
||||||
#define TO_NATIVE(x) (bswap(x))
|
|
||||||
|
|
||||||
#else /* endianness matches */
|
|
||||||
|
|
||||||
#define TO_NATIVE(x) (x)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NOFAIL(ptr) do_nofail((ptr), #ptr)
|
#define NOFAIL(ptr) do_nofail((ptr), #ptr)
|
||||||
|
|
||||||
|
|
@ -187,6 +180,8 @@ void add_moddevtable(struct buffer *buf, struct module *mod);
|
||||||
void get_src_version(const char *modname, char sum[], unsigned sumlen);
|
void get_src_version(const char *modname, char sum[], unsigned sumlen);
|
||||||
|
|
||||||
/* from modpost.c */
|
/* from modpost.c */
|
||||||
|
extern bool target_is_big_endian;
|
||||||
|
extern bool host_is_big_endian;
|
||||||
char *read_text_file(const char *filename);
|
char *read_text_file(const char *filename);
|
||||||
char *get_line(char **stringp);
|
char *get_line(char **stringp);
|
||||||
void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
|
void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue