]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
BaseTools/GenFw ARM: don't permit R_ARM_GOT_PREL relocations
[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
1794b98f 693 VerboseMsg ("%s unknown section type %x. We ignore this unknown section type.", mInImageName, (unsigned)Shdr->sh_type);\r
f51461c8
LG
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
f51461c8
LG
840 case R_ARM_THM_JUMP11:\r
841 case R_ARM_THM_JUMP8:\r
842 case R_ARM_TLS_GD32:\r
843 case R_ARM_TLS_LDM32:\r
844 case R_ARM_TLS_IE32:\r
845 // Thease are all PC-relative relocations and don't require modification\r
846 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
847 break;\r
848\r
849 case R_ARM_THM_MOVW_ABS_NC:\r
850 // MOVW is only lower 16-bits of the addres\r
851 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
852 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
853 break;\r
854\r
855 case R_ARM_THM_MOVT_ABS:\r
856 // MOVT is only upper 16-bits of the addres\r
857 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
858 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
859 break;\r
860\r
861 case R_ARM_ABS32:\r
862 case R_ARM_RABS32:\r
863 //\r
864 // Absolute relocation.\r
865 //\r
866 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
867 break;\r
868\r
869 default:\r
870 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
871 }\r
872 }\r
873 }\r
874 }\r
875 }\r
876\r
877 return TRUE;\r
878}\r
879\r
880UINTN gMovwOffset = 0;\r
881\r
882STATIC\r
883VOID\r
884WriteRelocations32 (\r
885 VOID\r
886 )\r
887{\r
888 UINT32 Index;\r
889 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
890 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
891 BOOLEAN FoundRelocations;\r
892 Elf_Dyn *Dyn;\r
893 Elf_Rel *Rel;\r
894 UINTN RelElementSize;\r
895 UINTN RelSize;\r
896 UINTN RelOffset;\r
897 UINTN K;\r
f51461c8 898 Elf32_Phdr *DynamicSegment;\r
f51461c8
LG
899\r
900 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
901 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
902 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
903 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
904 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
905 UINT32 RelIdx;\r
906\r
907 FoundRelocations = TRUE;\r
908 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
5aec6991 909 Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
f51461c8 910\r
f7496d71 911 if (mEhdr->e_machine == EM_386) {\r
f51461c8
LG
912 switch (ELF_R_TYPE(Rel->r_info)) {\r
913 case R_386_NONE:\r
914 case R_386_PC32:\r
915 //\r
916 // No fixup entry required.\r
917 //\r
918 break;\r
919 case R_386_32:\r
920 //\r
921 // Creates a relative relocation entry from the absolute entry.\r
922 //\r
923 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
924 + (Rel->r_offset - SecShdr->sh_addr),\r
925 EFI_IMAGE_REL_BASED_HIGHLOW);\r
926 break;\r
927 default:\r
928 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
929 }\r
930 } else if (mEhdr->e_machine == EM_ARM) {\r
931 switch (ELF32_R_TYPE(Rel->r_info)) {\r
932 case R_ARM_RBASE:\r
933 // No relocation - no action required\r
934 // break skipped\r
935\r
936 case R_ARM_PC24:\r
31643611 937 case R_ARM_REL32:\r
f51461c8
LG
938 case R_ARM_XPC25:\r
939 case R_ARM_THM_PC22:\r
940 case R_ARM_THM_JUMP19:\r
941 case R_ARM_CALL:\r
942 case R_ARM_JMP24:\r
f7496d71
LG
943 case R_ARM_THM_JUMP24:\r
944 case R_ARM_PREL31:\r
945 case R_ARM_MOVW_PREL_NC:\r
f51461c8
LG
946 case R_ARM_MOVT_PREL:\r
947 case R_ARM_THM_MOVW_PREL_NC:\r
948 case R_ARM_THM_MOVT_PREL:\r
949 case R_ARM_THM_JMP6:\r
950 case R_ARM_THM_ALU_PREL_11_0:\r
951 case R_ARM_THM_PC12:\r
952 case R_ARM_REL32_NOI:\r
953 case R_ARM_ALU_PC_G0_NC:\r
954 case R_ARM_ALU_PC_G0:\r
955 case R_ARM_ALU_PC_G1_NC:\r
956 case R_ARM_ALU_PC_G1:\r
957 case R_ARM_ALU_PC_G2:\r
958 case R_ARM_LDR_PC_G1:\r
959 case R_ARM_LDR_PC_G2:\r
960 case R_ARM_LDRS_PC_G0:\r
961 case R_ARM_LDRS_PC_G1:\r
962 case R_ARM_LDRS_PC_G2:\r
963 case R_ARM_LDC_PC_G0:\r
964 case R_ARM_LDC_PC_G1:\r
965 case R_ARM_LDC_PC_G2:\r
f51461c8
LG
966 case R_ARM_THM_JUMP11:\r
967 case R_ARM_THM_JUMP8:\r
968 case R_ARM_TLS_GD32:\r
969 case R_ARM_TLS_LDM32:\r
970 case R_ARM_TLS_IE32:\r
971 // Thease are all PC-relative relocations and don't require modification\r
972 break;\r
973\r
974 case R_ARM_THM_MOVW_ABS_NC:\r
975 CoffAddFixup (\r
976 mCoffSectionsOffset[RelShdr->sh_info]\r
977 + (Rel->r_offset - SecShdr->sh_addr),\r
978 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
979 );\r
980\r
981 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
982 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
983 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
984 break;\r
985\r
986 case R_ARM_THM_MOVT_ABS:\r
987 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
988 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
989 }\r
990 break;\r
991\r
992 case R_ARM_ABS32:\r
993 case R_ARM_RABS32:\r
994 CoffAddFixup (\r
995 mCoffSectionsOffset[RelShdr->sh_info]\r
996 + (Rel->r_offset - SecShdr->sh_addr),\r
997 EFI_IMAGE_REL_BASED_HIGHLOW\r
998 );\r
999 break;\r
1000\r
1001 default:\r
1002 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
1003 }\r
1004 } else {\r
1005 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
1006 }\r
1007 }\r
1008 }\r
1009 }\r
1010 }\r
1011\r
1012 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
1013 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
1014\r
1015 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
1016 RelElementSize = 0;\r
1017 RelSize = 0;\r
1018 RelOffset = 0;\r
1019\r
1020 DynamicSegment = GetPhdrByIndex (Index);\r
1021\r
1022 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
1023 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
1024\r
1025 while (Dyn->d_tag != DT_NULL) {\r
1026 switch (Dyn->d_tag) {\r
1027 case DT_REL:\r
1028 RelOffset = Dyn->d_un.d_val;\r
1029 break;\r
1030\r
1031 case DT_RELSZ:\r
1032 RelSize = Dyn->d_un.d_val;\r
1033 break;\r
1034\r
1035 case DT_RELENT:\r
1036 RelElementSize = Dyn->d_un.d_val;\r
1037 break;\r
1038\r
1039 default:\r
1040 break;\r
1041 }\r
1042 Dyn++;\r
1043 }\r
1044 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1045 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1046 }\r
1047\r
088dc245
AB
1048 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
1049 Elf_Shdr *shdr = GetShdrByIndex(Index);\r
1050\r
1051 //\r
1052 // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
1053 // field is relative to the base of a segment (or the entire image),\r
1054 // and not to the base of an ELF input section as is the case for\r
1055 // SHT_REL sections. This means that we cannot fix up such relocations\r
1056 // unless we cross-reference ELF sections and segments, considering\r
1057 // that the output placement recorded in mCoffSectionsOffset[] is\r
1058 // section based, not segment based.\r
1059 //\r
1060 // Fortunately, there is a simple way around this: we require that the\r
1061 // in-memory layout of the ELF and PE/COFF versions of the binary is\r
1062 // identical. That way, r_offset will retain its validity as a PE/COFF\r
1063 // image offset, and we can record it in the COFF fixup table\r
1064 // unmodified.\r
1065 //\r
1066 if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
1067 Error (NULL, 0, 3000,\r
1068 "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
1069 mInImageName);\r
1070 }\r
1071 }\r
1072\r
f51461c8
LG
1073 for (K = 0; K < RelSize; K += RelElementSize) {\r
1074\r
1075 if (DynamicSegment->p_paddr == 0) {\r
1076 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
1077 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
1078 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
1079 } else {\r
1080 // This is how it reads in the generic ELF specification\r
1081 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
1082 }\r
1083\r
1084 switch (ELF32_R_TYPE (Rel->r_info)) {\r
1085 case R_ARM_RBASE:\r
1086 break;\r
1087\r
1088 case R_ARM_RABS32:\r
088dc245 1089 CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
f51461c8 1090 break;\r
f7496d71 1091\r
f51461c8
LG
1092 default:\r
1093 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
1094 break;\r
1095 }\r
1096 }\r
1097 break;\r
1098 }\r
1099 }\r
1100 }\r
1101\r
1102 //\r
1103 // Pad by adding empty entries.\r
1104 //\r
1105 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1106 CoffAddFixupEntry(0);\r
1107 }\r
1108\r
1109 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1110 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1111 Dir->Size = mCoffOffset - mRelocOffset;\r
1112 if (Dir->Size == 0) {\r
1113 // If no relocations, null out the directory entry and don't add the .reloc section\r
1114 Dir->VirtualAddress = 0;\r
1115 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1116 } else {\r
1117 Dir->VirtualAddress = mRelocOffset;\r
1118 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1119 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1120 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1121 | EFI_IMAGE_SCN_MEM_READ);\r
1122 }\r
1123\r
1124}\r
1125\r
1126STATIC\r
1127VOID\r
1128WriteDebug32 (\r
1129 VOID\r
1130 )\r
1131{\r
1132 UINT32 Len;\r
f51461c8
LG
1133 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1134 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1135 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1136 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1137\r
1138 Len = strlen(mInImageName) + 1;\r
f51461c8 1139\r
0192b71c 1140 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1141 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1142 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1143 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1144 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1145\r
1146 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1147 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1148 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1149\r
1150\r
1151 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1152 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c 1153 DataDir->VirtualAddress = mDebugOffset;\r
60e85a39 1154 DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1155}\r
1156\r
1157STATIC\r
1158VOID\r
1159SetImageSize32 (\r
1160 VOID\r
1161 )\r
1162{\r
1163 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
f7496d71 1164\r
f51461c8
LG
1165 //\r
1166 // Set image size\r
1167 //\r
1168 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1169 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1170}\r
1171\r
1172STATIC\r
1173VOID\r
1174CleanUp32 (\r
1175 VOID\r
1176 )\r
1177{\r
1178 if (mCoffSectionsOffset != NULL) {\r
1179 free (mCoffSectionsOffset);\r
1180 }\r
1181}\r
1182\r
1183\r