]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/Elf32Convert.c
BaseTools: Updated tool_def to support 4K alignment.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf32Convert.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2Elf32 Convert solution\r
f51461c8 3\r
97fa0ee9 4Copyright (c) 2010 - 2014, 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
99STATIC const UINT32 mCoffAlignment = 0x20;\r
100\r
101//\r
102// PE section alignment.\r
103//\r
104STATIC const UINT16 mCoffNbrSections = 5;\r
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
119\r
120//\r
121// Initialization Function\r
122//\r
123BOOLEAN\r
124InitializeElf32 (\r
125 UINT8 *FileBuffer,\r
126 ELF_FUNCTION_TABLE *ElfFunctions\r
127 )\r
128{\r
129 //\r
130 // Initialize data pointer and structures.\r
131 //\r
132 mEhdr = (Elf_Ehdr*) FileBuffer; \r
133\r
134 //\r
135 // Check the ELF32 specific header information.\r
136 //\r
137 if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) {\r
138 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32");\r
139 return FALSE;\r
140 }\r
141 if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
142 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
143 return FALSE;\r
144 } \r
145 if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) {\r
146 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
147 return FALSE;\r
148 }\r
149 if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) { \r
150 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
151 return FALSE;\r
152 }\r
153 if (mEhdr->e_version != EV_CURRENT) {\r
154 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);\r
155 return FALSE;\r
156 }\r
157 \r
158 //\r
159 // Update section header pointers\r
160 //\r
161 mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff);\r
162 mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff);\r
163 \r
164 //\r
165 // Create COFF Section offset buffer and zero.\r
166 //\r
167 mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32));\r
168 memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32));\r
169\r
170 //\r
171 // Fill in function pointers.\r
172 //\r
173 ElfFunctions->ScanSections = ScanSections32;\r
174 ElfFunctions->WriteSections = WriteSections32;\r
175 ElfFunctions->WriteRelocations = WriteRelocations32;\r
176 ElfFunctions->WriteDebug = WriteDebug32;\r
177 ElfFunctions->SetImageSize = SetImageSize32;\r
178 ElfFunctions->CleanUp = CleanUp32;\r
179\r
180 return TRUE;\r
181}\r
182\r
183\r
184//\r
185// Header by Index functions\r
186//\r
187STATIC\r
188Elf_Shdr*\r
189GetShdrByIndex (\r
190 UINT32 Num\r
191 )\r
192{\r
193 if (Num >= mEhdr->e_shnum)\r
194 return NULL;\r
195 return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize);\r
196}\r
197\r
198STATIC\r
199Elf_Phdr*\r
200GetPhdrByIndex (\r
201 UINT32 num\r
202 )\r
203{\r
204 if (num >= mEhdr->e_phnum) {\r
205 return NULL;\r
206 }\r
207\r
208 return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize);\r
209}\r
210\r
211STATIC\r
212UINT32\r
213CoffAlign (\r
214 UINT32 Offset\r
215 )\r
216{\r
217 return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1);\r
218}\r
219\r
220//\r
221// filter functions\r
222//\r
223STATIC\r
224BOOLEAN\r
225IsTextShdr (\r
226 Elf_Shdr *Shdr\r
227 )\r
228{\r
229 return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC);\r
230}\r
231\r
232STATIC\r
233BOOLEAN\r
234IsHiiRsrcShdr (\r
235 Elf_Shdr *Shdr\r
236 )\r
237{\r
238 Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx);\r
239\r
240 return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
241}\r
242\r
243STATIC\r
244BOOLEAN\r
245IsDataShdr (\r
246 Elf_Shdr *Shdr\r
247 )\r
248{\r
249 if (IsHiiRsrcShdr(Shdr)) {\r
250 return FALSE;\r
251 }\r
252 return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
253}\r
254\r
255//\r
256// Elf functions interface implementation\r
257//\r
258\r
259STATIC\r
260VOID\r
261ScanSections32 (\r
262 VOID\r
263 )\r
264{\r
265 UINT32 i;\r
266 EFI_IMAGE_DOS_HEADER *DosHdr;\r
267 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
268 UINT32 CoffEntry;\r
269 UINT32 SectionCount;\r
234f9ff9 270 BOOLEAN FoundSection;\r
f51461c8
LG
271\r
272 CoffEntry = 0;\r
273 mCoffOffset = 0;\r
f51461c8
LG
274\r
275 //\r
276 // Coff file start with a DOS header.\r
277 //\r
278 mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
279 mNtHdrOffset = mCoffOffset;\r
280 switch (mEhdr->e_machine) {\r
281 case EM_386:\r
282 case EM_ARM:\r
283 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
284 break;\r
285 default:\r
286 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
287 mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
288 break;\r
289 }\r
290\r
291 mTableOffset = mCoffOffset;\r
292 mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
293\r
294 //\r
295 // First text sections.\r
296 //\r
297 mCoffOffset = CoffAlign(mCoffOffset);\r
234f9ff9
EB
298 mTextOffset = mCoffOffset;\r
299 FoundSection = FALSE;\r
f51461c8
LG
300 SectionCount = 0;\r
301 for (i = 0; i < mEhdr->e_shnum; i++) {\r
302 Elf_Shdr *shdr = GetShdrByIndex(i);\r
303 if (IsTextShdr(shdr)) {\r
304 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
305 // the alignment field is valid\r
306 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
307 // if the section address is aligned we must align PE/COFF\r
308 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
309 } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
310 // ARM RVCT tools have behavior outside of the ELF specification to try\r
311 // and make images smaller. If sh_addr is not aligned to sh_addralign\r
312 // then the section needs to preserve sh_addr MOD sh_addralign.\r
313 // Normally doing nothing here works great.\r
314 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
315 }\r
316 }\r
317\r
318 /* Relocate entry. */\r
319 if ((mEhdr->e_entry >= shdr->sh_addr) &&\r
320 (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
321 CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr;\r
322 }\r
323\r
324 //\r
325 // Set mTextOffset with the offset of the first '.text' section\r
326 //\r
234f9ff9 327 if (!FoundSection) {\r
f51461c8 328 mTextOffset = mCoffOffset;\r
234f9ff9 329 FoundSection = TRUE;\r
f51461c8
LG
330 }\r
331\r
332 mCoffSectionsOffset[i] = mCoffOffset;\r
333 mCoffOffset += shdr->sh_size;\r
334 SectionCount ++;\r
335 }\r
336 }\r
337\r
234f9ff9 338 if (!FoundSection) {\r
f51461c8
LG
339 Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section.");\r
340 assert (FALSE);\r
341 }\r
342\r
343 if (mEhdr->e_machine != EM_ARM) {\r
344 mCoffOffset = CoffAlign(mCoffOffset);\r
345 }\r
346\r
347 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
348 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName);\r
349 }\r
350\r
351 //\r
352 // Then data sections.\r
353 //\r
354 mDataOffset = mCoffOffset;\r
234f9ff9 355 FoundSection = FALSE;\r
f51461c8
LG
356 SectionCount = 0;\r
357 for (i = 0; i < mEhdr->e_shnum; i++) {\r
358 Elf_Shdr *shdr = GetShdrByIndex(i);\r
359 if (IsDataShdr(shdr)) {\r
360 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
361 // the alignment field is valid\r
362 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
363 // if the section address is aligned we must align PE/COFF\r
364 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
365 } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
366 // ARM RVCT tools have behavior outside of the ELF specification to try\r
367 // and make images smaller. If sh_addr is not aligned to sh_addralign\r
368 // then the section needs to preserve sh_addr MOD sh_addralign.\r
369 // Normally doing nothing here works great.\r
370 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
371 }\r
372 }\r
234f9ff9
EB
373\r
374 //\r
375 // Set mDataOffset with the offset of the first '.data' section\r
376 //\r
377 if (!FoundSection) {\r
378 mDataOffset = mCoffOffset;\r
379 FoundSection = TRUE;\r
380 }\r
381\r
f51461c8
LG
382 mCoffSectionsOffset[i] = mCoffOffset;\r
383 mCoffOffset += shdr->sh_size;\r
384 SectionCount ++;\r
385 }\r
386 }\r
387 mCoffOffset = CoffAlign(mCoffOffset);\r
388\r
389 if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) {\r
390 Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
391 }\r
392\r
393 //\r
394 // The HII resource sections.\r
395 //\r
396 mHiiRsrcOffset = mCoffOffset;\r
397 for (i = 0; i < mEhdr->e_shnum; i++) {\r
398 Elf_Shdr *shdr = GetShdrByIndex(i);\r
399 if (IsHiiRsrcShdr(shdr)) {\r
400 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
401 // the alignment field is valid\r
402 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
403 // if the section address is aligned we must align PE/COFF\r
404 mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
405 } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) {\r
406 // ARM RVCT tools have behavior outside of the ELF specification to try\r
407 // and make images smaller. If sh_addr is not aligned to sh_addralign\r
408 // then the section needs to preserve sh_addr MOD sh_addralign.\r
409 // Normally doing nothing here works great.\r
410 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
411 }\r
412 }\r
413 if (shdr->sh_size != 0) {\r
234f9ff9 414 mHiiRsrcOffset = mCoffOffset;\r
f51461c8
LG
415 mCoffSectionsOffset[i] = mCoffOffset;\r
416 mCoffOffset += shdr->sh_size;\r
417 mCoffOffset = CoffAlign(mCoffOffset);\r
418 SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset);\r
419 }\r
420 break;\r
421 }\r
422 }\r
423\r
424 mRelocOffset = mCoffOffset;\r
425\r
426 //\r
427 // Allocate base Coff file. Will be expanded later for relocations.\r
428 //\r
429 mCoffFile = (UINT8 *)malloc(mCoffOffset);\r
430 memset(mCoffFile, 0, mCoffOffset);\r
431\r
432 //\r
433 // Fill headers.\r
434 //\r
435 DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile;\r
436 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
437 DosHdr->e_lfanew = mNtHdrOffset;\r
438\r
439 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset);\r
440\r
441 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
442\r
443 switch (mEhdr->e_machine) {\r
444 case EM_386:\r
445 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
446 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
447 break;\r
448 case EM_ARM:\r
449 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
450 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
451 break;\r
452 default:\r
453 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine);\r
454 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
455 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
456 }\r
457\r
458 NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections;\r
459 NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
460 mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
461 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
462 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
463 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
464 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
465 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
466 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
467 | EFI_IMAGE_FILE_32BIT_MACHINE;\r
468\r
469 NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;\r
470 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset;\r
471 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
472 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
473\r
474 NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset;\r
475\r
476 NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset;\r
477 NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
478 NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment;\r
479 NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment;\r
480 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
481\r
482 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset;\r
483 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
484\r
485 //\r
486 // Section headers.\r
487 //\r
488 if ((mDataOffset - mTextOffset) > 0) {\r
489 CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset,\r
490 EFI_IMAGE_SCN_CNT_CODE\r
491 | EFI_IMAGE_SCN_MEM_EXECUTE\r
492 | EFI_IMAGE_SCN_MEM_READ);\r
493 } else {\r
494 // Don't make a section of size 0.\r
495 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
496 }\r
497\r
498 if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
499 CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
500 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
501 | EFI_IMAGE_SCN_MEM_WRITE\r
502 | EFI_IMAGE_SCN_MEM_READ);\r
503 } else {\r
504 // Don't make a section of size 0.\r
505 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
506 }\r
507\r
508 if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
509 CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
510 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
511 | EFI_IMAGE_SCN_MEM_READ);\r
512\r
513 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset;\r
514 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset;\r
515 } else {\r
516 // Don't make a section of size 0.\r
517 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
518 }\r
519\r
520}\r
521\r
522STATIC\r
523BOOLEAN\r
524WriteSections32 (\r
525 SECTION_FILTER_TYPES FilterType\r
526 )\r
527{\r
528 UINT32 Idx;\r
529 Elf_Shdr *SecShdr;\r
530 UINT32 SecOffset;\r
531 BOOLEAN (*Filter)(Elf_Shdr *);\r
532\r
533 //\r
534 // Initialize filter pointer\r
535 //\r
536 switch (FilterType) {\r
537 case SECTION_TEXT:\r
538 Filter = IsTextShdr;\r
539 break;\r
540 case SECTION_HII:\r
541 Filter = IsHiiRsrcShdr;\r
542 break;\r
543 case SECTION_DATA:\r
544 Filter = IsDataShdr;\r
545 break;\r
546 default:\r
547 return FALSE;\r
548 }\r
549\r
550 //\r
551 // First: copy sections.\r
552 //\r
553 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
554 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
555 if ((*Filter)(Shdr)) {\r
556 switch (Shdr->sh_type) {\r
557 case SHT_PROGBITS:\r
558 /* Copy. */\r
559 memcpy(mCoffFile + mCoffSectionsOffset[Idx],\r
560 (UINT8*)mEhdr + Shdr->sh_offset,\r
561 Shdr->sh_size);\r
562 break;\r
563\r
564 case SHT_NOBITS:\r
565 memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
566 break;\r
567\r
568 default:\r
569 //\r
570 // Ignore for unkown section type.\r
571 //\r
572 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
573 break;\r
574 }\r
575 }\r
576 }\r
577\r
578 //\r
579 // Second: apply relocations.\r
580 //\r
581 for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {\r
582 //\r
583 // Determine if this is a relocation section.\r
584 //\r
585 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
586 if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {\r
587 continue;\r
588 }\r
589 \r
590 //\r
591 // Relocation section found. Now extract section information that the relocations\r
592 // apply to in the ELF data and the new COFF data.\r
593 //\r
594 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
595 SecOffset = mCoffSectionsOffset[RelShdr->sh_info];\r
596 \r
597 //\r
598 // Only process relocations for the current filter type.\r
599 //\r
600 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
601 UINT32 RelOffset;\r
602 \r
603 //\r
604 // Determine the symbol table referenced by the relocation data.\r
605 //\r
606 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
607 UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;\r
608\r
609 //\r
610 // Process all relocation entries for this section.\r
611 //\r
612 for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) {\r
613 //\r
614 // Set pointer to relocation entry\r
615 //\r
616 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset);\r
617 \r
618 //\r
619 // Set pointer to symbol table entry associated with the relocation entry.\r
620 //\r
621 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
622 \r
623 Elf_Shdr *SymShdr;\r
624 UINT8 *Targ;\r
625 UINT16 Address;\r
626\r
627 //\r
628 // Check section header index found in symbol table and get the section \r
629 // header location.\r
630 //\r
631 if (Sym->st_shndx == SHN_UNDEF\r
632 || Sym->st_shndx == SHN_ABS\r
633 || Sym->st_shndx > mEhdr->e_shnum) {\r
634 Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
635 }\r
636 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
637\r
638 //\r
639 // Convert the relocation data to a pointer into the coff file.\r
640 //\r
641 // Note: \r
642 // r_offset is the virtual address of the storage unit to be relocated.\r
643 // sh_addr is the virtual address for the base of the section.\r
644 //\r
645 Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
646\r
647 //\r
648 // Determine how to handle each relocation type based on the machine type.\r
649 //\r
650 if (mEhdr->e_machine == EM_386) {\r
651 switch (ELF_R_TYPE(Rel->r_info)) {\r
652 case R_386_NONE:\r
653 break;\r
654 case R_386_32:\r
655 //\r
656 // Absolute relocation.\r
657 // Converts Targ from a absolute virtual address to the absolute\r
658 // COFF address.\r
659 //\r
660 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
661 + mCoffSectionsOffset[Sym->st_shndx];\r
662 break;\r
663 case R_386_PC32:\r
664 //\r
665 // Relative relocation: Symbol - Ip + Addend\r
666 //\r
667 *(UINT32 *)Targ = *(UINT32 *)Targ\r
668 + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
669 - (SecOffset - SecShdr->sh_addr);\r
670 break;\r
671 default:\r
672 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
673 }\r
674 } else if (mEhdr->e_machine == EM_ARM) {\r
675 switch (ELF32_R_TYPE(Rel->r_info)) {\r
676 case R_ARM_RBASE:\r
677 // No relocation - no action required\r
678 // break skipped\r
679\r
680 case R_ARM_PC24:\r
681 case R_ARM_XPC25:\r
682 case R_ARM_THM_PC22:\r
683 case R_ARM_THM_JUMP19:\r
684 case R_ARM_CALL:\r
685 case R_ARM_JMP24:\r
686 case R_ARM_THM_JUMP24: \r
687 case R_ARM_PREL31: \r
688 case R_ARM_MOVW_PREL_NC: \r
689 case R_ARM_MOVT_PREL:\r
690 case R_ARM_THM_MOVW_PREL_NC:\r
691 case R_ARM_THM_MOVT_PREL:\r
692 case R_ARM_THM_JMP6:\r
693 case R_ARM_THM_ALU_PREL_11_0:\r
694 case R_ARM_THM_PC12:\r
695 case R_ARM_REL32_NOI:\r
696 case R_ARM_ALU_PC_G0_NC:\r
697 case R_ARM_ALU_PC_G0:\r
698 case R_ARM_ALU_PC_G1_NC:\r
699 case R_ARM_ALU_PC_G1:\r
700 case R_ARM_ALU_PC_G2:\r
701 case R_ARM_LDR_PC_G1:\r
702 case R_ARM_LDR_PC_G2:\r
703 case R_ARM_LDRS_PC_G0:\r
704 case R_ARM_LDRS_PC_G1:\r
705 case R_ARM_LDRS_PC_G2:\r
706 case R_ARM_LDC_PC_G0:\r
707 case R_ARM_LDC_PC_G1:\r
708 case R_ARM_LDC_PC_G2:\r
709 case R_ARM_GOT_PREL:\r
710 case R_ARM_THM_JUMP11:\r
711 case R_ARM_THM_JUMP8:\r
712 case R_ARM_TLS_GD32:\r
713 case R_ARM_TLS_LDM32:\r
714 case R_ARM_TLS_IE32:\r
715 // Thease are all PC-relative relocations and don't require modification\r
716 // GCC does not seem to have the concept of a application that just needs to get relocated.\r
717 break;\r
718\r
719 case R_ARM_THM_MOVW_ABS_NC:\r
720 // MOVW is only lower 16-bits of the addres\r
721 Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
722 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
723 break;\r
724\r
725 case R_ARM_THM_MOVT_ABS:\r
726 // MOVT is only upper 16-bits of the addres\r
727 Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16);\r
728 ThumbMovtImmediatePatch ((UINT16 *)Targ, Address);\r
729 break;\r
730\r
731 case R_ARM_ABS32:\r
732 case R_ARM_RABS32:\r
733 //\r
734 // Absolute relocation.\r
735 //\r
736 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
737 break;\r
738\r
739 default:\r
740 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
741 }\r
742 }\r
743 }\r
744 }\r
745 }\r
746\r
747 return TRUE;\r
748}\r
749\r
750UINTN gMovwOffset = 0;\r
751\r
752STATIC\r
753VOID\r
754WriteRelocations32 (\r
755 VOID\r
756 )\r
757{\r
758 UINT32 Index;\r
759 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
760 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
761 BOOLEAN FoundRelocations;\r
762 Elf_Dyn *Dyn;\r
763 Elf_Rel *Rel;\r
764 UINTN RelElementSize;\r
765 UINTN RelSize;\r
766 UINTN RelOffset;\r
767 UINTN K;\r
768 UINT8 *Targ;\r
769 Elf32_Phdr *DynamicSegment;\r
770 Elf32_Phdr *TargetSegment;\r
771\r
772 for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) {\r
773 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
774 if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) {\r
775 Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info);\r
776 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
777 UINT32 RelIdx;\r
778\r
779 FoundRelocations = TRUE;\r
780 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
781 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);\r
782\r
783 if (mEhdr->e_machine == EM_386) { \r
784 switch (ELF_R_TYPE(Rel->r_info)) {\r
785 case R_386_NONE:\r
786 case R_386_PC32:\r
787 //\r
788 // No fixup entry required.\r
789 //\r
790 break;\r
791 case R_386_32:\r
792 //\r
793 // Creates a relative relocation entry from the absolute entry.\r
794 //\r
795 CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info]\r
796 + (Rel->r_offset - SecShdr->sh_addr),\r
797 EFI_IMAGE_REL_BASED_HIGHLOW);\r
798 break;\r
799 default:\r
800 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
801 }\r
802 } else if (mEhdr->e_machine == EM_ARM) {\r
803 switch (ELF32_R_TYPE(Rel->r_info)) {\r
804 case R_ARM_RBASE:\r
805 // No relocation - no action required\r
806 // break skipped\r
807\r
808 case R_ARM_PC24:\r
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 break;\r
845\r
846 case R_ARM_THM_MOVW_ABS_NC:\r
847 CoffAddFixup (\r
848 mCoffSectionsOffset[RelShdr->sh_info]\r
849 + (Rel->r_offset - SecShdr->sh_addr),\r
850 EFI_IMAGE_REL_BASED_ARM_MOV32T\r
851 );\r
852\r
853 // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction\r
854 // Track this address so we can log an error for unsupported sequence of MOVW/MOVT\r
855 gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr);\r
856 break;\r
857\r
858 case R_ARM_THM_MOVT_ABS:\r
859 if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) {\r
860 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
861 }\r
862 break;\r
863\r
864 case R_ARM_ABS32:\r
865 case R_ARM_RABS32:\r
866 CoffAddFixup (\r
867 mCoffSectionsOffset[RelShdr->sh_info]\r
868 + (Rel->r_offset - SecShdr->sh_addr),\r
869 EFI_IMAGE_REL_BASED_HIGHLOW\r
870 );\r
871 break;\r
872\r
873 default:\r
874 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
875 }\r
876 } else {\r
877 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
878 }\r
879 }\r
880 }\r
881 }\r
882 }\r
883\r
884 if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) {\r
885 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
886\r
887 for (Index = 0; Index < mEhdr->e_phnum; Index++) {\r
888 RelElementSize = 0;\r
889 RelSize = 0;\r
890 RelOffset = 0;\r
891\r
892 DynamicSegment = GetPhdrByIndex (Index);\r
893\r
894 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
895 Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset);\r
896\r
897 while (Dyn->d_tag != DT_NULL) {\r
898 switch (Dyn->d_tag) {\r
899 case DT_REL:\r
900 RelOffset = Dyn->d_un.d_val;\r
901 break;\r
902\r
903 case DT_RELSZ:\r
904 RelSize = Dyn->d_un.d_val;\r
905 break;\r
906\r
907 case DT_RELENT:\r
908 RelElementSize = Dyn->d_un.d_val;\r
909 break;\r
910\r
911 default:\r
912 break;\r
913 }\r
914 Dyn++;\r
915 }\r
916 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
917 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
918 }\r
919\r
920 for (K = 0; K < RelSize; K += RelElementSize) {\r
921\r
922 if (DynamicSegment->p_paddr == 0) {\r
923 // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL\r
924 // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools\r
925 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K);\r
926 } else {\r
927 // This is how it reads in the generic ELF specification\r
928 Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K);\r
929 }\r
930\r
931 switch (ELF32_R_TYPE (Rel->r_info)) {\r
932 case R_ARM_RBASE:\r
933 break;\r
934\r
935 case R_ARM_RABS32:\r
936 TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
937\r
938 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.\r
939 Targ = mCoffFile + mCoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
940\r
941 *(UINT32 *)Targ = *(UINT32 *)Targ + mCoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
942\r
943 CoffAddFixup (mCoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
944 break;\r
945 \r
946 default:\r
947 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
948 break;\r
949 }\r
950 }\r
951 break;\r
952 }\r
953 }\r
954 }\r
955\r
956 //\r
957 // Pad by adding empty entries.\r
958 //\r
959 while (mCoffOffset & (mCoffAlignment - 1)) {\r
960 CoffAddFixupEntry(0);\r
961 }\r
962\r
963 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
964 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
965 Dir->Size = mCoffOffset - mRelocOffset;\r
966 if (Dir->Size == 0) {\r
967 // If no relocations, null out the directory entry and don't add the .reloc section\r
968 Dir->VirtualAddress = 0;\r
969 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
970 } else {\r
971 Dir->VirtualAddress = mRelocOffset;\r
972 CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset,\r
973 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
974 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
975 | EFI_IMAGE_SCN_MEM_READ);\r
976 }\r
977\r
978}\r
979\r
980STATIC\r
981VOID\r
982WriteDebug32 (\r
983 VOID\r
984 )\r
985{\r
986 UINT32 Len;\r
987 UINT32 DebugOffset;\r
988 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
989 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
990 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
991 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
992\r
993 Len = strlen(mInImageName) + 1;\r
994 DebugOffset = mCoffOffset;\r
995\r
996 mCoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
997 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
998 + Len;\r
999 mCoffOffset = CoffAlign(mCoffOffset);\r
1000\r
1001 mCoffFile = realloc(mCoffFile, mCoffOffset);\r
1002 memset(mCoffFile + DebugOffset, 0, mCoffOffset - DebugOffset);\r
1003\r
1004 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + DebugOffset);\r
1005 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1006 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
1007 Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1008 Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1009\r
1010 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1011 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1012 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1013\r
1014\r
1015 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1016 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
1017 DataDir->VirtualAddress = DebugOffset;\r
1018 DataDir->Size = mCoffOffset - DebugOffset;\r
1019 if (DataDir->Size == 0) {\r
1020 // If no debug, null out the directory entry and don't add the .debug section\r
1021 DataDir->VirtualAddress = 0;\r
1022 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1023 } else {\r
1024 DataDir->VirtualAddress = DebugOffset;\r
1025 CreateSectionHeader (".debug", DebugOffset, mCoffOffset - DebugOffset,\r
1026 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1027 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1028 | EFI_IMAGE_SCN_MEM_READ);\r
1029\r
1030 }\r
1031}\r
1032\r
1033STATIC\r
1034VOID\r
1035SetImageSize32 (\r
1036 VOID\r
1037 )\r
1038{\r
1039 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1040 \r
1041 //\r
1042 // Set image size\r
1043 //\r
1044 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
1045 NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset;\r
1046}\r
1047\r
1048STATIC\r
1049VOID\r
1050CleanUp32 (\r
1051 VOID\r
1052 )\r
1053{\r
1054 if (mCoffSectionsOffset != NULL) {\r
1055 free (mCoffSectionsOffset);\r
1056 }\r
1057}\r
1058\r
1059\r