]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenFw/ElfConvert.c
BaseTools/GenFw: Add X64 GOTPCREL Support to GenFw
[mirror_edk2.git] / BaseTools / Source / C / GenFw / ElfConvert.c
1 /** @file
2 Elf convert solution
3
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "WinNtInclude.h"
17
18 #ifndef __GNUC__
19 #include <windows.h>
20 #include <io.h>
21 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <assert.h>
28
29 #include <Common/UefiBaseTypes.h>
30 #include <IndustryStandard/PeImage.h>
31
32 #include "EfiUtilityMsgs.h"
33
34 #include "GenFw.h"
35 #include "ElfConvert.h"
36 #include "Elf32Convert.h"
37 #include "Elf64Convert.h"
38
39 //
40 // Result Coff file in memory.
41 //
42 UINT8 *mCoffFile = NULL;
43
44 //
45 // COFF relocation data
46 //
47 EFI_IMAGE_BASE_RELOCATION *mCoffBaseRel;
48 UINT16 *mCoffEntryRel;
49
50 //
51 // Current offset in coff file.
52 //
53 UINT32 mCoffOffset;
54
55 //
56 // Offset in Coff file of headers and sections.
57 //
58 UINT32 mTableOffset;
59
60 //
61 //mFileBufferSize
62 //
63 UINT32 mFileBufferSize;
64
65 //
66 //*****************************************************************************
67 // Common ELF Functions
68 //*****************************************************************************
69 //
70
71 VOID
72 CoffAddFixupEntry(
73 UINT16 Val
74 )
75 {
76 *mCoffEntryRel = Val;
77 mCoffEntryRel++;
78 mCoffBaseRel->SizeOfBlock += 2;
79 mCoffOffset += 2;
80 }
81
82 VOID
83 CoffAddFixup(
84 UINT32 Offset,
85 UINT8 Type
86 )
87 {
88 if (mCoffBaseRel == NULL
89 || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
90 if (mCoffBaseRel != NULL) {
91 //
92 // Add a null entry (is it required ?)
93 //
94 CoffAddFixupEntry (0);
95
96 //
97 // Pad for alignment.
98 //
99 if (mCoffOffset % 4 != 0)
100 CoffAddFixupEntry (0);
101 }
102
103 mCoffFile = realloc (
104 mCoffFile,
105 mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
106 );
107 if (mCoffFile == NULL) {
108 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
109 }
110 assert (mCoffFile != NULL);
111 memset (
112 mCoffFile + mCoffOffset, 0,
113 sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
114 );
115
116 mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset);
117 mCoffBaseRel->VirtualAddress = Offset & ~0xfff;
118 mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
119
120 mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1);
121 mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
122 }
123
124 //
125 // Fill the entry.
126 //
127 CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff)));
128 }
129
130 VOID
131 CreateSectionHeader (
132 const CHAR8 *Name,
133 UINT32 Offset,
134 UINT32 Size,
135 UINT32 Flags
136 )
137 {
138 EFI_IMAGE_SECTION_HEADER *Hdr;
139 Hdr = (EFI_IMAGE_SECTION_HEADER*)(mCoffFile + mTableOffset);
140
141 strcpy((char *)Hdr->Name, Name);
142 Hdr->Misc.VirtualSize = Size;
143 Hdr->VirtualAddress = Offset;
144 Hdr->SizeOfRawData = Size;
145 Hdr->PointerToRawData = Offset;
146 Hdr->PointerToRelocations = 0;
147 Hdr->PointerToLinenumbers = 0;
148 Hdr->NumberOfRelocations = 0;
149 Hdr->NumberOfLinenumbers = 0;
150 Hdr->Characteristics = Flags;
151
152 mTableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
153 }
154
155 //
156 //*****************************************************************************
157 // Functions called from GenFw main code.
158 //*****************************************************************************
159 //
160
161 INTN
162 IsElfHeader (
163 UINT8 *FileBuffer
164 )
165 {
166 return (FileBuffer[EI_MAG0] == ELFMAG0 &&
167 FileBuffer[EI_MAG1] == ELFMAG1 &&
168 FileBuffer[EI_MAG2] == ELFMAG2 &&
169 FileBuffer[EI_MAG3] == ELFMAG3);
170 }
171
172 BOOLEAN
173 ConvertElf (
174 UINT8 **FileBuffer,
175 UINT32 *FileLength
176 )
177 {
178 ELF_FUNCTION_TABLE ElfFunctions;
179 UINT8 EiClass;
180
181 mFileBufferSize = *FileLength;
182 //
183 // Determine ELF type and set function table pointer correctly.
184 //
185 VerboseMsg ("Check Elf Image Header");
186 EiClass = (*FileBuffer)[EI_CLASS];
187 if (EiClass == ELFCLASS32) {
188 if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) {
189 return FALSE;
190 }
191 } else if (EiClass == ELFCLASS64) {
192 if (!InitializeElf64 (*FileBuffer, &ElfFunctions)) {
193 return FALSE;
194 }
195 } else {
196 Error (NULL, 0, 3000, "Unsupported", "ELF EI_CLASS not supported.");
197 return FALSE;
198 }
199
200 //
201 // Compute sections new address.
202 //
203 VerboseMsg ("Compute sections new address.");
204 ElfFunctions.ScanSections ();
205
206 //
207 // Write and relocate sections.
208 //
209 VerboseMsg ("Write and relocate sections.");
210 if (!ElfFunctions.WriteSections (SECTION_TEXT)) {
211 return FALSE;
212 }
213 if (!ElfFunctions.WriteSections (SECTION_DATA)) {
214 return FALSE;
215 }
216 if (!ElfFunctions.WriteSections (SECTION_HII)) {
217 return FALSE;
218 }
219
220 //
221 // Translate and write relocations.
222 //
223 VerboseMsg ("Translate and write relocations.");
224 ElfFunctions.WriteRelocations ();
225
226 //
227 // Write debug info.
228 //
229 VerboseMsg ("Write debug info.");
230 ElfFunctions.WriteDebug ();
231
232 //
233 // Make sure image size is correct before returning the new image.
234 //
235 VerboseMsg ("Set image size.");
236 ElfFunctions.SetImageSize ();
237
238 //
239 // Replace.
240 //
241 free (*FileBuffer);
242 *FileBuffer = mCoffFile;
243 *FileLength = mCoffOffset;
244
245 //
246 // Free resources used by ELF functions.
247 //
248 ElfFunctions.CleanUp ();
249
250 return TRUE;
251 }