📄 pe.c
字号:
file_read(headerdata+headerSize,imageSize) ;
imageSize+=headerSize; /* total file size */
headbuf.image_length_MOD_512 = imageSize%512; /* size mod 512 */
headbuf.image_length_DIV_512 = (imageSize+511)>>9; /* number of 512-byte pages */
/* copy header */
memcpy(headerdata,(byte_ptr)&headbuf,sizeof(headbuf)) ;
/* store pointer and size */
(*pstubData)=headerdata;
(*pstubSize)=imageSize;
Else
(*pstubData)=defaultStub;
(*pstubSize)=defaultStubSize;
EndIf ;
EndCode
/*+-------------------------------------------------------------------------+
| |
| write_pe_image |
| |
+-------------------------------------------------------------------------+*/
void write_pe_image(void)
BeginDeclarations
bit_32 i,j,k;
byte_ptr headbuf;
pe_header_ptr pehead ;
#define PEHead (*pehead)
pe_object_ptr peobject ;
#define PEObject (*peobject)
byte_ptr stubData;
FILE *outfile;
bit_32 headerSize;
bit_32 headerVirtSize;
bit_32 stubSize;
bit_32 sectionStart;
bit_32 headerStart;
int_32 relocSectNum,importSectNum,exportSectNum,resourceSectNum,cvSectNum;
bit_32 written ;
bit_32 highest_data_sect = n_pe_sections - 1 ;
bit_32 current_section ;
public_entry_ptr import ;
segment_entry_ptr seg;
lseg_ptr lseg ;
bit_32 data_index ;
bit_32 partial_length ;
bit_32 dataSize = 0 ;
bit_32 codeSize = 0 ;
#define Seg (*seg )
#define Lseg (*lseg)
EndDeclarations
BeginCode
ReturnIf (!n_pe_sections) ;
/* allocate section entries for imports, exports and relocs if required */
If n_imports
Then
importSectNum=createOutputSection(".idata",
WINF_INITDATA | WINF_READABLE | WINF_WRITEABLE | WINF_NEG_FLAGS);
Else
importSectNum=-1;
EndIf ;
If n_exports
Then
exportSectNum=createOutputSection(".edata",
WINF_INITDATA | WINF_READABLE | WINF_NEG_FLAGS);
Else
exportSectNum=-1;
EndIf ;
/* Windows NT requires a reloc section to relocate image files, even */
/* if it contains no actual fixups */
relocSectNum=createOutputSection(".reloc",
WINF_INITDATA | WINF_SHARED | WINF_READABLE | WINF_NEG_FLAGS);
If n_resources
Then
resourceSectNum=createOutputSection(".rsrc",
WINF_INITDATA | WINF_SHARED | WINF_READABLE | WINF_WRITEABLE | WINF_NEG_FLAGS);
Else
resourceSectNum=-1;
EndIf ;
// If debug.val
// Then
// cvSectNum = createOutputSection(".debug",
// WINF_INITDATA | WINF_SHARED | WINF_READABLE) ;
// Else
// cvSectNum = -1;
// EndIf
cvSectNum = -1 ;
/* build header */
load_stub(&stubData,&stubSize);
headerStart=stubSize; /* get start of PE header */
headerStart+=7;
headerStart&=0xfffffff8; /* align PE header to 8 byte boundary */
headerSize=sizeof(pe_header_type)+n_pe_sections*sizeof(pe_object_type)+stubSize;
headerVirtSize=headerSize+(objectAlign.val-1);
headerVirtSize&=(0xffffffff-(objectAlign.val-1));
headerSize+=(fileAlign.val-1);
headerSize&=(0xffffffff-(fileAlign.val-1));
headbuf=allocate_memory(headerSize);
memset(headbuf,0,headerSize);
memcpy(headbuf,stubData,stubSize ) ;
*(bit_32_ptr)( headbuf + 0x3c) = headerStart ; /* Pointer to PE header */
pehead = (pe_header_ptr)(headbuf + headerStart) ;
PEHead.sig = 0x00004550 ; /* PE__ */
PEHead.cpu_type = PE_INTEL386 ;
/* store time/date of creation */
PEHead.time=(bit_32)time(NULL);
PEHead.nt_hdr_size = PE_OPTIONAL_HEADER_SIZE ;
i=PE_FILE_EXECUTABLE | PE_FILE_32BIT | PE_FILE_REVERSE_BITS_HIGH |
PE_FILE_REVERSE_BITS_LOW | PE_FILE_LOCAL_SYMBOLS_STRIPPED | PE_FILE_LINE_NUMBERS_STRIPPED ;
If build_DLL.val IsTrue
Then
i|= PE_FILE_LIBRARY; /* if DLL, flag it */
EndIf ;
PEHead.flags = i ;
PEHead.magic = PE_MAGICNUM ;
PEHead.image_base = imageBase.val ;
PEHead.file_align = fileAlign.val ;
PEHead.object_align = objectAlign.val ;
PEHead.os_major_version = osMajor ;
PEHead.os_minor_version = osMinor ;
PEHead.subsys_major_version = subsysMajor ;
PEHead.subsys_minor_version = subsysMinor ;
PEHead.subsystem = win_subsystem.val ? PE_SUBSYS_WINDOWS : PE_SUBSYS_CONSOLE ;
PEHead.num_rvas = PE_NUM_VAS ;
PEHead.header_size = headerSize ;
PEHead.heap_size = heapSize.val ;
PEHead.heap_commit = heapCommitSize.val ;
PEHead.stack_size = stackSize.val ;
PEHead.stack_commit = stackCommitSize.val ;
/* shift segment start addresses up into place and build section headers */
sectionStart=headerSize;
peobject = (pe_object_ptr)(headbuf + headerStart + sizeof(pe_header_type)) ;
// So we don't write the BSS to the file
If PE_bss_seg IsNotZero
Then
outList[PE_bss_seg]->initlength = 0 ;
EndIf ;
For i=0;i<n_pe_sections;i++,peobject++
BeginFor
memcpy(PEObject.name,outList[i]->name,8) ;
PEObject.virtual_size = k = outList[i]->virtualSize ;
If Not pad_segments.val /* if not padding segments, reduce space consumption */
Then
k = PEObject.raw_size = outList[i]->initlength ;
Else
PEObject.raw_size = k ;
EndIf ;
PEObject.raw_ptr = sectionStart ;
k+=fileAlign.val-1;
k&=(0xffffffff-(fileAlign.val-1)); /* aligned initialised length */
sectionStart+=k; /* update section start address for next section */
// outList[i]->base+=headerVirtSize;
PEObject.virtual_addr = outList[i]->base - imageBase.val ;
// outList[i]->base += imageBase.val ;
PEObject.flags = (outList[i]->winFlags ^ WINF_NEG_FLAGS) & WINF_IMAGE_FLAGS; /* get characteristice for section */
EndFor ;
PEHead.num_objects = n_pe_sections ;
/* build import, export and relocation sections */
peobject = (pe_object_ptr) (headbuf + headerStart + sizeof(pe_header_type)) ;
BuildPEImports(importSectNum,peobject,pehead);
BuildPEExports(exportSectNum,peobject,pehead);
BuildPERelocs(relocSectNum,peobject,pehead);
BuildPEResources(resourceSectNum,peobject,pehead);
// BuildPEDebug( cvSectNum, peobject, pehead);
If start_address_found IsTrue
Then
fixup = start_address;
PEHead.entry_point = target(&import) - imageBase.val ; /* RVA */
If build_DLL.val IsTrue /* if library */
Then
/* flag that entry point should always be called */
PEHead.dll_flags = 0 ;
EndIf ;
Else /* No start address found. */
linker_error(4,"No start address.\n");
EndIf;
peobject = (pe_object_ptr)(headbuf + headerStart + sizeof(pe_header_type)) ;
For i=0;i<n_pe_sections;i++,peobject++
BeginFor
// k = (PEObject.raw_size + fileAlign.val - 1) & ~(fileAlign.val - 1) ;
k = PEObject.raw_size ;
If i IsZero
Then
codeSize += k ;
Else
dataSize += k ;
EndIf ;
EndFor ;
peobject = (pe_object_ptr)(headbuf + headerStart+sizeof (pe_header_type) + (n_pe_sections-1)*sizeof(pe_object_type));
i = PEObject.virtual_addr + PEObject.virtual_size ;
PEHead.image_size = i ;
PEHead.code_base = outList[0]->base - imageBase.val ;
PEHead.data_base = outList[1]->base - imageBase.val ;
PEHead.code_size = codeSize ;
PEHead.data_size = dataSize ;
/* zero out section start for all zero-length segments */
peobject = (pe_object_ptr)(headbuf + headerStart + sizeof(pe_header_type)) ;
For i=0; i LessThan n_pe_sections; i++,peobject++
BeginFor
If PEObject.raw_size IsZero
Then
PEObject.raw_ptr = 0;
EndIf ;
EndFor ;
// We have to dump the codeview data now so the time stamps will be
// correct for CCIDE
BuildPEDebug( cvSectNum, peobject, pehead);
file_open_for_write(exe_file_list.first) ;
file_write(headbuf,headerSize) ;
/* We will use object_file_element as a source for the gaps caused by
the alignment of segments. We will fill the gaps with zeros. */
current_section = 0;
far_set(BytePtr(object_file_element), 0, MAX_ELEMENT_SIZE);
next_available_address = outList[0]->base;
TraverseList(segment_list, seg)
BeginTraverse
LoopIf((*Seg.lsegs.first).align Is absolute_segment);
LoopIf(Seg.pe_section_number Is 2);
If current_section IsNotEqualTo Seg.pe_section_number
Then
If next_available_address Mod fileAlign.val IsNotZero
Then
write_gap(fileAlign.val - (next_available_address %fileAlign.val));
next_available_address += fileAlign.val - (next_available_address %fileAlign.val) ;
EndIf ;
If pad_segments.val IsTrue
Then
write_gap(Seg.address-next_available_address) ;
EndIf ;
current_section = Seg.pe_section_number ;
next_available_address = Seg.address ;
EndIf ;
TraverseList(Seg.lsegs, lseg)
BeginTraverse
If Lseg.address LessThan next_available_address
Then
LoopIf((Lseg.address+Lseg.length) NotGreaterThan \
next_available_address);
data_index = next_available_address - Lseg.address;
partial_length = Lseg.length - data_index;
If Seg.combine IsNot blank_common_combine
Then
file_write(Addr(Lseg.data[Bit_16(data_index)]), partial_length);
Else
write_gap(partial_length);
EndIf;
Else
write_gap(Lseg.address - next_available_address) ;
next_available_address = Lseg.address ;
If Seg.combine IsNot blank_common_combine
Then
file_write(Lseg.data, Lseg.length);
Else
write_gap(Lseg.length);
EndIf;
next_available_address += Lseg.length;
EndIf;
EndTraverse;
EndTraverse;
If next_available_address Mod fileAlign.val IsNotZero
Then
write_gap(fileAlign.val - (next_available_address %fileAlign.val));
next_available_address += fileAlign.val - (next_available_address %fileAlign.val );
EndIf ;
If pad_segments.val IsTrue
Then
write_gap(outList[highest_data_sect + 1]->base -next_available_address) ;
EndIf ;
For i=highest_data_sect + 1; i<n_pe_sections; i++
BeginFor
/* align section - for this to work objectAlign >= file_align*/
If pad_segments.val IsTrue AndIf i IsNotEqualTo highest_data_sect + 1
Then
write_gap(outList[i]->base - next_available_address);
EndIf ;
next_available_address=outList[i]->base;
file_write(outList[i]->data,written = outList[i]->initlength);
next_available_address += written ;
write_gap(fileAlign.val - (written % fileAlign.val)) ;
next_available_address += fileAlign.val - written % fileAlign.val ;
EndFor
file_close_for_write() ;
EndCode
#undef PEObject
#undef PEHead
#undef Seg
#undef Lseg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -