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