#include <IOKit/IOPlatformExpert.h>
#include <libkern/version.h>
+extern unsigned int not_in_kdp;
+extern int kdp_snapshot;
+extern void do_stackshot(void);
+
+#ifdef CONFIG_KDP_INTERACTIVE_DEBUGGING
+
extern int inet_aton(const char *, struct kdp_in_addr *); /* in libkern */
extern char *inet_ntoa_r(struct kdp_in_addr ina, char *buf,
size_t buflen); /* in libkern */
extern int kdp_getc(void);
extern int reattach_wait;
-/* only used by IONetworkingFamily */
-typedef uint32_t (*kdp_link_t)(void);
-typedef boolean_t (*kdp_mode_t)(boolean_t);
-void kdp_register_link(kdp_link_t link, kdp_mode_t mode);
-void kdp_unregister_link(kdp_link_t link, kdp_mode_t mode);
-
static u_short ip_id; /* ip packet ctr, for ids */
/* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */
volatile int kdp_flag = 0;
-static kdp_send_t kdp_en_send_pkt;
+kdp_send_t kdp_en_send_pkt;
static kdp_receive_t kdp_en_recv_pkt;
static kdp_link_t kdp_en_linkstatus;
static kdp_mode_t kdp_en_setmode;
volatile unsigned int kdp_trigger_core_dump = 0;
__private_extern__ volatile unsigned int flag_kdp_trigger_reboot = 0;
-extern unsigned int not_in_kdp;
extern unsigned int disableConsoleOutput;
static boolean_t gKDPDebug = FALSE;
#define KDP_DEBUG(...) if (gKDPDebug) printf(__VA_ARGS__);
-int kdp_snapshot = 0;
-static int stack_snapshot_ret = 0;
-static unsigned stack_snapshot_bytes_traced = 0;
-
-static void *stack_snapshot_buf;
-static uint32_t stack_snapshot_bufsize;
-static int stack_snapshot_pid;
-static uint32_t stack_snapshot_flags;
-static uint32_t stack_snapshot_dispatch_offset;
-
-static unsigned int old_debugger;
-
#define SBLOCKSZ (2048)
uint64_t kdp_dump_start_time = 0;
uint64_t kdp_min_superblock_dump_time = ~1ULL;
uint64_t kdp_max_superblock_dump_time = 0;
uint64_t kdp_superblock_dump_time = 0;
uint64_t kdp_superblock_dump_start_time = 0;
-
-void
-kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size,
- uint32_t flags, uint32_t dispatch_offset);
-
-void
-kdp_snapshot_postflight(void);
-
-extern int
-kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size,
- uint32_t flags, uint32_t dispatch_offset, uint32_t *pbytesTraced);
-
-int
-kdp_stack_snapshot_geterror(void);
-
-int
-kdp_stack_snapshot_bytes_traced(void);
-
static thread_call_t
kdp_timer_call;
kdp_en_recv_pkt = NULL;
}
-/* Cache stack snapshot parameters in preparation for a trace */
-void
-kdp_snapshot_preflight(int pid, void * tracebuf, uint32_t tracebuf_size, uint32_t flags, uint32_t dispatch_offset)
-{
- stack_snapshot_pid = pid;
- stack_snapshot_buf = tracebuf;
- stack_snapshot_bufsize = tracebuf_size;
- stack_snapshot_flags = flags;
- stack_snapshot_dispatch_offset = dispatch_offset;
- kdp_snapshot++;
- /* Mark this debugger as active, since the polled mode driver that
- * ordinarily does this may not be enabled (yet), or since KDB may be
- * the primary debugger.
- */
- old_debugger = current_debugger;
- if (old_debugger != KDP_CUR_DB) {
- current_debugger = KDP_CUR_DB;
- }
-}
-
-void
-kdp_snapshot_postflight(void)
-{
- kdp_snapshot--;
- if ((kdp_en_send_pkt == NULL) || (old_debugger == KDB_CUR_DB))
- current_debugger = old_debugger;
-}
-
-int
-kdp_stack_snapshot_geterror(void)
-{
- return stack_snapshot_ret;
-}
-
-int
-kdp_stack_snapshot_bytes_traced(void)
-{
- return stack_snapshot_bytes_traced;
-}
-
static void
kdp_schedule_debugger_reentry(unsigned interval) {
uint64_t deadline;;
}
}
-void
-kdp_raise_exception(
+static void
+kdp_debugger_loop(
unsigned int exception,
unsigned int code,
unsigned int subcode,
- void *saved_state
-)
+ void *saved_state)
{
int index;
- unsigned int initial_not_in_kdp = not_in_kdp;
-
- not_in_kdp = 0;
- /* Was a system trace requested ? */
- if (kdp_snapshot && (!panic_active()) && (panic_caller == 0)) {
- stack_snapshot_ret = kdp_stackshot(stack_snapshot_pid,
- stack_snapshot_buf, stack_snapshot_bufsize,
- stack_snapshot_flags, stack_snapshot_dispatch_offset,
- &stack_snapshot_bytes_traced);
- not_in_kdp = initial_not_in_kdp;
- return;
- }
-
- disable_preemption();
if (saved_state == 0)
printf("kdp_raise_exception with NULL state\n");
kdp_panic_dump();
if (!(kdp_flag & DBG_POST_CORE))
- goto exit_raise_exception;
+ goto exit_debugger_loop;
}
again:
if (reattach_wait == 1)
goto again;
-exit_raise_exception:
+exit_debugger_loop:
if (kdp_en_setmode)
(*kdp_en_setmode)(FALSE); /* link cleanup */
-
- not_in_kdp = initial_not_in_kdp;
-
- enable_preemption();
}
void
if ((panicstr != (char *) 0) && (kdp_flag & PANIC_LOG_DUMP)) {
kdb_printf_unbuffered("Transmitting panic log, please wait: ");
kdp_send_crashdump_data(KDP_DATA, corename_str,
- debug_buf_ptr - debug_buf,
- debug_buf);
+ debug_buf_ptr - debug_buf_addr,
+ debug_buf_addr);
kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0));
printf("Please file a bug report on this panic, if possible.\n");
goto panic_dump_exit;
}
-static void kdp_serial_callout(__unused void *arg, kdp_event_t event)
+static void
+kdp_serial_callout(__unused void *arg, kdp_event_t event)
{
/* When we stop KDP, set the bit to re-initialize the console serial port
* the next time we send/receive a KDP packet. We don't do it on
debug_log_init();
-#if defined(__x86_64__) || defined(__arm__)
+#if defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
if (vm_kernel_slide) {
char KASLR_stext[19];
strlcat(kdp_kernelversion_string, "; stext=", sizeof(kdp_kernelversion_string));
#endif /* CONFIG_SERIAL_KDP */
}
+
+#else /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
+void
+kdp_init(void)
+{
+}
+#endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
+
+#if defined(__arm64__) || !CONFIG_KDP_INTERACTIVE_DEBUGGING
+static void
+panic_spin_forever()
+{
+ kdb_printf("\nPlease go to https://panic.apple.com to report this panic\n");
+ for (;;) { }
+}
+#endif
+
+void
+kdp_raise_exception(
+ unsigned int exception,
+ unsigned int code,
+ unsigned int subcode,
+ void *saved_state
+)
+{
+ unsigned int initial_not_in_kdp = not_in_kdp;
+
+ not_in_kdp = 0;
+ /* Was a system trace requested ? */
+ if (kdp_snapshot && (!panic_active()) && (panic_caller == 0)) {
+ do_stackshot();
+ not_in_kdp = initial_not_in_kdp;
+ return;
+ }
+
+
+#if CONFIG_KDP_INTERACTIVE_DEBUGGING
+
+ if (current_debugger != KDP_CUR_DB) {
+ kdb_printf("\nDebugger not configured. Hanging.\n");
+ for (;;) { }
+ }
+
+ disable_preemption();
+
+ kdp_debugger_loop(exception, code, subcode, saved_state);
+ not_in_kdp = initial_not_in_kdp;
+ enable_preemption();
+#else /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
+ assert(current_debugger != KDP_CUR_DB);
+
+ /*
+ * If kernel debugging is enabled via boot-args, but KDP debugging
+ * is not compiled into the kernel, spin here waiting for debugging
+ * via another method. Why here? Because we want to have watchdog
+ * disabled (via KDP callout) while sitting waiting to be debugged.
+ */
+ panic_spin_forever();
+
+ (void)exception;
+ (void)code;
+ (void)subcode;
+ (void)saved_state;
+#endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */
+}
+
+