| 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 <jackie.huang@windriver.com> |
| |
| -- |
| 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, |