Subversion Repositories Kolibri OS

Rev

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

  1. /****************************  cof2elf.cpp   ********************************
  2. * Author:        Agner Fog
  3. * Date created:  2006-07-20
  4. * Last modified: 2008-05-22
  5. * Project:       objconv
  6. * Module:        cof2elf.cpp
  7. * Description:
  8. * Module for converting PE/COFF file to ELF file
  9. *
  10. * Copyright 2006-2008 GNU General Public License http://www.gnu.org/licenses
  11. *****************************************************************************/
  12. #include "stdafx.h"
  13.  
  14.  
  15. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  16. CCOF2ELF<ELFSTRUCTURES>::CCOF2ELF () {
  17.    // Constructor
  18.    memset(this, 0, sizeof(*this));
  19. }
  20.  
  21.  
  22. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  23. void CCOF2ELF<ELFSTRUCTURES>::Convert() {
  24.    // Do the conversion
  25.    NumSectionsNew = 5;                                    // Number of sections generated so far
  26.  
  27.    // Allocate variable size buffers
  28.    MaxSectionsNew    = NumSectionsNew + 2 * NSections;    // Max number of sections needed
  29.    NewSections.SetNum(MaxSectionsNew);                    // Allocate buffers for each section
  30.    NewSections.SetZero();                                 // Initialize
  31.    NewSectionHeaders.SetNum(MaxSectionsNew);              // Allocate array for temporary section headers
  32.    NewSectionHeaders.SetZero();                           // Initialize
  33.    NewSectIndex.SetNum(NSections);                        // Array for translating old section index (0-based) to new section index
  34.    NewSectIndex.SetZero();                                // Initialize
  35.    NewSymbolIndex.SetNum(NumberOfSymbols);                // Array of new symbol indices
  36.    NewSymbolIndex.SetZero();                              // Initialize
  37.  
  38.    // Call the subfunctions
  39.    ToFile.SetFileType(FILETYPE_ELF);   // Set type of to file
  40.    MakeSegments();                     // Make segment headers and code/data segments
  41.    MakeSymbolTable();                  // Symbol table and string tables
  42.    MakeRelocationTables();             // Relocation tables
  43.    MakeBinaryFile();                   // Putting sections together
  44.    *this << ToFile;                    // Take over new file buffer
  45. }
  46.  
  47.  
  48. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  49. void CCOF2ELF<ELFSTRUCTURES>::MakeSegments() {
  50.    // Convert subfunction: Make segment headers and code/data segments
  51.    TELF_SectionHeader NewSecHeader;    // New section header
  52.    int oldsec;                         // Section index in old file
  53.    int newsec;                         // Section index in new file
  54.    uint32 SecNameIndex;                // Section name index into shstrtab
  55.    char const * SecName;               // Name of new section
  56.    const int WordSize = sizeof(NewFileHeader.e_entry) * 8; // word size 32 or 64 bits
  57.  
  58.    // Special segment names
  59.    static const char * SpecialSegmentNames[] = {
  60.       "Null", ".symtab", ".shstrtab", ".strtab", ".stabstr"
  61.    };
  62.    // Indexes to these are:
  63.    symtab      = 1;               // Symbol table section number
  64.    shstrtab    = 2;               // Section name string table section number
  65.    strtab      = 3;               // Object name string table section number
  66.    stabstr     = 4;               // Debug string table section number
  67.  
  68.    // Number of special segments = number of names in SpecialSegmentNames:
  69.    const int NumSpecialSegments = sizeof(SpecialSegmentNames)/sizeof(SpecialSegmentNames[0]);
  70.  
  71.    // Make first section header string table entry empty
  72.    NewSections[shstrtab].PushString("");
  73.  
  74.    // Loop through special sections, except the first Null section:
  75.    for (newsec = 0; newsec < NumSpecialSegments; newsec++) {
  76.       // Put data into new section header:
  77.       // Initialize to zero
  78.       memset(&NewSecHeader, 0, sizeof(NewSecHeader));
  79.  
  80.       if (newsec > 0) {
  81.          // Put name into section header string table
  82.          SecName = SpecialSegmentNames[newsec];
  83.          SecNameIndex = NewSections[shstrtab].PushString(SecName);
  84.  
  85.          // Put name into new section header
  86.          NewSecHeader.sh_name = SecNameIndex;
  87.       }
  88.  
  89.       // Put section header into temporary buffer
  90.       NewSectionHeaders[newsec] = NewSecHeader;
  91.    }
  92.  
  93.    // Put type, flags, etc. into special segments:
  94.    NewSectionHeaders[symtab]  .sh_type  = SHT_SYMTAB;
  95.    NewSectionHeaders[symtab]  .sh_entsize = sizeof(TELF_Symbol);
  96.    NewSectionHeaders[symtab]  .sh_link  = strtab;
  97.    NewSectionHeaders[shstrtab].sh_type  = SHT_STRTAB;
  98.    NewSectionHeaders[shstrtab].sh_flags = SHF_STRINGS;
  99.    NewSectionHeaders[shstrtab].sh_addralign = 1;
  100.    NewSectionHeaders[strtab]  .sh_type  = SHT_STRTAB;
  101.    NewSectionHeaders[strtab]  .sh_flags = SHF_STRINGS;
  102.    NewSectionHeaders[strtab]  .sh_addralign = 1;
  103.    NewSectionHeaders[stabstr] .sh_type  = SHT_STRTAB;
  104.    NewSectionHeaders[stabstr] .sh_flags = SHF_STRINGS;
  105.    NewSectionHeaders[stabstr] .sh_addralign = 1;
  106.  
  107.    if (newsec != NumSectionsNew) {
  108.       // Check my program for internal consistency
  109.       // If you get this error then change the value of NumSectionsNew in
  110.       // the constructor CCOF2ELF::CCOF2ELF to equal the number of entries in
  111.       // SpecialSegmentNames, including the Null segment
  112.       err.submit(9000);
  113.    }
  114.  
  115.    // Loop through source file sections
  116.    for (oldsec = 0; oldsec < this->NSections; oldsec++) {
  117.  
  118.       // Pointer to old section header
  119.       SCOFF_SectionHeader * SectionHeader = &this->SectionHeaders[oldsec];
  120.  
  121.       // Get section name
  122.       SecName = this->GetSectionName(SectionHeader->Name);
  123.       if (strnicmp(SecName,"debug",5) == 0 || strnicmp(SecName+1,"debug",5) == 0) {
  124.          // This is a debug section
  125.          if (cmd.DebugInfo == CMDL_DEBUG_STRIP) {
  126.             // Remove debug info
  127.             NewSectIndex[oldsec] = COFF_SECTION_REMOVE_ME;  // Remember that this section is removed
  128.             cmd.CountDebugRemoved();
  129.             continue;
  130.          }
  131.          else if (cmd.InputType != cmd.OutputType) {
  132.             err.submit(1029); // Warn that debug information is incompatible
  133.          }
  134.       }
  135.       if (strnicmp(SecName,".drectve",8) == 0 || (SectionHeader->Flags & (PE_SCN_LNK_INFO | PE_SCN_LNK_REMOVE))) {
  136.          // This is a directive section
  137.          if (cmd.ExeptionInfo) {
  138.             // Remove directive section
  139.             NewSectIndex[oldsec] = COFF_SECTION_REMOVE_ME;  // Remember that this section is removed
  140.             cmd.CountExceptionRemoved();
  141.             continue;
  142.          }
  143.       }
  144.       if (strnicmp(SecName,".pdata", 6) == 0) {
  145.          // This section has exception information
  146.          if (cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
  147.             // Remove exception info
  148.             NewSectIndex[oldsec] = COFF_SECTION_REMOVE_ME;  // Remember that this section is removed
  149.             cmd.CountExceptionRemoved();
  150.             continue;
  151.          }
  152.          else if (cmd.InputType != cmd.OutputType) {
  153.             err.submit(1030); // Warn that exception information is incompatible
  154.          }
  155.       }
  156.      
  157.       if (strnicmp(SecName,".cormeta", 8) == 0) {
  158.          // This is a .NET Common Language Runtime section
  159.          err.submit(2014);
  160.       }
  161.       if (strnicmp(SecName,".rsrc", 5) == 0) {
  162.          // This section has Windows resource information
  163.          err.submit(1031);
  164.       }
  165.  
  166.       // Store section index in index translation table (zero-based index)
  167.       NewSectIndex[oldsec] = newsec;
  168.  
  169.       // Store section data
  170.       if (SectionHeader->SizeOfRawData > 0) {
  171.          NewSections[newsec].Push(Buf()+SectionHeader->PRawData, SectionHeader->SizeOfRawData);
  172.       }
  173.  
  174.       // Put data into new section header:
  175.       // Initialize to zero
  176.       memset(&NewSecHeader, 0, sizeof(NewSecHeader));
  177.  
  178.       // Section type
  179.       if (!(SectionHeader->Flags & PE_SCN_LNK_REMOVE)) {
  180.          NewSecHeader.sh_type = SHT_PROGBITS;  // Program code or data
  181.          NewSecHeader.sh_flags |= SHF_ALLOC;   // Occupies memory during execution
  182.       }
  183.       if (SectionHeader->Flags & PE_SCN_CNT_UNINIT_DATA) {
  184.          NewSecHeader.sh_type = SHT_NOBITS;    // BSS
  185.       }
  186.  
  187.       // Section flags
  188.       if (SectionHeader->Flags & PE_SCN_MEM_WRITE) {
  189.          NewSecHeader.sh_flags |= SHF_WRITE;
  190.       }
  191.       if (SectionHeader->Flags & PE_SCN_MEM_EXECUTE) {
  192.          NewSecHeader.sh_flags |= SHF_EXECINSTR;
  193.       }
  194.  
  195.       // Check for special sections
  196.       if (strcmp(SecName, COFF_CONSTRUCTOR_NAME)==0) {
  197.          // Constructors segment
  198.          SecName = ELF_CONSTRUCTOR_NAME;
  199.          NewSecHeader.sh_flags = SHF_WRITE | SHF_ALLOC;
  200.       }
  201.  
  202.       // Put name into section header string table
  203.       SecNameIndex = NewSections[shstrtab].PushString(SecName);
  204.  
  205.       // Put name into new section header
  206.       NewSecHeader.sh_name = SecNameIndex;
  207.  
  208.       // Section virtual memory address
  209.       NewSecHeader.sh_addr = SectionHeader->VirtualAddress;
  210.  
  211.       // Section size in memory
  212.       NewSecHeader.sh_size = SectionHeader->VirtualSize;
  213.  
  214.       // Section alignment
  215.       if (SectionHeader->Flags & PE_SCN_ALIGN_MASK) {
  216.          NewSecHeader.sh_addralign = uint32(1 << (((SectionHeader->Flags & PE_SCN_ALIGN_MASK) / PE_SCN_ALIGN_1) - 1));
  217.       }
  218.  
  219.       // Put section header into temporary buffer
  220.       NewSectionHeaders[newsec] = NewSecHeader;
  221.  
  222.       // Increment section number
  223.       newsec++;
  224.  
  225.       if (SectionHeader->NRelocations > 0) {
  226.          // Source section has relocations.
  227.          // Make a relocation section in destination file
  228.  
  229.          // Put data into relocation section header:
  230.          // Initialize to zero
  231.          memset(&NewSecHeader, 0, sizeof(NewSecHeader));
  232.  
  233.          // Name for relocation section = ".rel" or ".rela" + name of section
  234.          const int MAXSECTIONNAMELENGTH = 256;
  235.          char RelocationSectionName[MAXSECTIONNAMELENGTH] = ".rel";
  236.          if (WordSize == 64) strcat(RelocationSectionName, "a"); // 32-bit: .rel, 64-bit: .rela
  237.  
  238.          strncat(RelocationSectionName, SecName, MAXSECTIONNAMELENGTH-5);
  239.          RelocationSectionName[MAXSECTIONNAMELENGTH-1] = 0;
  240.  
  241.          // Put name into section header string table
  242.          uint32 SecNameIndex = NewSections[shstrtab].PushString(RelocationSectionName);
  243.  
  244.          // Put name into new section header
  245.          NewSecHeader.sh_name = SecNameIndex;
  246.  
  247.          // Section type
  248.          NewSecHeader.sh_type = (WordSize == 32) ? SHT_REL : SHT_RELA;  // Relocation section
  249.  
  250.          // Put section header into temporary buffer
  251.          NewSectionHeaders[newsec] = NewSecHeader;
  252.  
  253.          // Increment section number
  254.          newsec++;
  255.       }
  256.    }
  257.    // Number of sections generated
  258.    NumSectionsNew = newsec;
  259. }
  260.  
  261.  
  262. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  263. void CCOF2ELF<ELFSTRUCTURES>::MakeSymbolTable() {
  264.    // Convert subfunction: Make symbol table and string tables
  265.    int isym;                           // current symbol table entry
  266.    int numaux;                         // Number of auxiliary entries in source record
  267.    int OldSectionIndex;                // Index into old section table. 1-based
  268.    int NewSectionIndex;                // Index into new section table. 0-based
  269.    //const int WordSize = sizeof(NewFileHeader.e_entry) * 8; // word size 32 or 64 bits
  270.  
  271.    TELF_Symbol sym;                    // Temporary symbol table record
  272.    const char * name1;                 // Name of section or main record
  273.  
  274.    // Pointer to old symbol table
  275.    union {
  276.       SCOFF_SymTableEntry * p;         // Symtab entry pointer
  277.       int8 * b;                        // Used for increment
  278.    } OldSymtab;
  279.  
  280.    // Make the first record empty
  281.    NewSections[symtab].Push(0, sizeof(TELF_Symbol));
  282.  
  283.    // Make first string table entries empty
  284.    NewSections[strtab] .PushString("");
  285.    NewSections[stabstr].PushString("");
  286.  
  287.    // Loop twice through source symbol table to get local symbols first, global symbols last
  288.    // Loop 1: Look for local symbols only
  289.    OldSymtab.p = SymbolTable; // Pointer to source symbol table
  290.    for (isym = 0; isym < this->NumberOfSymbols; isym += numaux+1, OldSymtab.b += SIZE_SCOFF_SymTableEntry*(numaux+1)) {
  291.  
  292.       if (OldSymtab.b >= Buf() + DataSize) {
  293.          err.submit(2040);
  294.          break;
  295.       }
  296.  
  297.       // Number of auxiliary records belonging to same symbol
  298.       numaux = OldSymtab.p->s.NumAuxSymbols;  if (numaux < 0) numaux = 0;
  299.  
  300.       if (OldSymtab.p->s.StorageClass != COFF_CLASS_EXTERNAL && OldSymtab.p->s.StorageClass != COFF_CLASS_WEAK_EXTERNAL) {
  301.          // Symbol is local
  302.  
  303.          // Reset destination entry
  304.          memset(&sym, 0, sizeof(sym));
  305.  
  306.          // Binding
  307.          sym.st_bind = STB_LOCAL;
  308.  
  309.          // Get first aux record if numaux > 0
  310.          //SCOFF_SymTableEntryAux * sa = (SCOFF_SymTableEntryAux *)(OldSymtab.b + SIZE_SCOFF_SymTableEntry);
  311.  
  312.          // Symbol name
  313.          name1 = this->GetSymbolName(OldSymtab.p->s.Name);
  314.  
  315.          // Symbol value
  316.          sym.st_value = OldSymtab.p->s.Value;
  317.  
  318.          // Get section
  319.          OldSectionIndex = OldSymtab.p->s.SectionNumber;  // 1-based index into old section table
  320.          NewSectionIndex = 0;                 // 0-based index into old section table
  321.          if (OldSectionIndex > 0 && OldSectionIndex <= this->NSections) {
  322.             // Subtract 1 from OldSectionIndex because NewSectIndex[] is zero-based while OldSectionIndex is 1-based
  323.             // Get new section index from translation table
  324.             NewSectionIndex = NewSectIndex[OldSectionIndex-1];
  325.          }
  326.          if (NewSectionIndex == COFF_SECTION_REMOVE_ME) {
  327.             continue; // Section has been removed. Remove symbol too
  328.          }
  329.  
  330.          sym.st_shndx = (uint16)NewSectionIndex;
  331.  
  332.          // Check symbol type
  333.          if (OldSymtab.p->s.StorageClass == COFF_CLASS_FILE) {
  334.             // This is a filename record
  335.             if (numaux > 0 && numaux < 20) {
  336.                // Get filename from subsequent Aux records.
  337.                // Remove path from filename because the path makes no sense on a different platform.
  338.                const char * filename = GetShortFileName(OldSymtab.p);
  339.                // Put file name into string table and debug string table
  340.                sym.st_name = NewSections[strtab].PushString(filename);
  341.                NewSections[stabstr].PushString(filename);
  342.             }
  343.             // Attributes for filename record
  344.             sym.st_shndx  = (uint16)SHN_ABS;
  345.             sym.st_type   = STT_FILE;
  346.             sym.st_bind   = STB_LOCAL;
  347.             sym.st_value  = 0;
  348.          }
  349.          else if (numaux && OldSymtab.p->s.StorageClass == COFF_CLASS_STATIC
  350.          && OldSymtab.p->s.Value == 0 && OldSymtab.p->s.Type != 0x20) {
  351.             // This is a section definition record
  352.             sym.st_name  = 0;  name1 = 0;
  353.             sym.st_type  = STT_SECTION;
  354.             sym.st_bind  = STB_LOCAL;
  355.             sym.st_value = 0;
  356.             // aux record contains length and number of relocations. Ignore aux record
  357.          }
  358.          else if (OldSymtab.p->s.SectionNumber < 0) {
  359.             // This is an absolute or debug symbol
  360.             sym.st_type  = STT_NOTYPE;
  361.             sym.st_shndx = (uint16)SHN_ABS;
  362.          }
  363.          else if (OldSymtab.p->s.Type == 0 && OldSymtab.p->s.StorageClass == COFF_CLASS_FUNCTION) {
  364.             // This is a .bf, .lf, or .ef record following a function record
  365.             // Contains line number information etc. Ignore this record
  366.             continue;
  367.          }
  368.          else if (OldSymtab.p->s.SectionNumber <= 0) {
  369.             // Unknown
  370.             sym.st_type = STT_NOTYPE;
  371.          }
  372.          else {
  373.             // This is a local data definition record
  374.             sym.st_type = STT_OBJECT;
  375.             // The size is not specified in COFF record,
  376.             // so we may give it an arbitrary size:
  377.             // sym.size = 4;
  378.          }
  379.  
  380.          // Put symbol name into string table if we have not already done so
  381.          if (sym.st_name == 0 && name1) {
  382.             sym.st_name = NewSections[strtab].PushString(name1);
  383.          }
  384.  
  385.          // Put record into new symbol table
  386.          NewSections[symtab].Push(&sym, sizeof(sym));
  387.  
  388.          // Insert into symbol translation table
  389.          NewSymbolIndex[isym] = NewSections[symtab].GetLastIndex();
  390.  
  391.       } // End if not external
  392.    }  // End loop 1
  393.  
  394.    // Finished with local symbols
  395.    // Make index to first global symbol
  396.    NewSectionHeaders[symtab].sh_info = NewSections[symtab].GetLastIndex() + 1;
  397.  
  398.    // Loop 2: Look for global symbols only
  399.    OldSymtab.p = SymbolTable; // Pointer to source symbol table
  400.    for (isym = 0; isym < NumberOfSymbols; isym += numaux+1, OldSymtab.b += SIZE_SCOFF_SymTableEntry*(numaux+1)) {
  401.  
  402.       // Number of auxiliary records belonging to same symbol
  403.       numaux = OldSymtab.p->s.NumAuxSymbols;  if (numaux < 0) numaux = 0;
  404.  
  405.       if (OldSymtab.p->s.StorageClass == COFF_CLASS_EXTERNAL || OldSymtab.p->s.StorageClass == COFF_CLASS_WEAK_EXTERNAL) {
  406.          // Symbol is global (public or external)
  407.  
  408.          // Reset destination entry
  409.          memset(&sym, 0, sizeof(sym));
  410.  
  411.          // Binding
  412.          sym.st_bind = STB_GLOBAL;
  413.          if (OldSymtab.p->s.StorageClass == COFF_CLASS_WEAK_EXTERNAL) sym.st_bind = STB_WEAK;
  414.  
  415.          // Get first aux record if numaux > 0
  416.          SCOFF_SymTableEntry * sa = (SCOFF_SymTableEntry*)(OldSymtab.b + SIZE_SCOFF_SymTableEntry);
  417.  
  418.          // Symbol name
  419.          name1 = GetSymbolName(OldSymtab.p->s.Name);
  420.  
  421.          // Symbol value
  422.          sym.st_value = OldSymtab.p->s.Value;
  423.  
  424.          // Get section
  425.          OldSectionIndex = OldSymtab.p->s.SectionNumber; // 1-based index into old section table
  426.          NewSectionIndex = 0;                          // 0-based index into old section table
  427.          if (OldSectionIndex > 0 && OldSectionIndex <= NSections) {
  428.             // Subtract 1 from OldSectionIndex because NewSectIndex[] is zero-based while OldSectionIndex is 1-based
  429.             // Get new section index from translation table
  430.             NewSectionIndex = NewSectIndex[OldSectionIndex-1];
  431.          }
  432.          if (NewSectionIndex == COFF_SECTION_REMOVE_ME) {
  433.             continue; // Section has been removed. Remove symbol too
  434.          }
  435.          if ((int16)OldSectionIndex == COFF_SECTION_ABSOLUTE) {
  436.             NewSectionIndex = SHN_ABS;
  437.          }
  438.  
  439.          sym.st_shndx = (uint16)NewSectionIndex;
  440.  
  441.          // Check symbol type
  442.          if (OldSymtab.p->s.SectionNumber < 0) {
  443.             // This is an absolute or debug symbol
  444.             sym.st_type = STT_NOTYPE;
  445.          }
  446.          else if (OldSymtab.p->s.Type == COFF_TYPE_FUNCTION && OldSymtab.p->s.SectionNumber > 0) {
  447.             // This is a function definition record
  448.             sym.st_type = STT_FUNC;
  449.             if (numaux) {
  450.                // Get size from aux record
  451.                sym.st_size = sa->func.TotalSize;
  452.             }
  453.             if (sym.st_size == 0) {
  454.                // The size is not specified in the COFF file.
  455.                // We may give it an arbitrary size:
  456.                // sym.size = 1;
  457.             }
  458.          }
  459.          else if (OldSymtab.p->s.SectionNumber <= 0) {
  460.             // This is an external symbol
  461.             sym.st_type = STT_NOTYPE;
  462.          }
  463.          else {
  464.             // This is a data definition record
  465.             sym.st_type = STT_OBJECT;
  466.             // Symbol must have a size. The size is not specified in COFF record,
  467.             // so we just give it an arbitrary size
  468.             sym.st_size = 4;
  469.          }
  470.  
  471.          // Put symbol name into string table if we have not already done so
  472.          if (sym.st_name == 0 && name1) {
  473.             sym.st_name = NewSections[strtab].PushString(name1);
  474.          }
  475.  
  476.          // Put record into new symbol table
  477.          NewSections[symtab].Push(&sym, sizeof(sym));
  478.  
  479.          // Insert into symbol translation table
  480.          NewSymbolIndex[isym] = NewSections[symtab].GetLastIndex();
  481.  
  482.       } // End if external
  483.    }  // End loop 2
  484. }
  485.  
  486.  
  487. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  488. void CCOF2ELF<ELFSTRUCTURES>::MakeRelocationTables() {
  489.    // Convert subfunction: Relocation tables
  490.    int32 oldsec;                                 // Relocated section number in source file
  491.    int32 newsec;                                 // Relocated section number in destination file
  492.    int32 newsecr;                                // Relocation table section number in destination file
  493.    TELF_SectionHeader * NewRelTableSecHeader;    // Section header for new relocation table
  494.    char TempText[32];                            // Temporary text buffer
  495.    const int WordSize = sizeof(NewFileHeader.e_entry) * 8; // word size 32 or 64 bits
  496.  
  497.    // Loop through source file sections
  498.    for (oldsec = 0; oldsec < NSections; oldsec++) {
  499.  
  500.       // New section index
  501.       newsec = NewSectIndex[oldsec];
  502.       if (newsec == COFF_SECTION_REMOVE_ME) {
  503.          continue;   // This is a debug or exception handler section which has been removed
  504.       }
  505.  
  506.       // Pointer to old section header
  507.       SCOFF_SectionHeader * SectionHeader = &this->SectionHeaders[oldsec];
  508.  
  509.       if (SectionHeader->NRelocations > 0) {
  510.          // This section has relocations
  511.  
  512.          // Finc new relocation table section
  513.          newsecr = newsec + 1;
  514.  
  515.          // Check that we have allocated a relocation section
  516.          if (oldsec+1 < this->NSections && NewSectIndex[oldsec+1] == newsecr) err.submit(9000);
  517.          if (newsecr >= NumSectionsNew) err.submit(9000);
  518.  
  519.          // New relocation table section header
  520.          NewRelTableSecHeader = &NewSectionHeaders[newsecr];
  521.  
  522.          // Insert header info
  523.          NewRelTableSecHeader->sh_type  = (WordSize == 32) ? SHT_REL : SHT_RELA;
  524.          NewRelTableSecHeader->sh_flags = 0;
  525.          NewRelTableSecHeader->sh_addralign = WordSize / 8; // Alignment
  526.          NewRelTableSecHeader->sh_link = symtab; // Point to symbol table
  527.          NewRelTableSecHeader->sh_info = newsec; // Point to relocated section
  528.          // Entry size:
  529.          NewRelTableSecHeader->sh_entsize = (WordSize == 32) ? sizeof(Elf32_Rel) : sizeof(Elf64_Rela);
  530.  
  531.          // Pointer to old relocation entry
  532.          union {
  533.             SCOFF_Relocation * p;  // pointer to record
  534.             int8 * b;              // used for address calculation and incrementing
  535.          } OldReloc;
  536.  
  537.          // Loop through relocations
  538.  
  539.          OldReloc.b = Buf() + SectionHeader->PRelocations;
  540.          for (int i = 0; i < SectionHeader->NRelocations; i++, OldReloc.b += SIZE_SCOFF_Relocation) {
  541.  
  542.             // Make new relocation entry and set to zero
  543.             TELF_Relocation NewRelocEntry;
  544.             memset(&NewRelocEntry, 0, sizeof(NewRelocEntry));
  545.  
  546.             // Section offset of relocated address
  547.             NewRelocEntry.r_offset = OldReloc.p->VirtualAddress;
  548.  
  549.             // Target symbol
  550.             uint32 TargetSymbol = OldReloc.p->SymbolTableIndex;
  551.             if (TargetSymbol >= (uint32)NumberOfSymbols) {
  552.                err.submit(2031);  // Symbol not in table
  553.             }
  554.             else {  // Translate symbol number
  555.                NewRelocEntry.r_sym = NewSymbolIndex[TargetSymbol];
  556.             }
  557.  
  558.             if (WordSize == 32) {
  559.                // Interpret 32-bit COFF relocation types
  560.                switch (OldReloc.p->Type) {
  561.                case COFF32_RELOC_ABS:     // Ignored
  562.                   NewRelocEntry.r_type = R_386_NONE;  break;
  563.  
  564.                case COFF32_RELOC_TOKEN:   // .NET common language runtime token
  565.                   err.submit(2014);       // Error message
  566.                   // Continue in next case and insert absolute address as token:
  567.                case COFF32_RELOC_DIR32:   // 32-bit absolute virtual address
  568.                   NewRelocEntry.r_type = R_386_32;  break;
  569.  
  570.                case COFF32_RELOC_IMGREL:  // 32-bit image relative address
  571.                   // Image-relative relocation not supported in ELF
  572.                   if (cmd.OutputType == FILETYPE_MACHO_LE) {
  573.                      // Intermediate during conversion to MachO
  574.                      NewRelocEntry.r_type = R_UNSUPPORTED_IMAGEREL;
  575.                      break;
  576.                   }
  577.                   // Work-around unsupported image-relative relocation
  578.                   // Convert to absolute
  579.                   NewRelocEntry.r_type = R_386_32; // Absolute relocation
  580.                   if (cmd.ImageBase == 0) {
  581.                      // Default image base for 32-bit Linux
  582.                      cmd.ImageBase = 0x8048000; // 0x400000 ?
  583.                   }
  584.                   NewRelocEntry.r_addend -= cmd.ImageBase;
  585.                   // Warn that image base must be set to the specified value
  586.                   sprintf(TempText, "%X", cmd.ImageBase); // write value as hexadecimal
  587.                   err.submit(1301, TempText);  err.ClearError(1301);
  588.                   break;
  589.  
  590.                case COFF32_RELOC_REL32:   // 32-bit self-relative
  591.                   NewRelocEntry.r_type = R_386_PC32;
  592.                   // Difference between EIP-relative and self-relative relocation = size of address field
  593.                   NewRelocEntry.r_addend = -4;  break;
  594.                   /* !! error  if self-relative relocation with offset
  595.                    !! test data that fails = testpic32.obj */
  596.  
  597.                case COFF32_RELOC_SECTION:   // 16-bit section index in file
  598.                case COFF32_RELOC_SECREL:    // 32-bit section-relative
  599.                case COFF32_RELOC_SECREL7:   //  8-bit section-relative
  600.                   // These fixup types are not supported in ELF files
  601.                   if (cmd.DebugInfo != CMDL_DEBUG_STRIP) {
  602.                      // Issue warning. Ignore if stripping debug info
  603.                      err.submit(1010);
  604.                   }
  605.                   break;
  606.                  
  607.                default:
  608.                   err.submit(2030, OldReloc.p->Type);  break; // Error: Unknown relocation type (%i) ignored
  609.                }
  610.             }
  611.             else {
  612.                // Interpret 64-bit COFF relocation types
  613.                switch (OldReloc.p->Type) {
  614.                case COFF64_RELOC_ABS:        // Ignored
  615.                   NewRelocEntry.r_type = R_X86_64_NONE;  break;
  616.  
  617.                case COFF64_RELOC_TOKEN:      // .NET common language runtime token
  618.                   err.submit(2014);          // Error message
  619.                   // Continue in next case and insert absolute address as token:
  620.  
  621.                case COFF64_RELOC_ABS64:      // 64 bit absolute virtual address
  622.                   NewRelocEntry.r_type = R_X86_64_64;  break;
  623.  
  624.                case COFF64_RELOC_PPC_TOKEN:
  625.                   err.submit(2014);          // Error message
  626.                   // Continue in next case and insert absolute address as token:
  627.  
  628.                case COFF64_RELOC_ABS32:      // 32 bit absolute address
  629.                   NewRelocEntry.r_type = R_X86_64_32S;  break;
  630.  
  631.                case COFF64_RELOC_IMGREL:     // 32 bit image-relative
  632.                   // Image-relative relocation not supported in ELF
  633.                   if (cmd.OutputType == FILETYPE_MACHO_LE) {
  634.                      // Intermediate during conversion to MachO
  635.                      NewRelocEntry.r_type = R_UNSUPPORTED_IMAGEREL;
  636.                      break;
  637.                   }
  638.                   // Work-around unsupported image-relative relocation
  639.                   // Convert to absolute
  640.                   NewRelocEntry.r_type = R_X86_64_32S; // Absolute 32-bit relocation
  641.                   if (cmd.ImageBase == 0) {
  642.                      // Default image base for 64-bit Linux
  643.                      cmd.ImageBase = 0x400000;
  644.                   }
  645.                   NewRelocEntry.r_addend -= cmd.ImageBase;
  646.                   // Warn that image base must be set to the specified value
  647.                   sprintf(TempText, "%X", cmd.ImageBase); // write value as hexadecimal
  648.                   err.submit(1301, TempText);  err.ClearError(1301);
  649.                   break;
  650.  
  651.                case COFF64_RELOC_REL32:      // 32 bit, RIP-relative
  652.                case COFF64_RELOC_REL32_1:    // 32 bit, relative to RIP - 1. For instruction with immediate byte operand
  653.                case COFF64_RELOC_REL32_2:    // 32 bit, relative to RIP - 2. For instruction with immediate word operand
  654.                case COFF64_RELOC_REL32_3:    // 32 bit, relative to RIP - 3. (useless)
  655.                case COFF64_RELOC_REL32_4:    // 32 bit, relative to RIP - 4. For instruction with immediate dword operand
  656.                case COFF64_RELOC_REL32_5:    // 32 bit, relative to RIP - 5. (useless)
  657.                   NewRelocEntry.r_type = R_X86_64_PC32;
  658.                   // Note:
  659.                   // The microprocessor calculates RIP-relative addresses
  660.                   // relative to the value of the instruction pointer AFTER
  661.                   // the instruction. This is equal to the address of the
  662.                   // relocated field plus the size of the relocated field
  663.                   // itself plus the size of any immediate operand coming
  664.                   // after the relocated field.
  665.                   // The COFF format makes the correction for this offset in
  666.                   // the linker by using a differet relocation type for
  667.                   // immediate operand size = 0, 1, 2 or 4.
  668.                   // The ELF format makes the same correction by an explicit
  669.                   // addend, which is -4, -5, -6 or -8, respectively.
  670.                   // The difference between RIP-relative and self-relative
  671.                   // relocation is equal to the size of the address field plus
  672.                   // the size of any immediate operand:
  673.                   NewRelocEntry.r_addend = -(4 + OldReloc.p->Type - COFF64_RELOC_REL32);                  
  674.                   break;
  675.  
  676.                case COFF64_RELOC_SECTION:   // 16-bit section index in file
  677.                case COFF64_RELOC_SECREL:    // 32-bit section-relative
  678.                case COFF64_RELOC_SECREL7:   //  8-bit section-relative
  679.  
  680.                   // These fixup types are not supported in ELF files
  681.                   if (cmd.DebugInfo != CMDL_DEBUG_STRIP) {
  682.                      // Issue warning. Ignore if stripping debug info
  683.                      err.submit(1010);
  684.                   }
  685.                   break;
  686.  
  687.                default:
  688.                   err.submit(2030, OldReloc.p->Type);  break; // Error: Unknown relocation type (%i) ignored
  689.                }
  690.             }
  691.  
  692.             // Find inline addend
  693.             int32 * paddend = 0;
  694.             if (OldReloc.p->VirtualAddress + 4 > NewSections[newsec].GetDataSize()
  695.                || NewSectionHeaders[newsec].sh_type == SHT_NOBITS) {
  696.                   // Address of relocation is invalid
  697.                   err.submit(2032);
  698.                }
  699.             else {
  700.                // Make pointer to inline addend
  701.                paddend = (int32*)(NewSections[newsec].Buf()
  702.                   + NewSectionHeaders[newsec].sh_offset + OldReloc.p->VirtualAddress);
  703.             }
  704.  
  705.             // Put relocation record into table
  706.             if (WordSize == 32) {
  707.                if (NewRelocEntry.r_addend != 0) {
  708.                   // Use inline addends in 32 bit ELF (SHT_REL)
  709.                   // Put addend inline
  710.                   * paddend += uint32(NewRelocEntry.r_addend);
  711.                   NewRelocEntry.r_addend = 0;
  712.                }
  713.  
  714.                // Save 32-bit relocation record Elf32_Rel, not Elf32_Rela
  715.                if (NewRelocEntry.r_addend) err.submit(9000);
  716.                NewSections[newsecr].Push(&NewRelocEntry, sizeof(Elf32_Rel));
  717.             }
  718.             else {
  719.                // 64 bit
  720.                /*
  721.                if (*paddend != 0) {
  722.                   // Use explicit addend in 64 bit ELF (SHT_RELA)
  723.                   // Explicit addend may cause link error if it appears to point outside section
  724.                   NewRelocEntry.r_addend += *paddend;
  725.                   *paddend = 0;
  726.                }*/
  727.  
  728.                // Save 64-bit relocation record. Must be Elf64_Rela
  729.                NewSections[newsecr].Push(&NewRelocEntry, sizeof(Elf64_Rela));
  730.             }
  731.          }
  732.       }
  733.    }
  734. }
  735.  
  736.  
  737. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  738. void CCOF2ELF<ELFSTRUCTURES>::MakeBinaryFile() {
  739.    // Convert subfunction: Make section headers and file header,
  740.    // and combine everything into a single memory buffer.
  741.    int32  newsec;              // Section index
  742.    uint32 SecOffset;           // Section offset in file
  743.    uint32 SecSize;             // Section size in file
  744.    uint32 SectionHeaderOffset; // File offset to section headers
  745.  
  746.    // Set file type in ToFile
  747.    ToFile.SetFileType(FILETYPE_ELF);
  748.    
  749.    // Make space for file header in ToFile, but don't fill data into it yet
  750.    ToFile.Push(0, sizeof(TELF_Header));
  751.  
  752.    // Loop through new section buffers
  753.    for (newsec = 0; newsec < NumSectionsNew; newsec++) {
  754.  
  755.       // Size of section
  756.       SecSize = NewSections[newsec].GetDataSize();
  757.  
  758.       // Put section into ToFile
  759.       SecOffset = ToFile.Push(NewSections[newsec].Buf(), SecSize);
  760.  
  761.       // Put size and offset into section header
  762.       NewSectionHeaders[newsec].sh_offset = SecOffset;
  763.       NewSectionHeaders[newsec].sh_size   = SecSize;
  764.  
  765.       // Align before next entry
  766.       ToFile.Align(16);
  767.    }
  768.  
  769.    // Start offset of section headers
  770.    SectionHeaderOffset = ToFile.GetDataSize();
  771.  
  772.    // Loop through new section headers
  773.    for (newsec = 0; newsec < NumSectionsNew; newsec++) {
  774.  
  775.       // Put section header into ToFile
  776.       ToFile.Push(&NewSectionHeaders[newsec], sizeof(TELF_SectionHeader));
  777.    }
  778.  
  779.    // Make file header
  780.    TELF_Header FileHeader;
  781.    memset(&FileHeader, 0, sizeof(FileHeader)); // Initialize to 0
  782.  
  783.    // Put file type magic number in
  784.    strcpy((char*)(FileHeader.e_ident), ELFMAG);
  785.    // File class
  786.    FileHeader.e_ident[EI_CLASS] = (WordSize == 32) ? ELFCLASS32 : ELFCLASS64;
  787.    // Data Endian-ness
  788.    FileHeader.e_ident[EI_DATA] = ELFDATA2LSB;
  789.    // ELF version
  790.    FileHeader.e_ident[EI_VERSION] = EV_CURRENT;
  791.    // ABI
  792.    FileHeader.e_ident[EI_OSABI] = ELFOSABI_SYSV;
  793.    // ABI version
  794.    FileHeader.e_ident[EI_ABIVERSION] = 0;
  795.    // File type
  796.    FileHeader.e_type = ET_REL;
  797.    // Machine architecture
  798.    FileHeader.e_machine = (WordSize == 32) ? EM_386 : EM_X86_64;
  799.    // Version
  800.    FileHeader.e_version = EV_CURRENT;
  801.    // Flags
  802.    FileHeader.e_flags = 0;
  803.  
  804.    // Section header table offset
  805.    FileHeader.e_shoff = SectionHeaderOffset;
  806.  
  807.    // File header size
  808.    FileHeader.e_ehsize = sizeof(TELF_Header);
  809.  
  810.    // Section header size
  811.    FileHeader.e_shentsize = sizeof(TELF_SectionHeader);
  812.  
  813.    // Number of section headers
  814.    FileHeader.e_shnum = (uint16)NumSectionsNew;
  815.  
  816.    // Section header string table index
  817.    FileHeader.e_shstrndx = (uint16)shstrtab;
  818.  
  819.    // Put file header into beginning of ToFile where we made space for it
  820.    memcpy(ToFile.Buf(), &FileHeader, sizeof(FileHeader));
  821. }
  822.  
  823.  
  824. // Make template instances for 32 and 64 bits
  825. template class CCOF2ELF<ELF32STRUCTURES>;
  826. template class CCOF2ELF<ELF64STRUCTURES>;
  827.