]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
BaseTools: Check elf sections alignment with MAX_COFF_ALIGNMENT
[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
133 mEhdr = (Elf_Ehdr*) FileBuffer; \r
134\r
135 //\r
136 // Check the ELF32 specific header information.\r
137 //\r
138 if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) {\r
139 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32");\r
140 return FALSE;\r
141 }\r
142 if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
143 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
144 return FALSE;\r
145 } \r
146 if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {\r
147 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
148 return FALSE;\r
149 }\r
150 if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) { \r
151 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
152 return FALSE;\r
153 }\r
154 if (mEhdr->e_version != EV_CURRENT) {\r
155 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);\r
156 return FALSE;\r
157 }\r
158 \r
159 //\r
160 // Update section header pointers\r
161 //\r
162 mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);\r
163 mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);\r
164 \r
165 //\r
166 // Create COFF Section offset buffer and zero.\r
167 //\r
168 mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));\r
06b45735
HW
169 if (mCoffSectionsOffset == NULL) {\r
170 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
171 return FALSE;\r
172 }\r
f51461c8
LG
173 memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));\r
174\r
175 //\r
176 // Fill in function pointers.\r
177 //\r
178 ElfFunctions->ScanSections = ScanSections32;\r
179 ElfFunctions->WriteSections = WriteSections32;\r
180 ElfFunctions->WriteRelocations = WriteRelocations32;\r
181 ElfFunctions->WriteDebug = WriteDebug32;\r
182 ElfFunctions->SetImageSize = SetImageSize32;\r
183 ElfFunctions->CleanUp = CleanUp32;\r
184\r
185 return TRUE;\r
186}\r
187\r
188\r
189//\r
190// Header by Index functions\r
191//\r
192STATIC\r
193Elf_Shdr*\r
194GetShdrByIndex (\r
195 UINT32 Num\r
196 )\r
197{\r
17751c5f
ML
198 if (Num >= mEhdr->e_shnum) {\r
199 Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num);\r
200 exit(EXIT_FAILURE);\r
201 }\r
202\r
f51461c8
LG
203 return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);\r
204}\r
205\r
206STATIC\r
207Elf_Phdr*\r
208GetPhdrByIndex (\r
209 UINT32 num\r
210 )\r
211{\r
212 if (num >= mEhdr->e_phnum) {\r
17751c5f
ML
213 Error (NULL, 0, 3000, "Invalid", "GetPhdrByIndex: Index %u is too high.", num);\r
214 exit(EXIT_FAILURE);\r
f51461c8
LG
215 }\r
216\r
217 return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize);\r
218}\r
219\r
220STATIC\r
221UINT32\r
222CoffAlign (\r
223 UINT32 Offset\r
224 )\r
225{\r
226 return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
227}\r
228\r
4f7d5c67
AB
229STATIC\r
230UINT32\r
231DebugRvaAlign (\r
232 UINT32 Offset\r
233 )\r
234{\r
235 return (Offset + 3) & ~3;\r
236}\r
237\r
f51461c8
LG
238//\r
239// filter functions\r
240//\r
241STATIC\r
242BOOLEAN\r
243IsTextShdr (\r
244 Elf_Shdr *Shdr\r
245 )\r
246{\r
247 return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);\r
248}\r
249\r
250STATIC\r
251BOOLEAN\r
252IsHiiRsrcShdr (\r
253 Elf_Shdr *Shdr\r
254 )\r
255{\r
256 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
257\r
258 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
259}\r
260\r
261STATIC\r
262BOOLEAN\r
263IsDataShdr (\r
264 Elf_Shdr *Shdr\r
265 )\r
266{\r
267 if (IsHiiRsrcShdr(Shdr)) {\r
268 return FALSE;\r
269 }\r
270 return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
271}\r
272\r
621bb723
ML
273STATIC\r
274BOOLEAN\r
275IsStrtabShdr (\r
276 Elf_Shdr *Shdr\r
277 )\r
278{\r
279 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
280\r
281 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0);\r
282}\r
283\r
284STATIC\r
285Elf_Shdr *\r
286FindStrtabShdr (\r
287 VOID\r
288 )\r
289{\r
290 UINT32 i;\r
291 for (i = 0; i < mEhdr->e_shnum; i++) {\r
292 Elf_Shdr *shdr = GetShdrByIndex(i);\r
293 if (IsStrtabShdr(shdr)) {\r
294 return shdr;\r
295 }\r
296 }\r
297 return NULL;\r
298}\r
299\r
300STATIC\r
301const UINT8 *\r
302GetSymName (\r
303 Elf_Sym *Sym\r
304 )\r
305{\r
7be7b25d
HW
306 Elf_Shdr *StrtabShdr;\r
307 UINT8 *StrtabContents;\r
308 BOOLEAN foundEnd;\r
309 UINT32 i;\r
310\r
621bb723
ML
311 if (Sym->st_name == 0) {\r
312 return NULL;\r
313 }\r
314\r
7be7b25d 315 StrtabShdr = FindStrtabShdr();\r
621bb723
ML
316 if (StrtabShdr == NULL) {\r
317 return NULL;\r
318 }\r
319\r
320 assert(Sym->st_name < StrtabShdr->sh_size);\r
321\r
7be7b25d 322 StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset;\r
ea3e924a 323\r
7be7b25d 324 foundEnd = FALSE;\r
a754c70c 325 for (i = Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) {\r
7be7b25d 326 foundEnd = (BOOLEAN)(StrtabContents[i] == 0);\r
ea3e924a
ML
327 }\r
328 assert(foundEnd);\r
329\r
330 return StrtabContents + Sym->st_name;\r
621bb723
ML
331}\r
332\r
f51461c8
LG
333//\r
334// Elf functions interface implementation\r
335//\r
336\r
337STATIC\r
338VOID\r
339ScanSections32 (\r
340 VOID\r
341 )\r
342{\r
343 UINT32 i;\r
344 EFI_IMAGE_DOS_HEADER *DosHdr;\r
345 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
346 UINT32 CoffEntry;\r
347 UINT32 SectionCount;\r
234f9ff9 348 BOOLEAN FoundSection;\r
f51461c8
LG
349\r
350 CoffEntry = 0;\r
351 mCoffOffset = 0;\r
f51461c8
LG
352\r
353 //\r
354 // Coff file start with a DOS header.\r
355 //\r
356 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
357 mNtHdrOffset = mCoffOffset;\r
358 switch (mEhdr->e_machine) {\r
359 case EM_386:\r
360 case EM_ARM:\r
361 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
362 break;\r
363 default:\r
364 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
365 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
366 break;\r
367 }\r
368\r
369 mTableOffset = mCoffOffset;\r
370 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
371\r
54b1b57a
AB
372 //\r
373 // Set mCoffAlignment to the maximum alignment of the input sections\r
374 // we care about\r
375 //\r
376 for (i = 0; i < mEhdr->e_shnum; i++) {\r
377 Elf_Shdr *shdr = GetShdrByIndex(i);\r
378 if (shdr->sh_addralign <= mCoffAlignment) {\r
379 continue;\r
380 }\r
381 if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {\r
382 mCoffAlignment = (UINT32)shdr->sh_addralign;\r
383 }\r
384 }\r
385\r
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
677 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
678 (UINT8*)mEhdr + Shdr->sh_offset,\r
679 Shdr->sh_size);\r
680 break;\r
681\r
682 case SHT_NOBITS:\r
683 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
684 break;\r
685\r
686 default:\r
687 //\r
688 // Ignore for unkown section type.\r
689 //\r
690 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
691 break;\r
692 }\r
693 }\r
694 }\r
695\r
696 //\r
697 // Second: apply relocations.\r
698 //\r
699 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
700 //\r
701 // Determine if this is a relocation section.\r
702 //\r
703 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
704 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
705 continue;\r
706 }\r
707 \r
708 //\r
709 // Relocation section found. Now extract section information that the relocations\r
710 // apply to in the ELF data and the new COFF data.\r
711 //\r
712 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
713 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
714 \r
715 //\r
716 // Only process relocations for the current filter type.\r
717 //\r
718 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
719 UINT32 RelOffset;\r
720 \r
721 //\r
722 // Determine the symbol table referenced by the relocation data.\r
723 //\r
724 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
725 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
726\r
727 //\r
728 // Process all relocation entries for this section.\r
729 //\r
730 for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {\r
731 //\r
732 // Set pointer to relocation entry\r
733 //\r
734 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);\r
735 \r
736 //\r
737 // Set pointer to symbol table entry associated with the relocation entry.\r
738 //\r
739 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
740 \r
741 Elf_Shdr *SymShdr;\r
742 UINT8 *Targ;\r
743 UINT16 Address;\r
744\r
745 //\r
746 // Check section header index found in symbol table and get the section \r
747 // header location.\r
748 //\r
749 if (Sym->st_shndx == SHN_UNDEF\r
621bb723
ML
750 || Sym->st_shndx >= mEhdr->e_shnum) {\r
751 const UINT8 *SymName = GetSymName(Sym);\r
752 if (SymName == NULL) {\r
753 SymName = (const UINT8 *)"<unknown>";\r
754 }\r
755\r
756 Error (NULL, 0, 3000, "Invalid",\r
ea3e924a 757 "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type. "\r
621bb723
ML
758 "For example, absolute and undefined symbols are not supported.",\r
759 mInImageName, SymName, Sym->st_value);\r
760\r
761 exit(EXIT_FAILURE);\r
f51461c8
LG
762 }\r
763 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
764\r
765 //\r
766 // Convert the relocation data to a pointer into the coff file.\r
767 //\r
768 // Note: \r
769 // r_offset is the virtual address of the storage unit to be relocated.\r
770 // sh_addr is the virtual address for the base of the section.\r
771 //\r
772 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
773\r
774 //\r
775 // Determine how to handle each relocation type based on the machine type.\r
776 //\r
777 if (mEhdr->e_machine == EM_386) {\r
778 switch (ELF_R_TYPE(Rel->r_info)) {\r
779 case R_386_NONE:\r
780 break;\r
781 case R_386_32:\r
782 //\r
783 // Absolute relocation.\r
784 // Converts Targ from a absolute virtual address to the absolute\r
785 // COFF address.\r
786 //\r
787 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
788 + mCoffSectionsOffset[Sym->st_shndx];\r
789 break;\r
790 case R_386_PC32:\r
791 //\r
792 // Relative relocation: Symbol - Ip + Addend\r
793 //\r
794 *(UINT32 *)Targ = *(UINT32 *)Targ\r
795 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
796 - (SecOffset - SecShdr->sh_addr);\r
797 break;\r
798 default:\r
799 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
800 }\r
801 } else if (mEhdr->e_machine == EM_ARM) {\r
802 switch (ELF32_R_TYPE(Rel->r_info)) {\r
803 case R_ARM_RBASE:\r
804 // No relocation - no action required\r
805 // break skipped\r
806\r
807 case R_ARM_PC24:\r
31643611 808 case R_ARM_REL32:\r
f51461c8
LG
809 case R_ARM_XPC25:\r
810 case R_ARM_THM_PC22:\r
811 case R_ARM_THM_JUMP19:\r
812 case R_ARM_CALL:\r
813 case R_ARM_JMP24:\r
814 case R_ARM_THM_JUMP24: \r
815 case R_ARM_PREL31: \r
816 case R_ARM_MOVW_PREL_NC: \r
817 case R_ARM_MOVT_PREL:\r
818 case R_ARM_THM_MOVW_PREL_NC:\r
819 case R_ARM_THM_MOVT_PREL:\r
820 case R_ARM_THM_JMP6:\r
821 case R_ARM_THM_ALU_PREL_11_0:\r
822 case R_ARM_THM_PC12:\r
823 case R_ARM_REL32_NOI:\r
824 case R_ARM_ALU_PC_G0_NC:\r
825 case R_ARM_ALU_PC_G0:\r
826 case R_ARM_ALU_PC_G1_NC:\r
827 case R_ARM_ALU_PC_G1:\r
828 case R_ARM_ALU_PC_G2:\r
829 case R_ARM_LDR_PC_G1:\r
830 case R_ARM_LDR_PC_G2:\r
831 case R_ARM_LDRS_PC_G0:\r
832 case R_ARM_LDRS_PC_G1:\r
833 case R_ARM_LDRS_PC_G2:\r
834 case R_ARM_LDC_PC_G0:\r
835 case R_ARM_LDC_PC_G1:\r
836 case R_ARM_LDC_PC_G2:\r
837 case R_ARM_GOT_PREL:\r
838 case R_ARM_THM_JUMP11:\r
839 case R_ARM_THM_JUMP8:\r
840 case R_ARM_TLS_GD32:\r
841 case R_ARM_TLS_LDM32:\r
842 case R_ARM_TLS_IE32:\r
843 // Thease are all PC-relative relocations and don't require modification\r
844 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
845 break;\r
846\r
847 case R_ARM_THM_MOVW_ABS_NC:\r
848 // MOVW is only lower 16-bits of the addres\r
849 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
850 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
851 break;\r
852\r
853 case R_ARM_THM_MOVT_ABS:\r
854 // MOVT is only upper 16-bits of the addres\r
855 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
856 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
857 break;\r
858\r
859 case R_ARM_ABS32:\r
860 case R_ARM_RABS32:\r
861 //\r
862 // Absolute relocation.\r
863 //\r
864 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
865 break;\r
866\r
867 default:\r
868 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
869 }\r
870 }\r
871 }\r
872 }\r
873 }\r
874\r
875 return TRUE;\r
876}\r
877\r
878UINTN gMovwOffset = 0;\r
879\r
880STATIC\r
881VOID\r
882WriteRelocations32 (\r
883 VOID\r
884 )\r
885{\r
886 UINT32 Index;\r
887 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
888 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
889 BOOLEAN FoundRelocations;\r
890 Elf_Dyn *Dyn;\r
891 Elf_Rel *Rel;\r
892 UINTN RelElementSize;\r
893 UINTN RelSize;\r
894 UINTN RelOffset;\r
895 UINTN K;\r
f51461c8 896 Elf32_Phdr *DynamicSegment;\r
f51461c8
LG
897\r
898 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
899 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
900 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
901 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
902 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
903 UINT32 RelIdx;\r
904\r
905 FoundRelocations = TRUE;\r
906 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
5aec6991 907 Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
f51461c8
LG
908\r
909 if (mEhdr->e_machine == EM_386) { \r
910 switch (ELF_R_TYPE(Rel->r_info)) {\r
911 case R_386_NONE:\r
912 case R_386_PC32:\r
913 //\r
914 // No fixup entry required.\r
915 //\r
916 break;\r
917 case R_386_32:\r
918 //\r
919 // Creates a relative relocation entry from the absolute entry.\r
920 //\r
921 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
922 + (Rel->r_offset - SecShdr->sh_addr),\r
923 EFI_IMAGE_REL_BASED_HIGHLOW);\r
924 break;\r
925 default:\r
926 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
927 }\r
928 } else if (mEhdr->e_machine == EM_ARM) {\r
929 switch (ELF32_R_TYPE(Rel->r_info)) {\r
930 case R_ARM_RBASE:\r
931 // No relocation - no action required\r
932 // break skipped\r
933\r
934 case R_ARM_PC24:\r
31643611 935 case R_ARM_REL32:\r
f51461c8
LG
936 case R_ARM_XPC25:\r
937 case R_ARM_THM_PC22:\r
938 case R_ARM_THM_JUMP19:\r
939 case R_ARM_CALL:\r
940 case R_ARM_JMP24:\r
941 case R_ARM_THM_JUMP24: \r
942 case R_ARM_PREL31: \r
943 case R_ARM_MOVW_PREL_NC: \r
944 case R_ARM_MOVT_PREL:\r
945 case R_ARM_THM_MOVW_PREL_NC:\r
946 case R_ARM_THM_MOVT_PREL:\r
947 case R_ARM_THM_JMP6:\r
948 case R_ARM_THM_ALU_PREL_11_0:\r
949 case R_ARM_THM_PC12:\r
950 case R_ARM_REL32_NOI:\r
951 case R_ARM_ALU_PC_G0_NC:\r
952 case R_ARM_ALU_PC_G0:\r
953 case R_ARM_ALU_PC_G1_NC:\r
954 case R_ARM_ALU_PC_G1:\r
955 case R_ARM_ALU_PC_G2:\r
956 case R_ARM_LDR_PC_G1:\r
957 case R_ARM_LDR_PC_G2:\r
958 case R_ARM_LDRS_PC_G0:\r
959 case R_ARM_LDRS_PC_G1:\r
960 case R_ARM_LDRS_PC_G2:\r
961 case R_ARM_LDC_PC_G0:\r
962 case R_ARM_LDC_PC_G1:\r
963 case R_ARM_LDC_PC_G2:\r
964 case R_ARM_GOT_PREL:\r
965 case R_ARM_THM_JUMP11:\r
966 case R_ARM_THM_JUMP8:\r
967 case R_ARM_TLS_GD32:\r
968 case R_ARM_TLS_LDM32:\r
969 case R_ARM_TLS_IE32:\r
970 // Thease are all PC-relative relocations and don't require modification\r
971 break;\r
972\r
973 case R_ARM_THM_MOVW_ABS_NC:\r
974 CoffAddFixup (\r
975 mCoffSectionsOffset[RelShdr->sh_info]\r
976 + (Rel->r_offset - SecShdr->sh_addr),\r
977 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
978 );\r
979\r
980 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
981 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
982 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
983 break;\r
984\r
985 case R_ARM_THM_MOVT_ABS:\r
986 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
987 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
988 }\r
989 break;\r
990\r
991 case R_ARM_ABS32:\r
992 case R_ARM_RABS32:\r
993 CoffAddFixup (\r
994 mCoffSectionsOffset[RelShdr->sh_info]\r
995 + (Rel->r_offset - SecShdr->sh_addr),\r
996 EFI_IMAGE_REL_BASED_HIGHLOW\r
997 );\r
998 break;\r
999\r
1000 default:\r
1001 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
1002 }\r
1003 } else {\r
1004 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
1005 }\r
1006 }\r
1007 }\r
1008 }\r
1009 }\r
1010\r
1011 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
1012 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
1013\r
1014 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
1015 RelElementSize = 0;\r
1016 RelSize = 0;\r
1017 RelOffset = 0;\r
1018\r
1019 DynamicSegment = GetPhdrByIndex (Index);\r
1020\r
1021 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
1022 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
1023\r
1024 while (Dyn->d_tag != DT_NULL) {\r
1025 switch (Dyn->d_tag) {\r
1026 case DT_REL:\r
1027 RelOffset = Dyn->d_un.d_val;\r
1028 break;\r
1029\r
1030 case DT_RELSZ:\r
1031 RelSize = Dyn->d_un.d_val;\r
1032 break;\r
1033\r
1034 case DT_RELENT:\r
1035 RelElementSize = Dyn->d_un.d_val;\r
1036 break;\r
1037\r
1038 default:\r
1039 break;\r
1040 }\r
1041 Dyn++;\r
1042 }\r
1043 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1044 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1045 }\r
1046\r
088dc245
AB
1047 for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
1048 Elf_Shdr *shdr = GetShdrByIndex(Index);\r
1049\r
1050 //\r
1051 // The PT_DYNAMIC section contains DT_REL relocations whose r_offset\r
1052 // field is relative to the base of a segment (or the entire image),\r
1053 // and not to the base of an ELF input section as is the case for\r
1054 // SHT_REL sections. This means that we cannot fix up such relocations\r
1055 // unless we cross-reference ELF sections and segments, considering\r
1056 // that the output placement recorded in mCoffSectionsOffset[] is\r
1057 // section based, not segment based.\r
1058 //\r
1059 // Fortunately, there is a simple way around this: we require that the\r
1060 // in-memory layout of the ELF and PE/COFF versions of the binary is\r
1061 // identical. That way, r_offset will retain its validity as a PE/COFF\r
1062 // image offset, and we can record it in the COFF fixup table\r
1063 // unmodified.\r
1064 //\r
1065 if (shdr->sh_addr != mCoffSectionsOffset[Index]) {\r
1066 Error (NULL, 0, 3000,\r
1067 "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.",\r
1068 mInImageName);\r
1069 }\r
1070 }\r
1071\r
f51461c8
LG
1072 for (K = 0; K < RelSize; K += RelElementSize) {\r
1073\r
1074 if (DynamicSegment->p_paddr == 0) {\r
1075 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
1076 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
1077 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
1078 } else {\r
1079 // This is how it reads in the generic ELF specification\r
1080 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
1081 }\r
1082\r
1083 switch (ELF32_R_TYPE (Rel->r_info)) {\r
1084 case R_ARM_RBASE:\r
1085 break;\r
1086\r
1087 case R_ARM_RABS32:\r
088dc245 1088 CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW);\r
f51461c8
LG
1089 break;\r
1090 \r
1091 default:\r
1092 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
1093 break;\r
1094 }\r
1095 }\r
1096 break;\r
1097 }\r
1098 }\r
1099 }\r
1100\r
1101 //\r
1102 // Pad by adding empty entries.\r
1103 //\r
1104 while (mCoffOffset & (mCoffAlignment - 1)) {\r
1105 CoffAddFixupEntry(0);\r
1106 }\r
1107\r
1108 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1109 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1110 Dir->Size = mCoffOffset - mRelocOffset;\r
1111 if (Dir->Size == 0) {\r
1112 // If no relocations, null out the directory entry and don't add the .reloc section\r
1113 Dir->VirtualAddress = 0;\r
1114 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1115 } else {\r
1116 Dir->VirtualAddress = mRelocOffset;\r
1117 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
1118 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1119 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1120 | EFI_IMAGE_SCN_MEM_READ);\r
1121 }\r
1122\r
1123}\r
1124\r
1125STATIC\r
1126VOID\r
1127WriteDebug32 (\r
1128 VOID\r
1129 )\r
1130{\r
1131 UINT32 Len;\r
f51461c8
LG
1132 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1133 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1134 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1135 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1136\r
1137 Len = strlen(mInImageName) + 1;\r
f51461c8 1138\r
0192b71c 1139 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset);\r
f51461c8
LG
1140 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1141 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
0192b71c
AB
1142 Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1143 Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1144\r
1145 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1146 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1147 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1148\r
1149\r
1150 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1151 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
0192b71c 1152 DataDir->VirtualAddress = mDebugOffset;\r
60e85a39 1153 DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
f51461c8
LG
1154}\r
1155\r
1156STATIC\r
1157VOID\r
1158SetImageSize32 (\r
1159 VOID\r
1160 )\r
1161{\r
1162 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1163 \r
1164 //\r
1165 // Set image size\r
1166 //\r
1167 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1168 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1169}\r
1170\r
1171STATIC\r
1172VOID\r
1173CleanUp32 (\r
1174 VOID\r
1175 )\r
1176{\r
1177 if (mCoffSectionsOffset != NULL) {\r
1178 free (mCoffSectionsOffset);\r
1179 }\r
1180}\r
1181\r
1182\r