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