/* 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 far *word_location; EndDeclarations BeginCode file_read(BytePtr(Addr(fixup)), sizeof(fixup)); frame_address = frame(); target_address = target(); If ((target_address LessThan frame_address) OrIf (target_address Exceeds (frame_address + 65535L))) AndIf (fixup.frame_method IsNot 6) AndIf (frame_absolute IsFalse) Then linker_error(4, "Fixup error:\n" "\t Module: \"%Fs\"\n" "\t File: \"%Fs\"\n" "\tSegment: \"%Fs\"\n" "\t Offset: %u\n" "\t Error: Target not within frame.\n", (*(*temp_file_header.lseg).tmodule).symbol, (*(*temp_file_header.lseg).file).filename, (*(*(*temp_file_header.lseg).segment).segment_name).symbol, temp_file_header.offset); EndIf; byte_location = Addr((*temp_file_header.lseg).data[temp_file_header.offset]); word_location = (bit_16 far *) byte_location; If fixup.mode IsZero Then /* Self-relative fixup */ location_address = (*temp_file_header.lseg).address + Bit_32(temp_file_header.offset) + 1L; If fixup.location_type Is offset_location Then location_address++; EndIf; If (location_address LessThan frame_address) OrIf (location_address Exceeds (frame_address + 65535L)) OrIf (frame_absolute IsTrue) Then linker_error(4, "Fixup error:\n" "\t Module: \"%Fs\"\n" "\t File: \"%Fs\"\n" "\tSegment: \"%Fs\"\n" "\t Offset: %u\n" "\t Error: Location not within frame.\n", (*(*temp_file_header.lseg).tmodule).symbol, (*(*temp_file_header.lseg).file).filename, (*(*(*temp_file_header.lseg).segment).segment_name).symbol, temp_file_header.offset); EndIf; Using fixup.location_type BeginCase When lobyte_location: location_address = (*temp_file_header.lseg).address + Bit_32(temp_file_header.offset) + 1L; 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: \"%Fs\"\n" "\t File: \"%Fs\"\n" "\tSegment: \"%Fs\"\n" "\t Offset: %u\n" "\t Error: Distance to target out of range.\n", (*(*temp_file_header.lseg).tmodule).symbol, (*(*temp_file_header.lseg).file).filename, (*(*(*temp_file_header.lseg).segment).segment_name).symbol, temp_file_header.offset); EndIf; *byte_location += Bit_8(IP_distance_to_target); break; When offset_location: 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; EndCase; Else /* Segment-relative fixup */ fbval = Bit_16(frame_address ShiftedRight 4); foval = target_address - frame_address; 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 offset_location: *word_location += Bit_16(foval); break; When base_location: *word_location += fbval; If exefile IsTrue Then Exe_header.relocation_table[Exe_header.n_relocation_items++] = segment_offset(temp_file_header.lseg, temp_file_header.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(temp_file_header.lseg, temp_file_header.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_16 offset; bit_8 size; EndDeclarations BeginCode lseg = temp_file_header.lseg; len = temp_file_header.rec_len; file_read(BytePtr(object_file_element), len); obj_ptr.b8 = object_file_element; end_of_record.b8 = Addr(obj_ptr.b8[len]); size = *obj_ptr.b8++; Using size BeginCase When 0: While obj_ptr.b8 IsNot end_of_record.b8 BeginWhile offset = *obj_ptr.b16++; Lseg.data[offset] += *obj_ptr.b8++; EndWhile; break; When 1: While obj_ptr.b8 IsNot end_of_record.b8 BeginWhile offset = *obj_ptr.b16++; *((bit_16 far *) Addr(Lseg.data[offset])) += *obj_ptr.b16++; EndWhile; break; When 2: While obj_ptr.b8 IsNot end_of_record.b8 BeginWhile offset = *obj_ptr.b16++; *((bit_32 far *) Addr(Lseg.data[offset])) += *obj_ptr.b32++; EndWhile; break; Otherwise: linker_error(4, "Translator error:\n" "\t Module: \"%Fs\"\n" "\t File: \"%Fs\"\n" "\tSegment: \"%Fs\"\n" "\t Error: Invalid FORREF record.\n", (*(*temp_file_header.lseg).tmodule).symbol, (*(*temp_file_header.lseg).file).filename, (*(*(*temp_file_header.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 = temp_file_header.lseg; lseg_data_ptr = Addr(Lseg.data[temp_file_header.offset]); file_read(lseg_data_ptr, temp_file_header.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