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