📄 fixup.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 <dos.h>
#include <time.h>
#include "langext.h"
#include "defines.h"
#include "types.h"
#include "subs.h"
#include "globals.h"
/* FIXUP.C */
/*+-------------------------------------------------------------------------+
| |
| fixup_FIXUPP_record |
| |
+-------------------------------------------------------------------------+*/
void fixup_FIXUPP_record()
BeginDeclarations
byte_ptr byte_location;
int_32 IP_distance_to_target;
bit_16 fbval;
bit_32 foval;
bit_32 frame_address;
bit_32 location_address;
bit_32 target_address;
bit_16 *word_location;
bit_32 *dword_location;
bit_32 fixup32;
public_entry_ptr import ;
EndDeclarations
BeginCode
far_move(Addr(fixup),BytePtr((*fixup_temp).data), sizeof(fixup)) ;
frame_address = frame();
target_address = target(&import);
location_address = (*(*fixup_temp).lseg).address +
Bit_32((*fixup_temp).offset) ;
byte_location =
Addr((*(*fixup_temp).lseg).data[(*fixup_temp).offset]);
If import
Then
If lxfile.val IsTrue OrIf lefile.val IsTrue
Then
linker_error(4, "Fixup error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Offset: %08X\n"
"\t Error: Invalid fixup reference to import in LX file.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol,
(*fixup_temp).offset);
EndIf ;
If pefile.val IsTrue
Then
If fixup.mode IsNotZero
OrIf fixup.location_type IsNotEqualTo offset32_location
AndIf fixup.location_type IsNotEqualTo secondary_offset32_location
Then
#ifdef XXXXX
linker_error(4, "Fixup error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Offset: %08X\n"
"\t Error: Invalid fixup reference to import.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol,
(*fixup_temp).offset);
#endif
// relies on data not being relocated between now and when imports are applied
enter_pe_import_fixup(byte_location, location_address, import,1) ;
Else
// relies on data not being relocated between now and when imports are applied
enter_pe_import_fixup(byte_location, location_address, import,0) ;
EndIf ;
Else
linker_error(4, "Fixup error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Offset: %08X\n"
"\t Error: Import fixup needs a PE file.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol,
(*fixup_temp).offset);
EndIf
return ;
EndIf ;
If ((target_address LessThan frame_address) OrIf
(target_address Exceeds (frame_address + 65535L)) AndIf
Not use32.val) AndIf
(fixup.frame_method IsNot 6) AndIf (frame_absolute IsFalse)
Then
linker_error(4, "Fixup error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Offset: %08X\n"
"\t Error: Target not within frame.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol,
(*fixup_temp).offset);
EndIf
word_location = (bit_16 *) byte_location;
dword_location = (bit_32 *) byte_location;
If fixup.mode IsZero
Then /* Self-relative fixup */
Using fixup.location_type
BeginCase
When lobyte_location:
location_address ++ ;
IP_distance_to_target = Int_32(target_address) -
Int_32(location_address);
If (IP_distance_to_target < -128L) OrIf
(IP_distance_to_target > 127L)
Then
linker_error(4, "Byte self-relative fixup error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Offset: %08X\n"
"\t Error: Distance to target out of range.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol,
(*fixup_temp).offset);
EndIf;
*byte_location += Bit_8(IP_distance_to_target);
break;
When offset_location:
When secondary_offset_location:
location_address += 2;
IP_distance_to_target = target_address - location_address;
*word_location += Bit_16(IP_distance_to_target);
break;
When base_location: /* Undefined action */
When pointer_location: /* Undefined action */
When hibyte_location: /* Undefined action */
break;
When offset32_location:
When secondary_offset32_location:
location_address += 4 ;
IP_distance_to_target = Int_32(target_address) - Int_32(location_address);
*dword_location += IP_distance_to_target;
break;
EndCase;
Else /* Segment-relative fixup */
enter_pe_fixup(location_address,fixup.location_type) ;
enter_lx_fixup(target_address+*dword_location,location_address,fixup.location_type) ;
fbval = Bit_16(frame_address ShiftedRight 4);
If pefile.val IsTrue OrIf lxfile.val IsTrue OrIf lefile.val IsTrue
Then
foval = target_address;
Else
foval = target_address - frame_address;
EndIf ;
If (frame_absolute IsFalse) AndIf
(exefile IsFalse) AndIf
((fixup.location_type Is base_location) OrIf
(fixup.location_type Is pointer_location))
Then /* Count the relocation items we should not be getting. */
n_relocation_items++;
EndIf;
Using fixup.location_type
BeginCase
When lobyte_location:
*byte_location += Bit_8(foval);
break;
When secondary_offset_location:
When offset_location:
*word_location += Bit_16(foval);
break;
When secondary_offset32_location:
When offset32_location:
*dword_location += foval;
break;
When base_location:
*word_location += fbval;
If exefile IsTrue
Then
Exe_header.relocation_table[Exe_header.n_relocation_items++] =
segment_offset((*fixup_temp).lseg, (*fixup_temp).offset);
EndIf;
break;
When pointer_location:
*word_location++ += Bit_16(foval);
*word_location += fbval;
If exefile IsTrue
Then
Exe_header.relocation_table[Exe_header.n_relocation_items++] =
segment_offset((*fixup_temp).lseg, (*fixup_temp).offset+2);
EndIf;
break;
When hibyte_location:
*byte_location += Bit_8(foval ShiftedRight 8);
break;
EndCase;
EndIf;
return;
EndCode
/*+-------------------------------------------------------------------------+
| |
| fixup_FORREF_record |
| |
+-------------------------------------------------------------------------+*/
void fixup_FORREF_record()
BeginDeclarations
bit_16 len;
lseg_ptr lseg;
#define Lseg (*lseg)
bit_32 offset;
bit_32 value;
bit_8 size;
bit_32 forref32;
EndDeclarations
BeginCode
lseg = (*fixup_temp).lseg;
len = (*fixup_temp).rec_len;
far_move( BytePtr(object_file_element), (*fixup_temp).data, len) ;
obj_ptr.b8 = object_file_element;
end_of_record.b8 = Addr(obj_ptr.b8[len]);
size = *obj_ptr.b8++;
forref32 = (*fixup_temp).rec_typ & 1;
Using size
BeginCase
When 0:
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If forref32
Then
offset = *obj_ptr.b32++;
value = *obj_ptr.b32++;
Else
offset = *obj_ptr.b16++;
value = *obj_ptr.b16++;
EndIf
Lseg.data[offset] += value And 0xff;
enter_pe_fixup(Lseg.address + offset , lobyte_location) ;
EndWhile;
break;
When 1:
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If forref32
Then
offset = *obj_ptr.b32++;
value = *obj_ptr.b32++;
Else
offset = *obj_ptr.b16++;
value = *obj_ptr.b16++;
EndIf
*((bit_16 *) Addr(Lseg.data[offset])) += value And 0xffff;
enter_pe_fixup(Lseg.address + offset , offset_location) ;
EndWhile;
break;
When 2: /* should only be allowed for 32-bit records, but, don't know
* how to put an error here - DAL
*/
While obj_ptr.b8 IsNot end_of_record.b8
BeginWhile
If forref32
Then
offset = *obj_ptr.b32++;
value = *obj_ptr.b32++;
Else
offset = *obj_ptr.b16++;
value = *obj_ptr.b16++;
EndIf
*((bit_32 *) Addr(Lseg.data[offset])) += value;
enter_pe_fixup(Lseg.address + offset , offset32_location) ;
EndWhile;
break;
Otherwise:
linker_error(4, "Translator error:\n"
"\t Module: \"%s\"\n"
"\t File: \"%s\"\n"
"\tSegment: \"%s\"\n"
"\t Error: Invalid FORREF record.\n",
(*(*(*fixup_temp).lseg).tmodule).symbol,
(*(*(*fixup_temp).lseg).file).filename,
(*(*(*(*fixup_temp).lseg).segment).segment_name).symbol);
break;
EndCase;
return;
EndCode
#undef Lseg
/*+-------------------------------------------------------------------------+
| |
| fixup_LEDATA_record |
| |
+-------------------------------------------------------------------------+*/
void fixup_LEDATA_record()
BeginDeclarations
lseg_ptr lseg;
#define Lseg (*lseg)
EndDeclarations
BeginCode
lseg = (*fixup_temp).lseg;
// if (strstr(lseg->segment->segment_name->symbol,"Ted@Paint"))
// printf("bye") ;
lseg_data_ptr = Addr(Lseg.data[(*fixup_temp).offset]);
far_move(lseg_data_ptr, (*fixup_temp).data, (*fixup_temp).rec_len) ;
return;
EndCode
#undef Lseg
/*+-------------------------------------------------------------------------+
| |
| fixup_LIDATA_IDB |
| |
+-------------------------------------------------------------------------+*/
void fixup_LIDATA_IDB()
BeginDeclarations
bit_16 block_count;
bit_8 *content;
bit_16 i;
bit_16 j;
bit_16 len;
bit_16 repeat_count;
EndDeclarations
BeginCode
repeat_count = *obj_ptr.b16++;
block_count = *obj_ptr.b16++;
If block_count IsNotZero
Then /* Handle recursive case: Content is iterated data block */
content = obj_ptr.b8;
For i=0; i<repeat_count; i++
BeginFor
obj_ptr.b8 = content;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -