summaryrefslogtreecommitdiff
blob: 9487ba4c67313316877db9e4d7202ee7032d56dc (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
https://sourceforge.net/p/gnu-efi/code/merge-requests/1/

From 2cc0b085fb82e80d43cc08c8376dff9f9532a72d Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyfox@gentoo.org>
Date: Sat, 27 Jan 2018 20:29:05 +0000
Subject: [PATCH] gnuefi: preserve .gnu.hash sections (unbreaks elilo on IA-64)

Gentoo has slightly modified linker defaults: --hash-style=gnu
This means all ELF files in system have '.gnu.hash' section
but no '.hash' section.

gnuefi's ldscript did not account for it and as a result
one symbol 'ImageBase' did not resolve locally for elilo.so
and caused 'elilo' to fail to load by ia64 EFI:
  Loading.: Gentoo (try new elilo)
  ImageAddress: pointer is outside of image
  ImageAddress: pointer is outside of image

Those two relocations come from crt0-efi-ia64.S PE32 entry point
fdescr:

```
    #define IMAGE_REL_BASED_DIR64<->10
    .section .reloc, "a"
    data4   _start_plabel // Page RVA
    data4   12            // Block Size (2*4+2*2)
    data2   (IMAGE_REL_BASED_DIR64<<12) +  0 // reloc for plabel's entry point
    data2   (IMAGE_REL_BASED_DIR64<<12) +  8 // reloc for plabel's global pointer
```

These refer ImageBase.

The change adds '.gnu.hash' collection (follows existing '.hash'
collection).

Tested on IA-64 by successfully booting elilo-3.16.

Bug: https://bugs.gentoo.org/575300
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
---
 README.gnuefi                  | 8 +++++++-
 gnuefi/elf_ia32_efi.lds        | 4 +++-
 gnuefi/elf_ia32_fbsd_efi.lds   | 4 +++-
 gnuefi/elf_ia64_efi.lds        | 4 +++-
 gnuefi/elf_x86_64_efi.lds      | 4 +++-
 gnuefi/elf_x86_64_fbsd_efi.lds | 4 +++-
 6 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/README.gnuefi b/README.gnuefi
index a7feec0..512698c 100644
--- a/README.gnuefi
+++ b/README.gnuefi
@@ -231,11 +231,17 @@ and page sized.These eight sections are used to group together the much
 greater number of sections that are typically present in ELF object files.
 Specifically:
 
- .hash
+ .hash (and/or .gnu.hash)
 	Collects the ELF .hash info (this section _must_ be the first
 	section in order to build a shared object file; the section is
 	not actually loaded or used at runtime).
 
+	GNU binutils provides a mechanism to generate different hash info
+	via --hash-style=<sysv|gnu|both> option. In this case output
+	shared object will contain .hash section, .gnu.hash section or
+	both. In order to generate correct output linker script preserves
+	both types of hash sections.
+
  .text
 	Collects all sections containing executable code.
 
diff --git a/gnuefi/elf_ia32_efi.lds b/gnuefi/elf_ia32_efi.lds
index 6cc4ce1..f27fe5f 100644
--- a/gnuefi/elf_ia32_efi.lds
+++ b/gnuefi/elf_ia32_efi.lds
@@ -5,7 +5,9 @@ SECTIONS
 {
   . = 0;
   ImageBase = .;
-  .hash : { *(.hash) }	/* this MUST come first! */
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
   .text :
   {
diff --git a/gnuefi/elf_ia32_fbsd_efi.lds b/gnuefi/elf_ia32_fbsd_efi.lds
index 77d6fad..cd309e2 100644
--- a/gnuefi/elf_ia32_fbsd_efi.lds
+++ b/gnuefi/elf_ia32_fbsd_efi.lds
@@ -5,7 +5,9 @@ SECTIONS
 {
   . = 0;
   ImageBase = .;
-  .hash : { *(.hash) }	/* this MUST come first! */
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
   .text :
   {
diff --git a/gnuefi/elf_ia64_efi.lds b/gnuefi/elf_ia64_efi.lds
index baca962..190792a 100644
--- a/gnuefi/elf_ia64_efi.lds
+++ b/gnuefi/elf_ia64_efi.lds
@@ -5,7 +5,9 @@ SECTIONS
 {
   . = 0;
   ImageBase = .;
-  .hash : { *(.hash) }	/* this MUST come first! */
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
   .text :
   {
diff --git a/gnuefi/elf_x86_64_efi.lds b/gnuefi/elf_x86_64_efi.lds
index 942d1f3..7be5902 100644
--- a/gnuefi/elf_x86_64_efi.lds
+++ b/gnuefi/elf_x86_64_efi.lds
@@ -6,7 +6,9 @@ SECTIONS
 {
   . = 0;
   ImageBase = .;
-  .hash : { *(.hash) }	/* this MUST come first! */
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
   .eh_frame : 
   { 
diff --git a/gnuefi/elf_x86_64_fbsd_efi.lds b/gnuefi/elf_x86_64_fbsd_efi.lds
index 6fd2031..fe1f334 100644
--- a/gnuefi/elf_x86_64_fbsd_efi.lds
+++ b/gnuefi/elf_x86_64_fbsd_efi.lds
@@ -6,7 +6,9 @@ SECTIONS
 {
   . = 0;
   ImageBase = .;
-  .hash : { *(.hash) }	/* this MUST come first! */
+  /* .hash and/or .gnu.hash MUST come first! */
+  .hash : { *(.hash) }
+  .gnu.hash : { *(.gnu.hash) }
   . = ALIGN(4096);
   .eh_frame : 
   { 
-- 
2.16.1