Exemplo n.º 1
0
/* Returns true if the 64-bit register reg64 set by an instruction of the form
 *
 *    add %reg64 %RBASE
 *
 * The instruction checked is the "distance" instruction from the current
 * instruction being looked at by the specified iterator.
 */
static Bool NaClIsAddRbaseToReg64(NaClValidatorState* vstate,
                                  size_t distance,
                                  NaClOpKind reg64) {
  NaClInstState* state;
  const NaClInst* inst;
  int op_1, op_2;
  NaClExpVector* nodes;
  NaClExp* node;
  NaClOpKind reg;
  NaClInstIter* iter = vstate->cur_iter;

  /* Get the corresponding instruction. */
  if (!NaClInstIterHasLookbackStateInline(iter, distance)) return FALSE;
  state = NaClInstIterGetLookbackStateInline(iter, distance);
  inst = NaClInstStateInst(state);
  if (InstAdd != inst->name) return FALSE;
  DEBUG(NaClLog(LOG_INFO, "inst(%d): add rbase: ", (int) distance);
        NaClInstStateInstPrint(NaClLogGetGio(), state));

  /* Extract the values of the two operands for the and. */
  if (!NaClExtractBinaryOperandIndices(state, &op_1, &op_2)) return FALSE;

  /* Extract the destination register of the and. */
  nodes = NaClInstStateExpVector(state);
  node = &nodes->node[op_1];
  if (ExprRegister != node->kind) return FALSE;

  /* Check that destination register matches wanted register. */
  reg = NaClGetExpRegisterInline(node);
  if (reg != reg64) return FALSE;

  /* Check that source register is the base register. */
  return NaClGetExpVectorRegister(nodes, op_2) == vstate->base_register;
}
Exemplo n.º 2
0
/* Disassemble the code segment, using the given decoder tables.
 * Note: The decoder tables specified in the flags argument will
 * be ignored.
 *
 * Parameters:
 *    mbase - Memory region containing code segment.
 *    vbase - PC address associated with first byte of memory region.
 *    size - Number of bytes in memory region.
 *    flags - Flags to use when decoding.
 */
static void NaClDisassembleSegmentUsingTables(
    uint8_t* mbase, NaClPcAddress vbase,
    NaClMemorySize size, NaClDisassembleFlags flags,
    const struct NaClDecodeTables* decoder_tables)  {
  NaClSegment segment;
  NaClInstIter* iter;
  struct Gio* gout = NaClLogGetGio();
  Bool print_internals =
      NaClHasBit(flags, NACL_DISASSEMBLE_FLAG(NaClDisassembleAddInternals));
  NaClSegmentInitialize(mbase, vbase, size, &segment);
  iter = NaClInstIterCreate(decoder_tables, &segment);
  if (NULL == iter) {
    gprintf(gout, "Error: not enough memory\n");
  } else {
    for (; NaClInstIterHasNext(iter); NaClInstIterAdvance(iter)) {
      NaClInstState* state = NaClInstIterGetState(iter);
      NaClInstStateInstPrint(gout, state);
      if (print_internals) {
        NaClInstPrintOpcodeSeq(gout, state);
        NaClInstPrint(gout, state->decoder_tables, NaClInstStateInst(state));
        NaClExpVectorPrint(gout, state);
      }
    }
    NaClInstIterDestroy(iter);
  }
}
Exemplo n.º 3
0
void NaClInstStateInstPrint(struct Gio* file, NaClInstState* state) {
  int i;
  const NaClInst* inst;

  /* Print out the address and the inst bytes. */
  int length = NaClInstStateLength(state);

  DEBUG_OR_ERASE(
      NaClInstPrint(file, state->decoder_tables, NaClInstStateInst(state)));
  DEBUG(NaClExpVectorPrint(file, state));
  gprintf(file, "%"NACL_PRIxNaClPcAddressAll": ",
          NaClInstStatePrintableAddress(state));
  for (i = 0; i < length; ++i) {
    gprintf(file, "%02"NACL_PRIx8" ", NaClInstStateByte(state, i));
  }
  for (i = length; i < NACL_MAX_BYTES_PER_X86_INSTRUCTION; ++i) {
    gprintf(file, "   ");
  }

  /* Print out the assembly instruction it disassembles to. */
  inst = NaClInstStateInst(state);
  NaClPrintDisassembled(file, state, inst);
  gprintf(file, "\n");
}
Exemplo n.º 4
0
/* Returns the 32-bit register for instructions of the form
 *
 *    and %reg32, MASK
 *
 * where MASK is all 1/s except for the alignment mask bits, which must be zero.
 *
 * It is assumed that opcode 0x83 is used for the AND operation, and hence, the
 * mask is a single byte.
 *
 * Returns RegUnknown if the instruction doesn't match the form listed above.
 */
