99 return UNW_ADDR_WRONG;
106 xed_decoded_inst_t *xptr = &(res->
xedd);
108 xed_decoded_inst_zero_keep_mode(xptr);
109 res->
err = xed_decode(xptr, (uint8_t *)ins, 15);
118 void *possible_call = addr - offset;
123 if (xed.
err != XED_ERROR_NONE) {
126 xed_decoded_inst_t *xptr = &xed.
xedd;
127 if ( xed_decoded_inst_get_length(xptr) != offset ){
128 TMSG(VALIDATE_UNW,
"instruction @ offset %d from %p does not have length corresponding to the offset",
132 switch(xed_decoded_inst_get_iclass(xptr)) {
133 case XED_ICLASS_CALL_FAR:
134 case XED_ICLASS_CALL_NEAR:
135 TMSG(VALIDATE_UNW,
"call instruction confirmed @ %p", possible_call);
142 EMSG(
"MAJOR PROGRAMMING ERROR: impossible fall thru @confirm_call_fetch_addr");
150 TMSG(VALIDATE_UNW,
"Checking for true call immediately preceding %p",addr);
155 TMSG(VALIDATE_UNW,
"No true call instruction found, so true call REJECTED");
158 TMSG(VALIDATE_UNW,
"comparing called routine %p to actual routine %p",
160 return (the_call == routine);
169 TMSG(VALIDATE_UNW,
"No call instruction found @ %p, so indirect call at this location rejected",
173 if (callee ==
NULL) {
174 *call_ins = addr - offset;
176 return (callee ==
NULL);
182 TMSG(VALIDATE_UNW,
"trying to confirm an indirect call preceeding %p", addr);
183 for (
size_t i=1;i <= 7;i++) {
194 void *routine_start, *routine_end;
196 TMSG(VALIDATE_UNW,
"unwind addr %p does NOT have function bounds, so it is invalid",callee);
200 xed_decoded_inst_t
xedd;
201 xed_decoded_inst_t *xptr = &
xedd;
202 xed_error_enum_t xed_error;
207 void *ins = routine_start;
208 while (ins < routine_end) {
209 xed_decoded_inst_zero_keep_mode(xptr);
210 xed_error = xed_decode(xptr, (uint8_t*) ins, 15);
212 if (xed_error != XED_ERROR_NONE) {
217 xed_iclass_enum_t xiclass = xed_decoded_inst_get_iclass(xptr);
225 case XED_ICLASS_JNBE:
227 case XED_ICLASS_JNLE:
234 case XED_ICLASS_JRCXZ:
239 case XED_ICLASS_JMP_FAR:
242 if ((target >= routine_end) || (target < routine_start)) {
244 if (target == target_fn)
return UNW_ADDR_CONFIRMED;
245 status = UNW_ADDR_PROBABLE_TAIL;
252 ins = ins + xed_decoded_inst_get_length(xptr);
261 TMSG(VALIDATE_UNW,
"trying to confirm that instruction before %p is call to a routine with tail calls", addr);
266 TMSG(VALIDATE_UNW,
"No call instruction found @ %p, so tail call REJECTED", addr - 5);
267 return UNW_ADDR_WRONG;
270 TMSG(VALIDATE_UNW,
"Checking routine %p for possible tail calls", callee);
285 const xed_inst_t *xi = xed_decoded_inst_inst(xptr);
286 const xed_operand_t *op0 = xed_inst_operand(xi, 0);
287 xed_operand_enum_t op0_name = xed_operand_name(op0);
288 xed_operand_type_enum_t op0_type = xed_operand_type(op0);
290 if (op0_name == XED_OPERAND_MEM0 &&
291 op0_type == XED_OPERAND_TYPE_IMM_CONST) {
292 xed_operand_values_t *vals = xed_decoded_inst_operands(xptr);
293 xed_reg_enum_t reg = xed_operand_values_get_base_reg(vals,0);
294 if (x86_isReg_IP(reg)) {
295 int ins_len = xed_decoded_inst_get_length(xptr);
296 xed_int64_t disp = xed_operand_values_get_memory_displacement_int64(vals);
297 xed_int64_t **memloc = ins + disp +
ins_len;
298 xed_int64_t *memval = *memloc;
311 TMSG(VALIDATE_UNW,
"trying to confirm that instruction before %p is call to a routine through the PLT", addr);
316 TMSG(VALIDATE_UNW,
"No call instruction found @ %p, so PLT call REJECTED",
318 return UNW_ADDR_WRONG;
321 TMSG(VALIDATE_UNW,
"Checking at %p for PLT call", plt_ins);
325 xed_decoded_inst_t *xptr = &xed.
xedd;
328 if (plt_callee == callee)
return UNW_ADDR_CONFIRMED;
344 return UNW_ADDR_WRONG;
362 TMSG(VALIDATE_UNW,
"validating unwind step from %p ==> %p",cursor->
pc_unnorm,
367 TMSG(VALIDATE_UNW,
"unwind addr %p does NOT have function bounds, so it is invalid", addr);
375 TMSG(VALIDATE_UNW,
"beginning of my routine = %p", callee);
377 TMSG(VALIDATE_UNW,
"Instruction preceeding %p is a call to this routine. Unwind confirmed", addr);
378 return UNW_ADDR_CONFIRMED;
381 if (result != UNW_ADDR_WRONG) {
383 "Instruction preceeding %p is a call through the PLT to this routine. Unwind confirmed",
388 if (result != UNW_ADDR_WRONG) {
389 TMSG(VALIDATE_UNW,
"Instruction preceeding %p is a call to a routine that has tail calls. Unwind is LIKELY ok", addr);
395 TMSG(VALIDATE_UNW,
"Instruction preceeding %p is an indirect call. Unwind is LIKELY ok", addr);
396 return UNW_ADDR_PROBABLE_INDIRECT;
398 TMSG(VALIDATE_UNW,
"Unwind addr %p is NOT confirmed", addr);
418 UNW_ADDR_PROBABLE : UNW_ADDR_WRONG;
static validation_status status_is_wrong()
static bool confirm_indirect_call(void *addr, void **call_ins)
struct xed_decode_t xed_decode_t
validation_status validate_return_addr(void *addr, void *generic)
static size_t ins_len(void *seq)
static bool confirm_indirect_call_specific(void *addr, size_t offset, void **call_ins)
static int return_addr_valid(void *addr, unwindr_info_t *unwr_info)
static void xed_decode_i(void *ins, xed_decode_t *res)
#define UWI_RECIPE(btuwi)
bool uw_recipe_map_lookup(void *addr, unwinder_t uw, unwindr_info_t *unwr_info)
static bool confirm_call(void *addr, void *routine)
validation_status dbg_val(void *addr, void *pc)
static bool confirm_call_fetch_addr(void *addr, size_t offset, void **the_call)
xed_control_t x86_decoder_settings
void * x86_get_branch_target(void *ins, xed_decoded_inst_t *xptr)
static validation_status confirm_tail_call(void *addr, void *target_fn)
static validation_status contains_tail_call_to_f(void *callee, void *target_fn)
static void * x86_plt_branch_target(void *ins, xed_decoded_inst_t *xptr)
bitree_uwi_t unwind_interval
static validation_status confirm_plt_call(void *addr, void *callee)
validation_status deep_validate_return_addr(void *addr, void *generic)
bool fnbounds_enclosing_addr(void *ip, void **start, void **end, load_module_t **lm)