/* Given an instruction corresponding to a call, validate that the generated * return address is safe. * Parameters: * vstate - The state of the validator. */ static void NaClValidateCallAlignment(NaClValidatorState* vstate) { /* The return is safe only if it begins at an aligned address (since * return instructions are not explicit jumps). */ NaClPcAddress next_addr = vstate->cur_inst_state->inst_addr + NaClInstStateLength(vstate->cur_inst_state); if (next_addr & vstate->bundle_mask) { NaClPcAddress printable_next_addr = NaClInstStatePrintableAddress(vstate->cur_inst_state) + NaClInstStateLength(vstate->cur_inst_state); /* NOTE: Previously the validator recorded an error for call instructions * that were not aligned against the end of a bundle, as these, while * safe, are not correct with the current code generation idioms. * This #if defined(ERROR_ON_CALL_BUNDLE_ALIGNMENT) was added to allow * experimentation with different call/return idioms. */ if (!NACL_FLAGS_unsafe_single_inst_mode) { NaClValidatorInstMessage( #if defined(ERROR_ON_CALL_BUNDLE_ALIGNMENT) LOG_ERROR, #else LOG_WARNING, #endif vstate, vstate->cur_inst_state, "Bad call alignment, return pc = %"NACL_PRIxNaClPcAddress"\n", printable_next_addr); } } }
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"); }
/* Print out the given constant expression node to the given file. */ static void NaClPrintDisassembledConst( struct Gio* file, NaClInstState* state, NaClExp* node) { assert(node->kind == ExprConstant); if (node->flags & NACL_EFLAG(ExprJumpTarget)) { NaClPcAddress target = NaClInstStatePrintableAddress(state) + state->bytes.length + (NaClPcNumber) NaClGetExprSignedValue(node); gprintf(file, "0x%"NACL_PRIxNaClPcAddress, target); }else if (node->flags & NACL_EFLAG(ExprUnsignedHex)) { gprintf(file, "0x%"NACL_PRIx64, NaClGetExprUnsignedValue(node)); } else if (node->flags & NACL_EFLAG(ExprSignedHex)) { int64_t val = NaClGetExprSignedValue(node); if (val < 0) { val = -val; gprintf(file, "-0x%"NACL_PRIx64, val); } else { gprintf(file, "0x%"NACL_PRIx64, val); } } else if (node->flags & NACL_EFLAG(ExprUnsignedInt)) { gprintf(file, "%"NACL_PRIu64, NaClGetExprUnsignedValue(node)); } else { /* Assume ExprSignedInt. */ gprintf(file, "%"NACL_PRId64, NaClGetExprSignedValue(node)); } }