]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
BaseTools/GenFw: Enhance error message for bad symbol definitions
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2Elf32 Convert solution\r
f51461c8 3\r
5aec6991 4Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
5Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>\r
6\r
7This program and the accompanying materials are licensed and made available\r
8under the terms and conditions of the BSD License which accompanies this\r
9distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "WinNtInclude.h"\r
18\r
19#ifndef __GNUC__\r
20#include <windows.h>\r
21#include <io.h>\r
22#endif\r
23#include <assert.h>\r
24#include <stdio.h>\r
25#include <stdlib.h>\r
26#include <string.h>\r
27#include <time.h>\r
28#include <ctype.h>\r
29\r
30#include <Common/UefiBaseTypes.h>\r
31#include <IndustryStandard/PeImage.h>\r
32\r
33#include "PeCoffLib.h"\r
34#include "EfiUtilityMsgs.h"\r
35\r
36#include "GenFw.h"\r
37#include "ElfConvert.h"\r
38#include "Elf32Convert.h"\r
39\r
40STATIC\r
41VOID\r
42ScanSections32 (\r
43 VOID\r
44 );\r
45\r
46STATIC\r
47BOOLEAN\r
48WriteSections32 (\r
49 SECTION_FILTER_TYPES FilterType\r
50 );\r
51\r
52STATIC\r
53VOID\r
54WriteRelocations32 (\r
55 VOID\r
56 );\r
57\r
58STATIC\r
59VOID\r
60WriteDebug32 (\r
61 VOID\r
62 );\r
63\r
64STATIC\r
65VOID\r
66SetImageSize32 (\r
67 VOID\r
68 );\r
69\r
70STATIC\r
71VOID\r
72CleanUp32 (\r
73 VOID\r
74 );\r
75\r
76//\r
77// Rename ELF32 strucutres to common names to help when porting to ELF64.\r
78//\r
79typedef Elf32_Shdr Elf_Shdr;\r
80typedef Elf32_Ehdr Elf_Ehdr;\r
81typedef Elf32_Rel Elf_Rel;\r
82typedef Elf32_Sym Elf_Sym;\r
83typedef Elf32_Phdr Elf_Phdr;\r
84typedef Elf32_Dyn Elf_Dyn;\r
85#define ELFCLASS ELFCLASS32\r
86#define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
87#define ELF_R_SYM(r) ELF32_R_SYM(r)\r
88\r
89//\r
90// Well known ELF structures.\r
91//\r
92STATIC Elf_Ehdr *mEhdr;\r
93STATIC Elf_Shdr *mShdrBase;\r
94STATIC Elf_Phdr *mPhdrBase;\r
95\r
96//\r
97// Coff information\r
98//\r
54b1b57a 99STATIC UINT32 mCoffAlignment = 0x20;\r
f51461c8
LG
100\r
101//\r
102// PE section alignment.\r
103//\r
0192b71c 104STATIC const UINT16 mCoffNbrSections = 4;\r
f51461c8
LG
105\r
106//\r
107// ELF sections to offset in Coff file.\r
108//\r
109STATIC UINT32 *mCoffSectionsOffset = NULL;\r
110\r
111//\r
112// Offsets in COFF file\r
113//\r
114STATIC UINT32 mNtHdrOffset;\r
115STATIC UINT32 mTextOffset;\r
116STATIC UINT32 mDataOffset;\r
117STATIC UINT32 mHiiRsrcOffset;\r
118STATIC UINT32 mRelocOffset;\r
0192b71c 119STATIC UINT32 mDebugOffset;\r
f51461c8
LG
120\r
121//\r
122// Initialization Function\r
123//\r
124BOOLEAN\r
125InitializeElf32 (\r
126 UINT8 *FileBuffer,\r
127 ELF_FUNCTION_TABLE *ElfFunctions\r
128 )\r
129{\r
130 //\r
131 // Initialize data pointer and structures.\r
132 //\r
133 mEhdr = (Elf_Ehdr*) FileBuffer; \r
134\r
135 //\r
136 // Check the ELF32 specific header information.\r
137 //\r
138 if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) {\r
139 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32");\r
140 return FALSE;\r
141 }\r
142 if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
143 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
144 return FALSE;\r
145 } \r
146 if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {\r
147 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
148 return FALSE;\r
149 }\r
150 if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) { \r
151 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
152 return FALSE;\r
153 }\r
154 if (mEhdr->e_version != EV_CURRENT) {\r
155 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);\r
156 return FALSE;\r
157 }\r
158 \r
159 //\r
160 // Update section header pointers\r
161 //\r
162 mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);\r
163 mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);\r
164 \r
165 //\r
166 // Create COFF Section offset buffer and zero.\r
167 //\r
168 mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));\r
169 memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));\r
170\r
171 //\r
172 // Fill in function pointers.\r
173 //\r
174 ElfFunctions->ScanSections = ScanSections32;\r
175 ElfFunctions->WriteSections = WriteSections32;\r
176 ElfFunctions->WriteRelocations = WriteRelocations32;\r
177 ElfFunctions->WriteDebug = WriteDebug32;\r
178 ElfFunctions->SetImageSize = SetImageSize32;\r
179 ElfFunctions->CleanUp = CleanUp32;\r
180\r
181 return TRUE;\r
182}\r
183\r
184\r
185//\r
186// Header by Index functions\r
187//\r
188STATIC\r
189Elf_Shdr*\r
190GetShdrByIndex (\r
191 UINT32 Num\r
192 )\r
193{\r
17751c5f
ML
194 if (Num >= mEhdr->e_shnum) {\r
195 Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num);\r
196 exit(EXIT_FAILURE);\r
197 }\r
198\r
f51461c8
LG
199 return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);\r
200}\r
201\r
202STATIC\r
203Elf_Phdr*\r
204GetPhdrByIndex (\r
205 UINT32 num\r
206 )\r
207{\r
208 if (num >= mEhdr->e_phnum) {\r
17751c5f
ML
209 Error (NULL, 0, 3000, "Invalid", "GetPhdrByIndex: Index %u is too high.", num);\r
210 exit(EXIT_FAILURE);\r
f51461c8
LG
211 }\r
212\r
213 return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize);\r
214}\r
215\r
216STATIC\r
217UINT32\r
218CoffAlign (\r
219 UINT32 Offset\r
220 )\r
221{\r
222 return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
223}\r
224\r
4f7d5c67
AB
225STATIC\r
226UINT32\r
227DebugRvaAlign (\r
228 UINT32 Offset\r
229 )\r
230{\r
231 return (Offset + 3) & ~3;\r
232}\r
233\r
f51461c8
LG
234//\r
235// filter functions\r
236//\r
237STATIC\r
238BOOLEAN\r
239IsTextShdr (\r
240 Elf_Shdr *Shdr\r
241 )\r
242{\r
243 return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);\r
244}\r
245\r
246STATIC\r
247BOOLEAN\r
248IsHiiRsrcShdr (\r
249 Elf_Shdr *Shdr\r
250 )\r
251{\r
252 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
253\r
254 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
255}\r
256\r
257STATIC\r
258BOOLEAN\r
259IsDataShdr (\r
260 Elf_Shdr *Shdr\r
261 )\r
262{\r
263 if (IsHiiRsrcShdr(Shdr)) {\r
264 return FALSE;\r
265 }\r
266 return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
267}\r
268\r
621bb723
ML
269STATIC\r
270BOOLEAN\r
271IsStrtabShdr (\r
272 Elf_Shdr *Shdr\r
273 )\r
274{\r
275 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
276\r
277 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0);\r
278}\r
279\r
280STATIC\r
281Elf_Shdr *\r
282FindStrtabShdr (\r
283 VOID\r
284 )\r
285{\r
286 UINT32 i;\r
287 for (i = 0; i < mEhdr->e_shnum; i++) {\r
288 Elf_Shdr *shdr = GetShdrByIndex(i);\r
289 if (IsStrtabShdr(shdr)) {\r
290 return shdr;\r
291 }\r
292 }\r
293 return NULL;\r
294}\r
295\r
296STATIC\r
297const UINT8 *\r
298GetSymName (\r
299 Elf_Sym *Sym\r
300 )\r
301{\r
302 if (Sym->st_name == 0) {\r
303 return NULL;\r
304 }\r
305\r
306 Elf_Shdr *StrtabShdr = FindStrtabShdr();\r
307 if (StrtabShdr == NULL) {\r
308 return NULL;\r
309 }\r
310\r
311 assert(Sym->st_name < StrtabShdr->sh_size);\r
312\r
313 return (UINT8*)mEhdr + StrtabShdr->sh_offset + Sym->st_name;\r
314}\r
315\r
f51461c8
LG
316//\r
317// Elf functions interface implementation\r
318//\r
319\r
320STATIC\r
321VOID\r
322ScanSections32 (\r
323 VOID\r
324 )\r
325{\r
326 UINT32 i;\r
327 EFI_IMAGE_DOS_HEADER *DosHdr;\r
328 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
329 UINT32 CoffEntry;\r
330 UINT32 SectionCount;\r
234f9ff9 331 BOOLEAN FoundSection;\r
f51461c8
LG
332\r
333 CoffEntry = 0;\r
334 mCoffOffset = 0;\r
f51461c8
LG
335\r
336 //\r
337 // Coff file start with a DOS header.\r
338 //\r
339 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
340 mNtHdrOffset = mCoffOffset;\r
341 switch (mEhdr->e_machine) {\r
342 case EM_386:\r
343 case EM_ARM:\r
344 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
345 break;\r
346 default:\r
347 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
348 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
349 break;\r
350 }\r
351\r
352 mTableOffset = mCoffOffset;\r
353 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
354\r
54b1b57a
AB
355 //\r
356 // Set mCoffAlignment to the maximum alignment of the input sections\r
357 // we care about\r
358 //\r
359 for (i = 0; i < mEhdr->e_shnum; i++) {\r
360 Elf_Shdr *shdr = GetShdrByIndex(i);\r
361 if (shdr->sh_addralign <= mCoffAlignment) {\r
362 continue;\r
363 }\r
364 if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {\r
365 mCoffAlignment = (UINT32)shdr->sh_addralign;\r
366 }\r
367 }\r
368\r
02a5421f
AB
369 //\r
370 // Move the PE/COFF header right before the first section. This will help us\r
371 // save space when converting to TE.\r
372 //\r
373 if (mCoffAlignment > mCoffOffset) {\r
374 mNtHdrOffset += mCoffAlignment - mCoffOffset;\r
375 mTableOffset += mCoffAlignment - mCoffOffset;\r
376 mCoffOffset = mCoffAlignment;\r
377 }\r
378\r
f51461c8
LG
379 //\r
380 // First text sections.\r
381 //\r
382 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
383 mTextOffset = mCoffOffset;\r
384 FoundSection = FALSE;\r
f51461c8
LG
385 SectionCount = 0;\r
386 for (i = 0; i < mEhdr->e_shnum; i++) {\r
387 Elf_Shdr *shdr = GetShdrByIndex(i);\r
388 if (IsTextShdr(shdr)) {\r
389 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
390 // the alignment field is valid\r
391 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
392 // if the section address is aligned we must align PE/COFF\r
393 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
394 } else {\r
395 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
396 }\r
397 }\r
398\r
399 /* Relocate entry. */\r
400 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
401 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
402 CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;\r
403 }\r
404\r
405 //\r
406 // Set mTextOffset with the offset of the first '.text' section\r
407 //\r
234f9ff9 408 if (!FoundSection) {\r
f51461c8 409 mTextOffset = mCoffOffset;\r
234f9ff9 410 FoundSection = TRUE;\r
f51461c8
LG
411 }\r
412\r
413 mCoffSectionsOffset[i] = mCoffOffset;\r
414 mCoffOffset += shdr->sh_size;\r
415 SectionCount ++;\r
416 }\r
417 }\r
418\r
234f9ff9 419 if (!FoundSection) {\r
f51461c8
LG
420 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
421 assert (FALSE);\r
422 }\r
423\r
4f7d5c67 424 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0bd0d6df 425 mCoffOffset = CoffAlign(mCoffOffset);\r
f51461c8
LG
426\r
427 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
428 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
429 }\r
430\r
431 //\r
432 // Then data sections.\r
433 //\r
434 mDataOffset = mCoffOffset;\r
234f9ff9 435 FoundSection = FALSE;\r
f51461c8
LG
436 SectionCount = 0;\r
437 for (i = 0; i < mEhdr->e_shnum; i++) {\r
438 Elf_Shdr *shdr = GetShdrByIndex(i);\r
439 if (IsDataShdr(shdr)) {\r
440 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
441 // the alignment field is valid\r
442 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
443 // if the section address is aligned we must align PE/COFF\r
444 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
445 } else {\r
446 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
447 }\r
448 }\r
234f9ff9
EB
449\r
450 //\r
451 // Set mDataOffset with the offset of the first '.data' section\r
452 //\r
453 if (!FoundSection) {\r
454 mDataOffset = mCoffOffset;\r
455 FoundSection = TRUE;\r
456 }\r
457\r
f51461c8
LG
458 mCoffSectionsOffset[i] = mCoffOffset;\r
459 mCoffOffset += shdr->sh_size;\r
460 SectionCount ++;\r
461 }\r
462 }\r
f51461c8
LG
463\r
464 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
465 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
466 }\r
467\r
0192b71c
AB
468 //\r
469 // Make room for .debug data in .data (or .text if .data is empty) instead of\r
470 // putting it in a section of its own. This is explicitly allowed by the\r
471 // PE/COFF spec, and prevents bloat in the binary when using large values for\r
472 // section alignment.\r
473 //\r
474 if (SectionCount > 0) {\r
4f7d5c67 475 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0192b71c
AB
476 }\r
477 mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
478 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
479 strlen(mInImageName) + 1;\r
480\r
481 mCoffOffset = CoffAlign(mCoffOffset);\r
482 if (SectionCount == 0) {\r
483 mDataOffset = mCoffOffset;\r
484 }\r
485\r
f51461c8
LG
486 //\r
487 // The HII resource sections.\r
488 //\r
489 mHiiRsrcOffset = mCoffOffset;\r
490 for (i = 0; i < mEhdr->e_shnum; i++) {\r
491 Elf_Shdr *shdr = GetShdrByIndex(i);\r
492 if (IsHiiRsrcShdr(shdr)) {\r
493 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
494 // the alignment field is valid\r
495 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
496 // if the section address is aligned we must align PE/COFF\r
497 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
498 } else {\r
499 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
500 }\r
501 }\r
502 if (shdr->sh_size != 0) {\r
234f9ff9 503 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
504 mCoffSectionsOffset[i] = mCoffOffset;\r
505 mCoffOffset += shdr->sh_size;\r
506 mCoffOffset = CoffAlign(mCoffOffset);\r
507 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
508 }\r
509 break;\r
510 }\r
511 }\r
512\r
513 mRelocOffset = mCoffOffset;\r
514\r
515 //\r
516 // Allocate base Coff file. Will be expanded later for relocations.\r
517 //\r
518 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
519 memset(mCoffFile, 0, mCoffOffset);\r
520\r
521 //\r
522 // Fill headers.\r
523 //\r
524 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
525 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
526 DosHdr->e_lfanew = mNtHdrOffset;\r
527\r
528 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
529\r
530 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
531\r
532 switch (mEhdr->e_machine) {\r
533 case EM_386:\r
534 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
535 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
536 break;\r
537 case EM_ARM:\r
538 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
539 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
540 break;\r
541 default:\r
542 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
543 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
544 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
545 }\r
546\r
547 NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections;\r
548 NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
549 mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
550 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
551 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
552 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
553 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
554 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
555 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
556 | EFI_IMAGE_FILE_32BIT_MACHINE;\r
557\r
558 NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
559 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
560 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
561 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
562\r
563 NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset;\r
564\r
565 NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset;\r
566 NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
567 NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment;\r
568 NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment;\r
569 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
570\r
571 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset;\r
572 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
573\r
574 //\r
575 // Section headers.\r
576 //\r
577 if ((mDataOffset - mTextOffset) > 0) {\r
578 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
579 EFI_IMAGE_SCN_CNT_CODE\r
580 | EFI_IMAGE_SCN_MEM_EXECUTE\r
581 | EFI_IMAGE_SCN_MEM_READ);\r
582 } else {\r
583 // Don't make a section of size 0.\r
584 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
585 }\r
586\r
587 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
588 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
589 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
590 | EFI_IMAGE_SCN_MEM_WRITE\r
591 | EFI_IMAGE_SCN_MEM_READ);\r
592 } else {\r
593 // Don't make a section of size 0.\r
594 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
595 }\r
596\r
597 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
598 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
599 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
600 | EFI_IMAGE_SCN_MEM_READ);\r
601\r
602 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
603 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
604 } else {\r
605 // Don't make a section of size 0.\r
606 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
607 }\r
608\r
609}\r
610\r
611STATIC\r
612BOOLEAN\r
613WriteSections32 (\r
614 SECTION_FILTER_TYPES FilterType\r
615 )\r
616{\r
617 UINT32 Idx;\r
618 Elf_Shdr *SecShdr;\r
619 UINT32 SecOffset;\r
620 BOOLEAN (*Filter)(Elf_Shdr *);\r
621\r
622 //\r
623 // Initialize filter pointer\r
624 //\r
625 switch (FilterType) {\r
626 case SECTION_TEXT:\r
627 Filter = IsTextShdr;\r
628 break;\r
629 case SECTION_HII:\r
630 Filter = IsHiiRsrcShdr;\r
631 break;\r
632 case SECTION_DATA:\r
633 Filter = IsDataShdr;\r
634 break;\r
635 default:\r
636 return FALSE;\r
637 }\r
638\r
639 //\r
640 // First: copy sections.\r
641 //\r
642 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
643 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
644 if ((*Filter)(Shdr)) {\r
645 switch (Shdr->sh_type) {\r
646 case SHT_PROGBITS:\r
647 /* Copy. */\r
648 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
649 (UINT8*)mEhdr + Shdr->sh_offset,\r
650 Shdr->sh_size);\r
651 break;\r
652\r
653 case SHT_NOBITS:\r
654 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
655 break;\r
656\r
657 default:\r
658 //\r
659 // Ignore for unkown section type.\r
660 //\r
661 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
662 break;\r
663 }\r
664 }\r
665 }\r
666\r
667 //\r
668 // Second: apply relocations.\r
669 //\r
670 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
671 //\r
672 // Determine if this is a relocation section.\r
673 //\r
674 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
675 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
676 continue;\r
677 }\r
678 \r
679 //\r
680 // Relocation section found. Now extract section information that the relocations\r
681 // apply to in the ELF data and the new COFF data.\r
682 //\r
683 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
684 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
685 \r
686 //\r
687 // Only process relocations for the current filter type.\r
688 //\r
689 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
690 UINT32 RelOffset;\r
691 \r
692 //\r
693 // Determine the symbol table referenced by the relocation data.\r
694 //\r
695 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
696 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
697\r
698 //\r
699 // Process all relocation entries for this section.\r
700 //\r
701 for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {\r
702 //\r
703 // Set pointer to relocation entry\r
704 //\r
705 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);\r
706 \r
707 //\r
708 // Set pointer to symbol table entry associated with the relocation entry.\r
709 //\r
710 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
711 \r
712 Elf_Shdr *SymShdr;\r
713 UINT8 *Targ;\r
714 UINT16 Address;\r
715\r
716 //\r
717 // Check section header index found in symbol table and get the section \r
718 // header location.\r
719 //\r
720 if (Sym->st_shndx == SHN_UNDEF\r
621bb723
ML
721 || Sym->st_shndx >= mEhdr->e_shnum) {\r
722 const UINT8 *SymName = GetSymName(Sym);\r
723 if (SymName == NULL) {\r
724 SymName = (const UINT8 *)"<unknown>";\r
725 }\r
726\r
727 Error (NULL, 0, 3000, "Invalid",\r
728 "%s: Bad definition for symbol '%s'@%p or unsupported symbol type. "\r
729 "For example, absolute and undefined symbols are not supported.",\r
730 mInImageName, SymName, Sym->st_value);\r
731\r
732 exit(EXIT_FAILURE);\r
f51461c8
LG
733 }\r
734 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
735\r
736 //\r
737 // Convert the relocation data to a pointer into the coff file.\r
738 //\r
739 // Note: \r
740 // r_offset is the virtual address of the storage unit to be relocated.\r
741 // sh_addr is the virtual address for the base of the section.\r
742 //\r
743 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
744\r
745 //\r
746 // Determine how to handle each relocation type based on the machine type.\r
747 //\r
748 if (mEhdr->e_machine == EM_386) {\r
749 switch (ELF_R_TYPE(Rel->r_info)) {\r
750 case R_386_NONE:\r
751 break;\r
752 case R_386_32:\r
753 //\r
754 // Absolute relocation.\r
755 // Converts Targ from a absolute virtual address to the absolute\r
756 // COFF address.\r
757 //\r
758 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
759 + mCoffSectionsOffset[Sym->st_shndx];\r
760 break;\r
761 case R_386_PC32:\r
762 //\r
763 // Relative relocation: Symbol - Ip + Addend\r
764 //\r
765 *(UINT32 *)Targ = *(UINT32 *)Targ\r
766 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
767 - (SecOffset - SecShdr->sh_addr);\r
768 break;\r
769 default:\r
770 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
771 }\r
772 } else if (mEhdr->e_machine == EM_ARM) {\r
773 switch (ELF32_R_TYPE(Rel->r_info)) {\r
774 case R_ARM_RBASE:\r
775 // No relocation - no action required\r
776 // break skipped\r
777\r
778 case R_ARM_PC24:\r
31643611 779 case R_ARM_REL32:\r
f51461c8
LG
780 case R_ARM_XPC25:\r
781 case R_ARM_THM_PC22:\r
782 case R_ARM_THM_JUMP19:\r
783 case R_ARM_CALL:\r
784 case R_ARM_JMP24:\r
785 case R_ARM_THM_JUMP24: \r
786 case R_ARM_PREL31: \r
787 case R_ARM_MOVW_PREL_NC: \r
788 case R_ARM_MOVT_PREL:\r
789 case R_ARM_THM_MOVW_PREL_NC:\r
790 case R_ARM_THM_MOVT_PREL:\r
791 case R_ARM_THM_JMP6:\r
792 case R_ARM_THM_ALU_PREL_11_0:\r
793 case R_ARM_THM_PC12:\r
794 case R_ARM_REL32_NOI:\r
795 case R_ARM_ALU_PC_G0_NC:\r
796 case R_ARM_ALU_PC_G0:\r
797 case R_ARM_ALU_PC_G1_NC:\r
798 case R_ARM_ALU_PC_G1:\r
799 case R_ARM_ALU_PC_G2:\r
800 case R_ARM_LDR_PC_G1:\r
801 case R_ARM_LDR_PC_G2:\r
802 case R_ARM_LDRS_PC_G0:\r
803 case R_ARM_LDRS_PC_G1:\r
804 case R_ARM_LDRS_PC_G2:\r
805 case R_ARM_LDC_PC_G0:\r
806 case R_ARM_LDC_PC_G1:\r
807 case R_ARM_LDC_PC_G2:\r
808 case R_ARM_GOT_PREL:\r
809 case R_ARM_THM_JUMP11:\r
810 case R_ARM_THM_JUMP8:\r
811 case R_ARM_TLS_GD32:\r
812 case R_ARM_TLS_LDM32:\r
813 case R_ARM_TLS_IE32:\r
814 // Thease are all PC-relative relocations and don't require modification\r
815 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
816 break;\r
817\r
818 case R_ARM_THM_MOVW_ABS_NC:\r
819 // MOVW is only lower 16-bits of the addres\r
820 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
821 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
822 break;\r
823\r
824 case R_ARM_THM_MOVT_ABS:\r
825 // MOVT is only upper 16-bits of the addres\r
826 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
827 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
828 break;\r
829\r
830 case R_ARM_ABS32:\r
831 case R_ARM_RABS32:\r
832 //\r
833 // Absolute relocation.\r
834 //\r
835 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
836 break;\r
837\r
838 default:\r
839 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
840 }\r
841 }\r
842 }\r
843 }\r
844 }\r
845\r
846 return TRUE;\r
847}\r
848\r
849UINTN gMovwOffset = 0;\r
850\r
851STATIC\r
852VOID\r
853WriteRelocations32 (\r
854 VOID\r
855 )\r
856{\r
857 UINT32 Index;\r
858 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
859 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
860 BOOLEAN FoundRelocations;\r
861 Elf_Dyn *Dyn;\r
862 Elf_Rel *Rel;\r
863 UINTN RelElementSize;\r
864 UINTN RelSize;\r
865 UINTN RelOffset;\r
866 UINTN K;\r
f51461c8 867 Elf32_Phdr *DynamicSegment;\r
f51461c8
LG
868\r
869 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
870 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
871 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
872 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
873 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
874 UINT32 RelIdx;\r
875\r
876 FoundRelocations = TRUE;\r
877 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
5aec6991 878 Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
f51461c8
LG
879\r
880 if (mEhdr->e_machine == EM_386) { \r
881 switch (ELF_R_TYPE(Rel->r_info)) {\r
882 case R_386_NONE:\r
883 case R_386_PC32:\r
884 //\r
885 // No fixup entry required.\r
886 //\r
887 break;\r
888 case R_386_32:\r
889 //\r
890 // Creates a relative relocation entry from the absolute entry.\r
891 //\r
892 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
893 + (Rel->r_offset - SecShdr->sh_addr),\r
894 EFI_IMAGE_REL_BASED_HIGHLOW);\r
895 break;\r
896 default:\r
897 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
898 }\r
899 } else if (mEhdr->e_machine == EM_ARM) {\r
900 switch (ELF32_R_TYPE(Rel->r_info)) {\r
901 case R_ARM_RBASE:\r
902 // No relocation - no action required\r
903 // break skipped\r
904\r
905 case R_ARM_PC24:\r
31643611 906 case R_ARM_REL32:\r
f51461c8
LG
907 case R_ARM_XPC25:\r
908 case R_ARM_THM_PC22:\r
909 case R_ARM_THM_JUMP19:\r
910 case R_ARM_CALL:\r
911 case R_ARM_JMP24:\r
912 case R_ARM_THM_JUMP24: \r
913 case R_ARM_PREL31: \r
914 case R_ARM_MOVW_PREL_NC: \r
915 case R_ARM_MOVT_PREL:\r
916 case R_ARM_THM_MOVW_PREL_NC:\r
917 case R_ARM_THM_MOVT_PREL:\r
918 case R_ARM_THM_JMP6:\r
919 case R_ARM_THM_ALU_PREL_11_0:\r
920 case R_ARM_THM_PC12:\r
921 case R_ARM_REL32_NOI:\r
922 case R_ARM_ALU_PC_G0_NC:\r
923 case R_ARM_ALU_PC_G0:\r
924 case R_ARM_ALU_PC_G1_NC:\r
925 case R_ARM_ALU_PC_G1:\r
926 case R_ARM_ALU_PC_G2:\r
927 case R_ARM_LDR_PC_G1:\r
928 case R_ARM_LDR_PC_G2:\r
929 case R_ARM_LDRS_PC_G0:\r
930 case R_ARM_LDRS_PC_G1:\r
931 case R_ARM_LDRS_PC_G2:\r
932 case R_ARM_LDC_PC_G0:\r
933 case R_ARM_LDC_PC_G1:\r
934 case R_ARM_LDC_PC_G2:\r
935 case R_ARM_GOT_PREL:\r
936 case R_ARM_THM_JUMP11:\r
937 case R_ARM_THM_JUMP8:\r
938 case R_ARM_TLS_GD32:\r
939 case R_ARM_TLS_LDM32:\r
940 case R_ARM_TLS_IE32:\r
941 // Thease are all PC-relative relocations and don't require modification\r
942 break;\r
943\r
944 case R_ARM_THM_MOVW_ABS_NC:\r
945 CoffAddFixup (\r
946 mCoffSectionsOffset[RelShdr->sh_info]\r
947 + (Rel->r_offset - SecShdr->sh_addr),\r
948 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
949 );\r
950\r
951 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
952 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
953 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
954 break;\r
955\r
956 case R_ARM_THM_MOVT_ABS:\r
957 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
958 Error (NULL, 0, 3000, "Not Supported", "PE/COFF requires MOVW+MOVT instruction sequence %x +4 != %x.", gMovwOffset, mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr));\r
959 }\r
960 break;\r
961\r
962 case R_ARM_ABS32:\r
963 case R_ARM_RABS32:\r
964 CoffAddFixup (\r
965 mCoffSectionsOffset[RelShdr->sh_info]\r
966 + (Rel->r_offset - SecShdr->sh_addr),\r
967 EFI_IMAGE_REL_BASED_HIGHLOW\r
968 );\r
969 break;\r
970\r
971 default:\r
972 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
973 }\r
974 } else {\r
975 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
976 }\r
977 }\r
978 }\r
979 }\r
980 }\r
981\r
982 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
983 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
984\r
985 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
986 RelElementSize = 0;\r
987 RelSize = 0;\r
988 RelOffset = 0;\r
989\r
990 DynamicSegment = GetPhdrByIndex (Index);\r
991\r
992 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
993 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
994\r
995 while (Dyn->d_tag != DT_NULL) {\r
996 switch (Dyn->d_tag) {\r
997 case DT_REL:\r
998 RelOffset = Dyn->d_un.d_val;\r
999 break;\r
1000\r
1001 case DT_RELSZ:\r
1002 RelSize = Dyn->d_un.d_val;\r
1003 break;\r
1004\r
1005 case DT_RELENT:\r
1006 RelElementSize = Dyn->d_un.d_val;\r
1007 break;\r
1008\r
1009 default:\r
1010 break;\r
1011 }\r
1012 Dyn++;\r
1013 }\r
1014 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1015 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1016 }\r
1017\r
088dc245
AB
1018 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
1019 Elf_Shdr *shdr = GetShdrByIndex(Index);\r
1020\r
1021 //\r
1022 // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
1023 // field is relative to the base of a segment (or the entire image),\r
1024 // and not to the base of an ELF input section as is the case for\r
1025 // SHT_REL sections. This means that we cannot fix up such relocations\r
1026 // unless we cross-reference ELF sections and segments, considering\r
1027 // that the output placement recorded in mCoffSectionsOffset[] is\r
1028 // section based, not segment based.\r
1029 //\r
1030 // Fortunately, there is a simple way around this: we require that the\r
1031 // in-memory layout of the ELF and PE/COFF versions of the binary is\r
1032 // identical. That way, r_offset will retain its validity as a PE/COFF\r
1033 // image offset, and we can record it in the COFF fixup table\r
1034 // unmodified.\r
1035 //\r
1036 if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
1037 Error (NULL, 0, 3000,\r
1038 "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
1039 mInImageName);\r
1040 }\r
1041 }\r
1042\r
f51461c8
LG
1043 for (K = 0; K < RelSize; K += RelElementSize) {\r
1044\r
1045 if (DynamicSegment->p_paddr == 0) {\r
1046 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
1047 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
1048 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
1049 } else {\r
1050 // This is how it reads in the generic ELF specification\r
1051 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
1052 }\r
1053\r
1054 switch (ELF32_R_TYPE (Rel->r_info)) {\r
1055 case R_ARM_RBASE:\r
1056 break;\r
1057\r
1058 case R_ARM_RABS32:\r
088dc245 1059 CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
f51461c8
LG
1060 break;\r
1061 \r
1062 default:\r
1063 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
1064 break;\r
1065 }\r
1066 }\r
1067 break;\r
1068 }\r
1069 }\r
1070 }\r
1071\r
1072 //\r
1073 // Pad by adding empty entries.\r
1074 //\r
1075 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1076 CoffAddFixupEntry(0);\r
1077 }\r
1078\r
1079 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1080 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1081 Dir->Size = mCoffOffset - mRelocOffset;\r
1082 if (Dir->Size == 0) {\r
1083 // If no relocations, null out the directory entry and don't add the .reloc section\r
1084 Dir->VirtualAddress = 0;\r
1085 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1086 } else {\r
1087 Dir->VirtualAddress = mRelocOffset;\r
1088 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1089 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1090 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1091 | EFI_IMAGE_SCN_MEM_READ);\r
1092 }\r
1093\r
1094}\r
1095\r
1096STATIC\r
1097VOID\r
1098WriteDebug32 (\r
1099 VOID\r
1100 )\r
1101{\r
1102 UINT32 Len;\r
f51461c8
LG
1103 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1104 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1105 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1106 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1107\r
1108 Len = strlen(mInImageName) + 1;\r
f51461c8 1109\r
0192b71c 1110 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1111 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1112 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1113 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1114 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1115\r
1116 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1117 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1118 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1119\r
1120\r
1121 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1122 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c
AB
1123 DataDir->VirtualAddress = mDebugOffset;\r
1124 DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1125}\r
1126\r
1127STATIC\r
1128VOID\r
1129SetImageSize32 (\r
1130 VOID\r
1131 )\r
1132{\r
1133 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1134 \r
1135 //\r
1136 // Set image size\r
1137 //\r
1138 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1139 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1140}\r
1141\r
1142STATIC\r
1143VOID\r
1144CleanUp32 (\r
1145 VOID\r
1146 )\r
1147{\r
1148 if (mCoffSectionsOffset != NULL) {\r
1149 free (mCoffSectionsOffset);\r
1150 }\r
1151}\r
1152\r
1153\r