Allow a compilation without -mcmodel=large It's provided by Vladimir Serbinenko, and he will commit it upstream so it should be backport patch. Upstream-Status: Backport Signed-off-by: Jackie Huang -- diff --git a/configure.ac b/configure.ac index 9f8fb8a..2c5e6ed 100644 --- a/configure.ac +++ b/configure.ac @@ -723,9 +723,7 @@ if test "$target_cpu" = x86_64; then [grub_cv_cc_mcmodel=yes], [grub_cv_cc_mcmodel=no]) ]) - if test "x$grub_cv_cc_mcmodel" = xno; then - AC_MSG_ERROR([-mcmodel=large not supported. Upgrade your gcc.]) - else + if test "x$grub_cv_cc_mcmodel" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=large" fi fi diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c index 1409b5d..6e9dace 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -32,6 +32,12 @@ #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) #define PAGES_TO_BYTES(pages) ((pages) << 12) +#if defined (__code_model_large__) || !defined (__x86_64__) +#define MAX_USABLE_ADDRESS 0xffffffff +#else +#define MAX_USABLE_ADDRESS 0x7fffffff +#endif + /* The size of a memory map obtained from the firmware. This must be a multiplier of 4KB. */ #define MEMORY_MAP_SIZE 0x3000 @@ -58,7 +64,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, #if 1 /* Limit the memory access to less than 4GB for 32-bit platforms. */ - if (address > 0xffffffff) + if (address > MAX_USABLE_ADDRESS) return 0; #endif @@ -66,7 +72,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, if (address == 0) { type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; - address = 0xffffffff; + address = MAX_USABLE_ADDRESS; } else type = GRUB_EFI_ALLOCATE_ADDRESS; @@ -86,7 +92,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ - address = 0xffffffff; + address = MAX_USABLE_ADDRESS; status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) @@ -319,7 +325,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, { if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY #if 1 - && desc->physical_start <= 0xffffffff + && desc->physical_start <= MAX_USABLE_ADDRESS #endif && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 && desc->num_pages != 0) @@ -337,9 +343,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, #if 1 if (BYTES_TO_PAGES (filtered_desc->physical_start) + filtered_desc->num_pages - > BYTES_TO_PAGES (0x100000000LL)) + > BYTES_TO_PAGES (MAX_USABLE_ADDRESS+1LL)) filtered_desc->num_pages - = (BYTES_TO_PAGES (0x100000000LL) + = (BYTES_TO_PAGES (MAX_USABLE_ADDRESS+1LL) - BYTES_TO_PAGES (filtered_desc->physical_start)); #endif diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 65f09ef..17c1215 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -100,14 +100,32 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; case R_X86_64_PC32: - *addr32 += rel->r_addend + sym->st_value - - (Elf64_Xword) seg->addr - rel->r_offset; + { + grub_int64_t value; + value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value - + (Elf64_Xword) seg->addr - rel->r_offset; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } break; case R_X86_64_32: + { + grub_uint64_t value = *addr32 + rel->r_addend + sym->st_value; + if (value != (grub_uint32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; case R_X86_64_32S: - *addr32 += rel->r_addend + sym->st_value; - break; + { + grub_int64_t value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,