//                                                                           

//  Copyright (c) 1998, 1999, 2000, 2001, 2002, Intel Corporation            

//  All rights reserved.                                                     

//                                                                           

//  WARRANTY DISCLAIMER                                                      

//                                                                           

//  THESE MATERIALS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   

//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT        

//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR    

//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS      

//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,    

//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,      

//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR       

//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY      

//  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING   

//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THESE      

//  MATERIALS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.            

//                                                                           

//  Intel Corporation is the author of the Materials, and requests that all  

//  problem reports or change requests be submitted to it directly at        

//  http:                                                                   //developer.intel.com/opensource.                                   

//                                                                           

//

//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------

//

#include "pe32.h"

#include <sys/types.h>

#include <time.h>

#include "endianess.h"

//  a structure that is used to hold all available sections and sort them

//  by virtual address                                                    

struct sec_vlist {

    PE32_section_object *sec;

    PE32_vaddr vaddr;

};

struct sg_vlist {

    PE32_secgrp_object *sg;

    PE32_vaddr vaddr;

};

static FUNC mfl_err PE32_write_pe_file_header (PE32_file_object *fod);

#ifdef PECOFF32_EM

static FUNC mfl_err PE32_64_write_pe_file_header (PE32_file_object *fod);

#endif

static FUNC mfl_err PE32_prepare_PE32_sections_and_write (PE32_file_object *fod);

static FUNC mfl_err PE32_write_one_coff_sec_content (PE32_file_object *pfobj,

                                                PE32_section_object *psecobj);

static FUNC mfl_err PE32_write_pe_sections (PE32_file_object *fod);

static FUNC mfl_err PE32_write_pe_section_header

    (PE32_file_object *fod, struct sg_vlist *secl);

static FUNC mfl_err PE32_write_internal_hdr (PE32_file_object *fod,

                                             int internal, ULONG charac,

                                             PE32_offset *file_ptr);

static FUNC mfl_err PE32_write_pe_section_content

    (PE32_file_object *fod, struct sg_vlist *secl);

static FUNC mfl_err PE32_write_basereloc (PE32_file_object *fod,

                                          struct sg_vlist *secl);

static FUNC mfl_err PE32_write_export_symbols (PE32_file_object *fod);

static FUNC mfl_err PE32_write_import_symbols (PE32_file_object *fod);

static FUNC mfl_err PE32_write_file_pad_align (PE32_file_object *fod,

                                               PE32_offset *file_ptr,

                                               PE32_align align);

static FUNC mfl_err PE32_write_file_pad_offset (PE32_file_object *fod,

                                                PE32_offset file_ptr,

                                                PE32_offset offset);

static FUNC mfl_err PE32_open_for_write (PE32_file_object *fod, mfl_str name);

static FUNC mfl_err PE32_calculate_image_size (PE32_file_object *pfobj);

