Can now snap the first link, don't have bound segment name to search for in path...
authorNick Downing <nick@ndcode.org>
Sat, 19 Oct 2019 11:01:17 +0000 (22:01 +1100)
committerNick Downing <nick@ndcode.org>
Sat, 19 Oct 2019 11:02:40 +0000 (22:02 +1100)
Makefile
linkdcl.h [new file with mode: 0644]
multics_sim.c
pl1/linkdcl.incl.pl1 [new file with mode: 0644]

index a9606ef..d62db25 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-g -std=c99 -U__STRICT_ANSI__ -IdecNumber -Idps8 -D_GNU_SOURCE -DUSE_READER_THREAD -DUSE_INT64 -DTESTING -Wno-unused-result
+CFLAGS=-g -std=c99 -U__STRICT_ANSI__ -IdecNumber -Idps8 -D_GNU_SOURCE -DUSE_READER_THREAD -DUSE_INT64 -DTESTING -Wall -Wno-comment -Wno-unused-label -Wno-unused-result -Wno-unused-value -Wno-unused-variable -Wno-unused-function
 #-O3
 
 multics_sim: \
diff --git a/linkdcl.h b/linkdcl.h
new file mode 100644 (file)
index 0000000..4c0b552
--- /dev/null
+++ b/linkdcl.h
@@ -0,0 +1,147 @@
+#ifndef _LINKDCL_H
+#define _LINKDCL_H
+
+#include "pointer.h"
+
+// see pl1/linkdcl.incl.pl1
+
+// dcl 1 link based aligned, /* link pair in linkage section */
+struct link {
+  // 2 head_ptr bit (18) unal, /* rel pointer to beginning of linkage section */
+  // 2 ringno bit (3) unal,
+  // 2 mbz bit (6) unal,
+  // 2 run_depth fixed bin (2) unal, /* run unit depth, filled when link is snapped */
+  // 2 ft2 bit (6) unal, /* fault tag. 46(8) if not snapped, 43(8) if snapped */
+  uint64_t ft2 : 6;
+  int64_t run_depth : 3;
+  uint64_t mbz : 6;
+  uint64_t ringno : 3;
+  uint64_t head_ptr : 18;
+  uint64_t dummy0 : 28;
+
+  // 2 exp_ptr bit (18) unal, /* pointer (rel to defs) of expression word */
+  // 2 mbz2 bit (12) unal,
+  // 2 modifier bit (6) unal; /* modifier to be left in snapped link */
+  uint64_t modifier : 6;
+  uint64_t mbz2 : 12;
+  uint64_t exp_ptr : 18;
+  uint64_t dummy1 : 28;
+};
+
+#if 0 // avoid conflict with definition_dcls.h
+// dcl 1 exp_word based aligned, /* expression word in link definition */
+struct exp_word {
+  // 2 type_ptr bit (18) unal, /* pointer (rel to defs) of type pair structure */
+  // 2 exp bit (18) unal; /* constant expression to be added in when snapping link */
+  uint64_t exp : 18;
+  uint64_t type_ptr : 18;
+  uint64_t dummy0 : 28;
+};
+
+// dcl 1 type_pair based aligned, /* type pair in link definition */
+struct type_pair {
+  // 2 type bit (18) unal, /* type of link. may be 1,2,3,4,5, or 6 */
+  // 2 trap_ptr bit (18) unal, /* pointer (rel to defs) to the trap word */
+  uint64_t trap_ptr : 18;
+  uint64_t type : 18;
+  uint64_t dummy0 : 28;
+
+  // 2 seg_ptr bit (18) unal, /* pointer to ACC reference name for segment referenced */
+  // 2 ext_ptr bit (18) unal; /* pointer (rel to defs) of ACC segdef name */
+  uint64_t ext_ptr : 18;
+  uint64_t seg_ptr : 18;
+  uint64_t dummy1 : 28;
+};
+#endif
+
+// dcl 1 header based aligned, /* linkage block header */
+struct linkage_header {
+  // 2 def_ptr ptr, /* pointer to definition section */
+  struct its_pointer def_ptr;
+
+  // 2 symbol_ptr ptr unal, /* pointer to symbol section in object segment */
+  struct packed_pointer symbol_ptr;
+
+  // 2 original_linkage_ptr
+  // ptr unal, /* pointer to linkage section in object segment */
+  struct packed_pointer original_linkage_ptr;
+
+  // 2 unused bit (72),
+  uint64_t unused[2];
+
+  // 2 stats,
+  //   3 begin_links bit (18) unal, /* offset (rel to this section) of first link */
+  //   3 block_length bit (18) unal, /* number of words in this linkage section */
+  uint64_t stats_block_length : 18;
+  uint64_t stats_begin_links : 18;
+  uint64_t dummy0 : 28;
+
+  //   3 segment_number
+  // bit (18) unal, /* text segment number associated with this section */
+  //   3 static_length bit (18) unal; /* number of words of static for this segment */
+  uint64_t stats_static_length : 18;
+  uint64_t stats_segment_number : 18;
+  uint64_t dummy1 : 28;
+};
+
+// dcl 1 linkage_header_flags
+// aligned based, /* overlay of def_ptr for flags */
+struct linkage_header_flags {
+  // 2 pad1 bit (28) unaligned, /* flags are in first word */
+  // 2 static_vlas bit (1) unaligned, /* static section "owns" some LA/VLA segments */
+  // 2 perprocess_static
+  // bit (1) unaligned, /* 1 copy of static section is used by all tasks/run units */
+  // 2 pad2 bit (6) unaligned;
+  uint64_t pad2 : 6;
+  uint64_t perprocess_static : 1;
+  uint64_t static_vlas : 1;
+  uint64_t pad1 : 28;
+  uint64_t dummy0 : 28;
+};
+
+// dcl 1 virgin_linkage_header
+// aligned based, /* template for linkage header in object segment */
+struct virgin_linkage_header {
+  // 2 pad bit (30) unaligned, /* is filled in by linker */
+  // 2 defs_in_link bit (6) unaligned, /* =o20 if defs in linkage (nonstandard) */
+  uint64_t defs_in_link : 6;
+  uint64_t pad : 30;
+  uint64_t dummy0 : 28;
+
+  // 2 def_offset bit (18) unaligned, /* offset of definition section */
+  // 2 first_ref_relp bit (18) unaligned, /* offset of trap-at-first-reference offset array */
+  uint64_t first_ref_relp : 18;
+  uint64_t def_offset : 18;
+  uint64_t dummy1 : 28;
+
+  // 2 filled_in_later bit (144),
+  uint64_t filled_in_later[4];
+
+  // 2 link_begin bit (18) unaligned, /* offset of first link */
+  // 2 linkage_section_lng
+  // bit (18) unaligned, /* length of linkage section */
+  uint64_t linkage_section_lng : 18;
+  uint64_t link_begin : 18;
+  uint64_t dummy2 : 28;
+
+  // 2 segno_pad bit (18) unaligned, /* will be segment number of copied linkage */
+  // 2 static_length bit (18) unaligned; /* length of static section */
+  uint64_t static_length : 18;
+  uint64_t segno_pad : 18;
+  uint64_t dummy3 : 28;
+};
+
+// dcl 1 trap_word based aligned, /* trap word in link definition */
+struct trap_word {
+  // 2 call_ptr bit (18) unal, /* pointer (rel to link) of link to trap procedure */
+  // 2 arg_ptr bit (18) unal; /* pointer (rel to link) of link to arg info for trap proc */
+  uint64_t arg_ptr : 18;
+  uint64_t call_ptr : 18;
+  uint64_t dummy0 : 28;
+};
+
+// dcl 1 name based aligned, /* storage of ASCII names in definitions */
+//   2 nchars bit (9) unaligned, /* number of characters in name */
+//   2 char_string char (31) unaligned; /* 31-character name */
+
+#endif
index 520a3b2..577167b 100644 (file)
@@ -11,6 +11,7 @@
 #include "dps8/dps8.h"
 #include "dps8/dps8_cpu.h"
 #include "dps8/dps8_sys.h"
