//
// 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,