x86-qemu,boot: fix strict aliasing bug by union

* In gcc 12, by the strict-aliasing rule, gcc will consider elf32 and
  buf during calling copy_from_disk() point to different memory area.
  This will let gcc move the checking of EM_X86_64 ahead of
  copy_from_disk(), causing incorrectly parsing the x86_64 ELF header as
  x86_32.
This commit is contained in:
Zihao Yu 2024-06-01 11:02:06 +08:00
parent c52a41181f
commit de78d6ca0a

View file

@ -64,27 +64,29 @@ static void load_elf32(Elf32_Ehdr *elf) {
} }
void load_kernel(void) { void load_kernel(void) {
Elf32_Ehdr *elf32 = (void *)0x8000; union {
Elf64_Ehdr *elf64 = (void *)0x8000; Elf32_Ehdr elf32;
Elf64_Ehdr elf64;
} *u = (void *)0x8000;
int is_ap = boot_record()->is_ap; int is_ap = boot_record()->is_ap;
if (!is_ap) { if (!is_ap) {
// load argument (string) to memory // load argument (string) to memory
copy_from_disk((void *)MAINARG_ADDR, 1024, -1024); copy_from_disk((void *)MAINARG_ADDR, 1024, -1024);
// load elf header to memory // load elf header to memory
copy_from_disk(elf32, 4096, 0); copy_from_disk(u, 4096, 0);
if (elf32->e_machine == EM_X86_64) { if (u->elf32.e_machine == EM_X86_64) {
load_elf64(elf64); load_elf64(&u->elf64);
} else { } else {
load_elf32(elf32); load_elf32(&u->elf32);
} }
} else { } else {
// everything should be loaded // everything should be loaded
} }
if (elf32->e_machine == EM_X86_64) { if (u->elf32.e_machine == EM_X86_64) {
((void(*)())(uint32_t)elf64->e_entry)(); ((void(*)())(uint32_t)(u->elf64.e_entry))();
} else { } else {
((void(*)())(uint32_t)elf32->e_entry)(); ((void(*)())(uint32_t)(u->elf32.e_entry))();
} }
} }