+#include "linkdcl.h"
 #include "object_map.h"
 #include "rassert.h"
 #include "stack_header.h"
@@ -27,6 +28,7 @@ struct loaded_segment {
   const char *name;
   int segment;
   int bitcount;
+  int linkage_offset;
 } loaded_segment[N_LOADED_SEGMENT];
 
 #define N_SEGMENT 0x200
@@ -150,27 +152,57 @@ found_segment:
 found_bitcount:
   ;
   struct object_map *object_map = get_object_map(p);
+  rassert(
+    object_map->linkage_length >=
+      sizeof(struct linkage_header) / sizeof(uint64_t)
+  );
+  rassert(
+    next_linkage_offset +
+      object_map->linkage_length +
+      object_map->static_length <=
+      01000000
+  );
 
-  // copy linkage section
-  lot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
-  rassert(next_linkage_offset + object_map->linkage_length <= 01000000);
+  // copy and fill in linkage section
+  struct linkage_header *linkage_header = (struct linkage_header *)(
+    M[linkage_segment] + next_linkage_offset
+  );
   memcpy(
-    M[linkage_segment] + next_linkage_offset,
+    linkage_header,
     M[p->segment] + object_map->linkage_offset,
     object_map->linkage_length * sizeof(uint64_t)
   );
+  linkage_header->def_ptr = its_pointer(
+    p->segment,
+    object_map->definition_offset
+  );
+  linkage_header->symbol_ptr = packed_pointer(
+    p->segment,
+    object_map->symbol_offset
+  );
+  linkage_header->original_linkage_ptr = packed_pointer(
+    p->segment,
+    object_map->linkage_offset
+  );
+  linkage_header->stats_segment_number = linkage_segment;
+
+  // create LOT entry
+  p->linkage_offset = next_linkage_offset;
+  lot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
   next_linkage_offset += object_map->linkage_length;
 
   // copy static section
