home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / pgmutl / val_link.arc / FIXUP.C < prev    next >
Text File  |  1989-02-18  |  23KB  |  577 lines

  1. /*                                 FIXUP.C                                 */
  2.  
  3. /*+-------------------------------------------------------------------------+
  4.   |                                                                         |
  5.   |                            fixup_FIXUPP_record                          |
  6.   |                                                                         |
  7.   +-------------------------------------------------------------------------+*/
  8. void fixup_FIXUPP_record()
  9. BeginDeclarations
  10. byte_ptr                               byte_location;
  11. int_32                                 IP_distance_to_target;
  12. bit_16                                 fbval;
  13. bit_32                                 foval;
  14. bit_32                                 frame_address;
  15. bit_32                                 location_address;
  16. bit_32                                 target_address;
  17. bit_16 far                            *word_location;
  18. EndDeclarations
  19. BeginCode
  20.  file_read(BytePtr(Addr(fixup)), sizeof(fixup));
  21.  frame_address  = frame();
  22.  target_address = target();
  23.  If ((target_address LessThan frame_address) OrIf
  24.      (target_address Exceeds (frame_address + 65535L))) AndIf
  25.     (fixup.frame_method IsNot 6) AndIf (frame_absolute IsFalse)
  26.   Then
  27.    linker_error(4, "Fixup error:\n"
  28.                    "\t Module:  \"%Fs\"\n"
  29.                    "\t   File:  \"%Fs\"\n"
  30.                    "\tSegment:  \"%Fs\"\n"
  31.                    "\t Offset:  %u\n"
  32.                    "\t  Error:  Target not within frame.\n",
  33.                    (*(*temp_file_header.lseg).tmodule).symbol,
  34.                    (*(*temp_file_header.lseg).file).filename,
  35.                 (*(*(*temp_file_header.lseg).segment).segment_name).symbol,
  36.                    temp_file_header.offset);
  37.   EndIf;
  38.  byte_location  = 
  39.               Addr((*temp_file_header.lseg).data[temp_file_header.offset]);
  40.  word_location  = (bit_16 far *) byte_location;
  41.  If fixup.mode IsZero
  42.   Then /* Self-relative fixup */
  43.    location_address = (*temp_file_header.lseg).address +
  44.                       Bit_32(temp_file_header.offset) +
  45.                       1L;
  46.    If fixup.location_type Is offset_location
  47.     Then
  48.      location_address++;
  49.     EndIf;
  50.    If (location_address LessThan frame_address) OrIf
  51.       (location_address Exceeds (frame_address + 65535L)) OrIf
  52.       (frame_absolute IsTrue)
  53.     Then
  54.      linker_error(4, "Fixup error:\n"
  55.                      "\t Module:  \"%Fs\"\n"
  56.                      "\t   File:  \"%Fs\"\n"
  57.                      "\tSegment:  \"%Fs\"\n"
  58.                      "\t Offset:  %u\n"
  59.                      "\t  Error:  Location not within frame.\n",
  60.                      (*(*temp_file_header.lseg).tmodule).symbol,
  61.                      (*(*temp_file_header.lseg).file).filename,
  62.                  (*(*(*temp_file_header.lseg).segment).segment_name).symbol,
  63.                      temp_file_header.offset);
  64.     EndIf;
  65.    Using fixup.location_type
  66.     BeginCase
  67.      When lobyte_location:
  68.       location_address = (*temp_file_header.lseg).address +
  69.                          Bit_32(temp_file_header.offset) +
  70.                          1L;
  71.       IP_distance_to_target = Int_32(target_address) -
  72.                               Int_32(location_address);
  73.       If (IP_distance_to_target < -128L) OrIf
  74.          (IP_distance_to_target > 127L)
  75.        Then
  76.         linker_error(4, "Byte self-relative fixup error:\n"
  77.                         "\t Module:  \"%Fs\"\n"
  78.                         "\t   File:  \"%Fs\"\n"
  79.                         "\tSegment:  \"%Fs\"\n"
  80.                         "\t Offset:  %u\n"
  81.                         "\t  Error:  Distance to target out of range.\n",
  82.                         (*(*temp_file_header.lseg).tmodule).symbol,
  83.                         (*(*temp_file_header.lseg).file).filename,
  84.                 (*(*(*temp_file_header.lseg).segment).segment_name).symbol,
  85.                         temp_file_header.offset);
  86.        EndIf;
  87.       *byte_location += Bit_8(IP_distance_to_target);
  88.       break;
  89.      When offset_location:
  90.       IP_distance_to_target = target_address - location_address;
  91.       *word_location += Bit_16(IP_distance_to_target);
  92.       break;
  93.      When base_location:       /* Undefined action */
  94.      When pointer_location:    /* Undefined action */
  95.      When hibyte_location:     /* Undefined action */
  96.       break;
  97.     EndCase;
  98.   Else /* Segment-relative fixup */
  99.    fbval          = Bit_16(frame_address ShiftedRight 4);
  100.    foval          = target_address - frame_address;
  101.    If (frame_absolute IsFalse)                     AndIf
  102.       (exefile IsFalse)                            AndIf
  103.       ((fixup.location_type Is base_location)      OrIf
  104.        (fixup.location_type Is pointer_location))
  105.     Then  /* Count the relocation items we should not be getting. */
  106.      n_relocation_items++;
  107.     EndIf;
  108.    Using fixup.location_type
  109.     BeginCase
  110.      When lobyte_location:
  111.       *byte_location += Bit_8(foval);
  112.       break;
  113.      When offset_location:
  114.       *word_location += Bit_16(foval);
  115.       break;
  116.      When base_location:
  117.       *word_location += fbval;
  118.       If exefile IsTrue
  119.        Then
  120.         Exe_header.relocation_table[Exe_header.n_relocation_items++] =
  121.          segment_offset(temp_file_header.lseg, temp_file_header.offset);
  122.        EndIf;
  123.       break;
  124.      When pointer_location:
  125.       *word_location++ += Bit_16(foval);
  126.       *word_location   += fbval;
  127.       If exefile IsTrue
  128.        Then
  129.         Exe_header.relocation_table[Exe_header.n_relocation_items++] =
  130.          segment_offset(temp_file_header.lseg, temp_file_header.offset+2);
  131.        EndIf;
  132.       break;
  133.      When hibyte_location:
  134.       *byte_location += Bit_8(foval ShiftedRight 8);
  135.       break;
  136.     EndCase;
  137.   EndIf;
  138.  return;
  139. EndCode
  140.  
  141. /*+-------------------------------------------------------------------------+
  142.   |                                                                         |
  143.   |                           fixup_FORREF_record                           |
  144.   |                                                                         |
  145.   +-------------------------------------------------------------------------+*/
  146. void fixup_FORREF_record()
  147. BeginDeclarations
  148. bit_16                                 len;
  149. lseg_ptr                               lseg;
  150. #define Lseg                           (*lseg)
  151. bit_16                                 offset;
  152. bit_8                                  size;
  153. EndDeclarations
  154. BeginCode
  155.  lseg          = temp_file_header.lseg;
  156.  len           = temp_file_header.rec_len;
  157.  file_read(BytePtr(object_file_element), len);
  158.  obj_ptr.b8       = object_file_element;
  159.  end_of_record.b8 = Addr(obj_ptr.b8[len]);
  160.  size             = *obj_ptr.b8++;
  161.  Using size
  162.   BeginCase
  163.    When 0:
  164.     While obj_ptr.b8 IsNot end_of_record.b8
  165.      BeginWhile
  166.       offset = *obj_ptr.b16++;
  167.       Lseg.data[offset] += *obj_ptr.b8++;
  168.      EndWhile;
  169.     break;
  170.    When 1:
  171.     While obj_ptr.b8 IsNot end_of_record.b8
  172.      BeginWhile
  173.       offset = *obj_ptr.b16++;
  174.       *((bit_16 far *) Addr(Lseg.data[offset])) += *obj_ptr.b16++;
  175.      EndWhile;
  176.     break;
  177.    When 2:
  178.     While obj_ptr.b8 IsNot end_of_record.b8
  179.      BeginWhile
  180.       offset = *obj_ptr.b16++;
  181.       *((bit_32 far *) Addr(Lseg.data[offset])) += *obj_ptr.b32++;
  182.      EndWhile;
  183.     break;
  184.    Otherwise:
  185.     linker_error(4, "Translator error:\n"
  186.                     "\t Module:  \"%Fs\"\n"
  187.                     "\t   File:  \"%Fs\"\n"
  188.                     "\tSegment:  \"%Fs\"\n"
  189.                     "\t  Error:  Invalid FORREF record.\n",
  190.                     (*(*temp_file_header.lseg).tmodule).symbol,
  191.                     (*(*temp_file_header.lseg).file).filename,
  192.             (*(*(*temp_file_header.lseg).segment).segment_name).symbol);
  193.     break;
  194.   EndCase;
  195.  return;
  196. EndCode
  197. #undef Lseg
  198.  
  199. /*+-------------------------------------------------------------------------+
  200.   |                                                                         |
  201.   |                           fixup_LEDATA_record                           |
  202.   |                                                                         |
  203.   +-------------------------------------------------------------------------+*/
  204. void fixup_LEDATA_record()
  205. BeginDeclarations
  206. lseg_ptr                               lseg;
  207. #define Lseg                           (*lseg)
  208. EndDeclarations
  209. BeginCode
  210.  lseg          = temp_file_header.lseg;
  211.  lseg_data_ptr = Addr(Lseg.data[temp_file_header.offset]);
  212.  file_read(lseg_data_ptr, temp_file_header.rec_len);
  213.  return;
  214. EndCode
  215. #undef Lseg
  216.  
  217. /*+-------------------------------------------------------------------------+
  218.   |                                                                         |
  219.   |                            fixup_LIDATA_IDB                             |
  220.   |                                                                         |
  221.   +-------------------------------------------------------------------------+*/
  222. void fixup_LIDATA_IDB()
  223. BeginDeclarations
  224. bit_16                                 block_count;
  225. bit_8                                 *content;
  226. bit_16                                 i;
  227. bit_16                                 j;
  228. bit_16                                 len;
  229. bit_16                                 repeat_count;
  230. EndDeclarations
  231. BeginCode
  232.  repeat_count = *obj_ptr.b16++;
  233.  block_count  = *obj_ptr.b16++;
  234.  If block_count IsNotZero
  235.   Then  /* Handle recursive case:  Content is iterated data block */
  236.    content = obj_ptr.b8;
  237.    For i=0; i<repeat_count; i++
  238.     BeginFor
  239.      obj_ptr.b8 = content;
  240.      For j=0; j<block_count; j++
  241.       BeginFor
  242.        fixup_LIDATA_IDB();
  243.       EndFor;
  244.     EndFor;
  245.   Else  /* Handle non-recursive case:  Content is data. */
  246.    len = Bit_16(*obj_ptr.b8++);
  247.    For i=0; i<repeat_count; i++
  248.     BeginFor
  249.      far_move(lseg_data_ptr, obj_ptr.b8, len);
  250.      lseg_data_ptr += len;
  251.     EndFor;
  252.    obj_ptr.b8 += len;
  253.   EndIf;
  254.  return;
  255. EndCode
  256.  
  257. /*+-------------------------------------------------------------------------+
  258.   |                                                                         |
  259.   |                           fixup_LIDATA_record                           |
  260.   |                                                                         |
  261.   +-------------------------------------------------------------------------+*/
  262. void fixup_LIDATA_record()
  263. BeginDeclarations
  264. lseg_ptr                               lseg;
  265. #define Lseg                           (*lseg)
  266. EndDeclarations
  267. BeginCode
  268.  lseg          = temp_file_header.lseg;
  269.  lseg_data_ptr = Addr(Lseg.data[temp_file_header.offset]);
  270.  file_read(BytePtr(object_file_element), temp_file_header.rec_len);
  271.  obj_ptr.b8       = object_file_element;
  272.  end_of_record.b8 = Addr(obj_ptr.b8[temp_file_header.rec_len]);
  273.  While obj_ptr.b8 IsNot end_of_record.b8
  274.   BeginWhile
  275.    fixup_LIDATA_IDB();
  276.   EndWhile;
  277.  return;
  278. EndCode
  279. #undef Lseg
  280.  
  281. /*+-------------------------------------------------------------------------+
  282.   |                                                                         |
  283.   |                                 frame                                   |
  284.   |                                                                         |
  285.   +-------------------------------------------------------------------------+*/
  286. bit_32 frame()
  287. BeginDeclarations
  288. bit_32                                 frame_address;
  289. group_entry_ptr                        grp;
  290. #define Grp                            (*grp)
  291. lseg_ptr                               lseg;
  292. #define Lseg                           (*lseg)
  293. public_entry_ptr                       pub;
  294. #define Pub                            (*pub)
  295. segment_entry_ptr                      seg;
  296. #define Seg                            (*seg)
  297. EndDeclarations
  298. BeginCode
  299.  Using fixup.frame_method
  300.   BeginCase
  301.    When 0:  /* Frame is segment relative */
  302.     lseg           = (lseg_ptr) fixup.frame_referent;
  303.     frame_absolute = Lseg.align Is absolute_segment;
  304.     seg            = Lseg.segment;
  305.     frame_address  = Seg.address;
  306.     break;
  307.    When 1:  /* Frame is group relative */
  308.     grp            = (group_entry_ptr) fixup.frame_referent;
  309.     seg            = Grp.first_segment;
  310.     lseg           = Seg.lsegs.first;
  311.     frame_absolute = Lseg.align Is absolute_segment;
  312.     frame_address  = Seg.address;
  313.     break;
  314.    When 2:  /* Frame is relative to external */
  315.     pub = (public_entry_ptr) fixup.frame_referent;
  316.     frame_address = public_frame_address(pub);
  317.     break;
  318.    When 3:  /* Frame is absolute */
  319.     frame_absolute = True;
  320.     frame_address  = Bit_32(fixup.frame_referent);
  321.     break;
  322.    When 4:  /* Frame is segment containing location */
  323.     lseg           = temp_file_header.lseg;
  324.     seg            = Lseg.segment;
  325.     frame_absolute = Lseg.align Is absolute_segment;
  326.     frame_address  = Seg.address;
  327.     break;
  328.    When 5:  /* Frame is defined by target */
  329.     Using fixup.target_method
  330.      BeginCase
  331.       When 0:  /* Target is segment relative */
  332.        lseg           = (lseg_ptr) fixup.target_referent;
  333.        seg            = Lseg.segment;
  334.        frame_absolute = Lseg.align Is absolute_segment;
  335.        frame_address  = Seg.address;
  336.        break;
  337.       When 1:  /* Target is group relative */
  338.        grp = (group_entry_ptr) fixup.target_referent;
  339.        seg            = Grp.first_segment;
  340.        lseg           = Seg.lsegs.first;
  341.        frame_absolute = Lseg.align Is absolute_segment;
  342.        frame_address  = Seg.address;
  343.        break;
  344.       When 2:  /* Target is relative to an external */
  345.        pub = (public_entry_ptr) fixup.target_referent;
  346.        frame_address = public_frame_address(pub);
  347.        break;
  348.       When 3:  /* Target is absolute */
  349.        frame_absolute = True;
  350.        frame_address  = Bit_32(fixup.target_referent);
  351.        break;
  352.      EndCase;
  353.     break;
  354.    When 6:  /* No frame */
  355.     frame_absolute = False;
  356.     frame_address = 0L;
  357.     break;
  358.   EndCase;
  359.  return(frame_address & 0xFFFFFFF0L);
  360. EndCode
  361. #undef Grp
  362. #undef Lseg
  363. #undef Pub
  364. #undef Seg
  365.  
  366. /*+-------------------------------------------------------------------------+
  367.   |                                                                         |
  368.   |                               pass_two                                  |
  369.   |                                                                         |
  370.   +-------------------------------------------------------------------------+*/
  371. void pass_two()
  372. BeginDeclarations
  373. EndDeclarations
  374. BeginCode
  375.  fixup_start_time = Now;
  376. /*+-------------------------------------------------------------------------+
  377.   |                                                                         |
  378.   |      First, we will figure out how long the EXE header will be.         |
  379.   |                                                                         |
  380.   +-------------------------------------------------------------------------+*/
  381.  If exefile IsTrue
  382.   Then
  383.    exe_header_size  = Bit_32(sizeof(EXE_header_type)) - 
  384.                       Bit_32(sizeof(bit_32)) + 
  385.                      (Bit_32(sizeof(bit_32)) * Bit_32(n_relocation_items));
  386.    If align_exe_header.val IsTrue
  387.     Then
  388.      exe_header_size += AlignmentGap(exe_header_size, 0xFL);
  389.     Else
  390.      exe_header_size += AlignmentGap(exe_header_size, 0x1FFL);
  391.     EndIf;
  392.    exe_header       = (EXE_header_ptr)
  393.                        allocate_memory(Addr(static_pool),
  394.                                        exe_header_size);
  395.    far_set(BytePtr(exe_header), 0, Bit_16(exe_header_size));
  396.   EndIf;
  397.  file_open_for_read(temp_file);
  398.  file_read(BytePtr(Addr(temp_file_header)), sizeof(temp_file_header));
  399.  While temp_file_header.rec_typ IsNotZero
  400.   BeginWhile
  401.    Using temp_file_header.rec_typ
  402.     BeginCase
  403.      When FIXUPP_record:
  404.       fixup_FIXUPP_record();
  405.       break;
  406.      When FORREF_record:
  407.       fixup_FORREF_record();
  408.       break;
  409.      When LEDATA_record:
  410.       fixup_LEDATA_record();
  411.       break;
  412.      When LIDATA_record:
  413.       fixup_LIDATA_record();
  414.       break;
  415.      Otherwise:
  416.       linker_error(16, "Internal logic error:  Invalid temp file record.\n");
  417.       break;
  418.     EndCase;
  419.    file_read(BytePtr(Addr(temp_file_header)), sizeof(temp_file_header));
  420.   EndWhile;
  421.  file_close_for_read();
  422.  return;
  423. EndCode
  424.  
  425. /*+-------------------------------------------------------------------------+
  426.   |                                                                         |
  427.   |                          public_frame_address                           |
  428.   |                                                                         |
  429.   +-------------------------------------------------------------------------+*/
  430. bit_32 public_frame_address(public_entry_ptr pub)
  431. BeginDeclarations
  432. bit_32                                 address;
  433. #define Pub                            (*pub)
  434. segment_entry_ptr                      seg;
  435. #define Seg                            (*seg)
  436. EndDeclarations
  437. BeginCode
  438.  frame_absolute = False;
  439.  If Pub.type_entry IsNot internal
  440.   Then
  441.    seg = (*temp_file_header.lseg).segment;
  442.    If Not fixup.external_error_detected
  443.     Then
  444.      linker_error(4, "\tModule \"%Fs\" in file \"%Fs\"\n"
  445.                      "\treferences unresolved external \"%Fs\"\n"
  446.                      "\tat offset %04XH in segment \"%Fs\".\n",
  447.                      (*(*temp_file_header.lseg).tmodule).symbol,
  448.                      (*(*temp_file_header.lseg).file).filename,
  449.                      Pub.symbol,
  450.                      temp_file_header.offset,
  451.                      (*Seg.segment_name).symbol);
  452.      fixup.external_error_detected = True;
  453.     EndIf;
  454.    address = 0L;
  455.   Else
  456.    If Pub.Internal.group IsNull
  457.     Then
  458.      If Pub.Internal.lseg IsNull
  459.       Then
  460.        frame_absolute = True;
  461.        address        = (Bit_32(Pub.Internal.frame) ShiftedLeft 4);
  462.       Else
  463.        frame_absolute = (*Pub.Internal.lseg).align Is absolute_segment;
  464.        address        = (*(*Pub.Internal.lseg).segment).address;
  465.       EndIf;
  466.     Else
  467.      frame_absolute = 
  468.                (*(*(*Pub.Internal.group).first_segment).lsegs.first).align Is
  469.                absolute_segment;
  470.      address        = (*(*Pub.Internal.group).first_segment).address;
  471.     EndIf;
  472.   EndIf;
  473.  return(address);
  474. EndCode
  475. #undef Pub
  476. #undef Seg
  477.  
  478. /*+-------------------------------------------------------------------------+
  479.   |                                                                         |
  480.   |                         public_target_address                           |
  481.   |                                                                         |
  482.   +-------------------------------------------------------------------------+*/
  483. bit_32 public_target_address(public_entry_ptr pub)
  484. BeginDeclarations
  485. bit_32                                 address;
  486. #define Pub                            (*pub)
  487. segment_entry_ptr                      seg;
  488. #define Seg                            (*seg)
  489. EndDeclarations
  490. BeginCode
  491.  If Pub.type_entry IsNot internal
  492.   Then
  493.    seg = (*temp_file_header.lseg).segment;
  494.    If Not fixup.external_error_detected
  495.     Then
  496.      linker_error(4, "\tModule \"%Fs\" in file \"%Fs\"\n"
  497.                      "\treferences unresolved external \"%Fs\"\n"
  498.                      "\tat offset %04XH in segment \"%Fs\".\n",
  499.                      (*(*temp_file_header.lseg).tmodule).symbol,
  500.                      (*(*temp_file_header.lseg).file).filename,
  501.                      Pub.symbol,
  502.                      temp_file_header.offset,
  503.                      (*Seg.segment_name).symbol);
  504.      fixup.external_error_detected = True;
  505.     EndIf;
  506.    address = 0L;
  507.   Else
  508.    If Pub.Internal.lseg IsNull
  509.     Then
  510.      address = (Bit_32(Pub.Internal.frame) ShiftedLeft 4);
  511.     Else
  512.      address = (*Pub.Internal.lseg).address;
  513.     EndIf;
  514.   EndIf;
  515.  return(address + Bit_32(Pub.Internal.offset));
  516. EndCode
  517. #undef Pub
  518. #undef Seg
  519.  
  520. /*+-------------------------------------------------------------------------+
  521.   |                                                                         |
  522.   |                              segment_offset                             |
  523.   |                                                                         |
  524.   +-------------------------------------------------------------------------+*/
  525. bit_32 segment_offset(lseg_ptr lseg, bit_16 offset)
  526. BeginDeclarations
  527. #define Lseg                           (*lseg)
  528. EndDeclarations
  529. BeginCode
  530.  return ((Frame(lseg) ShiftedLeft 12L) Or (Bit_32(offset) + Target(lseg)));
  531. EndCode
  532. #undef Lseg
  533.  
  534. /*+-------------------------------------------------------------------------+
  535.   |                                                                         |
  536.   |                                 target                                   |
  537.   |                                                                         |
  538.   +-------------------------------------------------------------------------+*/
  539. bit_32 target()
  540. BeginDeclarations
  541. group_entry_ptr                        grp;
  542. #define Grp                            (*grp)
  543. lseg_ptr                               lseg;
  544. #define Lseg                           (*lseg)
  545. public_entry_ptr                       pub;
  546. #define Pub                            (*pub)
  547. bit_32                                 target_address;
  548. EndDeclarations
  549. BeginCode
  550.  Using fixup.target_method
  551.   BeginCase
  552.    When 0:  /* Target is segment relative */
  553.     lseg = (lseg_ptr) fixup.target_referent;
  554.     target_address = Lseg.address + Bit_32(fixup.target_offset);
  555.     break;
  556.    When 1:  /* Target is group relative */
  557.     grp = (group_entry_ptr) fixup.target_referent;
  558.     target_address = (*Grp.first_segment).address +
  559.                       Bit_32(fixup.target_offset);
  560.     break;
  561.    When 2:  /* Target is relative to an external */
  562.     pub = (public_entry_ptr) fixup.target_referent;
  563.     target_address = public_target_address(pub) +
  564.                       Bit_32(fixup.target_offset);
  565.     break;
  566.    When 3:  /* Target is absolute */
  567.     target_address = Bit_32(fixup.target_referent) +
  568.                       Bit_32(fixup.target_offset);
  569.     break;
  570.   EndCase;
  571.  return(target_address);
  572. EndCode
  573. #undef Grp
  574. #undef Lseg
  575. #undef Pub
  576.  
  577.