Commit a660deb0 authored by Masahiro Yamada's avatar Masahiro Yamada

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: default avatarMasahiro Yamada <masahiroy@kernel.org>
Reviewed-by: default avatarNicolas Schier <nicolas@fjasle.eu>
parent 4f32f799
...@@ -8,7 +8,6 @@ int ...@@ -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) ...@@ -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; ...@@ -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) ...@@ -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 { ...@@ -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) ...@@ -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 @@ ...@@ -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); ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment