]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - 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
1/** @file\r
2Elf64 convert solution\r
3\r
4Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>\r
5Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
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
100STATIC UINT32 mCoffAlignment = 0x20;\r
101\r
102//\r
103// PE section alignment.\r
104//\r
105STATIC const UINT16 mCoffNbrSections = 4;\r
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
120STATIC UINT32 mDebugOffset;\r
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
174 if (mCoffSectionsOffset == NULL) {\r
175 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
176 return FALSE;\r
177 }\r
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
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
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
221STATIC\r
222UINT32\r
223DebugRvaAlign (\r
224 UINT32 Offset\r
225 )\r
226{\r
227 return (Offset + 3) & ~3;\r
228}\r
229\r
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
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
298 Elf_Shdr *StrtabShdr;\r
299 UINT8 *StrtabContents;\r
300 BOOLEAN foundEnd;\r
301 UINT32 i;\r
302\r
303 if (Sym->st_name == 0) {\r
304 return NULL;\r
305 }\r
306\r
307 StrtabShdr = FindStrtabShdr();\r
308 if (StrtabShdr == NULL) {\r
309 return NULL;\r
310 }\r
311\r
312 assert(Sym->st_name < StrtabShdr->sh_size);\r
313\r
314 StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset;\r
315\r
316 foundEnd = FALSE;\r
317 for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {\r
318 foundEnd = (BOOLEAN)(StrtabContents[i] == 0);\r
319 }\r
320 assert(foundEnd);\r
321\r
322 return StrtabContents + Sym->st_name;\r
323}\r
324\r
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
340 BOOLEAN FoundSection;\r
341\r
342 CoffEntry = 0;\r
343 mCoffOffset = 0;\r
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
357 VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine);\r
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
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
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
389 //\r
390 // First text sections.\r
391 //\r
392 mCoffOffset = CoffAlign(mCoffOffset);\r
393 mTextOffset = mCoffOffset;\r
394 FoundSection = FALSE;\r
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
404 } else {\r
405 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
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
418 if (!FoundSection) {\r
419 mTextOffset = mCoffOffset;\r
420 FoundSection = TRUE;\r
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
429 if (!FoundSection) {\r
430 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
431 assert (FALSE);\r
432 }\r
433\r
434 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
435 mCoffOffset = CoffAlign(mCoffOffset);\r
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
445 FoundSection = FALSE;\r
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
455 } else {\r
456 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
457 }\r
458 }\r
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
467 mCoffSectionsOffset[i] = mCoffOffset;\r
468 mCoffOffset += (UINT32) shdr->sh_size;\r
469 SectionCount ++;\r
470 }\r
471 }\r
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
480 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
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
486 mCoffOffset = CoffAlign(mCoffOffset);\r
487 if (SectionCount == 0) {\r
488 mDataOffset = mCoffOffset;\r
489 }\r
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
507 } else {\r
508 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
509 }\r
510 }\r
511 if (shdr->sh_size != 0) {\r
512 mHiiRsrcOffset = mCoffOffset;\r
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
528 if (mCoffFile == NULL) {\r
529 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
530 }\r
531 assert (mCoffFile != NULL);\r
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
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
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
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
759 "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. "\r
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
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
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
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
842 switch (ELF_R_TYPE(Rel->r_info)) {\r
843\r
844 case R_AARCH64_ADR_PREL_PG_HI21:\r
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
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
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
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
895 if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 ||\r
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
898 mInImageName);\r
899 break;\r
900 }\r
901 /* fall through */\r
902\r
903 case R_AARCH64_ADR_PREL_LO21:\r
904 case R_AARCH64_CONDBR19:\r
905 case R_AARCH64_LD_PREL_LO19:\r
906 case R_AARCH64_CALL26:\r
907 case R_AARCH64_JUMP26:\r
908 case R_AARCH64_PREL64:\r
909 case R_AARCH64_PREL32:\r
910 case R_AARCH64_PREL16:\r
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
929 }\r
930 break;\r
931\r
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
974 case R_X86_64_PLT32:\r
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
997\r
998 switch (ELF_R_TYPE(Rel->r_info)) {\r
999 case R_AARCH64_ADR_PREL_LO21:\r
1000 case R_AARCH64_CONDBR19:\r
1001 case R_AARCH64_LD_PREL_LO19:\r
1002 case R_AARCH64_CALL26:\r
1003 case R_AARCH64_JUMP26:\r
1004 case R_AARCH64_PREL64:\r
1005 case R_AARCH64_PREL32:\r
1006 case R_AARCH64_PREL16:\r
1007 case R_AARCH64_ADR_PREL_PG_HI21:\r
1008 case R_AARCH64_ADD_ABS_LO12_NC:\r
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
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
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
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
1083\r
1084 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
1085 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1086 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
1087 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1088 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
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
1097 DataDir->VirtualAddress = mDebugOffset;\r
1098 DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
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