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