📄 pe.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <dos.h>
#include "langext.h"
#include "defines.h"
#include "types.h"
#include "subs.h"
#include "globals.h"
bit_16 osMajor =4;
bit_16 osMinor =0;
bit_16 subsysMajor =4 ;
bit_16 subsysMinor =0;
static byte defaultStub[]={
0x4D,0x5A,0x6C,0x00,0x01,0x00,0x00,0x00,
0x04,0x00,0x11,0x00,0xFF,0xFF,0x03,0x00,
0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,
0x21,0xB8,0x00,0x4C,0xCD,0x21,0x54,0x68,
0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,
0x61,0x6D,0x20,0x72,0x65,0x71,0x75,0x69,
0x72,0x65,0x73,0x20,0x57,0x69,0x6E,0x33,
0x32,0x0D,0x0A,0x24
};
static int_32 defaultStubSize=sizeof(defaultStub);
/*+-------------------------------------------------------------------------+
| |
| createOutputSection |
| |
+-------------------------------------------------------------------------+*/
bit_32 createOutputSection(byte_ptr name, bit_32 winflags)
BeginDeclarations
bit_32 rv = n_pe_sections++ ;
EndDeclarations
BeginCode
outList = (pe_section_ptr_array)reallocate_memory(outList,sizeof(pe_section_ptr) * n_pe_sections) ;
outList[rv] = (pe_section_ptr)allocate_memory(sizeof(pe_section_type)) ;
outList[rv]->winFlags = winflags ;
memcpy(outList[rv]->name,name,8) ;
return rv ;
EndCode
/*+-------------------------------------------------------------------------+
| |
| enter_pe_import_Fixup |
| |
+-------------------------------------------------------------------------+*/
void enter_pe_import_fixup(byte_ptr location_ptr,
bit_32 location_address,
public_entry_ptr import, bit_32 isdata)
BeginDeclarations
EndDeclarations
BeginCode
If pefile.val IsTrue
Then
If n_pe_import_fixups IsEqualTo max_pe_import_fixups
Then
max_pe_import_fixups += 20 ;
pe_import_fixup_array = (pe_import_fixup_ptr_array)reallocate_memory(pe_import_fixup_array, max_pe_import_fixups*sizeof(pe_import_fixup_ptr)) ;
EndIf ;
import->isdata = isdata ;
pe_import_fixup_array[n_pe_import_fixups] = (pe_import_fixup_ptr) allocate_memory(sizeof(pe_import_fixup_type)) ;
pe_import_fixup_array[n_pe_import_fixups]->pub = import ;
pe_import_fixup_array[n_pe_import_fixups]->location_ptr = location_ptr;
pe_import_fixup_array[n_pe_import_fixups]->isdata = isdata;
pe_import_fixup_array[n_pe_import_fixups++]->location_addr = location_address;
EndIf ;
EndCode
/*+-------------------------------------------------------------------------+
| |
| apply_pe_import_fixups |
| |
+-------------------------------------------------------------------------+*/
void apply_pe_import_fixups(pe_object_ptr objectTable)
BeginDeclarations
bit_32 i,j ;
pe_import_fixup_ptr fixup ;
#define Pub (*pub)
#define Fixup (*fixup)
EndDeclarations
BeginCode
For i=0; i LessThan n_pe_import_fixups; i++
BeginFor
fixup = pe_import_fixup_array[i] ;
If Fixup.isdata
Then
*(bit_32_ptr)(Fixup.location_ptr) = Fixup.pub->Internal.offset + import_thunk_table->address + *(bit_32_ptr)(Fixup.location_ptr);
Else
*(bit_32_ptr)(Fixup.location_ptr) = Fixup.pub->Internal.offset +
import_thunk_table->address - Fixup.location_addr - 4 ;
EndIf
EndFor ;
EndCode
#undef Fixup
#undef Pub
/*+-------------------------------------------------------------------------+
| |
| BuildPEImports |
| |
+-------------------------------------------------------------------------+*/
void BuildPEImports(int_32 sectNum,pe_object_ptr objectTable, pe_header_ptr pehead)
BeginDeclarations
bit_32 i,j,k;
bit_32 dllCount = 0;
bit_32 importCount = 0 ;
bit_32 nameSize = 0;
bit_32 impNameSize = 0;
bit_32 namePos, lookupPos,hintPos,addressPos ;
bit_32 reqCount = 0;
bit_32 raw ;
bit_32 impThunkAddress = 0;
pe_section_ptr sect;
pe_import_module_ptr modules =0;
pe_object_ptr lastObjectTable ;
pe_import_dir_ptr impdir ;
pe_import_lookup_ptr lookup, lookup2 ;
string_ptr name ;
#define Lookup (*lookup)
#define Lookup2 (*lookup2)
#define Sect (*sect )
#define ImpDir (*impdir)
#define ObjectTable (*objectTable)
#define LastObjectTable (*lastObjectTable)
#define PEHead (*pehead)
EndDeclarations
BeginCode
ReturnIf (sectNum LessThan 0) ;
sect = outList[sectNum] ;
For i=0;i<n_imports;i++
BeginFor
LoopIf(!imports[i]->use_count);
reqCount++ ;
For j=0; j<dllCount; j++
BeginFor
ExitIf( Not compare_string(modules[j].name,imports[i]->moduleident)) ;
EndFor ;
If j IsEqualTo dllCount
Then
modules = (pe_import_module_ptr)reallocate_memory(modules,(++dllCount)*sizeof(pe_import_module_type)) ;
modules[j].name = imports[i]->moduleident;
modules[j].n_imports = modules[j].max_imports = 0;
modules[j].funcnames = modules[j].ordinals = 0;
modules[j].pubs = 0 ;
nameSize += Length(modules[j].name) + 1;
If nameSize And 1
Then
nameSize++;
EndIf ;
EndIf ;
If modules[j].n_imports IsEqualTo modules[j].max_imports
Then
modules[j].max_imports += 16 ;
modules[j].funcnames = (string_ptr_array)reallocate_memory(modules[j].funcnames, modules[j].max_imports * sizeof(string_ptr)) ;
modules[j].ordinals = (bit_32_ptr)reallocate_memory(modules[j].ordinals,modules[j].max_imports*sizeof(bit_32)) ;
modules[j].pubs = (public_entry_ptr_array)reallocate_memory(modules[j].pubs,modules[j].max_imports * sizeof(public_entry_ptr)) ;
EndIf ;
name = imports[i]->entryident ;
/* If the entry identifier does not exist we have an ordinal;
* but just in case windows ordinals change places we will import
* by the public name.
*/
If name IsNull
Then
name = (string_ptr)&imports[i]->max_length ;
EndIf ;
modules[j].funcnames[modules[j].n_imports] = name;
modules[j].ordinals[modules[j].n_imports] = imports[i]->ordinal ;
modules[j].pubs[modules[j].n_imports++] = imports[i] ;
impNameSize += Length(name) + 1 + 2 ;
If impNameSize And 1
Then
impNameSize++;
EndIf ;
importCount++ ;
EndFor ;
ReturnIf(!importCount) ;
namePos = (dllCount+1) *sizeof(pe_import_dir_type) ;
lookupPos = namePos + nameSize ;
If lookupPos Mod 4
Then
lookupPos += 4 - (lookupPos Mod 4) ;
EndIf ;
hintPos = lookupPos + (importCount + dllCount) * sizeof(pe_import_lookup_type) ;
addressPos = hintPos + impNameSize ;
If addressPos Mod 4
Then
addressPos += 4- (addressPos Mod 4) ;
EndIf ;
Sect.initlength = Sect.length = addressPos + (importCount + dllCount) * sizeof(pe_import_lookup_type) ;
Sect.data = (byte_ptr) allocate_memory(Sect.length) ;
memset(Sect.data,0,Sect.length) ;
lastObjectTable = objectTable + sectNum-1 ;
objectTable = lastObjectTable + 1;
k = LastObjectTable.raw_ptr + LastObjectTable.raw_size ;
k+=fileAlign.val-1;
k&=(0xffffffff-(fileAlign.val-1)); /* aligned */
/* k is now physical location of this object */
ObjectTable.raw_ptr = k ;
k = LastObjectTable.virtual_size + LastObjectTable.virtual_addr ;
ObjectTable.virtual_addr = k ;
raw = k ;
Sect.base=k+imageBase.val; /* get base address of section */
impdir = (pe_import_dir_ptr)Sect.data ;
lookup = (pe_import_lookup_ptr)(Sect.data + lookupPos) ;
lookup2 = (pe_import_lookup_ptr)(Sect.data + addressPos) ;
For i=0; i < dllCount; i++
BeginFor
ImpDir.time = 0;
ImpDir.version = 0;
ImpDir.dllName = namePos + raw ;
ImpDir.thunkPos = (byte_ptr)lookup - (byte_ptr)Sect.data + raw ;
ImpDir.thunkPos2 = (byte_ptr)lookup2 - (byte_ptr)Sect.data + raw ;
impdir++ ;
memcpy(Sect.data + namePos,String(modules[i].name),Length(modules[i].name)) ;
namePos += Length(modules[i].name) + 1;
If namePos And 1
Then
namePos++ ;
EndIf;
For j=0; j < modules[i].n_imports; j++
BeginFor
If modules[i].funcnames[j] IsNotNull
Then
Lookup.ord_or_rva = hintPos + raw ;
Lookup2.ord_or_rva = hintPos + raw ;
*(bit_16_ptr)(Sect.data + hintPos) = modules[i].ordinals[j] ;
hintPos += 2 ;
memcpy(Sect.data + hintPos,String(modules[i].funcnames[j]),Length(modules[i].funcnames[j])) ;
hintPos += Length(modules[i].funcnames[j]) + 1;
If hintPos And 1
Then
hintPos++ ;
EndIf;
Else
Lookup.ord_or_rva = Lookup2.ord_or_rva = modules[i].ordinals[j];
Lookup.import_by_ordinal = 1 ;
Lookup2.import_by_ordinal = 1 ;
EndIf ;
/* now make a thunk that has nothing to do with PE files
* but it allows direct jumps to import functions rather than
* having the compiler generate indirect calls.
*/
// If modules[i].pubs[j]->isdata
// Then
// modules[i].pubs[j]->Internal.offset =
// (byte_ptr)lookup - (byte_ptr)Sect.data + Sect.base ;
// enter_pe_fixup(modules[i].pubs[j]->Internal.offset, offset32_location) ;
// Else
modules[i].pubs[j]->Internal.offset = impThunkAddress ; /* Store the offset to our generated thunk table... */
enter_pe_fixup(impThunkAddress + import_thunk_table->address+2, offset32_location) ;
*(bit_16_ptr)(impThunkAddress + import_thunk_table->data) = 0x25FF ; /* jump indirect */
impThunkAddress += 2 ;
*(bit_32_ptr)(impThunkAddress + import_thunk_table->data) =
(byte_ptr)lookup - (byte_ptr)Sect.data + Sect.base ;
impThunkAddress += 4 ;
// EndIf
lookup++ ;
lookup2++;
EndFor ;
lookup++;
lookup2++ ;
EndFor ;
k=Sect.length;
k+=objectAlign.val-1;
k&=(0xffffffff-(objectAlign.val-1));
Sect.virtualSize=k;
ObjectTable.virtual_size = k ;
ObjectTable.raw_size = Sect.length ;
PEHead.import_rva = outList[sectNum]->base-imageBase.val ;
PEHead.import_size = outList[sectNum]->length ;
apply_pe_import_fixups(objectTable);
}
#undef ImpDir
#undef PEHead
#undef ObjectTable
#undef LastObjectTable
#undef Sect
#undef Lookup
#undef Lookup2
/*+-------------------------------------------------------------------------+
| |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -