]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf64Convert.c
BaseTools/GenFw: disregard payload in PE debug directory entry size
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf64Convert.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2Elf64 convert solution\r
f51461c8 3\r
7be7b25d 4Copyright (c) 2010 - 2017, 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
02a5421f
AB
379 //\r
380 // Move the PE/COFF header right before the first section. This will help us\r
381 // save space when converting to TE.\r
382 //\r
383 if (mCoffAlignment > mCoffOffset) {\r
384 mNtHdrOffset += mCoffAlignment - mCoffOffset;\r
385 mTableOffset += mCoffAlignment - mCoffOffset;\r
386 mCoffOffset = mCoffAlignment;\r
387 }\r
388\r
f51461c8
LG
389 //\r
390 // First text sections.\r
391 //\r
392 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
393 mTextOffset = mCoffOffset;\r
394 FoundSection = FALSE;\r
f51461c8
LG
395 SectionCount = 0;\r
396 for (i = 0; i < mEhdr->e_shnum; i++) {\r
397 Elf_Shdr *shdr = GetShdrByIndex(i);\r
398 if (IsTextShdr(shdr)) {\r
399 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
400 // the alignment field is valid\r
401 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
402 // if the section address is aligned we must align PE/COFF\r
403 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
404 } else {\r
405 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
406 }\r
407 }\r
408\r
409 /* Relocate entry. */\r
410 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
411 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
412 CoffEntry = (UINT32) (mCoffOffset + mEhdr->e_entry - shdr->sh_addr);\r
413 }\r
414\r
415 //\r
416 // Set mTextOffset with the offset of the first '.text' section\r
417 //\r
234f9ff9 418 if (!FoundSection) {\r
f51461c8 419 mTextOffset = mCoffOffset;\r
234f9ff9 420 FoundSection = TRUE;\r
f51461c8
LG
421 }\r
422\r
423 mCoffSectionsOffset[i] = mCoffOffset;\r
424 mCoffOffset += (UINT32) shdr->sh_size;\r
425 SectionCount ++;\r
426 }\r
427 }\r
428\r
234f9ff9 429 if (!FoundSection) {\r
f51461c8
LG
430 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
431 assert (FALSE);\r
432 }\r
433\r
4f7d5c67 434 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0c960e86 435 mCoffOffset = CoffAlign(mCoffOffset);\r
f51461c8
LG
436\r
437 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
438 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
439 }\r
440\r
441 //\r
442 // Then data sections.\r
443 //\r
444 mDataOffset = mCoffOffset;\r
234f9ff9 445 FoundSection = FALSE;\r
f51461c8
LG
446 SectionCount = 0;\r
447 for (i = 0; i < mEhdr->e_shnum; i++) {\r
448 Elf_Shdr *shdr = GetShdrByIndex(i);\r
449 if (IsDataShdr(shdr)) {\r
450 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
451 // the alignment field is valid\r
452 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
453 // if the section address is aligned we must align PE/COFF\r
454 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
455 } else {\r
456 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
457 }\r
458 }\r
234f9ff9
EB
459\r
460 //\r
461 // Set mDataOffset with the offset of the first '.data' section\r
462 //\r
463 if (!FoundSection) {\r
464 mDataOffset = mCoffOffset;\r
465 FoundSection = TRUE;\r
466 }\r
f51461c8
LG
467 mCoffSectionsOffset[i] = mCoffOffset;\r
468 mCoffOffset += (UINT32) shdr->sh_size;\r
469 SectionCount ++;\r
470 }\r
471 }\r
0192b71c
AB
472\r
473 //\r
474 // Make room for .debug data in .data (or .text if .data is empty) instead of\r
475 // putting it in a section of its own. This is explicitly allowed by the\r
476 // PE/COFF spec, and prevents bloat in the binary when using large values for\r
477 // section alignment.\r
478 //\r
479 if (SectionCount > 0) {\r
4f7d5c67 480 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0192b71c
AB
481 }\r
482 mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
483 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
484 strlen(mInImageName) + 1;\r
485\r
f51461c8 486 mCoffOffset = CoffAlign(mCoffOffset);\r
0192b71c
AB
487 if (SectionCount == 0) {\r
488 mDataOffset = mCoffOffset;\r
489 }\r
f51461c8
LG
490\r
491 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
492 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
493 }\r
494\r
495 //\r
496 // The HII resource sections.\r
497 //\r
498 mHiiRsrcOffset = mCoffOffset;\r
499 for (i = 0; i < mEhdr->e_shnum; i++) {\r
500 Elf_Shdr *shdr = GetShdrByIndex(i);\r
501 if (IsHiiRsrcShdr(shdr)) {\r
502 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
503 // the alignment field is valid\r
504 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
505 // if the section address is aligned we must align PE/COFF\r
506 mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1));\r
0c960e86
AB
507 } else {\r
508 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
509 }\r
510 }\r
511 if (shdr->sh_size != 0) {\r
234f9ff9 512 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
513 mCoffSectionsOffset[i] = mCoffOffset;\r
514 mCoffOffset += (UINT32) shdr->sh_size;\r
515 mCoffOffset = CoffAlign(mCoffOffset);\r
516 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
517 }\r
518 break;\r
519 }\r
520 }\r
521\r
522 mRelocOffset = mCoffOffset;\r
523\r
524 //\r
525 // Allocate base Coff file. Will be expanded later for relocations.\r
526 //\r
527 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
06b45735
HW
528 if (mCoffFile == NULL) {\r
529 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
530 }\r
531 assert (mCoffFile != NULL);\r
f51461c8
LG
532 memset(mCoffFile, 0, mCoffOffset);\r
533\r
534 //\r
535 // Fill headers.\r
536 //\r
537 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
538 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
539 DosHdr->e_lfanew = mNtHdrOffset;\r
540\r
541 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
542\r
543 NtHdr->Pe32Plus.Signature = EFI_IMAGE_NT_SIGNATURE;\r
544\r
545 switch (mEhdr->e_machine) {\r
546 case EM_X86_64:\r
547 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
548 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
549 break;\r
550 case EM_IA_64:\r
551 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;\r
552 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
553 break;\r
554 case EM_AARCH64:\r
555 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64;\r
556 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
557 break;\r
558 default:\r
559 VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine);\r
560 NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
561 NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
562 }\r
563\r
564 NtHdr->Pe32Plus.FileHeader.NumberOfSections = mCoffNbrSections;\r
565 NtHdr->Pe32Plus.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
566 mImageTimeStamp = NtHdr->Pe32Plus.FileHeader.TimeDateStamp;\r
567 NtHdr->Pe32Plus.FileHeader.PointerToSymbolTable = 0;\r
568 NtHdr->Pe32Plus.FileHeader.NumberOfSymbols = 0;\r
569 NtHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32Plus.OptionalHeader);\r
570 NtHdr->Pe32Plus.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
571 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
572 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
573 | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE;\r
574\r
575 NtHdr->Pe32Plus.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
576 NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
577 NtHdr->Pe32Plus.OptionalHeader.SizeOfUninitializedData = 0;\r
578 NtHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
579\r
580 NtHdr->Pe32Plus.OptionalHeader.BaseOfCode = mTextOffset;\r
581\r
582 NtHdr->Pe32Plus.OptionalHeader.ImageBase = 0;\r
583 NtHdr->Pe32Plus.OptionalHeader.SectionAlignment = mCoffAlignment;\r
584 NtHdr->Pe32Plus.OptionalHeader.FileAlignment = mCoffAlignment;\r
585 NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = 0;\r
586\r
587 NtHdr->Pe32Plus.OptionalHeader.SizeOfHeaders = mTextOffset;\r
588 NtHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
589\r
590 //\r
591 // Section headers.\r
592 //\r
593 if ((mDataOffset - mTextOffset) > 0) {\r
594 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
595 EFI_IMAGE_SCN_CNT_CODE\r
596 | EFI_IMAGE_SCN_MEM_EXECUTE\r
597 | EFI_IMAGE_SCN_MEM_READ);\r
598 } else {\r
599 // Don't make a section of size 0.\r
600 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
601 }\r
602\r
603 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
604 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
605 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
606 | EFI_IMAGE_SCN_MEM_WRITE\r
607 | EFI_IMAGE_SCN_MEM_READ);\r
608 } else {\r
609 // Don't make a section of size 0.\r
610 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
611 }\r
612\r
613 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
614 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
615 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
616 | EFI_IMAGE_SCN_MEM_READ);\r
617\r
618 NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
619 NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
620 } else {\r
621 // Don't make a section of size 0.\r
622 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
623 }\r
624\r
625}\r
626\r
627STATIC\r
628BOOLEAN\r
629WriteSections64 (\r
630 SECTION_FILTER_TYPES FilterType\r
631 )\r
632{\r
633 UINT32 Idx;\r
634 Elf_Shdr *SecShdr;\r
635 UINT32 SecOffset;\r
636 BOOLEAN (*Filter)(Elf_Shdr *);\r
637\r
638 //\r
639 // Initialize filter pointer\r
640 //\r
641 switch (FilterType) {\r
642 case SECTION_TEXT:\r
643 Filter = IsTextShdr;\r
644 break;\r
645 case SECTION_HII:\r
646 Filter = IsHiiRsrcShdr;\r
647 break;\r
648 case SECTION_DATA:\r
649 Filter = IsDataShdr;\r
650 break;\r
651 default:\r
652 return FALSE;\r
653 }\r
654\r
655 //\r
656 // First: copy sections.\r
657 //\r
658 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
659 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
660 if ((*Filter)(Shdr)) {\r
661 switch (Shdr->sh_type) {\r
662 case SHT_PROGBITS:\r
663 /* Copy. */\r
664 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
665 (UINT8*)mEhdr + Shdr->sh_offset,\r
666 (size_t) Shdr->sh_size);\r
667 break;\r
668\r
669 case SHT_NOBITS:\r
670 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, (size_t) Shdr->sh_size);\r
671 break;\r
672\r
673 default:\r
674 //\r
675 // Ignore for unkown section type.\r
676 //\r
677 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
678 break;\r
679 }\r
680 }\r
681 }\r
682\r
683 //\r
684 // Second: apply relocations.\r
685 //\r
686 VerboseMsg ("Applying Relocations...");\r
687 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
688 //\r
689 // Determine if this is a relocation section.\r
690 //\r
691 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
692 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
693 continue;\r
694 }\r
695\r
4962fcfa
AB
696 //\r
697 // If this is a ET_DYN (PIE) executable, we will encounter a dynamic SHT_RELA\r
698 // section that applies to the entire binary, and which will have its section\r
699 // index set to #0 (which is a NULL section with the SHF_ALLOC bit cleared).\r
700 //\r
701 // In the absence of GOT based relocations (which we currently don't support),\r
702 // this RELA section will contain redundant R_xxx_RELATIVE relocations, one\r
703 // for every R_xxx_xx64 relocation appearing in the per-section RELA sections.\r
704 // (i.e., .rela.text and .rela.data)\r
705 //\r
706 if (RelShdr->sh_info == 0) {\r
707 continue;\r
708 }\r
709\r
f51461c8
LG
710 //\r
711 // Relocation section found. Now extract section information that the relocations\r
712 // apply to in the ELF data and the new COFF data.\r
713 //\r
714 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
715 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
716\r
717 //\r
718 // Only process relocations for the current filter type.\r
719 //\r
720 if (RelShdr->sh_type == SHT_RELA && (*Filter)(SecShdr)) {\r
721 UINT64 RelIdx;\r
722\r
723 //\r
724 // Determine the symbol table referenced by the relocation data.\r
725 //\r
726 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
727 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
728\r
729 //\r
730 // Process all relocation entries for this section.\r
731 //\r
732 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINT32) RelShdr->sh_entsize) {\r
733\r
734 //\r
735 // Set pointer to relocation entry\r
736 //\r
737 Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
738\r
739 //\r
740 // Set pointer to symbol table entry associated with the relocation entry.\r
741 //\r
742 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
743\r
744 Elf_Shdr *SymShdr;\r
745 UINT8 *Targ;\r
746\r
747 //\r
748 // Check section header index found in symbol table and get the section\r
749 // header location.\r
750 //\r
751 if (Sym->st_shndx == SHN_UNDEF\r
621bb723
ML
752 || Sym->st_shndx >= mEhdr->e_shnum) {\r
753 const UINT8 *SymName = GetSymName(Sym);\r
754 if (SymName == NULL) {\r
755 SymName = (const UINT8 *)"<unknown>";\r
756 }\r
757\r
758 Error (NULL, 0, 3000, "Invalid",\r
ea3e924a 759 "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. "\r
621bb723
ML
760 "For example, absolute and undefined symbols are not supported.",\r
761 mInImageName, SymName, Sym->st_value);\r
762\r
763 exit(EXIT_FAILURE);\r
f51461c8
LG
764 }\r
765 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
766\r
767 //\r
768 // Convert the relocation data to a pointer into the coff file.\r
769 //\r
770 // Note:\r
771 // r_offset is the virtual address of the storage unit to be relocated.\r
772 // sh_addr is the virtual address for the base of the section.\r
773 //\r
774 // r_offset in a memory address.\r
775 // Convert it to a pointer in the coff file.\r
776 //\r
777 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
778\r
779 //\r
780 // Determine how to handle each relocation type based on the machine type.\r
781 //\r
782 if (mEhdr->e_machine == EM_X86_64) {\r
783 switch (ELF_R_TYPE(Rel->r_info)) {\r
784 case R_X86_64_NONE:\r
785 break;\r
786 case R_X86_64_64:\r
787 //\r
788 // Absolute relocation.\r
789 //\r
790 VerboseMsg ("R_X86_64_64");\r
791 VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", \r
792 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), \r
793 *(UINT64 *)Targ);\r
794 *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
795 VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ);\r
796 break;\r
797 case R_X86_64_32:\r
798 VerboseMsg ("R_X86_64_32");\r
799 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", \r
800 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), \r
801 *(UINT32 *)Targ);\r
802 *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
803 VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ);\r
804 break;\r
805 case R_X86_64_32S:\r
806 VerboseMsg ("R_X86_64_32S");\r
807 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", \r
808 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), \r
809 *(UINT32 *)Targ);\r
810 *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
811 VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ);\r
812 break;\r
c9f29755
AB
813\r
814 case R_X86_64_PLT32:\r
815 //\r
816 // Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is\r
817 // possible since we know all code symbol references resolve to\r
818 // definitions in the same module (UEFI has no shared libraries),\r
819 // and so there is never a reason to jump via a PLT entry,\r
820 // allowing us to resolve the reference using the symbol directly.\r
821 //\r
822 VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ...");\r
823 /* fall through */\r
f51461c8
LG
824 case R_X86_64_PC32:\r
825 //\r
826 // Relative relocation: Symbol - Ip + Addend\r
827 //\r
828 VerboseMsg ("R_X86_64_PC32");\r
829 VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", \r
830 (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), \r
831 *(UINT32 *)Targ);\r
832 *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ\r
833 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
834 - (SecOffset - SecShdr->sh_addr));\r
835 VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ);\r
836 break;\r
837 default:\r
838 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
839 }\r
840 } else if (mEhdr->e_machine == EM_AARCH64) {\r
841\r
f51461c8
LG
842 switch (ELF_R_TYPE(Rel->r_info)) {\r
843\r
24d610e6 844 case R_AARCH64_ADR_PREL_PG_HI21:\r
24d610e6
AB
845 //\r
846 // AArch64 PG_H21 relocations are typically paired with ABS_LO12\r
847 // relocations, where a PC-relative reference with +/- 4 GB range is\r
848 // split into a relative high part and an absolute low part. Since\r
849 // the absolute low part represents the offset into a 4 KB page, we\r
026a82ab
AB
850 // either have to convert the ADRP into an ADR instruction, or we\r
851 // need to use a section alignment of at least 4 KB, so that the\r
852 // binary appears at a correct offset at runtime. In any case, we\r
24d610e6
AB
853 // have to make sure that the 4 KB relative offsets of both the\r
854 // section containing the reference as well as the section to which\r
855 // it refers have not been changed during PE/COFF conversion (i.e.,\r
856 // in ScanSections64() above).\r
857 //\r
026a82ab
AB
858 if (mCoffAlignment < 0x1000) {\r
859 //\r
860 // Attempt to convert the ADRP into an ADR instruction.\r
861 // This is only possible if the symbol is within +/- 1 MB.\r
862 //\r
863 INT64 Offset;\r
864\r
865 // Decode the ADRP instruction\r
866 Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8);\r
867 Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12));\r
868\r
869 //\r
870 // ADRP offset is relative to the previous page boundary,\r
871 // whereas ADR offset is relative to the instruction itself.\r
872 // So fix up the offset so it points to the page containing\r
873 // the symbol.\r
874 //\r
875 Offset -= (UINTN)(Targ - mCoffFile) & 0xfff;\r
876\r
877 if (Offset < -0x100000 || Offset > 0xfffff) {\r
878 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.",\r
879 mInImageName);\r
880 break;\r
881 }\r
882\r
883 // Re-encode the offset as an ADR instruction\r
884 *(UINT32 *)Targ &= 0x1000001f;\r
885 *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29);\r
886 }\r
887 /* fall through */\r
888\r
889 case R_AARCH64_ADD_ABS_LO12_NC:\r
890 case R_AARCH64_LDST8_ABS_LO12_NC:\r
891 case R_AARCH64_LDST16_ABS_LO12_NC:\r
892 case R_AARCH64_LDST32_ABS_LO12_NC:\r
893 case R_AARCH64_LDST64_ABS_LO12_NC:\r
894 case R_AARCH64_LDST128_ABS_LO12_NC:\r
24d610e6 895 if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 ||\r
026a82ab
AB
896 ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) {\r
897 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
898 mInImageName);\r
899 break;\r
87280982 900 }\r
24d610e6 901 /* fall through */\r
87280982 902\r
24d610e6 903 case R_AARCH64_ADR_PREL_LO21:\r
87280982 904 case R_AARCH64_CONDBR19:\r
f51461c8 905 case R_AARCH64_LD_PREL_LO19:\r
f51461c8 906 case R_AARCH64_CALL26:\r
f51461c8 907 case R_AARCH64_JUMP26:\r
0b6249f5
AB
908 case R_AARCH64_PREL64:\r
909 case R_AARCH64_PREL32:\r
910 case R_AARCH64_PREL16:\r
24d610e6
AB
911 //\r
912 // The GCC toolchains (i.e., binutils) may corrupt section relative\r
913 // relocations when emitting relocation sections into fully linked\r
914 // binaries. More specifically, they tend to fail to take into\r
915 // account the fact that a '.rodata + XXX' relocation needs to have\r
916 // its addend recalculated once .rodata is merged into the .text\r
917 // section, and the relocation emitted into the .rela.text section.\r
918 //\r
919 // We cannot really recover from this loss of information, so the\r
920 // only workaround is to prevent having to recalculate any relative\r
921 // relocations at all, by using a linker script that ensures that\r
922 // the offset between the Place and the Symbol is the same in both\r
923 // the ELF and the PE/COFF versions of the binary.\r
924 //\r
925 if ((SymShdr->sh_addr - SecShdr->sh_addr) !=\r
926 (mCoffSectionsOffset[Sym->st_shndx] - SecOffset)) {\r
927 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 relative relocations require identical ELF and PE/COFF section offsets",\r
928 mInImageName);\r
f51461c8
LG
929 }\r
930 break;\r
931\r
f51461c8
LG
932 // Absolute relocations.\r
933 case R_AARCH64_ABS64:\r
934 *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
935 break;\r
936\r
937 default:\r
938 Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
939 }\r
940 } else {\r
941 Error (NULL, 0, 3000, "Invalid", "Not a supported machine type");\r
942 }\r
943 }\r
944 }\r
945 }\r
946\r
947 return TRUE;\r
948}\r
949\r
950STATIC\r
951VOID\r
952WriteRelocations64 (\r
953 VOID\r
954 )\r
955{\r
956 UINT32 Index;\r
957 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
958 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
959\r
960 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
961 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
962 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
963 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
964 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
965 UINT64 RelIdx;\r
966\r
967 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
968 Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
969\r
970 if (mEhdr->e_machine == EM_X86_64) {\r
971 switch (ELF_R_TYPE(Rel->r_info)) {\r
972 case R_X86_64_NONE:\r
973 case R_X86_64_PC32:\r
c9f29755 974 case R_X86_64_PLT32:\r
f51461c8
LG
975 break;\r
976 case R_X86_64_64:\r
977 VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", \r
978 mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
979 CoffAddFixup(\r
980 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
981 + (Rel->r_offset - SecShdr->sh_addr)),\r
982 EFI_IMAGE_REL_BASED_DIR64);\r
983 break;\r
984 case R_X86_64_32S:\r
985 case R_X86_64_32:\r
986 VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", \r
987 mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
988 CoffAddFixup(\r
989 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
990 + (Rel->r_offset - SecShdr->sh_addr)),\r
991 EFI_IMAGE_REL_BASED_HIGHLOW);\r
992 break;\r
993 default:\r
994 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
995 }\r
996 } else if (mEhdr->e_machine == EM_AARCH64) {\r
24d610e6 997\r
f51461c8 998 switch (ELF_R_TYPE(Rel->r_info)) {\r
87280982 999 case R_AARCH64_ADR_PREL_LO21:\r
87280982 1000 case R_AARCH64_CONDBR19:\r
f51461c8 1001 case R_AARCH64_LD_PREL_LO19:\r
f51461c8 1002 case R_AARCH64_CALL26:\r
f51461c8 1003 case R_AARCH64_JUMP26:\r
0b6249f5
AB
1004 case R_AARCH64_PREL64:\r
1005 case R_AARCH64_PREL32:\r
1006 case R_AARCH64_PREL16:\r
f51461c8 1007 case R_AARCH64_ADR_PREL_PG_HI21:\r
f51461c8 1008 case R_AARCH64_ADD_ABS_LO12_NC:\r
24d610e6
AB
1009 case R_AARCH64_LDST8_ABS_LO12_NC:\r
1010 case R_AARCH64_LDST16_ABS_LO12_NC:\r
1011 case R_AARCH64_LDST32_ABS_LO12_NC:\r
1012 case R_AARCH64_LDST64_ABS_LO12_NC:\r
1013 case R_AARCH64_LDST128_ABS_LO12_NC:\r
0b6249f5
AB
1014 //\r
1015 // No fixups are required for relative relocations, provided that\r
1016 // the relative offsets between sections have been preserved in\r
1017 // the ELF to PE/COFF conversion. We have already asserted that\r
1018 // this is the case in WriteSections64 ().\r
1019 //\r
f51461c8
LG
1020 break;\r
1021\r
1022 case R_AARCH64_ABS64:\r
1023 CoffAddFixup(\r
1024 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
1025 + (Rel->r_offset - SecShdr->sh_addr)),\r
1026 EFI_IMAGE_REL_BASED_DIR64);\r
1027 break;\r
1028\r
1029 case R_AARCH64_ABS32:\r
1030 CoffAddFixup(\r
1031 (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
1032 + (Rel->r_offset - SecShdr->sh_addr)),\r
1033 EFI_IMAGE_REL_BASED_HIGHLOW);\r
1034 break;\r
1035\r
1036 default:\r
1037 Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
1038 }\r
1039 } else {\r
1040 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
1041 }\r
1042 }\r
1043 }\r
1044 }\r
1045 }\r
1046\r
1047 //\r
1048 // Pad by adding empty entries.\r
1049 //\r
1050 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1051 CoffAddFixupEntry(0);\r
1052 }\r
1053\r
1054 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1055 Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1056 Dir->Size = mCoffOffset - mRelocOffset;\r
1057 if (Dir->Size == 0) {\r
1058 // If no relocations, null out the directory entry and don't add the .reloc section\r
1059 Dir->VirtualAddress = 0;\r
1060 NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
1061 } else {\r
1062 Dir->VirtualAddress = mRelocOffset;\r
1063 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1064 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1065 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1066 | EFI_IMAGE_SCN_MEM_READ);\r
1067 }\r
1068}\r
1069\r
1070STATIC\r
1071VOID\r
1072WriteDebug64 (\r
1073 VOID\r
1074 )\r
1075{\r
1076 UINT32 Len;\r
f51461c8
LG
1077 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1078 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1079 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1080 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1081\r
1082 Len = strlen(mInImageName) + 1;\r
f51461c8 1083\r
0192b71c 1084 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1085 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1086 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1087 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1088 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1089\r
1090 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1091 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1092 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1093\r
1094\r
1095 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1096 DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c 1097 DataDir->VirtualAddress = mDebugOffset;\r
60e85a39 1098 DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1099}\r
1100\r
1101STATIC\r
1102VOID\r
1103SetImageSize64 (\r
1104 VOID\r
1105 )\r
1106{\r
1107 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1108\r
1109 //\r
1110 // Set image size\r
1111 //\r
1112 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1113 NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = mCoffOffset;\r
1114}\r
1115\r
1116STATIC\r
1117VOID\r
1118CleanUp64 (\r
1119 VOID\r
1120 )\r
1121{\r
1122 if (mCoffSectionsOffset != NULL) {\r
1123 free (mCoffSectionsOffset);\r
1124 }\r
1125}\r
1126\r
1127\r