-  isot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
-  rassert(next_linkage_offset + object_map->static_length <= 01000000);
   memcpy(
     M[linkage_segment] + next_linkage_offset,
     M[p->segment] + object_map->static_offset,
     object_map->static_length * sizeof(uint64_t)
   );
+
+  // create ISOT entry
+  isot[p->segment] = packed_pointer(linkage_segment, next_linkage_offset);
   next_linkage_offset += object_map->static_length;
 
+  // update LOT/ISOT high water
   stack_header->cur_lot_size = next_segment;
 
   return p;
@@ -300,20 +332,98 @@ bool snap_link(void) {
     cpu.TPR.CA
   );
 
-  struct loaded_segment *p;
-  struct object_map *object_map;
-  if (
-    cpu.PPR.PSR >= N_SEGMENT ||
-    (p = loaded_segment_xref[cpu.PPR.PSR]) == NULL ||
-    cpu.TPR.TSR != lot[cpu.PPR.PSR].segment ||
-    cpu.TPR.CA < lot[cpu.PPR.PSR].address ||
-    cpu.TPR.CA >= lot[cpu.PPR.PSR].address + (
-      object_map = get_object_map(p)
-    )->linkage_length
-  )
+  // find segment of faulting instruction (for validation purposes)
+  if (cpu.PPR.PSR >= N_SEGMENT)
+    return false;
+  struct loaded_segment *p = loaded_segment_xref[cpu.PPR.PSR];
+  if (p == NULL)
     return false;
 
-  abort();
+  // validate link address, using read-only linkage section (safer)
+  struct object_map *object_map = get_object_map(p);
+  struct virgin_linkage_header *virgin_linkage_header =
+    (struct virgin_linkage_header *)(
+      M[p->segment] + object_map->linkage_offset
+    );
+   if (
+     cpu.TPR.TSR != linkage_segment ||
+     cpu.TPR.CA & 1 ||
+     cpu.TPR.CA <
+       p->linkage_offset + virgin_linkage_header->first_ref_relp ||
+     cpu.TPR.CA >=
+       p->linkage_offset + object_map->linkage_length
+   )
+     return false;
+
+  // validate link, using read-only linkage section (safer)
+  int link_relp = (int)(cpu.TPR.CA - p->linkage_offset);
+  struct link *virgin_link = (struct link *)(
+    (uint64_t *)virgin_linkage_header + link_relp
+  );
+  rassert(virgin_link->head_ptr == (-link_relp & 0777777));
+  rassert(virgin_link->ft2 == 046);
+
+  // make sure writeable copy of link hasn't been corrupted
+  struct its_pointer *link = (struct its_pointer *)(
+    M[cpu.TPR.TSR] + cpu.TPR.CA
+  );
+  if (memcmp(link, virgin_link, sizeof(struct link)))
+    return false;
+
+  // look up link target
+  struct definition_header *definition_header = (struct definition_header *)(
+    M[p->segment] + object_map->definition_offset
+  );
+  struct exp_word *exp_word = (struct exp_word *)(
+    (uint64_t *)definition_header + virgin_link->exp_ptr
+  );
+  struct type_pair *type_pair = (struct type_pair *)(
+    (uint64_t *)definition_header + exp_word->type_relp
+  );
+  rassert(
+    type_pair->type >= LINK_SELF_BASE &&
+      type_pair->type <= LINK_CREATE_IF_NOT_FOUND
+  );
+  printf("link type %s\n", link_type_names[type_pair->type - 1]);
+
+  // process link by type
+  switch (type_pair->type) {
+  case LINK_REFNAME_OFFSETNAME:
+    {
+      char segname[0x20];
+      get_acc_string(
+        (uint64_t *)definition_header + type_pair->segname_relp,
+        segname,
+        sizeof(segname)
+      );
+
+      char offsetname[0x20];
+      get_acc_string(
+        (uint64_t *)definition_header + type_pair->offsetname_relp,
+        offsetname,
+        sizeof(offsetname)
+      );
+
+      printf(
+        "link target %s$%s + %06o\n",
+        segname,
+        offsetname,
+        exp_word->expression
+      );
+
+      struct loaded_segment *q = load_segment("bound_library_1_");
+      *link = its_pointer(
+        q->segment,
+        find_entry(q, segname, offsetname, false)
+      );
+      link->modifier1 = virgin_link->modifier;
+    }
+    break;
+  default:
+    rassert(false);
+  }
+
+  return true;
 }
 
 int main(int argc, char **argv) {
diff --git a/pl1/linkdcl.incl.pl1 b/pl1/linkdcl.incl.pl1
new file mode 100644 (file)
index 0000000..1152f45
--- /dev/null
@@ -0,0 +1,74 @@
+/* BEGIN INCLUDE FILE linkdcl.incl.pl1 --- last modified 15 Nov 1971 by C Garman */
+
+/* Last Modified (Date and Reason):
+   6/75 by M.Weaver to add virgin_linkage_header declaration
+   6/75 by S.Webber to comment existing structures better
+   9/77 by M. Weaver to add run_depth to link
+   2/83 by M. Weaver to add linkage header flags and change run_depth precision
+*/
+
+/* format: style3 */
+dcl    1 link          based aligned,          /* link pair in linkage section */
+         2 head_ptr    bit (18) unal,          /* rel pointer to beginning of linkage section */
+         2 ringno      bit (3) unal,
+         2 mbz         bit (6) unal,
+         2 run_depth   fixed bin (2) unal,             /* run unit depth, filled when link is snapped */
+         2 ft2         bit (6) unal,           /* fault tag. 46(8) if not snapped, 43(8) if snapped */
+         2 exp_ptr     bit (18) unal,          /* pointer (rel to defs) of expression word */
+         2 mbz2                bit (12) unal,
+         2 modifier    bit (6) unal;           /* modifier to be left in snapped link */
+
+dcl    1 exp_word      based aligned,          /* expression word in link definition */
+         2 type_ptr    bit (18) unal,          /* pointer (rel to defs) of type pair structure */
+         2 exp         bit (18) unal;          /* constant expression to be added in when snapping link */
+
+dcl    1 type_pair     based aligned,          /* type pair in link definition */
+         2 type                bit (18) unal,          /* type of link. may be 1,2,3,4,5, or 6 */
+         2 trap_ptr    bit (18) unal,          /* pointer (rel to defs) to the trap word */
+         2 seg_ptr     bit (18) unal,          /* pointer to ACC reference name for segment referenced */
+         2 ext_ptr     bit (18) unal;          /* pointer (rel to defs)  of ACC segdef name */
+
+dcl    1 header                based aligned,          /* linkage block header */
+         2 def_ptr     ptr,                    /* pointer to definition section */
+         2 symbol_ptr  ptr unal,                       /* pointer to symbol section in object segment */
+         2 original_linkage_ptr
+                       ptr unal,                       /* pointer to linkage section in object segment */
+         2 unused      bit (72),
+         2 stats,
+           3 begin_links       bit (18) unal,          /* offset (rel to this section) of first link */
+           3 block_length      bit (18) unal,          /* number of words in this linkage section */
+           3 segment_number
+                       bit (18) unal,          /* text segment number associated with this section */
+           3 static_length bit (18) unal;              /* number of words of static for this segment */
+
+dcl    1 linkage_header_flags
+                       aligned based,          /* overlay of def_ptr for flags */
+         2 pad1                bit (28) unaligned,             /* flags are in first word */
+         2 static_vlas bit (1) unaligned,              /* static section "owns" some LA/VLA segments */
+         2 perprocess_static
+                       bit (1) unaligned,              /* 1 copy of static section is used by all tasks/run units */
+         2 pad2                bit (6) unaligned;
+
+dcl    1 virgin_linkage_header
+                       aligned based,          /* template for linkage header in object segment */
+         2 pad         bit (30) unaligned,             /* is filled in by linker */
+         2 defs_in_link        bit (6) unaligned,              /* =o20 if defs in linkage (nonstandard) */
+         2 def_offset  bit (18) unaligned,             /* offset of definition section */
+         2 first_ref_relp      bit (18) unaligned,             /* offset of trap-at-first-reference offset array */
+         2 filled_in_later bit (144),
+         2 link_begin  bit (18) unaligned,             /* offset of first link */
+         2 linkage_section_lng
+                       bit (18) unaligned,             /* length of linkage section */
+         2 segno_pad   bit (18) unaligned,             /* will be segment number of copied linkage */
+         2 static_length       bit (18) unaligned;             /* length of static section */
+
+
+dcl    1 trap_word     based aligned,          /* trap word in link definition */
+         2 call_ptr    bit (18) unal,          /* pointer (rel to link) of link to trap procedure */
+         2 arg_ptr     bit (18) unal;          /* pointer (rel to link) of link to arg info for trap proc */
+
+dcl    1 name          based aligned,          /* storage of ASCII names in definitions */
+         2 nchars      bit (9) unaligned,              /* number of characters in name */
+         2 char_string char (31) unaligned;    /* 31-character name */
+
+/* END INCLUDE FILE linkdcl.incl.pl1 */