static void gum_gcc_backtracer_generate (GumBacktracer * backtracer, const GumCpuContext * cpu_context, GumReturnAddressArray * return_addresses) { GumGccBacktraceCtx btctx; btctx.return_addresses = return_addresses; if (cpu_context != NULL) { #ifdef HAVE_I386 btctx.start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context)); #else btctx.start_address = GSIZE_TO_POINTER (cpu_context->sp); #endif } else { btctx.start_address = ((gsize *) &return_addresses) + 1; } return_addresses->len = 0; _Unwind_Backtrace (gum_gcc_backtracer_append_address, &btctx); }
static void gum_x86_backtracer_generate (GumBacktracer * backtracer, const GumCpuContext * cpu_context, GumReturnAddressArray * return_addresses) { GumX86Backtracer * self = GUM_X86_BACKTRACER_CAST (backtracer); GumX86BacktracerPrivate * priv = self->priv; GumInvocationStack * invocation_stack; gsize * start_address; gsize first_address = 0; guint i; gsize * p; invocation_stack = gum_interceptor_get_current_stack (); if (cpu_context != NULL) start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context)); else start_address = (gsize *) &backtracer; for (i = 0, p = start_address; p < start_address + 2048; p++) { gboolean valid = FALSE; gsize value; GumMemoryRange vr; if ((GPOINTER_TO_SIZE (p) & (4096 - 1)) == 0) { GumMemoryRange next_range; next_range.base_address = GUM_ADDRESS (p); next_range.size = 4096; if (!gum_memory_map_contains (priv->writable, &next_range)) break; } value = *p; vr.base_address = value - 6; vr.size = 6; if (value != first_address && value > 4096 + 6 && gum_memory_map_contains (priv->code, &vr)) { gsize translated_value; translated_value = GPOINTER_TO_SIZE (gum_invocation_stack_translate ( invocation_stack, GSIZE_TO_POINTER (value))); if (translated_value != value) { value = translated_value; valid = TRUE; } else { guint8 * code_ptr = GSIZE_TO_POINTER (value); if (*(code_ptr - 5) == OPCODE_CALL_NEAR_RELATIVE || *(code_ptr - 6) == OPCODE_CALL_NEAR_ABS_INDIRECT || *(code_ptr - 3) == OPCODE_CALL_NEAR_ABS_INDIRECT || *(code_ptr - 2) == OPCODE_CALL_NEAR_ABS_INDIRECT) { valid = TRUE; } } } if (valid) { return_addresses->items[i++] = GSIZE_TO_POINTER (value); if (i == G_N_ELEMENTS (return_addresses->items)) break; if (first_address == 0) first_address = value; } } return_addresses->len = i; }