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