diff --git a/ChangeLog b/ChangeLog index 4e422b85a..572ee50d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2014-09-07 Colin Watson + + Support grub-emu on x32 (ILP32 but with x86-64 instruction set) + + * configure.ac: Remove -m64 from checks for -mcmodel=large and + -mno-red-zone. These are always either unnecessary (x86_64-emu) or + already in TARGET_CFLAGS at this point, and they produce incorrect + results when building for x32. + * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Cast + pointers to Elf64_Xword via grub_addr_t, in order to work on x32. + * include/grub/x86_64/types.h (GRUB_TARGET_SIZEOF_VOID_P, + GRUB_TARGET_SIZEOF_LONG): Define to 4 on x32. + 2014-09-07 Colin Watson * configure.ac: Remove several unnecessary semicolons. diff --git a/configure.ac b/configure.ac index a3610e157..8662bac68 100644 --- a/configure.ac +++ b/configure.ac @@ -862,7 +862,7 @@ LDFLAGS="$TARGET_LDFLAGS" if test "$target_cpu" = x86_64 || test "$target_cpu-$platform" = sparc64-emu ; then # Use large model to support 4G memory AC_CACHE_CHECK([whether option -mcmodel=large works], grub_cv_cc_mcmodel, [ - CFLAGS="$TARGET_CFLAGS -m64 -mcmodel=large" + CFLAGS="$TARGET_CFLAGS -mcmodel=large" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_mcmodel=yes], [grub_cv_cc_mcmodel=no]) @@ -877,7 +877,7 @@ fi if test "$target_cpu"-"$platform" = x86_64-efi; then # EFI writes to stack below %rsp, we must not use the red zone AC_CACHE_CHECK([whether option -mno-red-zone works], grub_cv_cc_no_red_zone, [ - CFLAGS="$TARGET_CFLAGS -m64 -mno-red-zone" + CFLAGS="$TARGET_CFLAGS -mno-red-zone" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_no_red_zone=yes], [grub_cv_cc_no_red_zone=no]) diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 6cb88bfcc..440690673 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -73,7 +73,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, { grub_int64_t value; value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value - - (Elf64_Xword) seg->addr - rel->r_offset; + (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; if (value != (grub_int32_t) value) return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); *addr32 = value; @@ -83,7 +83,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, case R_X86_64_PC64: { *addr64 += rel->r_addend + sym->st_value - - (Elf64_Xword) seg->addr - rel->r_offset; + (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; } break; diff --git a/include/grub/x86_64/types.h b/include/grub/x86_64/types.h index fec910952..0bbdc6d01 100644 --- a/include/grub/x86_64/types.h +++ b/include/grub/x86_64/types.h @@ -20,10 +20,14 @@ #define GRUB_TYPES_CPU_HEADER 1 /* The size of void *. */ +#ifdef __ILP32__ +#define GRUB_TARGET_SIZEOF_VOID_P 4 +#else #define GRUB_TARGET_SIZEOF_VOID_P 8 +#endif /* The size of long. */ -#ifdef __MINGW32__ +#if defined(__MINGW32__) || defined(__ILP32__) #define GRUB_TARGET_SIZEOF_LONG 4 #else #define GRUB_TARGET_SIZEOF_LONG 8