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