static NaClOpKind NaClGetAndMaskReg32(NaClValidatorState* vstate,
                                      size_t distance) {
  NaClInstState* state;
  const NaClInst* inst;
  int op_1, op_2;
  NaClExpVector* nodes;
  NaClExp* node;
  uint8_t mask;
  NaClOpKind reg32;
  NaClInstIter* iter = vstate->cur_iter;

  /* Get the corresponding and instruction. */
  if (!NaClInstIterHasLookbackStateInline(iter, distance)) return RegUnknown;
  state = NaClInstIterGetLookbackStateInline(iter, distance);
  inst = NaClInstStateInst(state);
  if ((InstAnd != inst->name) ||
      (state->num_opcode_bytes == 0) ||
      (0x83 != state->bytes.byte[state->num_prefix_bytes])) return RegUnknown;
  DEBUG(NaClLog(LOG_INFO, "inst(%d): and mask: ", (int) distance);
        NaClInstStateInstPrint(NaClLogGetGio(), state));

  /* Extract the values of the two operands for the and. */
  if (!NaClExtractBinaryOperandIndices(state, &op_1, &op_2)) return RegUnknown;

  /* Extract the destination register of the and. */
  nodes = NaClInstStateExpVector(state);
  node = &nodes->node[op_1];
  if (ExprRegister != node->kind) return RegUnknown;

  reg32 = NaClGetExpRegisterInline(node);
  DEBUG(NaClLog(LOG_INFO, "and mask reg = %s\n", NaClOpKindName(reg32)));

  /* Check that the mask is ok. */
  mask = NaClGetJumpMask(vstate);
  DEBUG(NaClLog(LOG_INFO, "mask = %"NACL_PRIx8"\n", mask));

  assert(0xf0 == mask || 0xe0 == mask); /* alignment must be either 16 or 32. */
  node = &nodes->node[op_2];
  /* Technically the operand is a signed value, but "mask" has not been sign
   * extended, so treat the value as an unsigned byte.
   */
  if (ExprConstant != node->kind || mask != NaClGetExprUnsignedValue(node))
    return RegUnknown;
  DEBUG(NaClLog(LOG_INFO, "is mask constant\n"));

  return reg32;
}
Bool NaClInstValidates(uint8_t* mbase,
                       uint8_t size,
                       NaClPcAddress vbase,
                       NaClInstStruct* inst) {
  NaClSegment segment;
  NaClValidatorState* state;
  Bool validates = FALSE;
  NaClCPUFeaturesX86 cpu_features;

  NaClGetCurrentCPUFeaturesX86((NaClCPUFeatures *) &cpu_features);
  NACL_FLAGS_unsafe_single_inst_mode = TRUE;
  state = NaClValidatorStateCreate(vbase, (NaClMemorySize) size, RegR15, FALSE,
                                   &cpu_features);
  do {
    NaClSegmentInitialize(mbase, vbase, (NaClMemorySize) size, &segment);
    NaClBaseRegisterMemoryInitialize(state);
    state->cur_iter = NaClInstIterCreate(kNaClDecoderTables, &segment);
    if (NULL == state->cur_iter) break;
    state->cur_inst_state = NaClInstIterGetState(state->cur_iter);
    state->cur_inst = NaClInstStateInst(state->cur_inst_state);
    state->cur_inst_vector = NaClInstStateExpVector(state->cur_inst_state);
    NaClValidateInstructionLegal(state);
    NaClBaseRegisterValidator(state);
    /* induce call to NaClMaybeReportPreviousBad() */
    NaClBaseRegisterSummarize(state);
    NaClMemoryReferenceValidator(state);
    NaClJumpValidator(state);
    validates = NaClValidatesOk(state);
    NaClInstIterDestroy(state->cur_iter);
    state->cur_iter = NULL;
    state->cur_inst_state = NULL;
    state->cur_inst = NULL;
    state->cur_inst_vector = NULL;
  } while(0);
  NaClValidatorStateDestroy(state);
  /* Strictly speaking this shouldn't be necessary, as the mode */
  /* should only be used from tests. Disabling it here as a     */
  /* defensive tactic. */
  NACL_FLAGS_unsafe_single_inst_mode = FALSE;
  return validates;
}
Exemplo n.º 6
0
/* Returns the segment register encoded in the corresponding
 * mnemonic name of the corresponding instruction.
 */
static NaClOpKind NaClGetMnemonicSegmentRegister(NaClInstState* state) {
  const NaClInst* inst = NaClInstStateInst(state);
  switch (inst->name) {
    case InstLds:
      return RegDS;
    case InstLes:
      return RegES;
    case InstLfs:
      return RegFS;
    case InstLgs:
      return RegGS;
    case InstLss:
      return RegSS;
    default:
      break;
  }
  NaClFatal("Unable to determine segment regsiter from instruction name",
            state);
  /* NOT REACHED */
  return RegUnknown;
}
const char *NaClOpcodeName(NaClInstStruct *inst) {
  const struct NaClInst *nacl_opcode = NaClInstStateInst(inst);
  return NaClMnemonicName(nacl_opcode->name);
}