⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pe.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -