-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: \
--- /dev/null
+#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
#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"
const char *name;
int segment;
int bitcount;
+ int linkage_offset;
} loaded_segment[N_LOADED_SEGMENT];
#define N_SEGMENT 0x200
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;
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) {
--- /dev/null
+/* 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 */