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