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