]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
PerformancePkg/Dp_App: Refine the code of locating all handles in DpTrace.c.
[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
317 for (UINT32 i = Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {\r
318 foundEnd = StrtabContents[i] == 0;\r
319 }\r
320 assert(foundEnd);\r
321\r
322 return StrtabContents + Sym->st_name;\r
621bb723
ML
323}\r
324\r
f51461c8
LG
325//\r
326// Elf functions interface implementation\r
327//\r
328\r
329STATIC\r
330VOID\r
331ScanSections32 (\r
332 VOID\r
333 )\r
334{\r
335 UINT32 i;\r
336 EFI_IMAGE_DOS_HEADER *DosHdr;\r
337 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
338 UINT32 CoffEntry;\r
339 UINT32 SectionCount;\r
234f9ff9 340 BOOLEAN FoundSection;\r
f51461c8
LG
341\r
342 CoffEntry = 0;\r
343 mCoffOffset = 0;\r
f51461c8
LG
344\r
345 //\r
346 // Coff file start with a DOS header.\r
347 //\r
348 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
349 mNtHdrOffset = mCoffOffset;\r
350 switch (mEhdr->e_machine) {\r
351 case EM_386:\r
352 case EM_ARM:\r
353 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
354 break;\r
355 default:\r
356 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
357 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
358 break;\r
359 }\r
360\r
361 mTableOffset = mCoffOffset;\r
362 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
363\r
54b1b57a
AB
364 //\r
365 // Set mCoffAlignment to the maximum alignment of the input sections\r
366 // we care about\r
367 //\r
368 for (i = 0; i < mEhdr->e_shnum; i++) {\r
369 Elf_Shdr *shdr = GetShdrByIndex(i);\r
370 if (shdr->sh_addralign <= mCoffAlignment) {\r
371 continue;\r
372 }\r
373 if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {\r
374 mCoffAlignment = (UINT32)shdr->sh_addralign;\r
375 }\r
376 }\r
377\r
02a5421f
AB
378 //\r
379 // Move the PE/COFF header right before the first section. This will help us\r
380 // save space when converting to TE.\r
381 //\r
382 if (mCoffAlignment > mCoffOffset) {\r
383 mNtHdrOffset += mCoffAlignment - mCoffOffset;\r
384 mTableOffset += mCoffAlignment - mCoffOffset;\r
385 mCoffOffset = mCoffAlignment;\r
386 }\r
387\r
f51461c8
LG
388 //\r
389 // First text sections.\r
390 //\r
391 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
392 mTextOffset = mCoffOffset;\r
393 FoundSection = FALSE;\r
f51461c8
LG
394 SectionCount = 0;\r
395 for (i = 0; i < mEhdr->e_shnum; i++) {\r
396 Elf_Shdr *shdr = GetShdrByIndex(i);\r
397 if (IsTextShdr(shdr)) {\r
398 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
399 // the alignment field is valid\r
400 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
401 // if the section address is aligned we must align PE/COFF\r
402 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
403 } else {\r
404 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
405 }\r
406 }\r
407\r
408 /* Relocate entry. */\r
409 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
410 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
411 CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;\r
412 }\r
413\r
414 //\r
415 // Set mTextOffset with the offset of the first '.text' section\r
416 //\r
234f9ff9 417 if (!FoundSection) {\r
f51461c8 418 mTextOffset = mCoffOffset;\r
234f9ff9 419 FoundSection = TRUE;\r
f51461c8
LG
420 }\r
421\r
422 mCoffSectionsOffset[i] = mCoffOffset;\r
423 mCoffOffset += shdr->sh_size;\r
424 SectionCount ++;\r
425 }\r
426 }\r
427\r
234f9ff9 428 if (!FoundSection) {\r
f51461c8
LG
429 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
430 assert (FALSE);\r
431 }\r
432\r
4f7d5c67 433 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0bd0d6df 434 mCoffOffset = CoffAlign(mCoffOffset);\r
f51461c8
LG
435\r
436 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
437 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
438 }\r
439\r
440 //\r
441 // Then data sections.\r
442 //\r
443 mDataOffset = mCoffOffset;\r
234f9ff9 444 FoundSection = FALSE;\r
f51461c8
LG
445 SectionCount = 0;\r
446 for (i = 0; i < mEhdr->e_shnum; i++) {\r
447 Elf_Shdr *shdr = GetShdrByIndex(i);\r
448 if (IsDataShdr(shdr)) {\r
449 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
450 // the alignment field is valid\r
451 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
452 // if the section address is aligned we must align PE/COFF\r
453 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
454 } else {\r
455 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
456 }\r
457 }\r
234f9ff9
EB
458\r
459 //\r
460 // Set mDataOffset with the offset of the first '.data' section\r
461 //\r
462 if (!FoundSection) {\r
463 mDataOffset = mCoffOffset;\r
464 FoundSection = TRUE;\r
465 }\r
466\r
f51461c8
LG
467 mCoffSectionsOffset[i] = mCoffOffset;\r
468 mCoffOffset += shdr->sh_size;\r
469 SectionCount ++;\r
470 }\r
471 }\r
f51461c8
LG
472\r
473 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
474 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
475 }\r
476\r
0192b71c
AB
477 //\r
478 // Make room for .debug data in .data (or .text if .data is empty) instead of\r
479 // putting it in a section of its own. This is explicitly allowed by the\r
480 // PE/COFF spec, and prevents bloat in the binary when using large values for\r
481 // section alignment.\r
482 //\r
483 if (SectionCount > 0) {\r
4f7d5c67 484 mDebugOffset = DebugRvaAlign(mCoffOffset);\r
0192b71c
AB
485 }\r
486 mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) +\r
487 sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) +\r
488 strlen(mInImageName) + 1;\r
489\r
490 mCoffOffset = CoffAlign(mCoffOffset);\r
491 if (SectionCount == 0) {\r
492 mDataOffset = mCoffOffset;\r
493 }\r
494\r
f51461c8
LG
495 //\r
496 // The HII resource sections.\r
497 //\r
498 mHiiRsrcOffset = mCoffOffset;\r
499 for (i = 0; i < mEhdr->e_shnum; i++) {\r
500 Elf_Shdr *shdr = GetShdrByIndex(i);\r
501 if (IsHiiRsrcShdr(shdr)) {\r
502 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
503 // the alignment field is valid\r
504 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
505 // if the section address is aligned we must align PE/COFF\r
506 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
0bd0d6df
AB
507 } else {\r
508 Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment.");\r
f51461c8
LG
509 }\r
510 }\r
511 if (shdr->sh_size != 0) {\r
234f9ff9 512 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
513 mCoffSectionsOffset[i] = mCoffOffset;\r
514 mCoffOffset += shdr->sh_size;\r
515 mCoffOffset = CoffAlign(mCoffOffset);\r
516 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
517 }\r
518 break;\r
519 }\r
520 }\r
521\r
522 mRelocOffset = mCoffOffset;\r
523\r
524 //\r
525 // Allocate base Coff file. Will be expanded later for relocations.\r
526 //\r
527 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
528 memset(mCoffFile, 0, mCoffOffset);\r
529\r
530 //\r
531 // Fill headers.\r
532 //\r
533 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
534 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
535 DosHdr->e_lfanew = mNtHdrOffset;\r
536\r
537 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
538\r
539 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
540\r
541 switch (mEhdr->e_machine) {\r
542 case EM_386:\r
543 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
544 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
545 break;\r
546 case EM_ARM:\r
547 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
548 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
549 break;\r
550 default:\r
ea3e924a 551 VerboseMsg ("%s unknown e_machine type %hu. Assume IA-32", mInImageName, mEhdr->e_machine);\r
f51461c8
LG
552 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
553 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
554 }\r
555\r
556 NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections;\r
557 NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
558 mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
559 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
560 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
561 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
562 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
563 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
564 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
565 | EFI_IMAGE_FILE_32BIT_MACHINE;\r
566\r
567 NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
568 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
569 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
570 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
571\r
572 NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset;\r
573\r
574 NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset;\r
575 NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
576 NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment;\r
577 NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment;\r
578 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
579\r
580 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset;\r
581 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
582\r
583 //\r
584 // Section headers.\r
585 //\r
586 if ((mDataOffset - mTextOffset) > 0) {\r
587 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
588 EFI_IMAGE_SCN_CNT_CODE\r
589 | EFI_IMAGE_SCN_MEM_EXECUTE\r
590 | EFI_IMAGE_SCN_MEM_READ);\r
591 } else {\r
592 // Don't make a section of size 0.\r
593 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
594 }\r
595\r
596 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
597 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
598 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
599 | EFI_IMAGE_SCN_MEM_WRITE\r
600 | EFI_IMAGE_SCN_MEM_READ);\r
601 } else {\r
602 // Don't make a section of size 0.\r
603 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
604 }\r
605\r
606 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
607 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
608 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
609 | EFI_IMAGE_SCN_MEM_READ);\r
610\r
611 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
612 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
613 } else {\r
614 // Don't make a section of size 0.\r
615 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
616 }\r
617\r
618}\r
619\r
620STATIC\r
621BOOLEAN\r
622WriteSections32 (\r
623 SECTION_FILTER_TYPES FilterType\r
624 )\r
625{\r
626 UINT32 Idx;\r
627 Elf_Shdr *SecShdr;\r
628 UINT32 SecOffset;\r
629 BOOLEAN (*Filter)(Elf_Shdr *);\r
630\r
631 //\r
632 // Initialize filter pointer\r
633 //\r
634 switch (FilterType) {\r
635 case SECTION_TEXT:\r
636 Filter = IsTextShdr;\r
637 break;\r
638 case SECTION_HII:\r
639 Filter = IsHiiRsrcShdr;\r
640 break;\r
641 case SECTION_DATA:\r
642 Filter = IsDataShdr;\r
643 break;\r
644 default:\r
645 return FALSE;\r
646 }\r
647\r
648 //\r
649 // First: copy sections.\r
650 //\r
651 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
652 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
653 if ((*Filter)(Shdr)) {\r
654 switch (Shdr->sh_type) {\r
655 case SHT_PROGBITS:\r
656 /* Copy. */\r
657 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
658 (UINT8*)mEhdr + Shdr->sh_offset,\r
659 Shdr->sh_size);\r
660 break;\r
661\r
662 case SHT_NOBITS:\r
663 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
664 break;\r
665\r
666 default:\r
667 //\r
668 // Ignore for unkown section type.\r
669 //\r
670 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
671 break;\r
672 }\r
673 }\r
674 }\r
675\r
676 //\r
677 // Second: apply relocations.\r
678 //\r
679 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
680 //\r
681 // Determine if this is a relocation section.\r
682 //\r
683 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
684 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
685 continue;\r
686 }\r
687 \r
688 //\r
689 // Relocation section found. Now extract section information that the relocations\r
690 // apply to in the ELF data and the new COFF data.\r
691 //\r
692 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
693 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
694 \r
695 //\r
696 // Only process relocations for the current filter type.\r
697 //\r
698 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
699 UINT32 RelOffset;\r
700 \r
701 //\r
702 // Determine the symbol table referenced by the relocation data.\r
703 //\r
704 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
705 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
706\r
707 //\r
708 // Process all relocation entries for this section.\r
709 //\r
710 for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {\r
711 //\r
712 // Set pointer to relocation entry\r
713 //\r
714 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);\r
715 \r
716 //\r
717 // Set pointer to symbol table entry associated with the relocation entry.\r
718 //\r
719 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
720 \r
721 Elf_Shdr *SymShdr;\r
722 UINT8 *Targ;\r
723 UINT16 Address;\r
724\r
725 //\r
726 // Check section header index found in symbol table and get the section \r
727 // header location.\r
728 //\r
729 if (Sym->st_shndx == SHN_UNDEF\r
621bb723
ML
730 || Sym->st_shndx >= mEhdr->e_shnum) {\r
731 const UINT8 *SymName = GetSymName(Sym);\r
732 if (SymName == NULL) {\r
733 SymName = (const UINT8 *)"<unknown>";\r
734 }\r
735\r
736 Error (NULL, 0, 3000, "Invalid",\r
ea3e924a 737 "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type. "\r
621bb723
ML
738 "For example, absolute and undefined symbols are not supported.",\r
739 mInImageName, SymName, Sym->st_value);\r
740\r
741 exit(EXIT_FAILURE);\r
f51461c8
LG
742 }\r
743 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
744\r
745 //\r
746 // Convert the relocation data to a pointer into the coff file.\r
747 //\r
748 // Note: \r
749 // r_offset is the virtual address of the storage unit to be relocated.\r
750 // sh_addr is the virtual address for the base of the section.\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_386) {\r
758 switch (ELF_R_TYPE(Rel->r_info)) {\r
759 case R_386_NONE:\r
760 break;\r
761 case R_386_32:\r
762 //\r
763 // Absolute relocation.\r
764 // Converts Targ from a absolute virtual address to the absolute\r
765 // COFF address.\r
766 //\r
767 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
768 + mCoffSectionsOffset[Sym->st_shndx];\r
769 break;\r
770 case R_386_PC32:\r
771 //\r
772 // Relative relocation: Symbol - Ip + Addend\r
773 //\r
774 *(UINT32 *)Targ = *(UINT32 *)Targ\r
775 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
776 - (SecOffset - SecShdr->sh_addr);\r
777 break;\r
778 default:\r
779 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
780 }\r
781 } else if (mEhdr->e_machine == EM_ARM) {\r
782 switch (ELF32_R_TYPE(Rel->r_info)) {\r
783 case R_ARM_RBASE:\r
784 // No relocation - no action required\r
785 // break skipped\r
786\r
787 case R_ARM_PC24:\r
31643611 788 case R_ARM_REL32:\r
f51461c8
LG
789 case R_ARM_XPC25:\r
790 case R_ARM_THM_PC22:\r
791 case R_ARM_THM_JUMP19:\r
792 case R_ARM_CALL:\r
793 case R_ARM_JMP24:\r
794 case R_ARM_THM_JUMP24: \r
795 case R_ARM_PREL31: \r
796 case R_ARM_MOVW_PREL_NC: \r
797 case R_ARM_MOVT_PREL:\r
798 case R_ARM_THM_MOVW_PREL_NC:\r
799 case R_ARM_THM_MOVT_PREL:\r
800 case R_ARM_THM_JMP6:\r
801 case R_ARM_THM_ALU_PREL_11_0:\r
802 case R_ARM_THM_PC12:\r
803 case R_ARM_REL32_NOI:\r
804 case R_ARM_ALU_PC_G0_NC:\r
805 case R_ARM_ALU_PC_G0:\r
806 case R_ARM_ALU_PC_G1_NC:\r
807 case R_ARM_ALU_PC_G1:\r
808 case R_ARM_ALU_PC_G2:\r
809 case R_ARM_LDR_PC_G1:\r
810 case R_ARM_LDR_PC_G2:\r
811 case R_ARM_LDRS_PC_G0:\r
812 case R_ARM_LDRS_PC_G1:\r
813 case R_ARM_LDRS_PC_G2:\r
814 case R_ARM_LDC_PC_G0:\r
815 case R_ARM_LDC_PC_G1:\r
816 case R_ARM_LDC_PC_G2:\r
817 case R_ARM_GOT_PREL:\r
818 case R_ARM_THM_JUMP11:\r
819 case R_ARM_THM_JUMP8:\r
820 case R_ARM_TLS_GD32:\r
821 case R_ARM_TLS_LDM32:\r
822 case R_ARM_TLS_IE32:\r
823 // Thease are all PC-relative relocations and don't require modification\r
824 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
825 break;\r
826\r
827 case R_ARM_THM_MOVW_ABS_NC:\r
828 // MOVW is only lower 16-bits of the addres\r
829 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
830 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
831 break;\r
832\r
833 case R_ARM_THM_MOVT_ABS:\r
834 // MOVT is only upper 16-bits of the addres\r
835 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
836 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
837 break;\r
838\r
839 case R_ARM_ABS32:\r
840 case R_ARM_RABS32:\r
841 //\r
842 // Absolute relocation.\r
843 //\r
844 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
845 break;\r
846\r
847 default:\r
848 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
849 }\r
850 }\r
851 }\r
852 }\r
853 }\r
854\r
855 return TRUE;\r
856}\r
857\r
858UINTN gMovwOffset = 0;\r
859\r
860STATIC\r
861VOID\r
862WriteRelocations32 (\r
863 VOID\r
864 )\r
865{\r
866 UINT32 Index;\r
867 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
868 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
869 BOOLEAN FoundRelocations;\r
870 Elf_Dyn *Dyn;\r
871 Elf_Rel *Rel;\r
872 UINTN RelElementSize;\r
873 UINTN RelSize;\r
874 UINTN RelOffset;\r
875 UINTN K;\r
f51461c8 876 Elf32_Phdr *DynamicSegment;\r
f51461c8
LG
877\r
878 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
879 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
880 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
881 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
882 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
883 UINT32 RelIdx;\r
884\r
885 FoundRelocations = TRUE;\r
886 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
5aec6991 887 Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
f51461c8
LG
888\r
889 if (mEhdr->e_machine == EM_386) { \r
890 switch (ELF_R_TYPE(Rel->r_info)) {\r
891 case R_386_NONE:\r
892 case R_386_PC32:\r
893 //\r
894 // No fixup entry required.\r
895 //\r
896 break;\r
897 case R_386_32:\r
898 //\r
899 // Creates a relative relocation entry from the absolute entry.\r
900 //\r
901 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
902 + (Rel->r_offset - SecShdr->sh_addr),\r
903 EFI_IMAGE_REL_BASED_HIGHLOW);\r
904 break;\r
905 default:\r
906 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
907 }\r
908 } else if (mEhdr->e_machine == EM_ARM) {\r
909 switch (ELF32_R_TYPE(Rel->r_info)) {\r
910 case R_ARM_RBASE:\r
911 // No relocation - no action required\r
912 // break skipped\r
913\r
914 case R_ARM_PC24:\r
31643611 915 case R_ARM_REL32:\r
f51461c8
LG
916 case R_ARM_XPC25:\r
917 case R_ARM_THM_PC22:\r
918 case R_ARM_THM_JUMP19:\r
919 case R_ARM_CALL:\r
920 case R_ARM_JMP24:\r
921 case R_ARM_THM_JUMP24: \r
922 case R_ARM_PREL31: \r
923 case R_ARM_MOVW_PREL_NC: \r
924 case R_ARM_MOVT_PREL:\r
925 case R_ARM_THM_MOVW_PREL_NC:\r
926 case R_ARM_THM_MOVT_PREL:\r
927 case R_ARM_THM_JMP6:\r
928 case R_ARM_THM_ALU_PREL_11_0:\r
929 case R_ARM_THM_PC12:\r
930 case R_ARM_REL32_NOI:\r
931 case R_ARM_ALU_PC_G0_NC:\r
932 case R_ARM_ALU_PC_G0:\r
933 case R_ARM_ALU_PC_G1_NC:\r
934 case R_ARM_ALU_PC_G1:\r
935 case R_ARM_ALU_PC_G2:\r
936 case R_ARM_LDR_PC_G1:\r
937 case R_ARM_LDR_PC_G2:\r
938 case R_ARM_LDRS_PC_G0:\r
939 case R_ARM_LDRS_PC_G1:\r
940 case R_ARM_LDRS_PC_G2:\r
941 case R_ARM_LDC_PC_G0:\r
942 case R_ARM_LDC_PC_G1:\r
943 case R_ARM_LDC_PC_G2:\r
944 case R_ARM_GOT_PREL:\r
945 case R_ARM_THM_JUMP11:\r
946 case R_ARM_THM_JUMP8:\r
947 case R_ARM_TLS_GD32:\r
948 case R_ARM_TLS_LDM32:\r
949 case R_ARM_TLS_IE32:\r
950 // Thease are all PC-relative relocations and don't require modification\r
951 break;\r
952\r
953 case R_ARM_THM_MOVW_ABS_NC:\r
954 CoffAddFixup (\r
955 mCoffSectionsOffset[RelShdr->sh_info]\r
956 + (Rel->r_offset - SecShdr->sh_addr),\r
957 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
958 );\r
959\r
960 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
961 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
962 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
963 break;\r
964\r
965 case R_ARM_THM_MOVT_ABS:\r
966 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
967 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
968 }\r
969 break;\r
970\r
971 case R_ARM_ABS32:\r
972 case R_ARM_RABS32:\r
973 CoffAddFixup (\r
974 mCoffSectionsOffset[RelShdr->sh_info]\r
975 + (Rel->r_offset - SecShdr->sh_addr),\r
976 EFI_IMAGE_REL_BASED_HIGHLOW\r
977 );\r
978 break;\r
979\r
980 default:\r
981 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
982 }\r
983 } else {\r
984 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
985 }\r
986 }\r
987 }\r
988 }\r
989 }\r
990\r
991 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
992 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
993\r
994 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
995 RelElementSize = 0;\r
996 RelSize = 0;\r
997 RelOffset = 0;\r
998\r
999 DynamicSegment = GetPhdrByIndex (Index);\r
1000\r
1001 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
1002 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
1003\r
1004 while (Dyn->d_tag != DT_NULL) {\r
1005 switch (Dyn->d_tag) {\r
1006 case DT_REL:\r
1007 RelOffset = Dyn->d_un.d_val;\r
1008 break;\r
1009\r
1010 case DT_RELSZ:\r
1011 RelSize = Dyn->d_un.d_val;\r
1012 break;\r
1013\r
1014 case DT_RELENT:\r
1015 RelElementSize = Dyn->d_un.d_val;\r
1016 break;\r
1017\r
1018 default:\r
1019 break;\r
1020 }\r
1021 Dyn++;\r
1022 }\r
1023 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1024 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1025 }\r
1026\r
088dc245
AB
1027 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
1028 Elf_Shdr *shdr = GetShdrByIndex(Index);\r
1029\r
1030 //\r
1031 // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
1032 // field is relative to the base of a segment (or the entire image),\r
1033 // and not to the base of an ELF input section as is the case for\r
1034 // SHT_REL sections. This means that we cannot fix up such relocations\r
1035 // unless we cross-reference ELF sections and segments, considering\r
1036 // that the output placement recorded in mCoffSectionsOffset[] is\r
1037 // section based, not segment based.\r
1038 //\r
1039 // Fortunately, there is a simple way around this: we require that the\r
1040 // in-memory layout of the ELF and PE/COFF versions of the binary is\r
1041 // identical. That way, r_offset will retain its validity as a PE/COFF\r
1042 // image offset, and we can record it in the COFF fixup table\r
1043 // unmodified.\r
1044 //\r
1045 if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
1046 Error (NULL, 0, 3000,\r
1047 "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
1048 mInImageName);\r
1049 }\r
1050 }\r
1051\r
f51461c8
LG
1052 for (K = 0; K < RelSize; K += RelElementSize) {\r
1053\r
1054 if (DynamicSegment->p_paddr == 0) {\r
1055 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
1056 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
1057 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
1058 } else {\r
1059 // This is how it reads in the generic ELF specification\r
1060 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
1061 }\r
1062\r
1063 switch (ELF32_R_TYPE (Rel->r_info)) {\r
1064 case R_ARM_RBASE:\r
1065 break;\r
1066\r
1067 case R_ARM_RABS32:\r
088dc245 1068 CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
f51461c8
LG
1069 break;\r
1070 \r
1071 default:\r
1072 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
1073 break;\r
1074 }\r
1075 }\r
1076 break;\r
1077 }\r
1078 }\r
1079 }\r
1080\r
1081 //\r
1082 // Pad by adding empty entries.\r
1083 //\r
1084 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1085 CoffAddFixupEntry(0);\r
1086 }\r
1087\r
1088 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1089 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1090 Dir->Size = mCoffOffset - mRelocOffset;\r
1091 if (Dir->Size == 0) {\r
1092 // If no relocations, null out the directory entry and don't add the .reloc section\r
1093 Dir->VirtualAddress = 0;\r
1094 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1095 } else {\r
1096 Dir->VirtualAddress = mRelocOffset;\r
1097 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1098 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1099 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1100 | EFI_IMAGE_SCN_MEM_READ);\r
1101 }\r
1102\r
1103}\r
1104\r
1105STATIC\r
1106VOID\r
1107WriteDebug32 (\r
1108 VOID\r
1109 )\r
1110{\r
1111 UINT32 Len;\r
f51461c8
LG
1112 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1113 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1114 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1115 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1116\r
1117 Len = strlen(mInImageName) + 1;\r
f51461c8 1118\r
0192b71c 1119 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1120 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1121 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1122 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1123 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1124\r
1125 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1126 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1127 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1128\r
1129\r
1130 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1131 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c
AB
1132 DataDir->VirtualAddress = mDebugOffset;\r
1133 DataDir->Size = Dir->SizeOfData + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1134}\r
1135\r
1136STATIC\r
1137VOID\r
1138SetImageSize32 (\r
1139 VOID\r
1140 )\r
1141{\r
1142 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1143 \r
1144 //\r
1145 // Set image size\r
1146 //\r
1147 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1148 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1149}\r
1150\r
1151STATIC\r
1152VOID\r
1153CleanUp32 (\r
1154 VOID\r
1155 )\r
1156{\r
1157 if (mCoffSectionsOffset != NULL) {\r
1158 free (mCoffSectionsOffset);\r
1159 }\r
1160}\r
1161\r
1162\r