/* */
/* 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,
(mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
} else {
WORD i;
for (i = 0; i < psecobj->Ish->NumberOfRelocations; ++i) {
if ((error = mfl_write(psecobj->prblock + i, IMAGE_SIZEOF_RELOCATION, (mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
}
}
}
}
}
return MFL_OK;
}
/*********************************************************************************
* PE32_write_coff_sec_content *
* *
* Write Coff sections' raw content and the sections' relocation table. *
* Before the writing check if the calculation process is correct. *
*********************************************************************************/
static FUNC mfl_err PE32_write_coff_sec_content (PE32_file_object *pfobj)
{
mfl_err error;
PE32_section_object *psecobj;
mfl_file_off foff;
mfl_rel_num num_of_relocs;
IMAGE_RELOCATION first_reloc;
psecobj = MFL_OD_FIRST;
while ((psecobj = hash_get_next(pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {
/* 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 architectura the section rawconten shuld 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,
(mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
} else {
WORD i;
for (i = 0; i < psecobj->Ish->NumberOfRelocations; ++i) {
if ((error = mfl_write(psecobj->prblock + i, IMAGE_SIZEOF_RELOCATION, (mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
}
}
}
}
}
return MFL_OK;
}
/***************************************************************************************
* PE32_write_coff_symtab_strtab *
* *
* Write the Coff symbol table and the Coff string table after the symbol table. *
***************************************************************************************/
static FUNC mfl_err PE32_write_coff_symtab_strtab (PE32_file_object *pfobj)
{
mfl_err error;
mfl_file_off foff;
/* Check that the file calculation is correct */
if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK) {
return error;
}
if ((unsigned)pfobj->nthdr.FileHeader.PointerToSymbolTable != foff) {
return MFL_ERR_INTERNAL;
}
/* Write the Coff symbol table */
if (IMAGE_SIZEOF_SYMBOL == sizeof(IMAGE_SYMBOL)) {
if ((error = mfl_write(pfobj->Coffsym,
pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL,
(mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
} else {
DWORD i;
for (i = 0; i < pfobj->nthdr.FileHeader.NumberOfSymbols; ++i) {
if ((error = mfl_write(pfobj->Coffsym + i, IMAGE_SIZEOF_SYMBOL, (mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
}
}
/* Write the Coff string table */
*(UINT *)pfobj->strtab = mfl_endian_select_int(*(UINT *)pfobj->strtab, 0);
if ((error = mfl_write(pfobj->strtab, pfobj->str_size, (mfl_file_obj *)pfobj)) != MFL_OK) {
return error;
}
*(UINT *)pfobj->strtab = mfl_endian_select_int(*(UINT *)pfobj->strtab, 0);
return MFL_OK;
}
#ifdef PECOFF32_EM
/****************************************************************************
* PE32_64_write_pe_file_header *
* *
* Write file headers *
****************************************************************************/
static FUNC mfl_err PE32_64_write_pe_file_header (PE32_file_object *fod)
{
mfl_err error;
if (fod->nthdr.OptionalHeader.pe3264.SectionAlignment < PE32_I386_PAGE_SIZE) {
fod->nthdr.OptionalHeader.pe3264.SectionAlignment = PE32_I386_PAGE_SIZE;
}
if (fod->nthdr.OptionalHeader.pe3264.SectionAlignment >=
((fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE) ||
(fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) ?
PE32_EM_PAGE_SIZE : PE32_I386_PAGE_SIZE)
) {
PE32_file_align(fod) = PE32_SECTOR_SIZE;
} else {
PE32_file_align(fod) = fod->nthdr.OptionalHeader.pe3264.SectionAlignment;
}
if ((error = mfl_write(&fod->doshdr, sizeof(fod->doshdr), (mfl_file_obj *)fod))
!= MFL_OK) {
return error;
}
if ((error = PE32_write_file_pad_offset(fod, sizeof(fod->doshdr), (ULONG)fod->doshdr.e_lfanew)) != MFL_OK) {
return error;
}
fod->nthdr.Signature = IMAGE_NT_SIGNATURE;
fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
fod->nthdr.FileHeader.Characteristics &= ~IMAGE_FILE_32BIT_MACHINE;
fod->nthdr.FileHeader.NumberOfSections = (USHORT)PE32_file_get_sec_num(fod);
fod->nthdr.FileHeader.TimeDateStamp = time (NULL);
fod->nthdr.FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264;
fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_BYTES_REVERSED_LO |
IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED;
/* set the pe header virsions */
fod->nthdr.OptionalHeader.pe3264.Magic = PE3264_NT_HEADER_MAGIC;
fod->nthdr.OptionalHeader.pe3264.MajorLinkerVersion = VER_MAJOR;
fod->nthdr.OptionalHeader.pe3264.MinorLinkerVersion = VER_MINOR;
fod->nthdr.OptionalHeader.pe3264.MajorOperatingSystemVersion = PE32_MAJOR_OS_VERSION;
fod->nthdr.OptionalHeader.pe3264.MinorOperatingSystemVersion = PE32_MINOR_OS_VERSION;
fod->nthdr.OptionalHeader.pe3264.MajorImageVersion = PE32_MAJOR_IMAGE_VERSION;
fod->nthdr.OptionalHeader.pe3264.MinorImageVersion = PE32_MINOR_IMAGE_VERSION;
fod->nthdr.OptionalHeader.pe3264.MajorSubsystemVersion = PE32_MAJOR_SUBSYS_VERSION;
fod->nthdr.OptionalHeader.pe3264.MinorSubsystemVersion = PE32_MINOR_SUBSYS_VERSION;
/* calculate file header size */
/* header size + section header table size */
fod->nthdr.OptionalHeader.pe3264.SizeOfHeaders = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +
sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264 +
sizeof (IMAGE_SECTION_HEADER) * PE32_file_sec_num (fod)
/* aligned to file alignment */
+ PE32_file_align (fod) -1) & ~(PE32_file_align (fod) -1);
PE32_file_get_grouped_size(fod);
/* calculate the image size */
if ((error = PE32_calculate_image_size(fod)) != MFL_OK) {
return error;
}
/* set in the file header table the address and the size of the PE spacial */
/* section like .rsrc , .debug */
if ((error = PE32_set_ft_spacial_sec(fod)) != MFL_OK) {
return error;
}
fod->nthdr.OptionalHeader.pe3264.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
#ifdef BIG_ENDIAN
/* patch the fields */
{IMAGE_NT_HEADERS_PE3264 nt_header;
nt_header = fod->nthdr;
mfl_int_swap((int *)&nt_header.Signature);
PE32_swap_filehdr(&nt_header.FileHeader);
PE32_swap_pehdr(NULL, &nt_header);
error = mfl_write(&nt_header, sizeof(nt_header), (mfl_file_obj *)fod);
/* swap the headers back */
mfl_int_swap((int *)&nt_header.Signature);
PE32_swap_filehdr(&nt_header.FileHeader);
PE32_swap_pehdr(NULL, &nt_header);
}
#else
error = mfl_write(&fod->nthdr, sizeof(fod->nthdr), (mfl_file_obj *)fod);
#endif
if (error == MFL_OK) {
error = PE32_write_file_pad_offset (fod, fod->doshdr.e_lfanew +
sizeof(fod->nthdr),
fod->doshdr.e_lfanew +
sizeof(fod->nthdr.Signature) +
sizeof(IMAGE_FILE_HEADER) +
IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264);
}
return error;
}
#endif /* PECOFF32_EM */
/****************************************************************************
* PE32_write_pe_file_header *
* *
* Write file headers *
****************************************************************************/
static FUNC mfl_err PE32_write_pe_file_header (PE32_file_object *fod)
{
mfl_err error;
#ifdef PECOFF32_EM
if (mfl_od_omf(fod) == MFL_OMF_PE3264)
return PE32_64_write_pe_file_header(fod);
#endif /* PECOFF32_EM */
if (fod->nthdr.OptionalHeader.pe32.SectionAlignment < PE32_SECTOR_SIZE) {
fod->nthdr.OptionalHeader.pe32.SectionAlignment = PE32_SECTOR_SIZE;
}
if (fod->nthdr.OptionalHeader.pe32.SectionAlignment >=
#ifdef PECOFF32_EM
((fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||
fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) ?
PE32_EM_PAGE_SIZE : PE32_I386_PAGE_SIZE)
#else /* PECOFF32_EM */
PE32_I386_PAGE_SIZE
#endif /* PECOFF32_EM */
) {
PE32_file_align(fod) = PE32_SECTOR_SIZE;
} else {
PE32_file_align(fod) = fod->nthdr.OptionalHeader.pe32.SectionAlignment;
}
if ((error = mfl_write(&fod->doshdr, sizeof(fod->doshdr), (mfl_file_obj *)fod)) != MFL_OK) {
return error;
}
if ((error = PE32_write_file_pad_offset(fod, sizeof(fod->doshdr), (ULONG)fod->doshdr.e_lfanew)) != MFL_OK) {
return error;
}
#ifdef PECOFF32_EM
fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
fod->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;
#else /* PECOFF32_EM */
/* fod->nthdr.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; */
fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
#endif /* PECOFF32_EM */
fod->nthdr.FileHeader.NumberOfSections = (USHORT)PE32_file_get_sec_num(fod);
fod->nthdr.FileHeader.TimeDateStamp = time (NULL);
fod->nthdr.FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER;
fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_BYTES_REVERSED_LO |
IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED;
/* set the pe header virsions */
fod->nthdr.OptionalHeader.pe32.Magic = PE32_NT_HEADER_MAGIC;
fod->nthdr.OptionalHeader.pe32.MajorLinkerVersion = VER_MAJOR;
fod->nthdr.OptionalHeader.pe32.MinorLinkerVersion = VER_MINOR;
fod->nthdr.OptionalHeader.pe32.MajorOperatingSystemVersion = PE32_MAJOR_OS_VERSION;
fod->nthdr.OptionalHeader.pe32.MinorOperatingSystemVersion = PE32_MINOR_OS_VERSION;
fod->nthdr.OptionalHeader.pe32.MajorImageVersion = PE32_MAJOR_IMAGE_VERSION;
fod->nthdr.OptionalHeader.pe32.MinorImageVersion = PE32_MINOR_IMAGE_VERSION;
fod->nthdr.OptionalHeader.pe32.MajorSubsystemVersion = PE32_MAJOR_SUBSYS_VERSION;
fod->nthdr.OptionalHeader.pe32.MinorSubsystemVersion = PE32_MINOR_SUBSYS_VERSION;
/* calculate file header size */
/* header size + section header table size */
fod->nthdr.OptionalHeader.pe32.SizeOfHeaders = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +
sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +
sizeof (IMAGE_SECTION_HEADER) * PE32_file_sec_num (fod)
/* aligned to file alignment */
+ PE32_file_align (fod) -1) & ~(PE32_file_align (fod) -1);
PE32_file_get_grouped_size(fod);
/* calculate the image size */
if ((error = PE32_calculate_image_size(fod)) != MFL_OK) {
return error;
}
/* set in the file header table the address and the size of the PE spacial */
/* section like .rsrc , .debug */
if ((error = PE32_set_ft_spacial_sec(fod)) != MFL_OK) {
return error;
}
fod->nthdr.OptionalHeader.pe32.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
/* write only the PE32 header */
#ifdef BIG_ENDIAN
/* patch the fields */
{IMAGE_NT_HEADERS_PE3264 nt_header;
nt_header = fod->nthdr;
mfl_int_swap((int *)&nt_header.Signature);
PE32_swap_filehdr(&nt_header.FileHeader);
PE32_swap_pehdr(NULL, &nt_header);
error = mfl_write(&nt_header, sizeof(nt_header.Signature) +
sizeof(IMAGE_FILE_HEADER),
(mfl_file_obj *)fod);
if (error == MFL_OK)
error = mfl_write(&nt_header.OptionalHeader.pe32,
sizeof(nt_header.OptionalHeader.pe32),
(mfl_file_obj *)fod);
/* swap the headers back */
mfl_int_swap((int *)&nt_header.Signature);
PE32_swap_filehdr(&nt_header.FileHeader);
PE32_swap_pehdr(NULL, &nt_header);
}
#else
error = mfl_write(&fod->nthdr, sizeof(fod->nthdr.Signature) +
sizeof(IMAGE_FILE_HEADER),
(mfl_file_obj *)fod);
if (error == MFL_OK)
error = mfl_write(&fod->nthdr.OptionalHeader.pe32,
sizeof(fod->nthdr.OptionalHeader.pe32),
(mfl_file_obj *)fod);
#endif
if (error == MFL_OK) {
error = PE32_write_file_pad_offset (fod, fod->doshdr.e_lfanew +
sizeof(fod->nthdr.Signature) +
sizeof(IMAGE_FILE_HEADER) +
IMAGE_SIZEOF_NT_OPTIONAL_HEADER,
fod->doshdr.e_lfanew +
sizeof(fod->nthdr.Signature) +
sizeof(IMAGE_FILE_HEADER) +
IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
}
return error;
}
/***************************************************************************/
/* PE32_calculate_image_size */
/* */
/* Calculate the size of the image file that load to the memory in the run */
/* time */
/***************************************************************************/
static FUNC mfl_err PE32_calculate_image_size (PE32_file_object *pfobj)
{
PE32_secgrp_object *psecgobj;
PE32_size image_size = 0;
PE32_size sg_image;
int idx;
/* In the meantime we assume the file doesn't have base relocations */
/* and therefore cannot be relocated at run time */
pfobj->nthdr.FileHeader.Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
for (psecgobj = pfobj->secgrps;
psecgobj != MFL_OD_NULL && psecgobj != MFL_OD_END;
psecgobj = (PE32_secgrp_object *)psecgobj->next) {
/* calculate regular section size */
if (psecgobj->sec != MFL_OD_NULL) {
sg_image = (PE32_section_size(psecgobj->sec) + PE32_section_vaddr(psecgobj->sec) +
PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);
image_size = MAX(image_size, sg_image);
continue;
}
/* calculate import section size */
if ((psecgobj->internal & PE32_SECTION_EXPAND) &&
((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {
idx = image_directory_idx[PE32_INTERNAL_SEC_IMPORT];
sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +
PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);
image_size = MAX(image_size, sg_image);
continue;
}
/* calculate export section size */
if ((psecgobj->internal & PE32_SECTION_EXPAND) &&
((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {
idx = image_directory_idx[PE32_INTERNAL_SEC_EXPORT];
sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +
PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);
image_size = MAX(image_size, sg_image);
continue;
}
/*calculate relocation size */
if ((psecgobj->internal & PE32_SECTION_EXPAND) &&
((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {
idx = image_directory_idx[PE32_INTERNAL_SEC_RELOC];
sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +
PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);
image_size = MAX(image_size, sg_image);
/* The file does have base relocations */
pfobj->nthdr.FileHeader.Characteristics &= ~(ULONG)IMAGE_FILE_RELOCS_STRIPPED;
continue;
}
}
IMAGE_NT_HEADERS_OptionalHeader(pfobj->nthdr, SizeOfImage) = image_size;
return MFL_OK;
}
static FUNC int cmpv (const void *v1, const void *v2)
{
return ((struct sg_vlist *)v1)->vaddr - ((struct sg_vlist *)v2)->vaddr;
}
/****************************************************************************
* PE32_write_pe_sections *
* *
* Write section function *
****************************************************************************/
static FUNC mfl_err PE32_write_pe_sections (PE32_file_object *fod)
{
mfl_err error = MFL_OK;
struct sg_vlist *sgl;
PE32_secgrp_object *sg;
int i;
if ((sgl = mfl_malloc(fod->secgrp_num * sizeof(struct sg_vlist))) == NULL) {
return MFL_ERR_NOT_ENOUGH_MEMORY;
}
for (i=0, sg=fod->secgrps; sg != NULL; i++, sg = (PE32_secgrp_object *)sg->next) {
sgl[i].sg = sg;
if (sg->sec != NULL) {
sgl[i].vaddr = PE32_section_vaddr(sg->sec);
} else if (sg->internal & PE32_SECTION_EXPAND) {
sgl[i].vaddr = PE32_file_dir_vaddr(fod,
image_directory_idx[sg->internal & PE32_INTERNAL_OVRHD_MASK]);
} else {
sgl[i].vaddr = 0;
}
}
qsort(sgl, (unsigned)fod->secgrp_num, sizeof(struct sg_vlist), cmpv);
error = PE32_write_pe_section_header(fod, sgl);
if (error == MFL_OK) {
error = PE32_write_pe_section_content(fod, sgl);
}
mfl_free(sgl);
return error;
}
/****************************************************************************
* PE32_write_pe_section_header *
* *
* Write header for all sections including internal secions. *
****************************************************************************/
static FUNC mfl_err PE32_write_pe_section_header
(PE32_file_object *fod, struct sg_vlist *sgl)
{
PE32_size size;
PE32_offset file_ptr;
int i, j;
mfl_err error = MFL_OK;
#if 0
/* verify that overhead on relocations counted */
if ((fod->ovrhd & PE32_INTERNAL_OVRHD_MASK) == 0)
return MFL_ERR_OVERHD_MIS;
#endif
/* calculate first section file offset */
/* header size + section header table size */
file_ptr = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +
sizeof(IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +
sizeof(IMAGE_SECTION_HEADER) * PE32_file_sec_num(fod) +
/* aligned to file alignment */
+ PE32_file_align(fod) - 1) & ~(PE32_file_align(fod) - 1);
for (i = j = 0; i < fod->secgrp_num; i++) {
/* write regular section header entry */
if (sgl[i].sg->sec != MFL_OD_NULL) {
/* VirtualSize will contain actual section size */
sgl[i].sg->sec->Ish->Misc.VirtualSize = size = PE32_section_size(sgl[i].sg->sec);
if (PE32_is_sec_mem_expand(sgl[i].sg->sec) == FALSE) {
sgl[i].sg->sec->Ish->PointerToRawData = file_ptr;
PE32_section_size(sgl[i].sg->sec) =
(size + PE32_file_align(fod) - 1) & ~(PE32_file_align(fod) - 1);
file_ptr += PE32_section_size(sgl[i].sg->sec);
} else {
/* set zero to the pointer to the raw content*/
/* if it is bss section */
sgl[i].sg->sec->Ish->PointerToRawData = 0;
PE32_section_size(sgl[i].sg->sec) = 0;
}
if ((error = mfl_write (sgl[i].sg->sec->Ish, sizeof(IMAGE_SECTION_HEADER),
(mfl_file_obj *)fod)) != MFL_OK)
{
break;
}
PE32_section_size(sgl[i].sg->sec) = size;
continue;
}
/* write import section header entry */
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {
if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_IMPORT,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ,
&file_ptr)) != MFL_OK)
{
return error;
}
continue;
}
/* write export section header entry */
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {
if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_EXPORT,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
&file_ptr)) != MFL_OK) {
return error;
}
continue;
}
/* relocation section header */
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {
if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_RELOC,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ,
&file_ptr)) != MFL_OK) {
return error;
}
continue;
}
}
/* Write gep of zero show the contenue of the file will be align in */
/* the file alignment */
/* calculate first section file offset */
/* header size + section header table size */
file_ptr = fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +
sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +
sizeof (IMAGE_SECTION_HEADER) * PE32_file_sec_num (fod);
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
return error;
}
/****************************************************************************
* PE32_write_internal_hdr *
* *
* Fill and write internal section header *
****************************************************************************/
static FUNC mfl_err PE32_write_internal_hdr (PE32_file_object *fod,
int internal, ULONG charac,
PE32_offset *file_ptr)
{
IMAGE_SECTION_HEADER sech;
mfl_err error;
int idx;
memset(&sech, 0, sizeof(IMAGE_SECTION_HEADER));
strcpy((mfl_str)sech.Name, str_internal[internal]);
idx = image_directory_idx[internal];
sech.VirtualAddress = PE32_file_dir_vaddr(fod, idx);
sech.Misc.VirtualSize = PE32_file_dir_size(fod, idx);
sech.SizeOfRawData = (PE32_file_dir_size(fod, idx) + PE32_file_align(fod) - 1) &
~(PE32_file_align(fod) - 1);
sech.PointerToRawData = *file_ptr;
sech.Characteristics = charac;
error = mfl_write(&sech, sizeof(IMAGE_SECTION_HEADER), (mfl_file_obj *)fod);
*file_ptr += sech.SizeOfRawData;
return error;
}
/****************************************************************************
* PE32_write_pe_section_content *
* *
* Write in file content of all sections *
****************************************************************************/
static FUNC mfl_err PE32_write_pe_section_content
(PE32_file_object *fod, struct sg_vlist *sgl)
{
int i;
PE32_offset file_ptr, Check_off;
mfl_err error;
/* calculate file offset */
file_ptr = IMAGE_NT_HEADERS_OptionalHeader(fod->nthdr, SizeOfHeaders);
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
for (i = 0; i < fod->secgrp_num; i++) {
Check_off = ftell(fod->mflfh.fhandle);
if (sgl[i].sg->sec != NULL && PE32_is_sec_mem_expand(sgl[i].sg->sec) == FALSE) {
if ((error = mfl_write(sgl[i].sg->sec->content,
sgl[i].sg->sec->Ish->SizeOfRawData,
(mfl_file_obj *)fod)) != MFL_OK) {
break;
}
file_ptr += sgl[i].sg->sec->Ish->SizeOfRawData;
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
continue;
}
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {
if ((error = PE32_write_import_symbols(fod)) != MFL_OK) {
return error;
}
file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_IMPORT);
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
continue;
}
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {
if ((error = PE32_write_export_symbols(fod)) != MFL_OK) {
return error;
}
file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_EXPORT);
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
continue;
}
if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&
((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {
if ((error = PE32_write_basereloc(fod, sgl)) != MFL_OK) {
return error;
}
file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_BASERELOC);
if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {
return error;
}
continue;
}
}
return error;
}
/****************************************************************************
* PE32_write_basereloc *
* *
* Write executable relocataions *
****************************************************************************/
static FUNC mfl_err PE32_write_basereloc (PE32_file_object *fod,
struct sg_vlist *sgl)
{
mfl_err error;
int i, j, nblock;
void *relbuf;
IMAGE_BASE_RELOCATION *block_header;
USHORT *type_offset;
PE32_vaddr addr;
PE32_reloc_object *rod;
PE32_section_object *sec;
mfl_file_off foff;
mfl_tell((mfl_file_obj *)fod,&foff);
if ((relbuf = block_header =
mfl_malloc (PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_BASERELOC)+
sizeof (USHORT))) == NULL)
return MFL_ERR_NOT_ENOUGH_MEMORY;
/* for each section */
for (i=0; i < fod->secgrp_num; i++)
if (sgl[i].sg->sec != NULL) {
sec = sgl[i].sg->sec;
/* get number of 4K blocks */
nblock = (PE32_section_size (sec) + 0xfff) >> 12;
/* for each 4K block */
for (j=0, addr = PE32_section_vaddr(sec); j < nblock;
j++, addr += 0x1000) {
/* if block has relocations */
if (sec->pdir[j].rcnt != 0) {
/* fill block header */
block_header->VirtualAddress = addr;
block_header->SizeOfBlock = sizeof (IMAGE_BASE_RELOCATION) +
sizeof (USHORT) * sec->pdir[j].rcnt;
/* for each relocation in block */
type_offset = (USHORT *)(block_header + 1);
for (rod=(PE32_reloc_object *)sec->pdir[j].rod;
rod != NULL; rod = rod->next, type_offset++)
/* fill type-offset value */
*type_offset = (rod->offset & 0xfff)| (rod->type << 12);
/* pad next entry (maybe last one) */
*type_offset = 0;
/* advance to next block header */
block_header = (IMAGE_BASE_RELOCATION *)((char *)block_header + block_header->SizeOfBlock);
}
}
}
/* write relocations */
error = mfl_write (relbuf,
PE32_file_dir_size(fod,IMAGE_DIRECTORY_ENTRY_BASERELOC),
(mfl_file_obj *)fod);
mfl_tell((mfl_file_obj *)fod,&foff);
mfl_free (relbuf);
return error;
}
/****************************************************************************
* PE32_write_export_symbols *
* *
* Write export symbol table *
****************************************************************************/
static FUNC mfl_err PE32_write_export_symbols (PE32_file_object *fod)
{
mfl_err error;
int i;
void *symbuf;
IMAGE_EXPORT_DIRECTORY *st_header;
PE32_symtab_object *stod;
static mfl_sym_grp grp = MFL_SYM_EXPORT;
static mfl_next next = {MFL_OD_FIRST, MFL_OBJ_SYMTAB, MFL_PROP_SYMTAB_GRP,
&grp};
PE32_symbol_object *sym;
PE32_size sec_size;
PE32_vaddr sec_addr;
PE32_vaddr *func_addr;
PE32_vaddr *name_addr;
USHORT *ord;
char *func_name;
PE32_vaddr name_ptr;
int sym_num;
int len;
mfl_file_off foff;
mfl_tell((mfl_file_obj *)fod,&foff);
sec_size = PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_EXPORT);
sec_addr = PE32_file_dir_vaddr (fod,IMAGE_DIRECTORY_ENTRY_EXPORT);
if ((symbuf = st_header = mfl_malloc (sec_size)) == NULL)
return MFL_ERR_NOT_ENOUGH_MEMORY;
/* get numbet of symbols in all export symbol tables */
next.od = MFL_OD_FIRST;
sym_num = 0;
while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {
sym_num += stod->syms->item_num;
next.od = (mfl_od)stod;
}
/* fill symbol table header */
st_header->Characteristics = 0;
st_header->TimeDateStamp = time(NULL);
st_header->MajorVersion = 0;
st_header->MinorVersion = 0;
st_header->Base = 1;
st_header->NumberOfFunctions = sym_num;
st_header->NumberOfNames = sym_num;
st_header->AddressOfFunctions = sec_addr + sizeof (IMAGE_EXPORT_DIRECTORY);
st_header->AddressOfNames = st_header->AddressOfFunctions + sym_num;
st_header->AddressOfNameOrdinals = st_header->AddressOfNames + sym_num;
st_header->Name = (ULONG)(st_header->AddressOfNameOrdinals + sym_num);
/* calculate pointer to smaller tables */
func_addr = (PE32_vaddr *)(st_header + 1);
name_addr = func_addr + sym_num;
ord = (PUSHORT)(name_addr + sym_num);
func_name = (char *)(ord + sym_num);
name_ptr = st_header->Name;
strcpy (func_name, fod->mflfh.name);
len = strlen (func_name) + 1;
func_name += len;
name_ptr += len;
i = 0;
/* for all export symbol tables */
next.od = MFL_OD_FIRST;
while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {
next.od = (mfl_od)stod;
/* for all symbols in symbol table */
sym = MFL_OD_FIRST;
while ((sym = hash_get_next (stod->syms, (mfl_hash_od)sym))
!= MFL_OD_END) {
func_addr[i] = PE32_symbol_vaddr (sym);
name_addr[i] = name_ptr;
ord[i] = i;
strcpy (func_name, PE32_symbol_name(sym));
len = strlen (func_name) + 1;
func_name += len;
name_ptr += len;
i++;
}
}
/* reset the rest of the buffer */
memset (func_name, 0, sec_size - ((ULONG)func_name - (ULONG)st_header));
/* write symbols */
error = mfl_write (st_header, sec_size, (mfl_file_obj *)fod);
mfl_tell((mfl_file_obj *)fod,&foff);
mfl_free (st_header);
return error;
}
/****************************************************************************
* PE32_write_import_symbols *
* *
* Write import symbol table *
****************************************************************************/
static FUNC mfl_err PE32_write_import_symbols (PE32_file_object *fod)
{
mfl_err error;
PE32_size sec_size;
PE32_vaddr sec_addr;
unsigned int i;
int j,len;
void *symbuf;
int sym_num;
int st_num;
PE32_symtab_object *stod;
PE32_symbol_object *sym;
PE32_vaddr *adr_tab_1, *adr_tab_2;
PE32_vaddr *ptr_tab_1, *ptr_tab_2;
IMAGE_IMPORT_BY_NAME *adr_hint_tab;
IMAGE_IMPORT_BY_NAME *ptr_hint_tab;
IMAGE_IMPORT_DESCRIPTOR *st_header;
static mfl_sym_grp grp = MFL_SYM_IMPORT;
static mfl_next next = {MFL_OD_FIRST, MFL_OBJ_SYMTAB, MFL_PROP_SYMTAB_GRP,
&grp};
mfl_file_off foff;
mfl_tell((mfl_file_obj *)fod,&foff);
sec_size = PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_IMPORT);
sec_addr = PE32_file_dir_vaddr (fod,IMAGE_DIRECTORY_ENTRY_IMPORT);
if ((symbuf = st_header = mfl_malloc (sec_size)) == NULL)
return MFL_ERR_NOT_ENOUGH_MEMORY;
/* for all import symbol tables */
next.od = MFL_OD_FIRST;
sym_num = 0;
st_num = 0;
while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {
sym_num += stod->syms->item_num;
st_num++;
next.od = (mfl_od)stod;
}
/* image based addresses */
adr_tab_1 = (PE32_vaddr *)(sec_addr + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (st_num+1));
adr_tab_2 = adr_tab_1 + sym_num + st_num;
adr_hint_tab = (IMAGE_IMPORT_BY_NAME *)(adr_tab_2 + sym_num + st_num);
/* buffer addresses */
ptr_tab_1 = (PE32_vaddr *)(st_header + st_num + 1);
ptr_tab_2 = ptr_tab_1 + sym_num + st_num;
ptr_hint_tab = (IMAGE_IMPORT_BY_NAME *)(ptr_tab_2 + sym_num + st_num);
next.od = MFL_OD_FIRST;
for (j=0; j < st_num; j++) {
/* get next symbol table */
if ((error = PE32_get_next_symtab (fod, &next, &stod)) != MFL_OK)
return error;
next.od = (mfl_od)stod;
/* fill symbol table header entry */
st_header[j].Characteristics = (ULONG)adr_tab_1;
st_header[j].TimeDateStamp = 0;
st_header[j].ForwarderChain = 0;
st_header[j].Name = (ULONG)adr_hint_tab;
/*st_header[j].FirstThunk = (IMAGE_THUNK_DATA *)adr_tab_2;*/
st_header[j].FirstThunk = (DWORD)adr_tab_2;
/* copy shared file name */
strcpy ((char *)ptr_hint_tab, stod->file);
((char *)ptr_hint_tab) [-1] = '\0';
/* advance pointers */
ptr_hint_tab =
(IMAGE_IMPORT_BY_NAME *)(ptr_hint_tab + ((strlen (stod->file) + 2) & (unsigned)~1));
adr_hint_tab =
(IMAGE_IMPORT_BY_NAME *)((char *)adr_hint_tab +
((strlen (stod->file) + 2) & (unsigned)~1));
sym = MFL_OD_FIRST;
for (i=0; i < stod->syms->item_num; i++) {
sym = hash_get_next (stod->syms, (mfl_hash_od)sym);
/* fill lookup and address table */
ptr_tab_1[i] = (PE32_vaddr)adr_hint_tab;
ptr_tab_2[i] = (PE32_vaddr)adr_hint_tab;
/* fill hint-name table */
ptr_hint_tab->Hint = (USHORT)sym->ord;
strcpy ((mfl_str)ptr_hint_tab->Name, sym->name);
((char *)ptr_hint_tab) [-1] = '\0';
/* addvance pointers */
len = (sizeof (USHORT) + strlen (sym->name) + 2) & (unsigned)~1;
adr_hint_tab = (IMAGE_IMPORT_BY_NAME *)((char *)adr_hint_tab + len);
ptr_hint_tab = (IMAGE_IMPORT_BY_NAME *)((char *)ptr_hint_tab + len);
}
/* advance image base addresses */
adr_tab_1 += stod->syms->item_num + 1;
adr_tab_2 += stod->syms->item_num + 1;
/* advance table pointers */
ptr_tab_1[stod->syms->item_num] = 0;
ptr_tab_2[stod->syms->item_num] = 0;
ptr_tab_1 += stod->syms->item_num + 1;
ptr_tab_2 += stod->syms->item_num + 1;
}
if (st_num > 0)
memset(&st_header[st_num],0,sizeof(IMAGE_IMPORT_DESCRIPTOR));
/* write import table */
if ((error = mfl_write (symbuf,sec_size,(mfl_file_obj *)fod)) != MFL_OK)
return error;
mfl_tell((mfl_file_obj *)fod,&foff);
mfl_free (symbuf);
return MFL_OK;
}
/****************************************************************************
* PE32_write_file_pad_align *
* *
* Pad file to required alignment *
****************************************************************************/
static FUNC mfl_err PE32_write_file_pad_align (PE32_file_object *fod,
PE32_offset *file_ptr,
PE32_align align)
{
PE32_offset end;
char *buf;
PE32_size size;
mfl_err error;
mfl_file_off foff;
mfl_tell((mfl_file_obj *)fod,&foff);
/* calculate next aligned offset */
end = (*file_ptr + align - 1) & ~(align-1);
/* return if offset already aligned */
if (end == *file_ptr)
return MFL_OK;
/* calculate fill size */
size = end - *file_ptr;
*file_ptr = end;
/* allocate and reset pad buffer */
if ((buf = mfl_malloc (size)) == NULL)
return MFL_ERR_NOT_ENOUGH_MEMORY;
memset (buf, 0, size);
/* write the pad buffer */
error = mfl_write (buf, size, (mfl_file_obj *)fod);
/* free pad buffer */
mfl_tell((mfl_file_obj *)fod,&foff);
mfl_free (buf);
return error;
}
/****************************************************************************
* PE32_write_file_pad_offset *
* *
* Pad file with zero from a certain offset to another offset *
****************************************************************************/
static FUNC mfl_err PE32_write_file_pad_offset (PE32_file_object *fod,
PE32_offset file_ptr,
PE32_offset offset)
{
char *buf;
PE32_size size;
mfl_err error;
/* calculate fill size */
size = offset - file_ptr;
/* allocate and reset pad buffer */
if ((buf = mfl_malloc (size)) == NULL)
return MFL_ERR_NOT_ENOUGH_MEMORY;
memset (buf, 0, size);
/* write the pad buffer */
error = mfl_write (buf, size, (mfl_file_obj *)fod);
/* free pad buffer */
mfl_free (buf);
return error;
}
/****************************************************************************
* PE32_open_for_write *
* *
* Open file for write if needed. Complete reading file content first if *
* the file was initialy opened for read. *
****************************************************************************/
static FUNC mfl_err PE32_open_for_write (PE32_file_object *fod, mfl_str name)
{
mfl_err error;
mfl_file_p pfout;
if (fod->mflfh.write_open == TRUE) {
return MFL_OK;
}
/* if file is open for read - read all file content and close it */
if ((error = PE32_read_all_cfile (fod)) != MFL_OK) {
return error;
}
if ((error = mfl_open_normal_or_fd_file (name, 0, &pfout, MFL_OPEN_WRITE_STD
)) != MFL_OK) {
return error;
}
mfl_file_header(fod)->mflfh.write_open = TRUE;
mfl_file_header(fod)->mflfh.file_open = TRUE;
mfl_file_header(fod)->mflfh.open_with_fd = FALSE;
/* mark that for now this file does not used with mmap */
mfl_file_header(fod)->mflfh.used_mmap = FALSE;
mfl_file_header(fod)->mflfh.fhandle = pfout;
/* insert the file to the open file list */
if ((error = mfl_insert_new_open_file((mfl_file_obj *)fod)) != MFL_OK) {
return error;
}
return MFL_OK;
}