Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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>
  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>
  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>
  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)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>
  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 oldsec;                     // Section number in old file
  76.    uint32 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 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>
  128. void CELF2COF<ELFSTRUCTURES>::MakeSections() {
  129.    uint32 oldsec;                   // Section number in old file
  130.    uint32 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 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(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)(OldHeader.sh_offset), (uint32)(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(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 * reltab = this->Buf() + uint32(OldRelHeader.sh_offset);
  203.                int8 * reltabend = reltab + uint32(OldRelHeader.sh_size);
  204.  
  205.                // Get entry size
  206.                int entrysize = uint32(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 InlinePosition = (uint32)(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 * piaddend = (int32*)(NewRawData.Buf() + InlinePosition);
  234.  
  235.                   // Symbol offset
  236.                   NewRelocation.VirtualAddress = uint32(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(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(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*)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(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(OldRelocation.r_addend);
  313.                         if (*piaddend >= -8 && *piaddend <= -4) {
  314.                            NewRelocation.Type = (uint16)(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
  381. static int SymbolOverflow(uint64 x) {
  382.    uint32 Upper = HighDWord(x);        // Upper 32 bits of 64 bit value
  383.    if (Upper == 0xFFFFFFFF) {          // Check for signed overflow
  384.       return int32(x) >= 0;            // Overflow if not signed
  385.    }
  386.    return Upper != 0;                  // Check for unsigned overflow
  387. }
  388. static int SymbolOverflow(uint32 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>
  395. void CELF2COF<ELFSTRUCTURES>::MakeSymbolTable() {
  396.    uint32 oldsec;                      // Section number in old file
  397.    TELF_SectionHeader OldHeader;           // Old section header
  398.    int FoundSymTab = 0;                // Found symbol table
  399.    int8 * strtab;                      // Old symbol string table
  400.    int8 * symtab;                      // Old symbol table
  401.    uint32 symtabsize;                  // Size of old symbol table
  402.    uint32 stringtabsize;               // Size of old string table
  403.    int8 * symtabend;                   // End of old symbol table
  404.    uint32 entrysize;                   // Size of each entry in old symbol table
  405.    uint32 OldSymI;                     // Symbol index in old symbol table
  406.    uint32 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 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 = this->Buf() + uint32(this->SectionHeaders[OldHeader.sh_link].sh_offset);
  430.          stringtabsize = uint32(this->SectionHeaders[OldHeader.sh_link].sh_size);
  431.            
  432.  
  433.          // Find old symbol table
  434.          entrysize = uint32(OldHeader.sh_entsize);
  435.          if (entrysize < sizeof(TELF_Symbol)) {err.submit(2033); entrysize = sizeof(TELF_Symbol);}
  436.  
  437.          symtab = this->Buf() + uint32(OldHeader.sh_offset);
  438.          symtabsize = uint32(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(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)(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)(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 len = (uint32)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)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)numaux;
  554.                // Store regular record
  555.                NewSymbolTable.Push(&NewSym, SIZE_SCOFF_SymTableEntry);              
  556.                // Store numaux auxiliary records for file name
  557.                for (uint32 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 * 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)(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(OldSecHdr->sh_size);
  593.                   // Find corresponding relocation section header
  594.                   // Assume that relocation section comes immediately after section record
  595.                   if ((uint32)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)(uint32(OldSecHdr[1].sh_size) / uint32(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>
  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 * 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>
  673. void CELF2COF<ELFSTRUCTURES>::MakeBinaryFile() {
  674.  
  675.    // Insert string table size
  676.    //NewStringTable.Get<uint32>(0) = NewStringTable.GetDataSize();
  677.    // Some compilers fail with the double template here. Avoid the template:
  678.    *(uint32*)(NewStringTable.Buf()) = NewStringTable.GetDataSize();
  679.  
  680.    // Update file header
  681.    NewFileHeader.NumberOfSections = (uint16)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.