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