Files
QNX/services/kdebug/main.c
2025-08-20 19:02:58 +08:00

236 lines
5.0 KiB
C

/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable
* license fees to QNX Software Systems before you may reproduce,
* modify or distribute this software, or any work that includes
* all or part of this software. Free development licenses are
* available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email
* licensing@qnx.com.
*
* This file may contain contributions from others. Please review
* this entire file for other proprietary rights or license notices,
* as well as the QNX Development Suite License Guide at
* http://licensing.qnx.com/license-guide/ for other information.
* $
*/
#include "kdebug.h"
#include <unistd.h>
#include <process.h>
#include <sys/image.h>
#include <sys/startup.h>
int debug_flag = 0;
char progname[16] = "kdebug";
char *debug_arg;
int force_use_image = 0;
int async_check = 1;
int interesting_faults = SIGCODE_FATAL | SIGCODE_INTR | SIGCODE_KERNEL | SIGCODE_PROC;
char mountpt[100] = "/usr/nto";
int protocol = 0;
int (*old_timer_reload)(struct syspage_entry *, struct qtime_entry *);
struct debug_callout *channel0;
struct debug_callout *hlink;
CPU_REGISTERS kerdebug_reg;
struct cpu_extra_state extra_state;
unsigned ser_clk;
unsigned ser_div;
struct kdebug_callback kdebug_callbacks = {
KDEBUG_CURRENT,
sizeof( struct kdebug_callback ),
outside_watch_entry,
outside_fault_entry,
outside_msg_entry,
outside_update_plist,
&extra_state
};
static int
dummy_timer_reload(struct syspage_entry *sysp, struct qtime_entry *qtime) {
return 1;
}
static void
dummy_display_char(struct syspage_entry *sysp, char c) {
}
static int
dummy_poll_key(struct syspage_entry *sysp) {
return -1;
}
static int
dummy_break_detect(struct syspage_entry *sysp) {
return 0;
}
int
main(int argc, char **argv) {
int t;
uintptr_t start_vaddr;
int kerdbg = 0;
struct callout_entry *callout;
cpu_init();
if(strlen(argv[0]) < sizeof progname - 1) {
strcpy(progname, argv[0]);
}
cpu_init_map();
cpu_init_extra(&extra_state);
while((t = getopt(argc, argv, "ac:IKvD:m:rP:U")) != -1) {
switch(t) {
case 'a':
async_check = 0;
break;
case 'c':
ser_clk = strtoul(optarg, &optarg, 10);
if(*optarg == '/') {
ser_div = strtoul(optarg + 1, NULL, 10);
}
break;
case 'I':
force_use_image = !force_use_image;
break;
case 'm':
strncpy(mountpt, optarg, sizeof mountpt);
break;
case 'v':
++debug_flag;
break;
case 'K':
++kerdbg;
break;
case 'D':
if(*optarg)
debug_arg = optarg;
break;
case 'U':
interesting_faults |= SIGCODE_USER;
break;
case 'P':
protocol = strtoul(optarg, &optarg, 10);
break;
}
}
callout = SYSPAGE_ENTRY(callout);
hlink = channel0 = &callout->debug[0];
if(debug_arg == NULL) ++hlink;
kprintf_init();
init_traps();
start_vaddr = next_bootstrap();
if(start_vaddr == 0) {
kprintf("%s: No next program to start.\n", progname);
_exit(1);
}
if(hlink->display_char == NULL || hlink->poll_key == NULL) {
// kprintf("\nRemote protocol channel missing required routines\n");
// _exit(1);
hlink->display_char = dummy_display_char;
hlink->poll_key = dummy_poll_key;
}
if(channel0->break_detect == NULL) {
channel0->break_detect = dummy_break_detect;
}
if(hlink->break_detect == NULL) {
hlink->break_detect = dummy_break_detect;
async_check = 0;
}
if(async_check) {
old_timer_reload = callout->timer_reload;
if(old_timer_reload == NULL) old_timer_reload = dummy_timer_reload;
callout->timer_reload = outside_timer_reload;
}
init_kerdebug(debug_arg);
if(debug_flag) kprintf("%s: starting next program at 0x%x\n", progname, start_vaddr);
private->kdebug_call = &kdebug_callbacks;
go(start_vaddr, kerdbg);
return 0;
}
char *
find_typed_string(int index) {
unsigned i;
unsigned type;
char *names;
names = SYSPAGE_ENTRY(typed_strings)->data;
i = 0;
for( ;; ) {
type = *(uint32_t *)&names[i];
if(type == index) return(&names[i+sizeof(uint32_t)]);
if(type == _CS_NONE) return(NULL);
i += sizeof(uint32_t);
i += strlen(&names[i]) + 1;
i = ROUND(i, sizeof(uint32_t));
}
}
void
dbg_putc(char c) {
hlink->display_char(_syspage_ptr, c);
}
int
dbg_getc(void) {
int c;
do {
c = hlink->poll_key(_syspage_ptr);
} while(c < 0);
return(c & 0xff);
}
int
dbg_getc_connect_check(void) {
int c;
do {
if(channel0 != hlink) {
c = channel0->poll_key(_syspage_ptr);
if(IS_ABORT_CHAR(c)) return(-1);
}
c = hlink->poll_key(_syspage_ptr);
if(IS_ABORT_CHAR(c)) return(-1);
} while(c < 0);
return(c & 0xff);
}
int
dbg_break_detect(void) {
int b;
b = hlink->break_detect(_syspage_ptr);
// if(!b && (hlink != channel0)) {
// b = channel0->break_detect(_syspage_ptr);
// }
return(b);
}
int
kdebug_timer_reload(struct syspage_entry *sysp, struct qtime_entry *qtime) {
int ret;
ret = old_timer_reload(sysp, qtime);
if(dbg_break_detect()) {
DebugKDBreak();
}
return(ret);
}