static FUNC mfl_err PE32_prepare_coff_file_for_write (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_file_header (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_sec_header (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_sec_content (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_symtab_strtab (PE32_file_object *pfobj);

//---------------------------------------------------------------------------

// -                         PE32_write_file                                  -

// -                                                                          -

// - Write function for pe32 files                                            -

// ---------------------------------------------------------------------------

FUNC mfl_err PE32_write_file (mfl_str name, mfl_od od)

{

    mfl_err error;

    PE32_file_object *fod;

    mfl_file_type file_type;

    fod = (PE32_file_object *)od;

    if ((error = PE32_open_for_write (fod, name)) != MFL_OK)

      return error;

    if (fod->mflfh.name != NULL)

        mfl_free (fod->mflfh.name);

    if ((fod->mflfh.name = mfl_malloc(strlen(name) +1)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    strcpy(fod->mflfh.name, name);

    if ((error = PE32_get_file_type(od,MFL_PROP_FILE_TYPE,NULL,&file_type)) != MFL_OK)

        return error;

    if (file_type == MFL_FILE_TYPE_DYN_EXEC || file_type == MFL_FILE_TYPE_SHARED)

    {

        if ((error = PE32_prepare_PE32_sections_and_write(fod)) != MFL_OK)

           return error;

        //

//        if ((error = PE32_write_pe_file_header (fod)) != MFL_OK)

//            return error;

//

//        if ((error = PE32_prepare_section_for_write(fod)) != MFL_OK) {

//            return error;

//        }

//

//        if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

//            return error;

//        }

//

//        if ((error = PE32_write_pe_sections (fod)) != MFL_OK)

//           return error;

//        

        if ((error = PE32_write_coff_symtab_strtab(fod)) != MFL_OK)

           return error;

     }

     else

     {

        //  Write Coff OMF file (relocatble files only )

        if (file_type == MFL_FILE_TYPE_RELOC)

        {

            if ((error = PE32_prepare_coff_file_for_write(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_file_header(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_sec_header(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_sec_content(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_symtab_strtab(fod)) != MFL_OK)

               return error;

        }

        else

          //  In the case of non support write file type

          return MFL_ERR_INV_FILE_TYPE;

     }

    return MFL_OK;

}

static FUNC int cmpvv (const void *v1, const void *v2)

{

    return ((struct sec_vlist *)v1)->vaddr - ((struct sec_vlist *)v2)->vaddr;

}

//-----------------------------------------------------------------------------

// -                      PE32_prepare_PE32_sections_and_write                  -

// - Prepare the PE32 file for writing and calculate the total size of the file

// - and the final place of all the tables (relocation tables symbol table and

// - string table).  Very similar to the PE32_prepare_coff_file_for_write.

// - The only difference is that the sections are sorted by their virtual addr,

// - and the section size is put into Ish->Misc.VirtualSize field of the section.

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_prepare_PE32_sections_and_write (PE32_file_object *pfobj)

{

    mfl_err              error;

    mfl_32size           file_size, sec_size, aligned_sec_size;

    PE32_section_object  *psecobj;

    struct sec_vlist *scl;

    unsigned int i, sec_ind, sec_num, total_num_sec;

    //  create new COFF string table

    if ((error = PE32_strtab_init(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build Coff symbol table and string table

    if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

        return error;

    }

    //  build the sections list

    sec_num = 0;

    total_num_sec = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

        total_num_sec++;

        if (PE32_is_sec_mem_expand(psecobj) == FALSE)

            sec_num++;

        else

            //  In the case of .bss section

            psecobj->Ish->PointerToRawData = 0;

     }

    sec_size = 0;

    file_size = pfobj->doshdr.e_lfanew +

                sizeof(pfobj->nthdr.Signature) +

                sizeof(IMAGE_FILE_HEADER) +

                pfobj->nthdr.FileHeader.SizeOfOptionalHeader;

    pfobj->nthdr.FileHeader.NumberOfSections = total_num_sec;

    file_size += total_num_sec * IMAGE_SIZEOF_SECTION_HEADER;

  if (sec_num > 0)

   {

    if ((scl = mfl_malloc(sec_num * sizeof(struct sec_vlist))) == NULL) {

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    }

    sec_ind = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

        if (PE32_is_sec_mem_expand(psecobj) == FALSE) {

            scl[sec_ind].sec = psecobj;

            scl[sec_ind].vaddr = PE32_section_vaddr(psecobj);

            sec_ind++;

        }

     }

    qsort(scl, sec_num, sizeof(struct sec_vlist), cmpvv);

    for (i=0; i< sec_num; i++)

     {

      psecobj = scl[i].sec;

      psecobj->Ish->PointerToRawData = file_size;

      file_size += PE32_section_size(psecobj);

      // In sco the section get virtualAddress is the place of the section

//        in the file.

      if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

      aligned_sec_size = (PE32_section_size(psecobj) +

                          PE32_section_alignment(psecobj) - 1) &

                        ~(PE32_section_alignment(psecobj) - 1);

      psecobj->Ish->Misc.VirtualSize = PE32_section_size(psecobj);

      sec_size += PE32_section_size(psecobj);

      //  Transfer MOFL relocation table to COFF table and update the

      //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

      if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

          pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                    pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

      //  Prepare for lineinfo

      if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

      }

      if (psecobj->Ish->NumberOfLinenumbers > 0)

       {

        psecobj->Ish->PointerToLinenumbers = file_size;

        file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

       }

      else

       {

        psecobj->Ish->PointerToLinenumbers = 0;

       }

     }

   }

    //  compute data offset for the remaining sections

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

      if (PE32_is_sec_mem_expand(psecobj) == FALSE)

        continue;

      psecobj->Ish->PointerToRawData = file_size;

      file_size += PE32_section_size(psecobj);

      // In sco the section get virtualAddress is the place of the section

//        in the file.

      if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

      aligned_sec_size = (PE32_section_size(psecobj) +

                          PE32_section_alignment(psecobj) - 1) &

                        ~(PE32_section_alignment(psecobj) - 1);

      psecobj->Ish->Misc.VirtualSize = PE32_section_size(psecobj);

      sec_size += PE32_section_size(psecobj);

      //  Transfer MOFL relocation table to COFF table and update the

      //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

      if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

          pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                        pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

      //  Prepare for lineinfo

      if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

      }

      if (psecobj->Ish->NumberOfLinenumbers > 0)

       {

        psecobj->Ish->PointerToLinenumbers = file_size;

        file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

       }

      else

       {

        psecobj->Ish->PointerToLinenumbers = 0;

       }

     }

    //  Update the Value field of all the define symbol in any section

    if ((error = PE32_update_coff_symbol(pfobj)) != MFL_OK) {

        return error;

    }

    pfobj->nthdr.FileHeader.PointerToSymbolTable = file_size;

    file_size += pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL;

    file_size += pfobj->str_size;

    //  write the file

    //  first, the header

    if ((error = PE32_write_pe_file_header (pfobj)) != MFL_OK)

        return error;

    //  now, write the section headers

    if ((error = PE32_write_coff_sec_header(pfobj)) != MFL_OK)

       return error;

    //  write the sections themselves

    for (i=0; i< sec_num; i++)

     {

      psecobj = scl[i].sec;

      if ((error = PE32_write_one_coff_sec_content(pfobj, psecobj)) != MFL_OK)

        return error;

     }

    //  write the remaining sections

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

      if (PE32_is_sec_mem_expand(psecobj) == FALSE)

        continue;

      if ((error = PE32_write_one_coff_sec_content(pfobj, psecobj)) != MFL_OK)

        return error;

     }

    if (scl)

     {

        mfl_free(scl);

        scl = 0;

     }

    return MFL_OK;

}

//-------------------------------------------------------------------------------------

// -                          PE32_prepare_coff_file_for_write                          -

// - Prepare the Coff file for writing and calculate the total size of the file and the -

// - final place of all the tables (relocation tables symbol table and string table ).  -

// -------------------------------------------------------------------------------------

static FUNC mfl_err PE32_prepare_coff_file_for_write (PE32_file_object *pfobj)

{

    mfl_err              error;

    mfl_32size           file_size, sec_size;

    PE32_section_object  *psecobj;

    //  create new COFF string table

    if ((error = PE32_strtab_init(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build the Coff section list

    if ((error = PE32_prepare_section_for_write(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build Coff symbol table and string table

    if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

        return error;

    }

    //  Find the file size and the symbol table place

    file_size = IMAGE_SIZEOF_FILE_HEADER;

    file_size += pfobj->nthdr.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;

    sec_size = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END) {

        if (PE32_is_sec_mem_expand(psecobj) == FALSE) {

            psecobj->Ish->PointerToRawData = file_size;

            file_size += PE32_section_size(psecobj);

        } else {

            //  In the case of .bss section

            psecobj->Ish->PointerToRawData = 0;

        }

        //  In sco the section get virtualAddress is the place of the section in the file.

        if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

        psecobj->Ish->Misc.VirtualSize = 0;

#if 0

        psecobj->Ish->Misc.PhysicalAddress = sec_size;

#endif                                                                      //  0

        sec_size += PE32_section_size(psecobj);

        //  Transfer MOFL relocation table to COFF table and update the

        //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

        if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

            pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                        pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

    //  In the GNT architecture the section raw content should come in one piece.

    //  Set the pointer of the relocation table in the output file.

    if (mfl_od_omf(pfobj) != MFL_OMF_GNT32)

     {

      mfl_rel_num num_of_relocs = psecobj->relocations_num;

      if (num_of_relocs > 0)

       {

        psecobj->Ish->PointerToRelocations = file_size;

        file_size += num_of_relocs * IMAGE_SIZEOF_RELOCATION;

        if (num_of_relocs > USHRT_MAX)

         {

          //  too much relocations? For Microsoft formats the number of relocs

          //  is written as the 1st relocation, see winnt.h, line 3931

          file_size += IMAGE_SIZEOF_RELOCATION;

         }

       }

      else

       {

        psecobj->Ish->PointerToRelocations = 0;

       }

     }

        //  Prepare for lineinfo

        if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

        }

        if (psecobj->Ish->NumberOfLinenumbers > 0) {

            psecobj->Ish->PointerToLinenumbers = file_size;

            file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

        } else {

            psecobj->Ish->PointerToLinenumbers = 0;

        }

    }

    //  In the GNT architecture the section raw content should come in one piece.

    //  Set the pointer of the relocation table in the output file.

    if (mfl_od_omf(pfobj) == MFL_OMF_GNT32) {

        psecobj = MFL_OD_FIRST;

        while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

            if (psecobj->Ish->NumberOfRelocations > 0) {

                psecobj->Ish->PointerToRelocations = file_size;

                file_size += psecobj->Ish->NumberOfRelocations * IMAGE_SIZEOF_RELOCATION;

            } else {

                psecobj->Ish->PointerToRelocations = 0;

            }

        }

    }

    //  Update the Value field of all the define symbol in any section

    if ((error = PE32_update_coff_symbol(pfobj)) != MFL_OK) {

        return error;

    }

    pfobj->nthdr.FileHeader.PointerToSymbolTable = file_size;

    file_size += pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL;

    file_size += pfobj->str_size;

    return MFL_OK;

}

//-----------------------------------------------------------------------------

// -                      PE32_write_coff_file_header                           -

// -                                                                            -

// - Write the COFF file header.                                                -

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_file_header (PE32_file_object *pfobj)

{

    mfl_err error;

#ifdef PECOFF32_EM

    if (mfl_od_omf(pfobj) == MFL_OMF_PE3264 ||

        (mfl_od_omf(pfobj) == MFL_OMF_COFF32 &&

         pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432 &&

         (pfobj->nthdr.FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)))

     {

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_32BIT_MACHINE;

      pfobj->nthdr.FileHeader.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;

      pfobj->nthdr.FileHeader.TimeDateStamp = time (NULL);

     }

    else

     {

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_32BIT_MACHINE;

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;

      pfobj->nthdr.FileHeader.TimeDateStamp = time (NULL);

     }

     if (mfl_od_omf(pfobj) == MFL_OMF_COFF32)

     {

        pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;

     }

#endif                                                                      //  PECOFF32_EM

    PE32_swap_filehdr(&pfobj->nthdr.FileHeader);

    //  Write the COFF file header

    if ((error = mfl_write(&pfobj->nthdr.FileHeader, IMAGE_SIZEOF_FILE_HEADER, (mfl_file_obj *)pfobj)) != MFL_OK) {

        return error;

    }

    //  Restore file header

    PE32_swap_filehdr(&pfobj->nthdr.FileHeader);

    return MFL_OK;

}

//-----------------------------------------------------------------------------

// -                      PE32_write_coff_sec_header                            -

// -                                                                            -

// - Write Coff section header table                                            -

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_sec_header (PE32_file_object *pfobj)

{

    mfl_err             error;

    PE32_section_object *psecobj;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

        if (IMAGE_SCN_CNT_CODE & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &=

                ~(IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA);

            psecobj->Ish->Characteristics |= (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);

        } else if (IMAGE_SCN_CNT_INITIALIZED_DATA & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;

        } else if ((IMAGE_SCN_CNT_UNINITIALIZED_DATA & psecobj->Ish->Characteristics) == 0) {

            if (IMAGE_SCN_MEM_EXECUTE & psecobj->Ish->Characteristics) {

                psecobj->Ish->Characteristics |= IMAGE_SCN_CNT_CODE;

            } else if (IMAGE_SCN_MEM_READ & psecobj->Ish->Characteristics) {

                psecobj->Ish->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;

            }

        }

#ifdef DUMMY_CODE

        //  Copied from PE32_set_sec_rt_attr()

        if (IMAGE_SCN_MEM_EXECUTE & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA;

        } else if (IMAGE_SCN_MEM_READ & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_CODE;

        }

#endif                                                                      //  DUMMY_CODE

    if (psecobj->relocations_num > USHRT_MAX)

     {//  too much relocations

      psecobj->Ish->Characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL;

      psecobj->Ish->NumberOfRelocations = USHRT_MAX;

     }

        PE32_swap_shdr(psecobj->Ish);

        if ((error = mfl_write(psecobj->Ish, IMAGE_SIZEOF_SECTION_HEADER, (mfl_file_obj *)pfobj)) != MFL_OK) {

            return error;

        }

        //  Restore section header

        PE32_swap_shdr(psecobj->Ish);

    }

    return MFL_OK;

}

//-------------------------------------------------------------------------------

// -                     PE32_write_one_sec_content                               -

// -                                                                              -

// - Write Coff section's raw content and the section's relocation table.         -

// - Before the writing check if the calculation process is correct.              -

// ------------------------------------------------------------------------------

static FUNC mfl_err PE32_write_one_coff_sec_content (PE32_file_object *pfobj,

                                                PE32_section_object *psecobj)

{

 mfl_err            error;

 mfl_file_off       foff;

 mfl_rel_num        num_of_relocs;

 IMAGE_RELOCATION   first_reloc;

  //  Write the section raw content if for non .bss section

  if (PE32_is_sec_mem_expand(psecobj) == FALSE)

   {

    //  Check that the file calculation is correct

    if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

            return error;

    if (foff != psecobj->Ish->PointerToRawData)

            return MFL_ERR_INTERNAL;

    if ((error = mfl_write(psecobj->content, PE32_section_size(psecobj),

                            (mfl_file_obj *)pfobj)) != MFL_OK)

            return error;

   }

  //  In the GNT architecture the section raw content should come in one piece.

  if (mfl_od_omf(pfobj) != MFL_OMF_GNT32)

   {

    //  write the section relocation table if exist

    num_of_relocs = psecobj->relocations_num;

    if (num_of_relocs > 0)

     {

      //  Check that the file calculation is correct

      if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

                return error;

      if (foff != psecobj->Ish->PointerToRelocations)

                return MFL_ERR_INTERNAL;

      if (num_of_relocs > USHRT_MAX)

       {

        //  too much relocations? For Microsoft formats the number of relocs

        //  is written as the 1st relocation, see winnt.h, line 3931

        first_reloc.VirtualAddress = num_of_relocs;

        first_reloc.SymbolTableIndex = 0;

        first_reloc.Type = 0;

        if ((error = mfl_write(&first_reloc,

                               IMAGE_SIZEOF_RELOCATION,

                               (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

       }

      if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION))

       {

        if ((error = mfl_write(psecobj->prblock,

                               (mfl_32size)num_of_relocs *

                                    IMAGE_SIZEOF_RELOCATION,

                               (mfl_file_obj *)pfobj)) != MFL_OK)

                    return error;

       }

      else

       {

        WORD i;

        for (i = 0; i < num_of_relocs; ++i)

         {

          if ((error = mfl_write(psecobj->prblock + i,

                                 IMAGE_SIZEOF_RELOCATION,

                                 (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

         }

       }

     }

   }

  //  Write lineinfo if exist

  if (psecobj->Ish->NumberOfLinenumbers > 0)

   {

    //  Check that the file calculation is correct

    if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

            return error;

    if (foff != psecobj->Ish->PointerToLinenumbers)

            return MFL_ERR_INTERNAL;

    if ((error = mfl_write(psecobj->lineinfo,

                           (mfl_32size)psecobj->Ish->NumberOfLinenumbers *

                                IMAGE_SIZEOF_LINENUMBER,

                           (mfl_file_obj *)pfobj)) != MFL_OK)

            return error;

   }

    //  In the GNT architecture the section raw content should come in one piece.

    if (mfl_od_omf(pfobj) == MFL_OMF_GNT32) {

        psecobj = MFL_OD_FIRST;

        while ((psecobj = hash_get_next(pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

            //  write the section relocation table if exist

            if (psecobj->Ish->NumberOfRelocations > 0) {

                //  Check that the file calculation is correct

                if ((error = mfl_tell((mfl_file_obj *)pfobj,&foff)) != MFL_OK) {

                    return error;

                }

                if (foff != psecobj->Ish->PointerToRelocations) {

                    return MFL_ERR_INTERNAL;

                }

                if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION)) {

                    if ((error = mfl_write(psecobj->prblock,

                                           (mfl_32size)psecobj->Ish->NumberOfRelocations * IMAGE_SIZEOF_RELOCATION,