Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | Allow a compilation without -mcmodel=large |
| 2 | |
| 3 | It's provided by Vladimir Serbinenko, and he will commit |
| 4 | it upstream so it should be backport patch. |
| 5 | |
| 6 | Upstream-Status: Backport |
| 7 | |
| 8 | Signed-off-by: Jackie Huang <jackie.huang@windriver.com> |
| 9 | |
| 10 | -- |
| 11 | diff --git a/configure.ac b/configure.ac |
| 12 | index 9f8fb8a..2c5e6ed 100644 |
| 13 | --- a/configure.ac |
| 14 | +++ b/configure.ac |
| 15 | @@ -723,9 +723,7 @@ if test "$target_cpu" = x86_64; then |
| 16 | [grub_cv_cc_mcmodel=yes], |
| 17 | [grub_cv_cc_mcmodel=no]) |
| 18 | ]) |
| 19 | - if test "x$grub_cv_cc_mcmodel" = xno; then |
| 20 | - AC_MSG_ERROR([-mcmodel=large not supported. Upgrade your gcc.]) |
| 21 | - else |
| 22 | + if test "x$grub_cv_cc_mcmodel" = xyes; then |
| 23 | TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=large" |
| 24 | fi |
| 25 | fi |
| 26 | diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
| 27 | index 1409b5d..6e9dace 100644 |
| 28 | --- a/grub-core/kern/efi/mm.c |
| 29 | +++ b/grub-core/kern/efi/mm.c |
| 30 | @@ -32,6 +32,12 @@ |
| 31 | #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) |
| 32 | #define PAGES_TO_BYTES(pages) ((pages) << 12) |
| 33 | |
| 34 | +#if defined (__code_model_large__) || !defined (__x86_64__) |
| 35 | +#define MAX_USABLE_ADDRESS 0xffffffff |
| 36 | +#else |
| 37 | +#define MAX_USABLE_ADDRESS 0x7fffffff |
| 38 | +#endif |
| 39 | + |
| 40 | /* The size of a memory map obtained from the firmware. This must be |
| 41 | a multiplier of 4KB. */ |
| 42 | #define MEMORY_MAP_SIZE 0x3000 |
| 43 | @@ -58,7 +64,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, |
| 44 | |
| 45 | #if 1 |
| 46 | /* Limit the memory access to less than 4GB for 32-bit platforms. */ |
| 47 | - if (address > 0xffffffff) |
| 48 | + if (address > MAX_USABLE_ADDRESS) |
| 49 | return 0; |
| 50 | #endif |
| 51 | |
| 52 | @@ -66,7 +72,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, |
| 53 | if (address == 0) |
| 54 | { |
| 55 | type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; |
| 56 | - address = 0xffffffff; |
| 57 | + address = MAX_USABLE_ADDRESS; |
| 58 | } |
| 59 | else |
| 60 | type = GRUB_EFI_ALLOCATE_ADDRESS; |
| 61 | @@ -86,7 +92,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, |
| 62 | { |
| 63 | /* Uggh, the address 0 was allocated... This is too annoying, |
| 64 | so reallocate another one. */ |
| 65 | - address = 0xffffffff; |
| 66 | + address = MAX_USABLE_ADDRESS; |
| 67 | status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); |
| 68 | grub_efi_free_pages (0, pages); |
| 69 | if (status != GRUB_EFI_SUCCESS) |
| 70 | @@ -319,7 +325,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, |
| 71 | { |
| 72 | if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY |
| 73 | #if 1 |
| 74 | - && desc->physical_start <= 0xffffffff |
| 75 | + && desc->physical_start <= MAX_USABLE_ADDRESS |
| 76 | #endif |
| 77 | && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 |
| 78 | && desc->num_pages != 0) |
| 79 | @@ -337,9 +343,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, |
| 80 | #if 1 |
| 81 | if (BYTES_TO_PAGES (filtered_desc->physical_start) |
| 82 | + filtered_desc->num_pages |
| 83 | - > BYTES_TO_PAGES (0x100000000LL)) |
| 84 | + > BYTES_TO_PAGES (MAX_USABLE_ADDRESS+1LL)) |
| 85 | filtered_desc->num_pages |
| 86 | - = (BYTES_TO_PAGES (0x100000000LL) |
| 87 | + = (BYTES_TO_PAGES (MAX_USABLE_ADDRESS+1LL) |
| 88 | - BYTES_TO_PAGES (filtered_desc->physical_start)); |
| 89 | #endif |
| 90 | |
| 91 | diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c |
| 92 | index 65f09ef..17c1215 100644 |
| 93 | --- a/grub-core/kern/x86_64/dl.c |
| 94 | +++ b/grub-core/kern/x86_64/dl.c |
| 95 | @@ -100,14 +100,32 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) |
| 96 | break; |
| 97 | |
| 98 | case R_X86_64_PC32: |
| 99 | - *addr32 += rel->r_addend + sym->st_value - |
| 100 | - (Elf64_Xword) seg->addr - rel->r_offset; |
| 101 | + { |
| 102 | + grub_int64_t value; |
| 103 | + value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value - |
| 104 | + (Elf64_Xword) seg->addr - rel->r_offset; |
| 105 | + if (value != (grub_int32_t) value) |
| 106 | + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); |
| 107 | + *addr32 = value; |
| 108 | + } |
| 109 | break; |
| 110 | |
| 111 | case R_X86_64_32: |
| 112 | + { |
| 113 | + grub_uint64_t value = *addr32 + rel->r_addend + sym->st_value; |
| 114 | + if (value != (grub_uint32_t) value) |
| 115 | + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); |
| 116 | + *addr32 = value; |
| 117 | + } |
| 118 | + break; |
| 119 | case R_X86_64_32S: |
| 120 | - *addr32 += rel->r_addend + sym->st_value; |
| 121 | - break; |
| 122 | + { |
| 123 | + grub_int64_t value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value; |
| 124 | + if (value != (grub_int32_t) value) |
| 125 | + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); |
| 126 | + *addr32 = value; |
| 127 | + } |
| 128 | + break; |
| 129 | |
| 130 | default: |
| 131 | return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, |