1 /**************************** elf2cof.cpp *********************************
2 * Author: Agner Fog
3 * Date created: 2006-08-19
4 * Last modified: 2013-11-27
5 * Project: objconv
6 * Module: elf2cof.cpp
7 * Description:
8 * Module for converting ELF file to PE/COFF file
9 *
10 * Copyright 2006-2013 GNU General Public License http://www.gnu.org/licenses
11 *****************************************************************************/
12 #include "stdafx.h"
13 // All functions in this module are templated to make two versions: 32 and 64 bits.
14 // See instantiations at the end of this file.
15
16
17 // Constructor
18 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
CELF2COF()19 CELF2COF<ELFSTRUCTURES>::CELF2COF() {
20 // Reset all
21 memset(this, 0, sizeof(*this));
22 }
23
24
25 // Convert(): Do the conversion
26 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
Convert()27 void CELF2COF<ELFSTRUCTURES>::Convert() {
28
29 // Some compilers require this-> for accessing members of template base class,
30 // according to the so-called two-phase lookup rule.
31
32 // Allocate variable size buffers
33 NewSectIndex.SetNum(this->NSections);// Allocate section translation table
34 NewSectIndex.SetZero(); // Initialize
35
36 // Call the subfunctions
37 ToFile.SetFileType(FILETYPE_COFF); // Set type of to file
38 MakeFileHeader(); // Make file header
39 MakeSectionsIndex(); // Make sections index translation table
40 MakeSymbolTable(); // Make symbol table and string tables
41 MakeSections(); // Make sections and relocation tables
42 HideUnusedSymbols(); // Hide unused symbols
43 MakeBinaryFile(); // Put sections together
44 *this << ToFile; // Take over new file buffer
45 }
46
47
48 // MakeFileHeader(): Convert subfunction to make file header
49 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
MakeFileHeader()50 void CELF2COF<ELFSTRUCTURES>::MakeFileHeader() {
51
52 // Make PE file header
53 NewFileHeader.Machine = (this->WordSize == 32) ? PE_MACHINE_I386 : PE_MACHINE_X8664;
54 NewFileHeader.TimeDateStamp = (uint32_t)time(0);
55 NewFileHeader.SizeOfOptionalHeader = 0;
56 NewFileHeader.Flags = 0;
57
58 // Values inserted later:
59 NewFileHeader.NumberOfSections = 0;
60 NewFileHeader.PSymbolTable = 0;
61 NewFileHeader.NumberOfSymbols = 0;
62
63 // Put file header into file
64 ToFile.Push(&NewFileHeader, sizeof(NewFileHeader));
65 }
66
67
68 // MakeSectionsIndex(): Make sections index translation table
69 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
MakeSectionsIndex()70 void CELF2COF<ELFSTRUCTURES>::MakeSectionsIndex() {
71 // We must make this table before the segments, because it is needed for the
72 // symbol table, and we must make the symbol table before the relocation table,
73 // and we must make the relocation table together with the sections.
74
75 uint32_t oldsec; // Section number in old file
76 uint32_t newsec = 0; // Section number in new file
77
78 // Loop through old sections
79 for (oldsec = 0; oldsec < this->NSections; oldsec++) {
80
81 // Get section name
82 const char * sname = "";
83 uint32_t namei = this->SectionHeaders[oldsec].sh_name;
84 if (namei >= this->SecStringTableLen) err.submit(2112);
85 else sname = this->SecStringTable + namei;
86
87 if (cmd.DebugInfo == CMDL_DEBUG_STRIP) {
88 // Check for debug section names
89 if (strncmp(sname, ".note", 5) == 0
90 || strncmp(sname, ".comment", 8) == 0
91 || strncmp(sname, ".stab", 5) == 0
92 || strncmp(sname, ".debug", 6) == 0) {
93 // Remove this section
94 this->SectionHeaders[oldsec].sh_type = SHT_REMOVE_ME;
95 cmd.CountDebugRemoved();
96 }
97 }
98
99 if (cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
100 // Check for exception section name
101 if (strncmp(sname, ".eh_frame", 9) == 0) {
102 // Remove this section
103 this->SectionHeaders[oldsec].sh_type = SHT_REMOVE_ME;
104 cmd.CountExceptionRemoved();
105 }
106 }
107
108 // Search for program data sections only
109 if (this->SectionHeaders[oldsec].sh_type == SHT_PROGBITS
110 || this->SectionHeaders[oldsec].sh_type == SHT_NOBITS) {
111 // Section index translation table
112 NewSectIndex[oldsec] = newsec++;
113 }
114 else {
115 NewSectIndex[oldsec] = 0;
116 }
117 }
118 // Store number of sections in new file
119 NumSectionsNew = newsec;
120
121 // Calculate file offset of raw data
122 RawDataOffset = sizeof(SCOFF_FileHeader) + NumSectionsNew * sizeof(SCOFF_SectionHeader);
123 }
124
125
126 // MakeSections(): Convert subfunction to make sections and relocation tables
127 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
MakeSections()128 void CELF2COF<ELFSTRUCTURES>::MakeSections() {
129 uint32_t oldsec; // Section number in old file
130 uint32_t relsec; // Relocation section in old file
131 SCOFF_SectionHeader NewHeader; // New section header
132 TELF_SectionHeader OldHeader; // Old section header
133 TELF_SectionHeader OldRelHeader; // Old relocation section header
134 TELF_Relocation OldRelocation; // Old relocation table entry
135 SCOFF_Relocation NewRelocation; // New relocation table entry
136
137 // Loop through old sections
138 for (oldsec = 0; oldsec < this->NSections; oldsec++) {
139
140 // Copy old header for convenience
141 OldHeader = this->SectionHeaders[oldsec];
142
143 // Search for program data sections only
144 if (OldHeader.sh_type == SHT_PROGBITS || OldHeader.sh_type == SHT_NOBITS) {
145
146 // Reset new section header
147 memset(&NewHeader, 0, sizeof(NewHeader));
148
149 // Section name
150 const char * sname = "";
151 uint32_t namei = OldHeader.sh_name;
152 if (namei >= this->SecStringTableLen) err.submit(2112);
153 else sname = this->SecStringTable + namei;
154
155 // Check for special names
156 if (strcmp(sname, ELF_CONSTRUCTOR_NAME)==0) {
157 // This is the constructors segment
158 sname = COFF_CONSTRUCTOR_NAME;
159 OldHeader.sh_flags &= ~ SHF_WRITE;
160 }
161
162 // Store name in section header
163 COFF_PutNameInSectionHeader(NewHeader, sname, NewStringTable);
164
165 // Raw data
166 NewHeader.SizeOfRawData = uint32_t(OldHeader.sh_size); // section size in file
167 if (OldHeader.sh_size && OldHeader.sh_type != SHT_NOBITS) {
168 // File to raw data for section
169 NewHeader.PRawData = NewRawData.GetDataSize() + RawDataOffset;
170
171 // Copy raw data
172 NewRawData.Push(this->Buf()+(uint32_t)(OldHeader.sh_offset), (uint32_t)(OldHeader.sh_size));
173 NewRawData.Align(4);
174 }
175
176 // Section flags
177 NewHeader.Flags = PE_SCN_MEM_READ;
178 if (OldHeader.sh_flags & SHF_WRITE) NewHeader.Flags |= PE_SCN_MEM_WRITE;
179 if (OldHeader.sh_flags & SHF_EXECINSTR) {
180 NewHeader.Flags |= PE_SCN_MEM_EXECUTE | PE_SCN_CNT_CODE;
181 }
182 else {
183 NewHeader.Flags |= (OldHeader.sh_type == SHT_PROGBITS) ?
184 PE_SCN_CNT_INIT_DATA : PE_SCN_CNT_UNINIT_DATA;
185 }
186 // Alignment
187 int NewAlign = FloorLog2(uint32_t(OldHeader.sh_addralign)) + 1;
188 if (NewAlign > 14) NewAlign = 14; // limit for highest alignment
189 NewHeader.Flags |= PE_SCN_ALIGN_1 * NewAlign;
190
191 // Find relocation table for this section by searching through all sections
192 for (relsec = 1; relsec < this->NSections; relsec++) {
193
194 // Get section header
195 OldRelHeader = this->SectionHeaders[relsec];
196
197 // Check if this is a relocations section referring to oldsec
198 if ((OldRelHeader.sh_type == SHT_REL || OldRelHeader.sh_type == SHT_RELA) // if section is relocation
199 && OldRelHeader.sh_info == oldsec) { // and if section refers to current section
200
201 // Found the right relocation table. Get pointer
202 int8_t * reltab = this->Buf() + uint32_t(OldRelHeader.sh_offset);
203 int8_t * reltabend = reltab + uint32_t(OldRelHeader.sh_size);
204
205 // Get entry size
206 int entrysize = uint32_t(OldRelHeader.sh_entsize);
207 int expectedentrysize = (OldRelHeader.sh_type == SHT_RELA) ?
208 sizeof(TELF_Relocation) : // Elf32_Rela, Elf64_Rela
209 sizeof(TELF_Relocation) - this->WordSize/8; // Elf32_Rel, Elf64_Rel
210 if (entrysize < expectedentrysize) {err.submit(2033); entrysize = expectedentrysize;}
211
212 // File pointer for new relocations
213 NewHeader.PRelocations = NewRawData.GetDataSize() + RawDataOffset; // file to relocation entries
214
215 // Loop through relocation table entries
216 for (; reltab < reltabend; reltab += entrysize) {
217
218 // Copy relocation table entry with or without addend
219 OldRelocation.r_addend = 0;
220 memcpy(&OldRelocation, reltab, entrysize);
221
222 // Find inline addend
223 uint32_t InlinePosition = (uint32_t)(NewHeader.PRawData - RawDataOffset + OldRelocation.r_offset);
224
225 // Check that address is valid
226 if (InlinePosition >= this->GetDataSize()) {
227 // Address is invalid
228 err.submit(2032);
229 break;
230 }
231
232 // Pointer to inline addend
233 int32_t * piaddend = (int32_t*)(NewRawData.Buf() + InlinePosition);
234
235 // Symbol offset
236 NewRelocation.VirtualAddress = uint32_t(OldRelocation.r_offset);
237
238 // Symbol table index
239 if (OldRelocation.r_sym < NewSymbolIndex.GetNumEntries()) {
240 NewRelocation.SymbolTableIndex = NewSymbolIndex[OldRelocation.r_sym];
241 }
242 else {
243 NewRelocation.SymbolTableIndex = 0; // Symbol table index out of range
244 }
245
246 // Get relocation type and fix addend
247 if (this->WordSize == 32) {
248 switch(OldRelocation.r_type) {
249 case R_386_NONE: // Ignored
250 NewRelocation.Type = COFF32_RELOC_ABS; break;
251
252 case R_386_IRELATIVE:
253 err.submit(1063); // Warning: Gnu indirect function cannot be converted
254 // continue in next case?:
255 case R_386_32: // 32-bit absolute virtual address
256 NewRelocation.Type = COFF32_RELOC_DIR32;
257 *piaddend += uint32_t(OldRelocation.r_addend);
258 break;
259
260 case R_386_PC32: // 32-bit self-relative
261 NewRelocation.Type = COFF32_RELOC_REL32;
262 // Difference between EIP-relative and self-relative relocation = size of address field
263 // Adjust inline addend for different relocation method:
264 *piaddend += 4 + uint32_t(OldRelocation.r_addend);
265 break;
266
267 case R_386_GOT32: case R_386_GLOB_DAT: case R_386_GOTOFF: case R_386_GOTPC:
268 // Global offset table
269 err.submit(2042); // cannot convert position-independent code
270 err.ClearError(2042); // report this error only once
271 NewRelocation.Type = 0;
272 break;
273
274 case R_386_PLT32: case R_386_JMP_SLOT:
275 // procedure linkage table
276 err.submit(2043); // cannot convert import table
277 err.ClearError(2043); // report this error only once
278 NewRelocation.Type = 0;
279 break;
280
281 case R_386_RELATIVE: // adjust by program base
282 default: // Unknown or unsupported relocation method
283 err.submit(2030, OldRelocation.r_type);
284 err.ClearError(2030); // report this error only once
285 NewRelocation.Type = 0;
286 break;
287 }
288 }
289 else { // WordSize == 64
290 switch(OldRelocation.r_type) {
291 case R_X86_64_NONE: // Ignored
292 NewRelocation.Type = COFF64_RELOC_ABS;
293 break;
294
295 case R_X86_64_64: // 64 bit absolute virtual addres
296 NewRelocation.Type = COFF64_RELOC_ABS64;
297 *(int64_t*)piaddend += OldRelocation.r_addend;
298 break;
299
300 case R_X86_64_IRELATIVE:
301 err.submit(1063); // Warning: Gnu indirect function cannot be converted
302 // continue in next case?:
303 case R_X86_64_32S: // 32 bit absolute virtual address, sign extended
304 case R_X86_64_32: // 32 bit absolute virtual address, zero extended
305 NewRelocation.Type = COFF64_RELOC_ABS32;
306 *piaddend += uint32_t(OldRelocation.r_addend);
307 break;
308
309 case R_X86_64_PC32: // 32 bit, self-relative
310 // See COFF2ELF.cpp for an explanation of the difference between
311 // COFF and ELF relative relocation methods
312 *piaddend += uint32_t(OldRelocation.r_addend);
313 if (*piaddend >= -8 && *piaddend <= -4) {
314 NewRelocation.Type = (uint16_t)(COFF64_RELOC_REL32 - *piaddend - 4);
315 *piaddend = 0;
316 }
317 else {
318 NewRelocation.Type = COFF64_RELOC_REL32;
319 *piaddend += 4;
320 }
321 break;
322
323 case R_X86_64_RELATIVE: // Adjust by program base
324 err.submit(2030, OldRelocation.r_type);
325 err.ClearError(2030); // report this error only once
326 NewRelocation.Type = 0;
327 break;
328
329 case R_X86_64_GOT32: case R_X86_64_GLOB_DAT: case R_X86_64_GOTPCREL:
330 // Global offset table
331 err.submit(2042); // cannot convert position-independent code
332 err.ClearError(2042); // report this error only once
333 NewRelocation.Type = 0;
334 break;
335
336 case R_X86_64_PLT32: case R_X86_64_JUMP_SLOT:
337 // procedure linkage table
338 err.submit(2042); // cannot convert import table
339 err.ClearError(2043); // report this error only once
340 NewRelocation.Type = 0;
341 break;
342
343 default: // Unknown or unsupported relocation method
344 err.submit(2030, OldRelocation.r_type);
345 err.ClearError(2030); // report this error only once
346 NewRelocation.Type = 0;
347 break;
348 }
349 }
350
351 // Store relocation entry
352 NewRawData.Push(&NewRelocation, SIZE_SCOFF_Relocation);
353 NewHeader.NRelocations++;
354
355 // Remember that symbol is used
356 if (OldRelocation.r_type) {
357 SymbolsUsed[NewRelocation.SymbolTableIndex]++;
358 }
359
360 } // End of relocations loop
361
362 } // End of if right relocation table
363
364 } // End of search for relocation table
365
366 // Align raw data for next section
367 NewRawData.Align(4);
368
369 // Store section header in file
370 ToFile.Push(&NewHeader, sizeof(NewHeader));
371
372 } // End of if section has program data
373
374 } // End of loop through old sections
375
376 } // End of function MakeSections
377
378
379 // Check for overflow when converting 64 bit symbol value to 32 bits.
380 // Value may be signed or unsigned
SymbolOverflow(uint64_t x)381 static int SymbolOverflow(uint64_t x) {
382 uint32_t Upper = HighDWord(x); // Upper 32 bits of 64 bit value
383 if (Upper == 0xFFFFFFFF) { // Check for signed overflow
384 return int32_t(x) >= 0; // Overflow if not signed
385 }
386 return Upper != 0; // Check for unsigned overflow
387 }
SymbolOverflow(uint32_t x)388 static int SymbolOverflow(uint32_t x) { // Overloaded 32 bit version
389 return 0; // Cannot overflow if already 32 bits
390 }
391
392
393 // MakeSymbolTable(): Convert subfunction to make symbol table and string tables
394 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
MakeSymbolTable()395 void CELF2COF<ELFSTRUCTURES>::MakeSymbolTable() {
396 uint32_t oldsec; // Section number in old file
397 TELF_SectionHeader OldHeader; // Old section header
398 int FoundSymTab = 0; // Found symbol table
399 char * strtab; // Old symbol string table
400 int8_t * symtab; // Old symbol table
401 uint32_t symtabsize; // Size of old symbol table
402 uint32_t stringtabsize; // Size of old string table
403 int8_t * symtabend; // End of old symbol table
404 uint32_t entrysize; // Size of each entry in old symbol table
405 uint32_t OldSymI; // Symbol index in old symbol table
406 uint32_t NewSymI = 0; // Symbol index in new symbol table
407 const char * symname = 0; // Symbol name
408 TELF_Symbol OldSym; // Old symbol table record
409 SCOFF_SymTableEntry NewSym; // New symbol table record
410 SCOFF_SymTableEntry AuxSym; // Auxiliary symbol table entry
411 uint32_t numaux; // Number of auxiliary records for new entry
412
413 // Initialize new string table. make space for 4-bytes size
414 NewStringTable.Push(0, 4);
415
416 // Loop through old sections to find symbol table
417 for (oldsec = 0; oldsec < this->NSections; oldsec++) {
418
419 // Search for program data sections only
420 if (this->SectionHeaders[oldsec].sh_type == SHT_SYMTAB
421 || this->SectionHeaders[oldsec].sh_type==SHT_DYNSYM) {
422 FoundSymTab++; numaux = 0;
423
424 // Copy symbol table header for convenience
425 OldHeader = this->SectionHeaders[oldsec];
426
427 // Find associated string table
428 if (OldHeader.sh_link >= this->NSections) {err.submit(2035); OldHeader.sh_link = 0;}
429 strtab = (char*)this->Buf() + uint32_t(this->SectionHeaders[OldHeader.sh_link].sh_offset);
430 stringtabsize = uint32_t(this->SectionHeaders[OldHeader.sh_link].sh_size);
431
432
433 // Find old symbol table
434 entrysize = uint32_t(OldHeader.sh_entsize);
435 if (entrysize < sizeof(TELF_Symbol)) {err.submit(2033); entrysize = sizeof(TELF_Symbol);}
436
437 symtab = this->Buf() + uint32_t(OldHeader.sh_offset);
438 symtabsize = uint32_t(OldHeader.sh_size);
439 symtabend = symtab + symtabsize;
440
441 // Loop through old symbol table
442 for (OldSymI = 0; symtab < symtabend; symtab += entrysize, OldSymI++) {
443
444 // Copy old symbol table entry
445 OldSym = *(TELF_Symbol*)symtab;
446
447 // Reset new symbol table entry
448 memset(&NewSym, 0, sizeof(NewSym));
449
450 // New symbol index
451 NewSymI = NewSymbolTable.GetNumEntries();
452
453 // Symbol type
454 int type = OldSym.st_type;
455
456 // Symbol storage class = binding
457 int binding = OldSym.st_bind;
458
459 // Get symbol name
460 if (OldSym.st_name < stringtabsize) {
461 symname = strtab + OldSym.st_name;
462
463 if (symname && *symname && type != STT_FILE) {
464 // Symbol has a name that we want to store
465 COFF_PutNameInSymbolTable(NewSym, symname, NewStringTable);
466 }
467 }
468 else { // points outside string table
469 err.submit(2112); continue;
470 }
471
472 // Value
473 NewSym.s.Value = uint32_t(OldSym.st_value);
474 // Check for overflow if converting 64 bit symbol value to 32 bits
475 if (SymbolOverflow(OldSym.st_value)) err.submit(2020, symname);
476
477 // Section
478 if (OldSym.st_shndx == SHN_UNDEF) {
479 NewSym.s.SectionNumber = COFF_SECTION_UNDEF; // External
480 }
481 else if ((int16_t)(OldSym.st_shndx) == SHN_ABS) {
482 NewSym.s.SectionNumber = COFF_SECTION_ABSOLUTE; // Absolute symbol
483 }
484 else if (OldSym.st_shndx >= this->NSections) {
485 err.submit(2036, OldSym.st_shndx); // Special/unknown section index or out of range
486 }
487 else {
488 // Normal section index.
489 // Look up in section index translation table and add 1 because it is 1-based
490 NewSym.s.SectionNumber = (int16_t)(NewSectIndex[OldSym.st_shndx] + 1);
491 }
492
493 // Convert binding/storage class
494 switch (binding) {
495 case STB_LOCAL:
496 NewSym.s.StorageClass = COFF_CLASS_STATIC; break;
497
498 case STB_GLOBAL:
499 NewSym.s.StorageClass = COFF_CLASS_EXTERNAL; break;
500
501 case STB_WEAK:
502 err.submit(1051, symname); // Weak public symbol not supported
503 NewSym.s.StorageClass = COFF_CLASS_WEAK_EXTERNAL; break;
504
505 default:
506 err.submit(2037, binding); // Other. Not supported
507 }
508
509 // Make record depending on type
510 switch (type) {
511 case STT_OBJECT: case STT_NOTYPE:
512 // Data object
513 NewSym.s.Type = COFF_TYPE_NOT_FUNCTION;
514 if (OldSymI > 0) { // First symbol entry in ELF file is unused
515 NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
516 }
517 break;
518
519 case STT_GNU_IFUNC:
520 err.submit(1063); // Warning: Gnu indirect function cannot be converted
521 // continue in next case:
522 case STT_FUNC:
523 // Function
524 NewSym.s.Type = COFF_TYPE_FUNCTION;
525 NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
526 // Aux records needed only if debug information included
527 break;
528
529 case STT_FILE: {
530 // File name record
531 memset(&NewSym, 0, sizeof(NewSym));
532 strcpy(NewSym.s.Name, ".file");
533 NewSym.s.StorageClass = COFF_CLASS_FILE;
534 NewSym.s.SectionNumber = COFF_SECTION_DEBUG;
535 // Remove path from file name
536 const char * shortname = symname;
537 uint32_t len = (uint32_t)strlen(symname);
538 if (len > 1) {
539 // Scan backwards for last '/'
540 for (int scan = len-2; scan >= 0; scan--) {
541 if (symname[scan] == '/' || symname[scan] == '\\') {
542 // Path found. Short name starts after this character
543 shortname = symname + scan + 1;
544 break;
545 }
546 }
547 }
548 len = (uint32_t)strlen(shortname);
549 if (len > 35) len = 35; // arbitrary limit to file name length
550
551 // Number of auxiliary records for storing file name
552 numaux = (len + SIZE_SCOFF_SymTableEntry - 1) / SIZE_SCOFF_SymTableEntry;
553 NewSym.s.NumAuxSymbols = (uint8_t)numaux;
554 // Store regular record
555 NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
556 // Store numaux auxiliary records for file name
557 for (uint32_t i = 0; i < numaux; i++) { // Can't push all in one operation because NumEntries will be wrong
558 NewSymbolTable.Push(0, SIZE_SCOFF_SymTableEntry);
559 }
560 // copy name into NewSymbolTable aux records
561 int8_t * PointAux = NewSymbolTable.Buf() + NewSymbolTable.GetDataSize();
562 memcpy(PointAux - numaux*SIZE_SCOFF_SymTableEntry, shortname, len);
563 break;}
564
565 case STT_SECTION: {
566 // Section name record
567 NewSym.s.Value = 0;
568 NewSym.s.Type = 0;
569 NewSym.s.StorageClass = COFF_CLASS_STATIC;
570 NewSym.s.NumAuxSymbols = (uint8_t)(numaux = 1);
571
572 // Find corresponding section header
573 TELF_SectionHeader * OldSecHdr = 0;
574 if (OldSym.st_shndx < this->NSections) {
575 OldSecHdr = &(this->SectionHeaders[OldSym.st_shndx]);
576
577 // Find section name
578 char * sname;
579 if (OldSecHdr->sh_name < this->SecStringTableLen) {
580 sname = this->SecStringTable + OldSecHdr->sh_name;
581 // Put into symbol table
582 COFF_PutNameInSymbolTable(NewSym, sname, NewStringTable);
583 }
584 }
585
586 // Store regular record
587 NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);
588
589 // Make auxiliary record
590 memset(&AuxSym, 0, sizeof(AuxSym));
591 if (OldSecHdr) {
592 AuxSym.section.Length = uint32_t(OldSecHdr->sh_size);
593 // Find corresponding relocation section header
594 // Assume that relocation section comes immediately after section record
595 if ((uint32_t)OldSym.st_shndx + 1 < this->NSections // if not last section
596 && (OldSecHdr[1].sh_type == SHT_REL || OldSecHdr[1].sh_type == SHT_RELA) // and if next section is relocation
597 && OldSecHdr[1].sh_info == OldSym.st_shndx // and if next section refers to current section
598 && OldSecHdr[1].sh_entsize > 0) { // Avoid division by 0
599 // Calculate number of relocations
600 AuxSym.section.NumberOfRelocations = (uint16_t)(uint32_t(OldSecHdr[1].sh_size) / uint32_t(OldSecHdr[1].sh_entsize));
601 }
602 }
603 // Store auxiliary record
604 NewSymbolTable.Push(&AuxSym, SIZE_SCOFF_SymTableEntry);
605 break;}
606
607 case STT_COMMON:
608 default:
609 err.submit(2038, type); // Symbol type not supported
610 }
611
612 if (FoundSymTab == 1) {
613 // Make translation table from old symbol index to new symbol index,
614 // assuming there is only one symbol table.
615 // Make sure all old symbols have an entry in the NewSymbolIndex table,
616 // even if they are discarded.
617 NewSymbolIndex.Push(NewSymI);
618 }
619 } // End OldSymI loop
620 }
621 } // End search for symbol table
622 if (FoundSymTab == 0) err.submit(2034); // Symbol table not found
623 if (FoundSymTab > 1) err.submit(1032); // More than one symbol table found
624
625 // Allocate space for SymbolsUsed table
626 SymbolsUsed.SetNum(NewSymI+1);
627 SymbolsUsed.SetZero(); // Initialize
628 }
629
630
631 // HideUnusedSymbols(): Hide unused symbols if stripping debug info or exception info
632 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
HideUnusedSymbols()633 void CELF2COF<ELFSTRUCTURES>::HideUnusedSymbols() {
634
635 if (cmd.DebugInfo != CMDL_DEBUG_STRIP && cmd.ExeptionInfo != CMDL_EXCEPTION_STRIP) {
636 // No sections removed. Do nothing
637 return;
638 }
639
640 // Pointer to new symbol table
641 union {
642 SCOFF_SymTableEntry * p; // Symtab entry pointer
643 int8_t * b; // Used for increment
644 } NewSymtab;
645 NewSymtab.b = NewSymbolTable.Buf();
646 int numaux = 0, isym;
647 int NumberOfSymbols = NewSymbolTable.GetNumEntries();
648
649 // Loop through new symbol table
650 for (isym = 0; isym < NumberOfSymbols; isym += numaux+1, NewSymtab.b += SIZE_SCOFF_SymTableEntry*(numaux+1)) {
651
652 // Number of auxiliary records belonging to same symbol
653 numaux = NewSymtab.p->s.NumAuxSymbols; if (numaux < 0) numaux = 0;
654
655 if (NewSymtab.p->s.StorageClass == COFF_CLASS_EXTERNAL
656 || NewSymtab.p->s.StorageClass == COFF_CLASS_WEAK_EXTERNAL) {
657 if (NewSymtab.p->s.SectionNumber == COFF_SECTION_UNDEF) {
658 // External symbol. Check if it is used
659 if (!SymbolsUsed[isym]) {
660 // Symbol is unused. Hide it to prevent linking errors
661 NewSymtab.p->s.StorageClass = COFF_CLASS_NULL;
662 NewSymtab.p->s.SectionNumber = COFF_SECTION_UNDEF;
663 NewSymtab.p->s.Type = COFF_TYPE_NOT_FUNCTION;
664 cmd.CountSymbolsHidden();
665 }
666 }
667 }
668 }
669 }
670
671 // MakeBinaryFile(): Convert subfunction to put all sections together
672 template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
MakeBinaryFile()673 void CELF2COF<ELFSTRUCTURES>::MakeBinaryFile() {
674
675 // Insert string table size
676 //NewStringTable.Get<uint32_t>(0) = NewStringTable.GetDataSize();
677 // Some compilers fail with the double template here. Avoid the template:
678 *(uint32_t*)(NewStringTable.Buf()) = NewStringTable.GetDataSize();
679
680 // Update file header
681 NewFileHeader.NumberOfSections = (uint16_t)NumSectionsNew;
682 NewFileHeader.PSymbolTable = RawDataOffset + NewRawData.GetDataSize();
683 NewFileHeader.NumberOfSymbols = NewSymbolTable.GetNumEntries();
684
685 // Replace file header in new file with updated version
686 memcpy(ToFile.Buf(), &NewFileHeader, sizeof(NewFileHeader));
687
688 // Section headers have already been inserted.
689 // Insert raw data in file
690 ToFile.Push(NewRawData.Buf(), NewRawData.GetDataSize());
691
692 // Insert symbol table
693 ToFile.Push(NewSymbolTable.Buf(), NewSymbolTable.GetDataSize());
694
695 // Insert string table
696 ToFile.Push(NewStringTable.Buf(), NewStringTable.GetDataSize());
697 }
698
699
700 // Make template instances for 32 and 64 bits
701 template class CELF2COF<ELF32STRUCTURES>;
702 template class CELF2COF<ELF64STRUCTURES>;
703