1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
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,
|