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