MdeModulePkg CapsuleApp: Fix NestedCapsuleHeader->Flags assigned wrong
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf64Convert.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2Elf64 convert solution\r
f51461c8 3\r
3f021800 4Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
87280982 5Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
f51461c8
LG
6\r
7This program and the accompanying materials are licensed and made available\r
8under the terms and conditions of the BSD License which accompanies this\r
9distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "WinNtInclude.h"\r
18\r
19#ifndef __GNUC__\r
20#include <windows.h>\r
21#include <io.h>\r
22#endif\r
23#include <assert.h>\r
24#include <stdio.h>\r
25#include <stdlib.h>\r
26#include <string.h>\r
27#include <time.h>\r
28#include <ctype.h>\r
29\r
30#include <Common/UefiBaseTypes.h>\r
31#include <IndustryStandard/PeImage.h>\r
32\r
33#include "PeCoffLib.h"\r
34#include "EfiUtilityMsgs.h"\r
35\r
36#include "GenFw.h"\r
37#include "ElfConvert.h"\r
38#include "Elf64Convert.h"\r
39\r
40STATIC\r
41VOID\r
42ScanSections64 (\r
43 VOID\r
44 );\r
45\r
46STATIC\r
47BOOLEAN\r
48WriteSections64 (\r
49 SECTION_FILTER_TYPES FilterType\r
50 );\r
51\r
52STATIC\r
53VOID\r
54WriteRelocations64 (\r
55 VOID\r
56 );\r
57\r
58STATIC\r
59VOID\r
60WriteDebug64 (\r
61 VOID\r
62 );\r
63\r
64STATIC\r
65VOID\r
66SetImageSize64 (\r
67 VOID\r
68 );\r
69\r
70STATIC\r
71VOID\r
72CleanUp64 (\r
73 VOID\r
74 );\r
75\r
76//\r
77// Rename ELF32 strucutres to common names to help when porting to ELF64.\r
78//\r
79typedef Elf64_Shdr Elf_Shdr;\r
80typedef Elf64_Ehdr Elf_Ehdr;\r
81typedef Elf64_Rel Elf_Rel;\r
82typedef Elf64_Rela Elf_Rela;\r
83typedef Elf64_Sym Elf_Sym;\r
84typedef Elf64_Phdr Elf_Phdr;\r
85typedef Elf64_Dyn Elf_Dyn;\r
86#define ELFCLASS ELFCLASS64\r
87#define ELF_R_TYPE(r) ELF64_R_TYPE(r)\r
88#define ELF_R_SYM(r) ELF64_R_SYM(r)\r
89\r
90//\r
91// Well known ELF structures.\r
92//\r
93STATIC Elf_Ehdr *mEhdr;\r
94STATIC Elf_Shdr *mShdrBase;\r
95STATIC Elf_Phdr *mPhdrBase;\r
96\r
97//\r
98// Coff information\r
99//\r
54b1b57a 100STATIC UINT32 mCoffAlignment = 0x20;\r
f51461c8
LG
101\r
102//\r
103// PE section alignment.\r
104//\r
0192b71c 105STATIC const UINT16 mCoffNbrSections = 4;\r
f51461c8
LG
106\r
107//\r
108// ELF sections to offset in Coff file.\r
109//\r
110STATIC UINT32 *mCoffSectionsOffset = NULL;\r
111\r
112//\r
113// Offsets in COFF file\r
114//\r
115STATIC UINT32 mNtHdrOffset;\r
116STATIC UINT32 mTextOffset;\r
117STATIC UINT32 mDataOffset;\r
118STATIC UINT32 mHiiRsrcOffset;\r
119STATIC UINT32 mRelocOffset;\r
0192b71c 120STATIC UINT32 mDebugOffset;\r
f51461c8
LG
121\r
122//\r
123// Initialization Function\r
124//\r
125BOOLEAN\r
126InitializeElf64 (\r
127 UINT8 *FileBuffer,\r
128 ELF_FUNCTION_TABLE *ElfFunctions\r
129 )\r
130{\r
131 //\r
132 // Initialize data pointer and structures.\r
133 //\r
134 VerboseMsg ("Set EHDR");\r
135 mEhdr = (Elf_Ehdr*) FileBuffer;\r
136\r
137 //\r
138 // Check the ELF64 specific header information.\r
139 //\r
140 VerboseMsg ("Check ELF64 Header Information");\r
141 if (mEhdr->e_ident[EI_CLASS] != ELFCLASS64) {\r
142 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS64");\r
143 return FALSE;\r
144 }\r
145 if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
146 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
147 return FALSE;\r
148 }\r
149 if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {\r
150 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
151 return FALSE;\r
152 }\r
153 if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64))) {\r
154 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_X86_64 or EM_AARCH64");\r
155 return FALSE;\r
156 }\r
157 if (mEhdr->e_version != EV_CURRENT) {\r
158 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);\r
159 return FALSE;\r
160 }\r
161\r
162 //\r
163 // Update section header pointers\r
164 //\r
165 VerboseMsg ("Update Header Pointers");\r
166 mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);\r
167 mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);\r
168\r
169 //\r
170 // Create COFF Section offset buffer and zero.\r
171 //\r
172 VerboseMsg ("Create COFF Section Offset Buffer");\r
173 mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));\r
06b45735
HW
174 if (mCoffSectionsOffset == NULL) {\r
175 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
176 return FALSE;\r
177 }\r
f51461c8
LG
178 memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));\r
179\r
180 //\r
181 // Fill in function pointers.\r
182 //\r
183 VerboseMsg ("Fill in Function Pointers");\r
184 ElfFunctions->ScanSections = ScanSections64;\r
185 ElfFunctions->WriteSections = WriteSections64;\r
186 ElfFunctions->WriteRelocations = WriteRelocations64;\r
187 ElfFunctions->WriteDebug = WriteDebug64;\r
188 ElfFunctions->SetImageSize = SetImageSize64;\r
189 ElfFunctions->CleanUp = CleanUp64;\r
190\r
191 return TRUE;\r
192}\r
193\r
194\r
195//\r
196// Header by Index functions\r
197//\r
198STATIC\r
199Elf_Shdr*\r
200GetShdrByIndex (\r
201 UINT32 Num\r
202 )\r
203{\r
17751c5f
ML
204 if (Num >= mEhdr->e_shnum) {\r
205 Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num);\r
206 exit(EXIT_FAILURE);\r
207 }\r
208\r
f51461c8
LG
209 return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);\r
210}\r
211\r
212STATIC\r
213UINT32\r
214CoffAlign (\r
215 UINT32 Offset\r
216 )\r
217{\r
218 return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
219}\r
220\r
4f7d5c67
AB
221STATIC\r
222UINT32\r
223DebugRvaAlign (\r
224 UINT32 Offset\r
225 )\r
226{\r
227 return (Offset + 3) & ~3;\r
228}\r
229\r
f51461c8
LG
230//\r
231// filter functions\r
232//\r
233STATIC\r
234BOOLEAN\r
235IsTextShdr (\r
236 Elf_Shdr *Shdr\r
237 )\r
238{\r
239 return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);\r
240}\r
241\r
242STATIC\r
243BOOLEAN\r
244IsHiiRsrcShdr (\r
245 Elf_Shdr *Shdr\r
246 )\r
247{\r
248 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
249\r
250 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
251}\r
252\r
253STATIC\r
254BOOLEAN\r
255IsDataShdr (\r
256 Elf_Shdr *Shdr\r
257 )\r
258{\r
259 if (IsHiiRsrcShdr(Shdr)) {\r
260 return FALSE;\r
261 }\r
262 return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
263}\r
264\r
621bb723
ML
265STATIC\r
266BOOLEAN\r
267IsStrtabShdr (\r
268 Elf_Shdr *Shdr\r
269 )\r
270{\r
271 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
272\r
273 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0);\r
274}\r
275\r
276STATIC\r
277Elf_Shdr *\r
278FindStrtabShdr (\r
279 VOID\r
280 )\r
281{\r
282 UINT32 i;\r
283 for (i = 0; i < mEhdr->e_shnum; i++) {\r
284 Elf_Shdr *shdr = GetShdrByIndex(i);\r
285 if (IsStrtabShdr(shdr)) {\r
286 return shdr;\r
287 }\r
288 }\r
289 return NULL;\r
290}\r
291\r
292STATIC\r
293const UINT8 *\r
294GetSymName (\r
295 Elf_Sym *Sym\r
296 )\r
297{\r
7be7b25d
HW
298 Elf_Shdr *StrtabShdr;\r
299 UINT8 *StrtabContents;\r
300 BOOLEAN foundEnd;\r
301 UINT32 i;\r
302\r
621bb723
ML
303 if (Sym->st_name == 0) {\r
304 return NULL;\r
305 }\r
306\r
7be7b25d 307 StrtabShdr = FindStrtabShdr();\r
621bb723
ML
308 if (StrtabShdr == NULL) {\r
309 return NULL;\r
310 }\r
311\r
312 assert(Sym->st_name < StrtabShdr->sh_size);\r
313\r
7be7b25d 314 StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset;\r
ea3e924a 315\r
7be7b25d 316 foundEnd = FALSE;\r
a754c70c 317 for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {\r
7be7b25d 318 foundEnd = (BOOLEAN)(StrtabContents[i] == 0);\r
ea3e924a
ML
319 }\r
320 assert(foundEnd);\r
321\r
322 return StrtabContents + Sym->st_name;\r
621bb723
ML
323}\r
324\r
f51461c8
LG
325//\r
326// Elf functions interface implementation\r
327//\r
328\r
329STATIC\r
330VOID\r
331ScanSections64 (\r
332 VOID\r
333 )\r
334{\r
335 UINT32 i;\r
336 EFI_IMAGE_DOS_HEADER *DosHdr;\r
337 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
338 UINT32 CoffEntry;\r
339 UINT32 SectionCount;\r
234f9ff9 340 BOOLEAN FoundSection;\r
f51461c8
LG
341\r
342 CoffEntry = 0;\r
343 mCoffOffset = 0;\r
f51461c8
LG
344\r
345 //\r
346 // Coff file start with a DOS header.\r
347 //\r
348 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
349 mNtHdrOffset = mCoffOffset;\r
350 switch (mEhdr->e_machine) {\r
351 case EM_X86_64:\r
352 case EM_IA_64:\r
353 case EM_AARCH64:\r
354 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
355 break;\r
356 default:\r
ea3e924a 357 VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine);\r
f51461c8
LG
358 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
359 break;\r
360 }\r
361\r
362 mTableOffset = mCoffOffset;\r
363 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
364\r
54b1b57a
AB
365 //\r
366 // Set mCoffAlignment to the maximum alignment of the input sections\r
367 // we care about\r
368 //\r
369 for (i = 0; i < mEhdr->e_shnum; i++) {\r
370 Elf_Shdr *shdr = GetShdrByIndex(i);\r
371 if (shdr->sh_addralign <= mCoffAlignment) {\r
372 continue;\r
373 }\r
374 if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {\r
375 mCoffAlignment = (UINT32)shdr->sh_addralign;\r
376 }\r
377 }\r
378\r
3f021800
YF
379 //\r
380 // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT\r
381 //\r
382 if (mCoffAlignment > MAX_COFF_ALIGNMENT) {\r
383 Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT.");\r
384 assert (FALSE);\r
385 }\r
386\r
387\r
02a5421f
AB
388 //\r
389 // Move the PE/COFF header right before the first section. This will help us\r
390 // save space when converting to TE.\r
391 //\r
392 if (mCoffAlignment > mCoffOffset) {\r
393 mNtHdrOffset += mCoffAlignment - mCoffOffset;\r
394 mTableOffset += mCoffAlignment - mCoffOffset;\r
395 mCoffOffset = mCoffAlignment;\r
396 }\r
397\r
f51461c8
LG
398 //\r
399 // First text sections.\r
400 //\r
401 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
402 mTextOffset = mCoffOffset;\r
403 FoundSection = FALSE;\r
f51461c8
LG
404 SectionCount = 0;\r
405 for (i = 0; i < mEhdr->e_shnum; i++) {\r
406 Elf_Shdr *shdr = GetShdrByIndex(i);\r
407 if (IsTextShdr(shdr)) {\r
408 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
409 // the alignment field is valid\r
410 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
411 // if the section address is aligned we must align PE/COFF\r
412 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
413 } else {\r
414 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
415 }\r
416 }\r
417\r
418 /* Relocate entry. */\r
419 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
420 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
421 CoffEntry = (UINT32) (mCoffOffset + mEhdr->e_entry - shdr->sh_addr);\r
422 }\r
423\r
424 //\r
425 // Set mTextOffset with the offset of the first '.text' section\r
426 //\r
234f9ff9 427 if (!FoundSection) {\r
f51461c8 428 mTextOffset = mCoffOffset;\r
234f9ff9 429 FoundSection = TRUE;\r
f51461c8
LG
430 }\r
431\r
432 mCoffSectionsOffset[i] = mCoffOffset;\r
433 mCoffOffset += (UINT32) shdr->sh_size;\r
434 SectionCount ++;\r
435 }\r
436 }\r
437\r
234f9ff9 438 if (!FoundSection) {\r
f51461c8
LG
439 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
440 assert (FALSE);\r
441 }\r
442\r
4f7d5c67 443 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0c960e86 444 mCoffOffset = CoffAlign(mCoffOffset);\r
f51461c8
LG
445\r
446 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
447 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
448 }\r
449\r
450 //\r
451 // Then data sections.\r
452 //\r
453 mDataOffset = mCoffOffset;\r
234f9ff9 454 FoundSection = FALSE;\r
f51461c8
LG
455 SectionCount = 0;\r
456 for (i = 0; i < mEhdr->e_shnum; i++) {\r
457 Elf_Shdr *shdr = GetShdrByIndex(i);\r
458 if (IsDataShdr(shdr)) {\r
459 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
460 // the alignment field is valid\r
461 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
462 // if the section address is aligned we must align PE/COFF\r
463 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
464 } else {\r
465 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
466 }\r
467 }\r
234f9ff9
EB
468\r
469 //\r
470 // Set mDataOffset with the offset of the first '.data' section\r
471 //\r
472 if (!FoundSection) {\r
473 mDataOffset = mCoffOffset;\r
474 FoundSection = TRUE;\r
475 }\r
f51461c8
LG
476 mCoffSectionsOffset[i] = mCoffOffset;\r
477 mCoffOffset += (UINT32) shdr->sh_size;\r
478 SectionCount ++;\r
479 }\r
480 }\r
0192b71c
AB
481\r
482 //\r
483 // Make room for .debug data in .data (or .text if .data is empty) instead of\r
484 // putting it in a section of its own. This is explicitly allowed by the\r
485 // PE/COFF spec, and prevents bloat in the binary when using large values for\r
486 // section alignment.\r
487 //\r
488 if (SectionCount > 0) {\r
4f7d5c67 489 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0192b71c
AB
490 }\r
491 mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
492 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
493 strlen(mInImageName) + 1;\r
494\r
f51461c8 495 mCoffOffset = CoffAlign(mCoffOffset);\r
0192b71c
AB
496 if (SectionCount == 0) {\r
497 mDataOffset = mCoffOffset;\r
498 }\r
f51461c8
LG
499\r
500 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
501 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
502 }\r
503\r
504 //\r
505 // The HII resource sections.\r
506 //\r
507 mHiiRsrcOffset = mCoffOffset;\r
508 for (i = 0; i < mEhdr->e_shnum; i++) {\r
509 Elf_Shdr *shdr = GetShdrByIndex(i);\r
510 if (IsHiiRsrcShdr(shdr)) {\r
511 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
512 // the alignment field is valid\r
513 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
514 // if the section address is aligned we must align PE/COFF\r
515 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
516 } else {\r
517 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
518 }\r
519 }\r
520 if (shdr->sh_size != 0) {\r
234f9ff9 521 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
522 mCoffSectionsOffset[i] = mCoffOffset;\r
523 mCoffOffset += (UINT32) shdr->sh_size;\r
524 mCoffOffset = CoffAlign(mCoffOffset);\r
525 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
526 }\r
527 break;\r
528 }\r
529 }\r
530\r
531 mRelocOffset = mCoffOffset;\r
532\r
533 //\r
534 // Allocate base Coff file. Will be expanded later for relocations.\r
535 //\r
536 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
06b45735
HW
537 if (mCoffFile == NULL) {\r
538 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
539 }\r
540 assert (mCoffFile != NULL);\r
f51461c8
LG
541 memset(mCoffFile, 0, mCoffOffset);\r
542\r
543 //\r
544 // Fill headers.\r
545 //\r
546 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
547 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
548 DosHdr->e_lfanew = mNtHdrOffset;\r
549\r
550 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
551\r
552 NtHdr->Pe32Plus.Signature = EFI_IMAGE_NT_SIGNATURE;\r
553\r
554 switch (mEhdr->e_machine) {\r
555 case EM_X86_64:\r
556 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
557 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
558 break;\r
559 case EM_IA_64:\r
560 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;\r
561 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
562 break;\r
563 case EM_AARCH64:\r
564 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64;\r
565 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
566 break;\r
567 default:\r
568 VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine);\r
569 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
570 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
571 }\r
572\r
573 NtHdr->Pe32Plus.FileHeader.NumberOfSections = mCoffNbrSections;\r
574 NtHdr->Pe32Plus.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
575 mImageTimeStamp = NtHdr->Pe32Plus.FileHeader.TimeDateStamp;\r
576 NtHdr->Pe32Plus.FileHeader.PointerToSymbolTable = 0;\r
577 NtHdr->Pe32Plus.FileHeader.NumberOfSymbols = 0;\r
578 NtHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32Plus.OptionalHeader);\r
579 NtHdr->Pe32Plus.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
580 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
581 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
582 | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE;\r
583\r
584 NtHdr->Pe32Plus.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
585 NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
586 NtHdr->Pe32Plus.OptionalHeader.SizeOfUninitializedData = 0;\r
587 NtHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
588\r
589 NtHdr->Pe32Plus.OptionalHeader.BaseOfCode = mTextOffset;\r
590\r
591 NtHdr->Pe32Plus.OptionalHeader.ImageBase = 0;\r
592 NtHdr->Pe32Plus.OptionalHeader.SectionAlignment = mCoffAlignment;\r
593 NtHdr->Pe32Plus.OptionalHeader.FileAlignment = mCoffAlignment;\r
594 NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = 0;\r
595\r
596 NtHdr->Pe32Plus.OptionalHeader.SizeOfHeaders = mTextOffset;\r
597 NtHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
598\r
599 //\r
600 // Section headers.\r
601 //\r
602 if ((mDataOffset - mTextOffset) > 0) {\r
603 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
604 EFI_IMAGE_SCN_CNT_CODE\r
605 | EFI_IMAGE_SCN_MEM_EXECUTE\r
606 | EFI_IMAGE_SCN_MEM_READ);\r
607 } else {\r
608 // Don't make a section of size 0.\r
609 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
610 }\r
611\r
612 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
613 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
614 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
615 | EFI_IMAGE_SCN_MEM_WRITE\r
616 | EFI_IMAGE_SCN_MEM_READ);\r
617 } else {\r
618 // Don't make a section of size 0.\r
619 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
620 }\r
621\r
622 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
623 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
624 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
625 | EFI_IMAGE_SCN_MEM_READ);\r
626\r
627 NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
628 NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
629 } else {\r
630 // Don't make a section of size 0.\r
631 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
632 }\r
633\r
634}\r
635\r
636STATIC\r
637BOOLEAN\r
638WriteSections64 (\r
639 SECTION_FILTER_TYPES FilterType\r
640 )\r
641{\r
642 UINT32 Idx;\r
643 Elf_Shdr *SecShdr;\r
644 UINT32 SecOffset;\r
645 BOOLEAN (*Filter)(Elf_Shdr *);\r
646\r
647 //\r
648 // Initialize filter pointer\r
649 //\r
650 switch (FilterType) {\r
651 case SECTION_TEXT:\r
652 Filter = IsTextShdr;\r
653 break;\r
654 case SECTION_HII:\r
655 Filter = IsHiiRsrcShdr;\r
656 break;\r
657 case SECTION_DATA:\r
658 Filter = IsDataShdr;\r
659 break;\r
660 default:\r
661 return FALSE;\r
662 }\r
663\r
664 //\r
665 // First: copy sections.\r
666 //\r
667 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
668 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
669 if ((*Filter)(Shdr)) {\r
670 switch (Shdr->sh_type) {\r
671 case SHT_PROGBITS:\r
672 /* Copy. */\r
d78675d1
YF
673 if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) {\r
674 return FALSE;\r
675 }\r
f51461c8
LG
676 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
677 (UINT8*)mEhdr + Shdr->sh_offset,\r
678 (size_t) Shdr->sh_size);\r
679 break;\r
680\r
681 case SHT_NOBITS:\r
682 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, (size_t) Shdr->sh_size);\r
683 break;\r
684\r
685 default:\r
686 //\r
687 // Ignore for unkown section type.\r
688 //\r
689 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
690 break;\r
691 }\r
692 }\r
693 }\r
694\r
695 //\r
696 // Second: apply relocations.\r
697 //\r
698 VerboseMsg ("Applying Relocations...");\r
699 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
700 //\r
701 // Determine if this is a relocation section.\r
702 //\r
703 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
704 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
705 continue;\r
706 }\r
707\r
4962fcfa
AB
708 //\r
709 // If this is a ET_DYN (PIE) executable, we will encounter a dynamic SHT_RELA\r
710 // section that applies to the entire binary, and which will have its section\r
711 // index set to #0 (which is a NULL section with the SHF_ALLOC bit cleared).\r
712 //\r
713 // In the absence of GOT based relocations (which we currently don't support),\r
714 // this RELA section will contain redundant R_xxx_RELATIVE relocations, one\r
715 // for every R_xxx_xx64 relocation appearing in the per-section RELA sections.\r
716 // (i.e., .rela.text and .rela.data)\r
717 //\r
718 if (RelShdr->sh_info == 0) {\r
719 continue;\r
720 }\r
721\r
f51461c8
LG
722 //\r
723 // Relocation section found. Now extract section information that the relocations\r
724 // apply to in the ELF data and the new COFF data.\r
725 //\r
726 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
727 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
728\r
729 //\r
730 // Only process relocations for the current filter type.\r
731 //\r
732 if (RelShdr->sh_type == SHT_RELA && (*Filter)(SecShdr)) {\r
733 UINT64 RelIdx;\r
734\r
735 //\r
736 // Determine the symbol table referenced by the relocation data.\r
737 //\r
738 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
739 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
740\r
741 //\r
742 // Process all relocation entries for this section.\r
743 //\r
744 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINT32) RelShdr->sh_entsize) {\r
745\r
746 //\r
747 // Set pointer to relocation entry\r
748 //\r
749 Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
750\r
751 //\r
752 // Set pointer to symbol table entry associated with the relocation entry.\r
753 //\r
754 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
755\r
756 Elf_Shdr *SymShdr;\r
757 UINT8 *Targ;\r
758\r
759 //\r
760 // Check section header index found in symbol table and get the section\r
761 // header location.\r
762 //\r
763 if (Sym->st_shndx == SHN_UNDEF\r
621bb723
ML
764 || Sym->st_shndx >= mEhdr->e_shnum) {\r
765 const UINT8 *SymName = GetSymName(Sym);\r
766 if (SymName == NULL) {\r
767 SymName = (const UINT8 *)"<unknown>";\r
768 }\r
769\r
770 Error (NULL, 0, 3000, "Invalid",\r
ea3e924a 771 "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. "\r
621bb723
ML
772 "For example, absolute and undefined symbols are not supported.",\r
773 mInImageName, SymName, Sym->st_value);\r
774\r
775 exit(EXIT_FAILURE);\r
f51461c8
LG
776 }\r
777 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
778\r
779 //\r
780 // Convert the relocation data to a pointer into the coff file.\r
781 //\r
782 // Note:\r
783 // r_offset is the virtual address of the storage unit to be relocated.\r
784 // sh_addr is the virtual address for the base of the section.\r
785 //\r
786 // r_offset in a memory address.\r
787 // Convert it to a pointer in the coff file.\r
788 //\r
789 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
790\r
791 //\r
792 // Determine how to handle each relocation type based on the machine type.\r
793 //\r
794 if (mEhdr->e_machine == EM_X86_64) {\r
795 switch (ELF_R_TYPE(Rel->r_info)) {\r
796 case R_X86_64_NONE:\r
797 break;\r
798 case R_X86_64_64:\r
799 //\r
800 // Absolute relocation.\r
801 //\r
802 VerboseMsg ("R_X86_64_64");\r
f7496d71
LG
803 VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX",\r
804 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)),\r
f51461c8
LG
805 *(UINT64 *)Targ);\r
806 *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
807 VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ);\r
808 break;\r
809 case R_X86_64_32:\r
810 VerboseMsg ("R_X86_64_32");\r
f7496d71
LG
811 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X",\r
812 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)),\r
f51461c8
LG
813 *(UINT32 *)Targ);\r
814 *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
815 VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ);\r
816 break;\r
817 case R_X86_64_32S:\r
818 VerboseMsg ("R_X86_64_32S");\r
f7496d71
LG
819 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X",\r
820 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)),\r
f51461c8
LG
821 *(UINT32 *)Targ);\r
822 *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
823 VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ);\r
824 break;\r
c9f29755
AB
825\r
826 case R_X86_64_PLT32:\r
827 //\r
828 // Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is\r
829 // possible since we know all code symbol references resolve to\r
830 // definitions in the same module (UEFI has no shared libraries),\r
831 // and so there is never a reason to jump via a PLT entry,\r
832 // allowing us to resolve the reference using the symbol directly.\r
833 //\r
834 VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ...");\r
835 /* fall through */\r
f51461c8
LG
836 case R_X86_64_PC32:\r
837 //\r
838 // Relative relocation: Symbol - Ip + Addend\r
839 //\r
840 VerboseMsg ("R_X86_64_PC32");\r
f7496d71
LG
841 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X",\r
842 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)),\r
f51461c8
LG
843 *(UINT32 *)Targ);\r
844 *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ\r
845 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
846 - (SecOffset - SecShdr->sh_addr));\r
847 VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ);\r
848 break;\r
849 default:\r
850 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
851 }\r
852 } else if (mEhdr->e_machine == EM_AARCH64) {\r
853\r
f51461c8
LG
854 switch (ELF_R_TYPE(Rel->r_info)) {\r
855\r
24d610e6 856 case R_AARCH64_ADR_PREL_PG_HI21:\r
24d610e6
AB
857 //\r
858 // AArch64 PG_H21 relocations are typically paired with ABS_LO12\r
859 // relocations, where a PC-relative reference with +/- 4 GB range is\r
860 // split into a relative high part and an absolute low part. Since\r
861 // the absolute low part represents the offset into a 4 KB page, we\r
026a82ab
AB
862 // either have to convert the ADRP into an ADR instruction, or we\r
863 // need to use a section alignment of at least 4 KB, so that the\r
864 // binary appears at a correct offset at runtime. In any case, we\r
24d610e6
AB
865 // have to make sure that the 4 KB relative offsets of both the\r
866 // section containing the reference as well as the section to which\r
867 // it refers have not been changed during PE/COFF conversion (i.e.,\r
868 // in ScanSections64() above).\r
869 //\r
026a82ab
AB
870 if (mCoffAlignment < 0x1000) {\r
871 //\r
872 // Attempt to convert the ADRP into an ADR instruction.\r
873 // This is only possible if the symbol is within +/- 1 MB.\r
874 //\r
875 INT64 Offset;\r
876\r
877 // Decode the ADRP instruction\r
878 Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8);\r
879 Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12));\r
880\r
881 //\r
882 // ADRP offset is relative to the previous page boundary,\r
883 // whereas ADR offset is relative to the instruction itself.\r
884 // So fix up the offset so it points to the page containing\r
885 // the symbol.\r
886 //\r
887 Offset -= (UINTN)(Targ - mCoffFile) & 0xfff;\r
888\r
889 if (Offset < -0x100000 || Offset > 0xfffff) {\r
890 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.",\r
891 mInImageName);\r
892 break;\r
893 }\r
894\r
895 // Re-encode the offset as an ADR instruction\r
896 *(UINT32 *)Targ &= 0x1000001f;\r
897 *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29);\r
898 }\r
899 /* fall through */\r
900\r
901 case R_AARCH64_ADD_ABS_LO12_NC:\r
902 case R_AARCH64_LDST8_ABS_LO12_NC:\r
903 case R_AARCH64_LDST16_ABS_LO12_NC:\r
904 case R_AARCH64_LDST32_ABS_LO12_NC:\r
905 case R_AARCH64_LDST64_ABS_LO12_NC:\r
906 case R_AARCH64_LDST128_ABS_LO12_NC:\r
24d610e6 907 if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 ||\r
026a82ab
AB
908 ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) {\r
909 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.",\r
24d610e6
AB
910 mInImageName);\r
911 break;\r
87280982 912 }\r
24d610e6 913 /* fall through */\r
87280982 914\r
24d610e6 915 case R_AARCH64_ADR_PREL_LO21:\r
87280982 916 case R_AARCH64_CONDBR19:\r
f51461c8 917 case R_AARCH64_LD_PREL_LO19:\r
f51461c8 918 case R_AARCH64_CALL26:\r
f51461c8 919 case R_AARCH64_JUMP26:\r
0b6249f5
AB
920 case R_AARCH64_PREL64:\r
921 case R_AARCH64_PREL32:\r
922 case R_AARCH64_PREL16:\r
24d610e6
AB
923 //\r
924 // The GCC toolchains (i.e., binutils) may corrupt section relative\r
925 // relocations when emitting relocation sections into fully linked\r
926 // binaries. More specifically, they tend to fail to take into\r
927 // account the fact that a '.rodata + XXX' relocation needs to have\r
928 // its addend recalculated once .rodata is merged into the .text\r
929 // section, and the relocation emitted into the .rela.text section.\r
930 //\r
931 // We cannot really recover from this loss of information, so the\r
932 // only workaround is to prevent having to recalculate any relative\r
933 // relocations at all, by using a linker script that ensures that\r
934 // the offset between the Place and the Symbol is the same in both\r
935 // the ELF and the PE/COFF versions of the binary.\r
936 //\r
937 if ((SymShdr->sh_addr - SecShdr->sh_addr) !=\r
938 (mCoffSectionsOffset[Sym->st_shndx] - SecOffset)) {\r
939 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 relative relocations require identical ELF and PE/COFF section offsets",\r
940 mInImageName);\r
f51461c8
LG
941 }\r
942 break;\r
943\r
f51461c8
LG
944 // Absolute relocations.\r
945 case R_AARCH64_ABS64:\r
946 *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
947 break;\r
948\r
949 default:\r
950 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
951 }\r
952 } else {\r
953 Error (NULL, 0, 3000, "Invalid", "Not a supported machine type");\r
954 }\r
955 }\r
956 }\r
957 }\r
958\r
959 return TRUE;\r
960}\r
961\r
962STATIC\r
963VOID\r
964WriteRelocations64 (\r
965 VOID\r
966 )\r
967{\r
968 UINT32 Index;\r
969 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
970 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
971\r
972 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
973 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
974 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
975 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
976 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
977 UINT64 RelIdx;\r
978\r
979 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
980 Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
981\r
982 if (mEhdr->e_machine == EM_X86_64) {\r
983 switch (ELF_R_TYPE(Rel->r_info)) {\r
984 case R_X86_64_NONE:\r
985 case R_X86_64_PC32:\r
c9f29755 986 case R_X86_64_PLT32:\r
f51461c8
LG
987 break;\r
988 case R_X86_64_64:\r
f7496d71 989 VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X",\r
f51461c8
LG
990 mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
991 CoffAddFixup(\r
992 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
993 + (Rel->r_offset - SecShdr->sh_addr)),\r
994 EFI_IMAGE_REL_BASED_DIR64);\r
995 break;\r
996 case R_X86_64_32S:\r
997 case R_X86_64_32:\r
f7496d71 998 VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X",\r
f51461c8
LG
999 mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
1000 CoffAddFixup(\r
1001 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
1002 + (Rel->r_offset - SecShdr->sh_addr)),\r
1003 EFI_IMAGE_REL_BASED_HIGHLOW);\r
1004 break;\r
1005 default:\r
1006 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
1007 }\r
1008 } else if (mEhdr->e_machine == EM_AARCH64) {\r
24d610e6 1009\r
f51461c8 1010 switch (ELF_R_TYPE(Rel->r_info)) {\r
87280982 1011 case R_AARCH64_ADR_PREL_LO21:\r
87280982 1012 case R_AARCH64_CONDBR19:\r
f51461c8 1013 case R_AARCH64_LD_PREL_LO19:\r
f51461c8 1014 case R_AARCH64_CALL26:\r
f51461c8 1015 case R_AARCH64_JUMP26:\r
0b6249f5
AB
1016 case R_AARCH64_PREL64:\r
1017 case R_AARCH64_PREL32:\r
1018 case R_AARCH64_PREL16:\r
f51461c8 1019 case R_AARCH64_ADR_PREL_PG_HI21:\r
f51461c8 1020 case R_AARCH64_ADD_ABS_LO12_NC:\r
24d610e6
AB
1021 case R_AARCH64_LDST8_ABS_LO12_NC:\r
1022 case R_AARCH64_LDST16_ABS_LO12_NC:\r
1023 case R_AARCH64_LDST32_ABS_LO12_NC:\r
1024 case R_AARCH64_LDST64_ABS_LO12_NC:\r
1025 case R_AARCH64_LDST128_ABS_LO12_NC:\r
0b6249f5
AB
1026 //\r
1027 // No fixups are required for relative relocations, provided that\r
1028 // the relative offsets between sections have been preserved in\r
1029 // the ELF to PE/COFF conversion. We have already asserted that\r
1030 // this is the case in WriteSections64 ().\r
1031 //\r
f51461c8
LG
1032 break;\r
1033\r
1034 case R_AARCH64_ABS64:\r
1035 CoffAddFixup(\r
1036 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
1037 + (Rel->r_offset - SecShdr->sh_addr)),\r
1038 EFI_IMAGE_REL_BASED_DIR64);\r
1039 break;\r
1040\r
1041 case R_AARCH64_ABS32:\r
1042 CoffAddFixup(\r
1043 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
1044 + (Rel->r_offset - SecShdr->sh_addr)),\r
1045 EFI_IMAGE_REL_BASED_HIGHLOW);\r
1046 break;\r
1047\r
1048 default:\r
1049 Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
1050 }\r
1051 } else {\r
1052 Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine);\r
1053 }\r
1054 }\r
1055 }\r
1056 }\r
1057 }\r
1058\r
1059 //\r
1060 // Pad by adding empty entries.\r
1061 //\r
1062 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1063 CoffAddFixupEntry(0);\r
1064 }\r
1065\r
1066 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1067 Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1068 Dir->Size = mCoffOffset - mRelocOffset;\r
1069 if (Dir->Size == 0) {\r
1070 // If no relocations, null out the directory entry and don't add the .reloc section\r
1071 Dir->VirtualAddress = 0;\r
1072 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
1073 } else {\r
1074 Dir->VirtualAddress = mRelocOffset;\r
1075 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1076 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1077 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1078 | EFI_IMAGE_SCN_MEM_READ);\r
1079 }\r
1080}\r
1081\r
1082STATIC\r
1083VOID\r
1084WriteDebug64 (\r
1085 VOID\r
1086 )\r
1087{\r
1088 UINT32 Len;\r
f51461c8
LG
1089 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1090 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1091 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1092 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1093\r
1094 Len = strlen(mInImageName) + 1;\r
f51461c8 1095\r
0192b71c 1096 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1097 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1098 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1099 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1100 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1101\r
1102 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1103 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1104 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1105\r
1106\r
1107 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1108 DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c 1109 DataDir->VirtualAddress = mDebugOffset;\r
60e85a39 1110 DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1111}\r
1112\r
1113STATIC\r
1114VOID\r
1115SetImageSize64 (\r
1116 VOID\r
1117 )\r
1118{\r
1119 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1120\r
1121 //\r
1122 // Set image size\r
1123 //\r
1124 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1125 NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = mCoffOffset;\r
1126}\r
1127\r
1128STATIC\r
1129VOID\r
1130CleanUp64 (\r
1131 VOID\r
1132 )\r
1133{\r
1134 if (mCoffSectionsOffset != NULL) {\r
1135 free (mCoffSectionsOffset);\r
1136 }\r
1137}\r
1138\r
1139\r