]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/C/GenFw/Elf64Convert.c
BaseTools/VfrCompile: Add two new option for VfrCompile
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf64Convert.c
... / ...
CommitLineData
1/** @file\r
2Elf64 convert solution\r
3\r
4Copyright (c) 2010 - 2014, 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 <stdbool.h>\r
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
101STATIC UINT32 mCoffAlignment = 0x20;\r
102\r
103//\r
104// PE section alignment.\r
105//\r
106STATIC const UINT16 mCoffNbrSections = 4;\r
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
121STATIC UINT32 mDebugOffset;\r
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
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
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
218STATIC\r
219UINT32\r
220DebugRvaAlign (\r
221 UINT32 Offset\r
222 )\r
223{\r
224 return (Offset + 3) & ~3;\r
225}\r
226\r
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
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
306 UINT8* StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset;\r
307\r
308 bool foundEnd = false;\r
309 UINT32 i;\r
310 for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {\r
311 foundEnd = StrtabContents[i] == 0;\r
312 }\r
313 assert(foundEnd);\r
314\r
315 return StrtabContents + Sym->st_name;\r
316}\r
317\r
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
333 BOOLEAN FoundSection;\r
334\r
335 CoffEntry = 0;\r
336 mCoffOffset = 0;\r
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
350 VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine);\r
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
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
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
382 //\r
383 // First text sections.\r
384 //\r
385 mCoffOffset = CoffAlign(mCoffOffset);\r
386 mTextOffset = mCoffOffset;\r
387 FoundSection = FALSE;\r
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
397 } else {\r
398 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
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
411 if (!FoundSection) {\r
412 mTextOffset = mCoffOffset;\r
413 FoundSection = TRUE;\r
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
422 if (!FoundSection) {\r
423 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
424 assert (FALSE);\r
425 }\r
426\r
427 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
428 mCoffOffset = CoffAlign(mCoffOffset);\r
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
438 FoundSection = FALSE;\r
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
448 } else {\r
449 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
450 }\r
451 }\r
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
460 mCoffSectionsOffset[i] = mCoffOffset;\r
461 mCoffOffset += (UINT32) shdr->sh_size;\r
462 SectionCount ++;\r
463 }\r
464 }\r
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
473 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
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
479 mCoffOffset = CoffAlign(mCoffOffset);\r
480 if (SectionCount == 0) {\r
481 mDataOffset = mCoffOffset;\r
482 }\r
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
500 } else {\r
501 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
502 }\r
503 }\r
504 if (shdr->sh_size != 0) {\r
505 mHiiRsrcOffset = mCoffOffset;\r
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
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
734 "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. "\r
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
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
806 switch (ELF_R_TYPE(Rel->r_info)) {\r
807\r
808 case R_AARCH64_ADR_PREL_PG_HI21:\r
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
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
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
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
859 if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 ||\r
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
862 mInImageName);\r
863 break;\r
864 }\r
865 /* fall through */\r
866\r
867 case R_AARCH64_ADR_PREL_LO21:\r
868 case R_AARCH64_CONDBR19:\r
869 case R_AARCH64_LD_PREL_LO19:\r
870 case R_AARCH64_CALL26:\r
871 case R_AARCH64_JUMP26:\r
872 case R_AARCH64_PREL64:\r
873 case R_AARCH64_PREL32:\r
874 case R_AARCH64_PREL16:\r
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
893 }\r
894 break;\r
895\r
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
960\r
961 switch (ELF_R_TYPE(Rel->r_info)) {\r
962 case R_AARCH64_ADR_PREL_LO21:\r
963 case R_AARCH64_CONDBR19:\r
964 case R_AARCH64_LD_PREL_LO19:\r
965 case R_AARCH64_CALL26:\r
966 case R_AARCH64_JUMP26:\r
967 case R_AARCH64_PREL64:\r
968 case R_AARCH64_PREL32:\r
969 case R_AARCH64_PREL16:\r
970 case R_AARCH64_ADR_PREL_PG_HI21:\r
971 case R_AARCH64_ADD_ABS_LO12_NC:\r
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
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
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
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
1046\r
1047 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
1048 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1049 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
1050 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1051 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
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
1060 DataDir->VirtualAddress = mDebugOffset;\r
1061 DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
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