/* Disassemble the expression EXPR, writing to F. */ void ax_print (struct ui_file *f, struct agent_expr *x) { int i; fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope)); fprintf_filtered (f, _("Reg mask:")); for (i = 0; i < x->reg_mask_len; ++i) fprintf_filtered (f, _(" %02x"), x->reg_mask[i]); fprintf_filtered (f, _("\n")); /* Check the size of the name array against the number of entries in the enum, to catch additions that people didn't sync. */ if ((sizeof (aop_map) / sizeof (aop_map[0])) != aop_last) error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync")); for (i = 0; i < x->len;) { enum agent_op op = x->buf[i]; if (op >= (sizeof (aop_map) / sizeof (aop_map[0])) || !aop_map[op].name) { fprintf_filtered (f, _("%3d <bad opcode %02x>\n"), i, op); i++; continue; } if (i + 1 + aop_map[op].op_size > x->len) { fprintf_filtered (f, _("%3d <incomplete opcode %s>\n"), i, aop_map[op].name); break; } fprintf_filtered (f, "%3d %s", i, aop_map[op].name); if (aop_map[op].op_size > 0) { fputs_filtered (" ", f); print_longest (f, 'd', 0, read_const (x, i + 1, aop_map[op].op_size)); } /* Handle the complicated printf arguments specially. */ else if (op == aop_printf) { int slen, nargs; i++; nargs = x->buf[i++]; slen = x->buf[i++]; slen = slen * 256 + x->buf[i++]; fprintf_filtered (f, _(" \"%s\", %d args"), &(x->buf[i]), nargs); i += slen - 1; } fprintf_filtered (f, "\n"); i += 1 + aop_map[op].op_size; } }
PCFOP * read_instr(struct PCFState * st, const char * line, uint32_t iptr) { char buf[LINE_MAX], *bitr; buf[0] = '\0'; bitr = buf; assert(line[0] == '('); line++; while((line[0] != ' ') && (line[0] != ')')) { bitr[0] = line[0]; line++; bitr++; } bitr[0] = '\0'; if(strcmp(buf, "LABEL") == 0) return read_label(line, st, iptr); else if(strcmp(buf, "INITBASE") == 0) return read_initbase(line); else if(strcmp(buf, "CONST") == 0) return read_const(line); else if(strcmp(buf, "GATE") == 0) return read_gate(line); else if(strcmp(buf, "BITS") == 0) return read_bits(line); else if(strcmp(buf, "MKPTR") == 0) return read_mkptr(line); else if(strcmp(buf, "COPY") == 0) return read_copy(line); else if(strcmp(buf, "COPY-INDIR") == 0) return read_copy_indir(line); else if(strcmp(buf, "INDIR-COPY") == 0) return read_indir_copy(line); else if(strcmp(buf, "CALL") == 0) return read_call(line); else if(strcmp(buf, "RET") == 0) return read_ret(line); else if(strcmp(buf, "BRANCH") == 0) return read_branch(line); else if(strcmp(buf, "CLEAR") == 0) return read_clear(line); else if(strcmp(buf, "JOIN") == 0) return read_join(line); else if(strcmp(buf, "ADD") == 0) return read_add(line); else if(strcmp(buf, "MUL") == 0) return read_mul(line); assert(0); }
/* Disassemble the expression EXPR, writing to F. */ void ax_print(struct ui_file *f, struct agent_expr *x) { long i; bool is_float = 0; /* Check the size of the name array against the number of entries in * the enum, to catch additions that people did NOT sync: */ if ((sizeof(aop_map) / sizeof(aop_map[0])) != aop_last) error(_("GDB bug: ax-general.c (ax_print): opcode map out of sync")); for (i = 0; i < (long)x->len;) { enum agent_op op = (enum agent_op)x->buf[i]; if ((op >= (sizeof(aop_map) / sizeof(aop_map[0]))) || !aop_map[op].name) { fprintf_filtered(f, _("%3d <bad opcode %02x>\n"), (int)i, op); i++; continue; } if (((size_t)(i + 1L) + aop_map[op].op_size) > x->len) { fprintf_filtered(f, _("%3d <incomplete opcode %s>\n"), (int)i, aop_map[op].name); break; } fprintf_filtered(f, "%3d %s", (int)i, aop_map[op].name); if (aop_map[op].op_size > 0) { fputs_filtered(" ", f); print_longest(f, 'd', 0, read_const(x, (int)(i + 1), (int)aop_map[op].op_size)); } fprintf_filtered(f, "\n"); i += (1L + (long)aop_map[op].op_size); is_float = (op == aop_float); if (is_float) { ; /* ??? */ } } }
/* Disassemble the expression EXPR, writing to F. */ void ax_print (struct ui_file *f, struct agent_expr *x) { int i; int is_float = 0; /* Check the size of the name array against the number of entries in the enum, to catch additions that people didn't sync. */ if ((sizeof (aop_map) / sizeof (aop_map[0])) != aop_last) error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync")); for (i = 0; i < x->len;) { enum agent_op op = x->buf[i]; if (op >= (sizeof (aop_map) / sizeof (aop_map[0])) || !aop_map[op].name) { fprintf_filtered (f, _("%3d <bad opcode %02x>\n"), i, op); i++; continue; } if (i + 1 + aop_map[op].op_size > x->len) { fprintf_filtered (f, _("%3d <incomplete opcode %s>\n"), i, aop_map[op].name); break; } fprintf_filtered (f, "%3d %s", i, aop_map[op].name); if (aop_map[op].op_size > 0) { fputs_filtered (" ", f); print_longest (f, 'd', 0, read_const (x, i + 1, aop_map[op].op_size)); } fprintf_filtered (f, "\n"); i += 1 + aop_map[op].op_size; is_float = (op == aop_float); } }
/* Given an agent expression AX, fill in requirements and other descriptive bits. */ void ax_reqs (struct agent_expr *ax) { int i; int height; /* Jump target table. targets[i] is non-zero iff we have found a jump to offset i. */ char *targets = (char *) alloca (ax->len * sizeof (targets[0])); /* Instruction boundary table. boundary[i] is non-zero iff our scan has reached an instruction starting at offset i. */ char *boundary = (char *) alloca (ax->len * sizeof (boundary[0])); /* Stack height record. If either targets[i] or boundary[i] is non-zero, heights[i] is the height the stack should have before executing the bytecode at that point. */ int *heights = (int *) alloca (ax->len * sizeof (heights[0])); /* Pointer to a description of the present op. */ struct aop_map *op; memset (targets, 0, ax->len * sizeof (targets[0])); memset (boundary, 0, ax->len * sizeof (boundary[0])); ax->max_height = ax->min_height = height = 0; ax->flaw = agent_flaw_none; ax->max_data_size = 0; for (i = 0; i < ax->len; i += 1 + op->op_size) { if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0]))) { ax->flaw = agent_flaw_bad_instruction; return; } op = &aop_map[ax->buf[i]]; if (!op->name) { ax->flaw = agent_flaw_bad_instruction; return; } if (i + 1 + op->op_size > ax->len) { ax->flaw = agent_flaw_incomplete_instruction; return; } /* If this instruction is a forward jump target, does the current stack height match the stack height at the jump source? */ if (targets[i] && (heights[i] != height)) { ax->flaw = agent_flaw_height_mismatch; return; } boundary[i] = 1; heights[i] = height; height -= op->consumed; if (height < ax->min_height) ax->min_height = height; height += op->produced; if (height > ax->max_height) ax->max_height = height; if (op->data_size > ax->max_data_size) ax->max_data_size = op->data_size; /* For jump instructions, check that the target is a valid offset. If it is, record the fact that that location is a jump target, and record the height we expect there. */ if (aop_goto == op - aop_map || aop_if_goto == op - aop_map) { int target = read_const (ax, i + 1, 2); if (target < 0 || target >= ax->len) { ax->flaw = agent_flaw_bad_jump; return; } /* Do we have any information about what the stack height should be at the target? */ if (targets[target] || boundary[target]) { if (heights[target] != height) { ax->flaw = agent_flaw_height_mismatch; return; } } /* Record the target, along with the stack height we expect. */ targets[target] = 1; heights[target] = height; } /* For unconditional jumps with a successor, check that the successor is a target, and pick up its stack height. */ if (aop_goto == op - aop_map && i + 3 < ax->len) { if (!targets[i + 3]) { ax->flaw = agent_flaw_hole; return; } height = heights[i + 3]; } /* For reg instructions, record the register in the bit mask. */ if (aop_reg == op - aop_map) { int reg = read_const (ax, i + 1, 2); ax_reg_mask (ax, reg); } } /* Check that all the targets are on boundaries. */ for (i = 0; i < ax->len; i++) if (targets[i] && !boundary[i]) { ax->flaw = agent_flaw_bad_jump; return; } ax->final_height = height; }
/* Given an agent expression AX, fill in an agent_reqs structure REQS describing it. */ void ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs) { int i; int height; /* Bit vector for registers used. */ int reg_mask_len = 1; unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0])); /* Jump target table. targets[i] is non-zero iff we have found a jump to offset i. */ char *targets = (char *) alloca (ax->len * sizeof (targets[0])); /* Instruction boundary table. boundary[i] is non-zero iff our scan has reached an instruction starting at offset i. */ char *boundary = (char *) alloca (ax->len * sizeof (boundary[0])); /* Stack height record. If either targets[i] or boundary[i] is non-zero, heights[i] is the height the stack should have before executing the bytecode at that point. */ int *heights = (int *) alloca (ax->len * sizeof (heights[0])); /* Pointer to a description of the present op. */ struct aop_map *op; memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0])); memset (targets, 0, ax->len * sizeof (targets[0])); memset (boundary, 0, ax->len * sizeof (boundary[0])); reqs->max_height = reqs->min_height = height = 0; reqs->flaw = agent_flaw_none; reqs->max_data_size = 0; for (i = 0; i < ax->len; i += 1 + op->op_size) { if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0]))) { reqs->flaw = agent_flaw_bad_instruction; xfree (reg_mask); return; } op = &aop_map[ax->buf[i]]; if (!op->name) { reqs->flaw = agent_flaw_bad_instruction; xfree (reg_mask); return; } if (i + 1 + op->op_size > ax->len) { reqs->flaw = agent_flaw_incomplete_instruction; xfree (reg_mask); return; } /* If this instruction is a forward jump target, does the current stack height match the stack height at the jump source? */ if (targets[i] && (heights[i] != height)) { reqs->flaw = agent_flaw_height_mismatch; xfree (reg_mask); return; } boundary[i] = 1; heights[i] = height; height -= op->consumed; if (height < reqs->min_height) reqs->min_height = height; height += op->produced; if (height > reqs->max_height) reqs->max_height = height; if (op->data_size > reqs->max_data_size) reqs->max_data_size = op->data_size; /* For jump instructions, check that the target is a valid offset. If it is, record the fact that that location is a jump target, and record the height we expect there. */ if (aop_goto == op - aop_map || aop_if_goto == op - aop_map) { int target = read_const (ax, i + 1, 2); if (target < 0 || target >= ax->len) { reqs->flaw = agent_flaw_bad_jump; xfree (reg_mask); return; } /* Do we have any information about what the stack height should be at the target? */ if (targets[target] || boundary[target]) { if (heights[target] != height) { reqs->flaw = agent_flaw_height_mismatch; xfree (reg_mask); return; } } /* Record the target, along with the stack height we expect. */ targets[target] = 1; heights[target] = height; } /* For unconditional jumps with a successor, check that the successor is a target, and pick up its stack height. */ if (aop_goto == op - aop_map && i + 3 < ax->len) { if (!targets[i + 3]) { reqs->flaw = agent_flaw_hole; xfree (reg_mask); return; } height = heights[i + 3]; } /* For reg instructions, record the register in the bit mask. */ if (aop_reg == op - aop_map) { int reg = read_const (ax, i + 1, 2); int byte = reg / 8; /* Grow the bit mask if necessary. */ if (byte >= reg_mask_len) { /* It's not appropriate to double here. This isn't a string buffer. */ int new_len = byte + 1; reg_mask = xrealloc (reg_mask, new_len * sizeof (reg_mask[0])); memset (reg_mask + reg_mask_len, 0, (new_len - reg_mask_len) * sizeof (reg_mask[0])); reg_mask_len = new_len; } reg_mask[byte] |= 1 << (reg % 8); } } /* Check that all the targets are on boundaries. */ for (i = 0; i < ax->len; i++) if (targets[i] && !boundary[i]) { reqs->flaw = agent_flaw_bad_jump; xfree (reg_mask); return; } reqs->final_height = height; reqs->reg_mask_len = reg_mask_len; reqs->reg_mask = reg_mask; }
int Linker::read_code(FILE* f, FILE* pFtarg, long init_pos, int length, aBYTE* buf) { aBYTE op; int x; #ifdef BUG_LINK int i; #endif while( init_pos < length) { #ifdef BUG_LINK fprintf(lout, "\nstart length %d init_pos %d ", length, init_pos); #endif if (0 == fread(buf, CODESIZE, 1, f)) aborteof(aS("code")); ucFWRITE(buf, CODESIZE, 1, pFtarg); init_pos += CODESIZE; op = *buf; #ifdef BUG_LINK fprintf(lout, "\nop %d, %s: ", (int) op, lops[op]); #endif switch(op) { case Ono_op: // no args case Ofail: case Oproceed: case Odealloc: case Ocut: case Ocut64: case Otrust_me_else: case Ou_var_getlist: case Ounify_nil: break; case Ounify_y_var: // Xi or Yi case Ounify_y_val: case Ounify_unsafe: case Oget_nil: case Oget_list: case Oput_nil: case Oput_list: case Ounify_x_var: case Ounify_x_val: if (0 == fread(buf, 2, 1, f)) aborteof(aS("unify x val")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; break; case Oget_y_var: // Xi and Yi or Xj case Oget_y_val: case Oput_y_var: case Oput_y_val: case Oput_unsafe: case Oget_x_var: case Oget_x_val: case Oput_x_var: case Oput_x_val: if (0 == fread(buf, 2, 2, f)) aborteof(aS("put x val")); ucFWRITE(buf, 2, 2, pFtarg); init_pos += 4; break; case Ounify_void: // short int case Oalloc: case Ocutd: case Oretry_me_else: case Oretry: case Otrust: case Ogoto: case Otrust_me_2_else: case Olabel: if (0 == fread(buf, 2, 1, f)) aborteof(aS("label")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; #ifdef BUG_LINK fprintf(lout, "%d", (int) getint16(buf)); #endif break; case Otry_me_else: case Otry_me_or_else: case Otry: // 2 short ints if (0 == fread(buf, 2, 2, f)) aborteof(aS("try")); ucFWRITE(buf, 2, 2, pFtarg); init_pos += 4; #ifdef BUG_LINK fprintf(lout, "%d, %d", (int) getint16(buf), (int) getint16(buf+2)); #endif break; case Oget_con: // Constant, Xi case Oput_con: read_const(f, pFtarg, &init_pos); if (0 == fread(buf, 2, 1, f)) aborteof(aS("put con")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; break; case Oexec: case Oescape: case Ocall: case Omod_call: case Omod_exec: case Oget_struc: // functor, arity, (Xi or short or null) case Oput_struc: read_atom(f, pFtarg); // functor init_pos += 2; if (op == Ocall || op == Oexec || op == Omod_call || op == Omod_exec) // new style call/exec { //if (0 == fread(buf, 2, 1, f)) // aborteof(aS("put struc")); //ucFWRITE(buf, 2, 1, pFtarg); // shouldn't this be a read atom, not just a buf?? read_atom(f, pFtarg); init_pos += 2; } if (0 == fread(buf, 2, 1, f)) aborteof(aS("put struc 2")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; #ifdef BUG_LINK fprintf(lout, " arity = %d", (int) getint16(buf)); #endif // now figure third (optional arg if (op == Oget_struc || op == Oput_struc) // Xi { if (0 == fread(buf, 2, 1, f)) aborteof(aS("put struc 3")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; #ifdef BUG_LINK fprintf(lout, " xi(get/put_struc) = %d", (int) getint16(buf)); #endif } else if (op == Ocall || op == Omod_call) // short { if (0 == fread(buf, 2, 1, f)) aborteof(aS("put struc 4")); ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; #ifdef BUG_LINK fprintf(lout, " short(call/mod_call) = %d", (int) getint16(buf)); #endif } // else no 3rd arg break; case Ounify_con: read_const(f, pFtarg, &init_pos); break; case Oswitch_on_term: if (0 == fread(buf, 2, 3, f)) // lab1, lab2, lab3 aborteof(aS("switch on term")); init_pos += 6; ucFWRITE(buf, 2, 3, pFtarg); #ifdef BUG_LINK for (i=0; i<3; i++) fprintf(lout, " %d ",(int) getint16(buf + 2 * i)); #endif break; case Oswitch_on_cons: // short size, (size x |CELL|LABEL|) if (0 == fread(buf, 2, 1, f)) aborteof(aS("switch on cons")); ucFWRITE(buf, 2, 1, pFtarg); x = getint16(buf); init_pos += 2; while(x--) { read_const(f, pFtarg, &init_pos); // get const if (0 == fread(buf, 2, 1, f)) // branch label aborteof(aS("switch on cons 2")); #ifdef BUG_LINK fprintf(lout, " branch[%d] ", (int) getint16(buf)); #endif ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2; } break; case Oswitch_on_struc: // short size, (size x |NAME|ARITY|LABEL|) if (0 == fread(buf, 2, 1, f)) aborteof(aS("switch on struc")); ucFWRITE(buf, 2, 1, pFtarg); x = getint16(buf); init_pos += 2; while(x--) { read_atom(f, pFtarg); if (0 == fread(buf, 2, 1, f)) // arity aborteof(aS("switch on struc 2")); ucFWRITE(buf, 2, 1, pFtarg); if (0 == fread(buf, 2, 1, f)) // label aborteof(aS("switch on struc 2")); #ifdef BUG_LINK fprintf(lout, " branch[%d] ", (int) getint16(buf)); #endif ucFWRITE(buf, 2, 1, pFtarg); init_pos += 2 + 2 + 2; } break; default: abort_linker(aS("Error: Bad opcode in CodeStream %d"), op); } #ifdef BUG_LINK fprintf(lout, "\nend length %d init_pos %d ", length, init_pos); #endif } return(1); }
/* Given an agent expression AX, fill in an agent_reqs structure REQS describing it. */ void ax_reqs(struct agent_expr *ax, struct agent_reqs *reqs) { long i; int height; /* Bit vector for registers used: */ size_t reg_mask_len = 1UL; unsigned char *reg_mask = (unsigned char *)xmalloc(reg_mask_len * sizeof(reg_mask[0])); /* Jump target table. targets[i] is non-zero iff there is a jump to offset i. */ char *targets = (char *)alloca(ax->len * sizeof(targets[0])); /* Instruction boundary table. boundary[i] is non-zero iff an instruction starts at offset i. */ char *boundary = (char *)alloca(ax->len * sizeof(boundary[0])); /* Stack height record. iff either targets[i] or boundary[i] is non-zero, heights[i] is the height the stack should have before executing the bytecode at that point. */ int *heights = (int *)alloca(ax->len * sizeof(heights[0])); /* Pointer to a description of the present op: */ struct aop_map *op; memset(reg_mask, 0, (reg_mask_len * sizeof(reg_mask[0]))); memset(targets, 0, (ax->len * sizeof(targets[0]))); memset(boundary, 0, (ax->len * sizeof(boundary[0]))); memset(heights, 0, (ax->len * sizeof(heights[0]))); reqs->max_height = reqs->min_height = height = 0; reqs->flaw = agent_flaw_none; reqs->max_data_size = 0; for (i = 0; i < (long)ax->len; i += (long)(1UL + op->op_size)) { if (ax->buf[i] > (sizeof(aop_map) / sizeof(aop_map[0]))) { reqs->flaw = agent_flaw_bad_instruction; xfree(reg_mask); return; } op = &aop_map[ax->buf[i]]; if (!op->name) { reqs->flaw = agent_flaw_bad_instruction; xfree (reg_mask); return; } if (((size_t)(i + 1L) + op->op_size) > ax->len) { reqs->flaw = agent_flaw_incomplete_instruction; xfree(reg_mask); return; } /* If this instruction is a jump target, does the current stack height match the stack height at the jump source? */ if (targets[i] && (heights[i] != height)) { reqs->flaw = agent_flaw_height_mismatch; xfree(reg_mask); return; } boundary[i] = 1; heights[i] = height; height -= op->consumed; if (height < reqs->min_height) reqs->min_height = height; height += op->produced; if (height > reqs->max_height) reqs->max_height = height; if (op->data_size > reqs->max_data_size) reqs->max_data_size = op->data_size; /* For jump instructions, check that the target is a valid offset. If it is, record the fact that that location is a jump target, and record the height we expect there. */ if ((aop_goto == (op - aop_map)) || (aop_if_goto == (op - aop_map))) { int target = (int)read_const(ax, (int)(i + 1), 2); if ((target < 0) || (target >= (int)ax->len)) { reqs->flaw = agent_flaw_bad_jump; xfree(reg_mask); return; } /* Have we already found other jumps to the same location? */ else if (targets[target]) { if (heights[i] != height) { reqs->flaw = agent_flaw_height_mismatch; xfree(reg_mask); return; } } else { targets[target] = 1; heights[target] = height; } } /* For unconditional jumps with a successor, check that the successor is a target, and pick up its stack height. */ if ((aop_goto == (op - aop_map)) && ((i + 3L) < (long)ax->len)) { if (!targets[i + 3]) { reqs->flaw = agent_flaw_hole; xfree(reg_mask); return; } height = heights[i + 3]; } /* For reg instructions, record the register in the bit mask: */ if (aop_reg == (op - aop_map)) { int reg = (int)read_const(ax, (int)(i + 1), 2); int byte = (reg / 8); /* Grow the bit mask if necessary: */ if (byte >= (int)reg_mask_len) { /* It is not appropriate to double here. This is NOT a string buffer. */ size_t new_len = ((size_t)byte + 1UL); reg_mask = (unsigned char *)xrealloc(reg_mask, (new_len * sizeof(reg_mask[0]))); memset((reg_mask + reg_mask_len), 0, ((new_len - reg_mask_len) * sizeof(reg_mask[0]))); reg_mask_len = new_len; } reg_mask[byte] |= (1 << (reg % 8)); } } /* Check that all the targets are on boundaries: */ for (i = 0L; i < (long)ax->len; i++) if (targets[i] && !boundary[i]) { reqs->flaw = agent_flaw_bad_jump; xfree(reg_mask); return; } reqs->final_height = height; reqs->reg_mask_len = reg_mask_len; reqs->reg_mask = reg_mask; }