} system_link[N_SYSTEM_LINK];
#define N_LOADED_SEGMENT 0x100
-int n_loaded_segment;
-struct loaded_segment {
+int n_known_segment;
+struct known_segment {
const char *name;
int segment;
int bitcount;
int linkage_offset;
struct system_link *system_link_head;
-} loaded_segment[N_LOADED_SEGMENT];
+} known_segment[N_LOADED_SEGMENT];
#define N_SEGMENT 0x200
-struct loaded_segment *loaded_segment_xref[N_SEGMENT];
+struct known_segment *known_segment_xref[N_SEGMENT];
int next_segment;
int linkage_segment;
int next_linkage_offset;
+int emcall_stubs_offset;
struct packed_pointer *lot;
struct packed_pointer *isot;
return segment;
}
-struct object_map *get_object_map(struct loaded_segment *p) {
+struct object_map *get_object_map(struct known_segment *p) {
rassert(p->bitcount % 36 == 0);
int wordcount = (p->bitcount / 36) & 0777777;
rassert(wordcount >= 1);
return offset;
}
-const char *xlate_segment(const char *name) {
+const char *xlate_segname(const char *name) {
// search for segment in path
int path_index;
for (path_index = 0; path_index < N_PATHS; ++path_index) {
return name;
}
-struct loaded_segment *load_segment(const char *name) {
+struct known_segment *make_known(const char *name) {
+ name = xlate_segname(name);
+
// see if already loaded
- for (int i = 0; i < n_loaded_segment; ++i)
- if (strcmp(loaded_segment[i].name, name) == 0)
- return loaded_segment + i;
+ for (int i = 0; i < n_known_segment; ++i)
+ if (strcmp(known_segment[i].name, name) == 0)
+ return known_segment + i;
// allocate table entries
- rassert(n_loaded_segment < N_LOADED_SEGMENT);
- struct loaded_segment *p =
- loaded_segment + n_loaded_segment++;
+ rassert(n_known_segment < N_LOADED_SEGMENT);
+ struct known_segment *p =
+ known_segment + n_known_segment++;
p->name = strdup(name);
rassert(p->name);
p->segment = allocate_segment();
fprintf(stderr, "load segname %s into segment %06o\n", name, p->segment);
- loaded_segment_xref[p->segment] = p;
+ known_segment_xref[p->segment] = p;
// search for segment in path
int path_index;
exit(EXIT_FAILURE);
found_bitcount:
- ;
- // validate linkage header
- struct object_map *object_map = get_object_map(p);
- rassert(
- object_map->linkage_length >=
- sizeof(struct linkage_header) / sizeof(uint64_t)
- );
- struct virgin_linkage_header *virgin_linkage_header =
- (struct virgin_linkage_header *)(
- M[p->segment] + object_map->linkage_offset
+ p->linkage_offset = 0;
+ p->system_link_head = NULL;
+ return p;
+}
+
+struct known_segment *link_segment(const char *name) {
+ struct known_segment *p = make_known(name);
+
+ if (p->linkage_offset == 0) {
+ // validate linkage header
+ struct object_map *object_map = get_object_map(p);
+ rassert(
+ object_map->linkage_length >=
+ sizeof(struct linkage_header) / sizeof(uint64_t)
);
- rassert(virgin_linkage_header->def_offset == object_map->definition_offset);
- rassert(virgin_linkage_header->first_ref_relp == 0);
- rassert(virgin_linkage_header->static_length == object_map->static_length);
+ struct virgin_linkage_header *virgin_linkage_header =
+ (struct virgin_linkage_header *)(
+ M[p->segment] + object_map->linkage_offset
+ );
+ rassert(virgin_linkage_header->def_offset == object_map->definition_offset);
+ rassert(virgin_linkage_header->first_ref_relp == 0);
+ rassert(virgin_linkage_header->static_length == object_map->static_length);
- // copy and fill in linkage section
- p->linkage_offset = allocate_linkage(object_map->linkage_length, 2);
- fprintf(
- stderr,
- "allocate_linkage %06o$[%06o, %06o)\n",
- linkage_segment,
- p->linkage_offset,
- p->linkage_offset + (int)object_map->linkage_length
- );
- if (strcmp(p->name, "hcs_") == 0)
- // patch in .my_lp
- *(struct its_pointer *)(M[p->segment] + 0312) = its_pointer(
+ // copy and fill in linkage section
+ p->linkage_offset = allocate_linkage(object_map->linkage_length, 2);
+ fprintf(
+ stderr,
+ "allocate_linkage %06o$[%06o, %06o)\n",
linkage_segment,
- p->linkage_offset
+ p->linkage_offset,
+ p->linkage_offset + (int)object_map->linkage_length
+ );
+ if (strcmp(p->name, "hcs_") == 0)
+ // patch in .my_lp
+ *(struct its_pointer *)(M[p->segment] + 0312) = its_pointer(
+ linkage_segment,
+ p->linkage_offset
+ );
+ struct linkage_header *linkage_header = (struct linkage_header *)(
+ M[linkage_segment] + p->linkage_offset
+ );
+ memcpy(
+ linkage_header,
+ virgin_linkage_header,
+ 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;
+
+ // copy static section
+ int static_offset = allocate_linkage(object_map->static_length, 2);
+ memcpy(
+ M[linkage_segment] + static_offset,
+ M[p->segment] + object_map->static_offset,
+ object_map->static_length * sizeof(uint64_t)
);
- struct linkage_header *linkage_header = (struct linkage_header *)(
- M[linkage_segment] + p->linkage_offset
- );
- memcpy(
- linkage_header,
- virgin_linkage_header,
- 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;
-
- // copy static section
- int static_offset = allocate_linkage(object_map->static_length, 2);
- memcpy(
- M[linkage_segment] + static_offset,
- M[p->segment] + object_map->static_offset,
- object_map->static_length * sizeof(uint64_t)
- );
-
- // update LOT, ISOT and LOT/ISOT high water
- lot[p->segment] = packed_pointer(linkage_segment, p->linkage_offset);
- isot[p->segment] = packed_pointer(linkage_segment, static_offset);
- stack_header->cur_lot_size = next_segment;
- p->system_link_head = NULL;
+ // update LOT, ISOT and LOT/ISOT high water
+ lot[p->segment] = packed_pointer(linkage_segment, p->linkage_offset);
+ isot[p->segment] = packed_pointer(linkage_segment, static_offset);
+ stack_header->cur_lot_size = next_segment;
+ }
return p;
}
buf[len] = 0;
}
+void get_string(char *buf, const uint64_t *string, int string_len) {
+ static int shifts[4] = {27, 18, 9, 0};
+ for (int i = 0; i < string_len; ++i)
+ buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
+ buf[string_len] = 0;
+}
+
+void get_string_rstrip(char *buf, const uint64_t *string, int string_len) {
+ static int shifts[4] = {27, 18, 9, 0};
+ for (int i = 0; i < string_len; ++i)
+ buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
+ while (string_len && buf[string_len - 1] == ' ')
+ --string_len;
+ buf[string_len] = 0;
+}
+
struct its_pointer find_definition(
- struct loaded_segment *p,
+ struct known_segment *p,
const char *name,
int class,
bool entry
) {
+ // redirect specific entry points to emcall stubs
+ if (strcmp(p->name, "hcs_") == 0) {
+ if (strcmp(name, "make_ptr") == 0)
+ return its_pointer(linkage_segment, emcall_stubs_offset);
+ }
+
struct object_map *object_map = get_object_map(p);
struct definition_header *definition_header = (struct definition_header *)(
M[p->segment] + object_map->definition_offset
// find segment of faulting instruction (for validation purposes)
rassert(cpu.PPR.PSR < N_SEGMENT);
- struct loaded_segment *p = loaded_segment_xref[cpu.PPR.PSR];
+ struct known_segment *p = known_segment_xref[cpu.PPR.PSR];
rassert(p);
// validate link address, using read-only linkage section (safer)
sizeof(segname)
);
*link = find_definition(
- load_segment(xlate_segment(segname)),
+ link_segment(segname),
offsetname,
-1,
false
);
}
+void emcall_exit_emulation(void) {
+ longjmp(exit_emulation, 1);
+}
+
+void emcall_make_ptr(void) {
+ struct arg_list *arg_list = (struct arg_list *)(
+ M[stack_segment] + cpu.rX[1]
+ );
+
+ rassert(arg_list->arg_count == 10);
+ struct its_pointer *ref_pointer = (struct its_pointer *)(
+ M[arg_list->args[0].segment] + arg_list->args[0].address
+ );
+ uint64_t *entryname = (uint64_t *)(
+ M[arg_list->args[1].segment] + arg_list->args[1].address
+ );
+ uint64_t *entry_point_name = (uint64_t *)(
+ M[arg_list->args[2].segment] + arg_list->args[2].address
+ );
+ struct its_pointer *entry_point_pointer = (struct its_pointer *)(
+ M[arg_list->args[3].segment] + arg_list->args[3].address
+ );
+ uint64_t *code = (uint64_t *)(
+ M[arg_list->args[4].segment] + arg_list->args[4].address
+ );
+
+ char entryname_buf[NAME_LEN + 1];
+ get_string_rstrip(entryname_buf, entryname, NAME_LEN);
+
+ char entry_point_name_buf[NAME_LEN + 1];
+ get_string_rstrip(entry_point_name_buf, entry_point_name, NAME_LEN);
+ printf("%s:%s\n", entryname_buf, entry_point_name_buf);
+
+ *ref_pointer =
+ entry_point_name_buf[0] ?
+ find_definition(
+ link_segment(entryname_buf),
+ entry_point_name_buf,
+ -1,
+ false
+ ) :
+ its_pointer(make_known(entryname_buf)->segment, 0);
+
+ fprintf(
+ stderr,
+ "make_ptr %s$%s -> %06o:%06o\n",
+ entryname_buf,
+ entry_point_name_buf,
+ ref_pointer->segment,
+ ref_pointer->address
+ );
+
+ *code = 0;
+}
+
int main(int argc, char **argv) {
bool af = false;
if (argc >= 2 && strcmp(argv[1], "--af") == 0) {
//DBG_ADDRMOD |
//DBG_APPENDING |
//DBG_TRACEEXT |
- //DBG_WARN |
+ DBG_WARN |
//DBG_DEBUG |
//DBG_INFO |
//DBG_NOTIFY |
stack_header->isot_ptr = its_pointer(linkage_segment, isot_offset);
// load pl1 operators
- struct loaded_segment *p = load_segment(xlate_segment("pl1_operators_"));
+ struct known_segment *p = link_segment("pl1_operators_");
struct its_pointer operator_table_pointer = find_definition(
p,
"operator_table",
allocate_stack(0, 8)
);
+ // create emcall stubs
+ emcall_stubs_offset = allocate_linkage(3, 1);
+ uint64_t *emcall_stubs = (uint64_t *)(
+ M[linkage_segment] + emcall_stubs_offset
+ );
+ emcall_stubs[0] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
+ emcall_stubs[1] = 0000027420400L; // emcall make_ptr
+ emcall_stubs[2] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
+
// create calling stub
int calling_stub_offset = allocate_linkage(2, 1);
uint64_t *calling_stub = (uint64_t *)(
calling_stub[0] = 0000622700100L; // tsx0 pr0|402 call_ext_out_desc
calling_stub[1] = 0000026420400L; // emcall exit_emulation
- cpu.rA = (word36)(n_args_af) << 19;
+ cpu.rA = (word36)n_args_af << 19;
cpu.rX[1] = arg_list_offset;
cpu.PR[0].RNR = 3;
cpu.PR[0].WORDNO = operator_table_pointer.address;
struct its_pointer entry_pointer = find_definition(
- load_segment(xlate_segment(entry_segname)),
+ link_segment(entry_segname),
entry_name,
-1,
true
// print result string
if (af) {
- char text[RESULT_LEN + 1];
+ char buf[RESULT_LEN + 1];
uint64_t *result = (uint64_t *)(M[stack_segment] + result_offset);
- int len = (int)(*result++ & 0777777);
- rassert(len < sizeof(text));
- static int shifts[4] = {27, 18, 9, 0};
- for (int i = 0; i < len; ++i)
- text[i] = (char)(result[i >> 2] >> shifts[i & 3]);
- text[len] = 0;
- printf("%s\n", text);
+ int result_len = (int)(*result++ & 0777777);
+ rassert(result_len < sizeof(buf));
+ get_string(buf, result, result_len);
+ printf("%s\n", buf);
}
return 0;