13613bfc8SMichael Lotz /*
23613bfc8SMichael Lotz * Copyright 2009, Michael Lotz, mmlr@mlotz.ch
33613bfc8SMichael Lotz * Distributed under the terms of the MIT License.
43613bfc8SMichael Lotz */
53613bfc8SMichael Lotz #include <debug.h>
63613bfc8SMichael Lotz #include <signal.h>
73613bfc8SMichael Lotz #include <string.h>
83613bfc8SMichael Lotz #include <image.h>
93613bfc8SMichael Lotz
103613bfc8SMichael Lotz
113613bfc8SMichael Lotz static sem_id sRequestSem = -1;
123613bfc8SMichael Lotz static char sCommandBuffer[1024];
133613bfc8SMichael Lotz static uint32 sCommandOffset = 0;
143613bfc8SMichael Lotz static uint32 sCommandCount = 0;
153613bfc8SMichael Lotz
163613bfc8SMichael Lotz
173613bfc8SMichael Lotz static int32
run_on_exit_loop(void * data)183613bfc8SMichael Lotz run_on_exit_loop(void *data)
193613bfc8SMichael Lotz {
203613bfc8SMichael Lotz while (true) {
213613bfc8SMichael Lotz if (acquire_sem(sRequestSem) != B_OK)
223613bfc8SMichael Lotz break;
233613bfc8SMichael Lotz
243613bfc8SMichael Lotz char *pointer = sCommandBuffer;
253613bfc8SMichael Lotz while (sCommandCount > 0) {
263613bfc8SMichael Lotz uint8 argCount = (uint8)pointer[0];
273613bfc8SMichael Lotz pointer++;
283613bfc8SMichael Lotz
293613bfc8SMichael Lotz const char *args[argCount];
303613bfc8SMichael Lotz for (uint8 i = 0; i < argCount; i++) {
313613bfc8SMichael Lotz args[i] = pointer;
323613bfc8SMichael Lotz uint32 length = strlen(pointer);
333613bfc8SMichael Lotz pointer += length + 1;
343613bfc8SMichael Lotz }
353613bfc8SMichael Lotz
363613bfc8SMichael Lotz thread_id thread = load_image(argCount, args, NULL);
373613bfc8SMichael Lotz if (thread >= B_OK)
383613bfc8SMichael Lotz resume_thread(thread);
393613bfc8SMichael Lotz sCommandCount--;
403613bfc8SMichael Lotz }
413613bfc8SMichael Lotz
423613bfc8SMichael Lotz sCommandOffset = 0;
433613bfc8SMichael Lotz }
443613bfc8SMichael Lotz
453613bfc8SMichael Lotz return 0;
463613bfc8SMichael Lotz }
473613bfc8SMichael Lotz
483613bfc8SMichael Lotz
493613bfc8SMichael Lotz static int
add_run_on_exit_command(int argc,char ** argv)503613bfc8SMichael Lotz add_run_on_exit_command(int argc, char **argv)
513613bfc8SMichael Lotz {
523613bfc8SMichael Lotz if (argc < 2 || strcmp(argv[1], "--help") == 0) {
533613bfc8SMichael Lotz print_debugger_command_usage(argv[0]);
543613bfc8SMichael Lotz return 0;
553613bfc8SMichael Lotz }
563613bfc8SMichael Lotz
573613bfc8SMichael Lotz if (argc > 256) {
583613bfc8SMichael Lotz kprintf("too many arguments\n");
593613bfc8SMichael Lotz return 0;
603613bfc8SMichael Lotz }
613613bfc8SMichael Lotz
623613bfc8SMichael Lotz size_t totalLength = 1;
633613bfc8SMichael Lotz for (int32 i = 1; i < argc; i++)
643613bfc8SMichael Lotz totalLength += strlen(argv[i]) + 1;
653613bfc8SMichael Lotz
663613bfc8SMichael Lotz if (sCommandOffset + totalLength > sizeof(sCommandBuffer)) {
673613bfc8SMichael Lotz kprintf("no space left in command buffer\n");
683613bfc8SMichael Lotz return 0;
693613bfc8SMichael Lotz }
703613bfc8SMichael Lotz
713613bfc8SMichael Lotz char *pointer = sCommandBuffer + sCommandOffset;
723613bfc8SMichael Lotz *pointer++ = (char)(argc - 1);
733613bfc8SMichael Lotz
743613bfc8SMichael Lotz for (int32 i = 1; i < argc; i++) {
753613bfc8SMichael Lotz strcpy(pointer, argv[i]);
763613bfc8SMichael Lotz pointer += strlen(argv[i]) + 1;
773613bfc8SMichael Lotz }
783613bfc8SMichael Lotz
793613bfc8SMichael Lotz sCommandOffset += totalLength;
803613bfc8SMichael Lotz sCommandCount++;
813613bfc8SMichael Lotz return 0;
823613bfc8SMichael Lotz }
833613bfc8SMichael Lotz
843613bfc8SMichael Lotz
853613bfc8SMichael Lotz static void
exit_debugger()863613bfc8SMichael Lotz exit_debugger()
873613bfc8SMichael Lotz {
883613bfc8SMichael Lotz if (sCommandCount > 0)
893613bfc8SMichael Lotz release_sem_etc(sRequestSem, 1, B_DO_NOT_RESCHEDULE);
903613bfc8SMichael Lotz }
913613bfc8SMichael Lotz
923613bfc8SMichael Lotz
933613bfc8SMichael Lotz static status_t
std_ops(int32 op,...)943613bfc8SMichael Lotz std_ops(int32 op, ...)
953613bfc8SMichael Lotz {
963613bfc8SMichael Lotz if (op == B_MODULE_INIT) {
973613bfc8SMichael Lotz sRequestSem = create_sem(0, "run_on_exit_request");
983613bfc8SMichael Lotz if (sRequestSem < B_OK)
993613bfc8SMichael Lotz return sRequestSem;
1003613bfc8SMichael Lotz
1013613bfc8SMichael Lotz thread_id thread = spawn_kernel_thread(&run_on_exit_loop,
1023613bfc8SMichael Lotz "run_on_exit_loop", B_NORMAL_PRIORITY, NULL);
1033613bfc8SMichael Lotz if (thread < B_OK)
1043613bfc8SMichael Lotz return thread;
1053613bfc8SMichael Lotz
106*24df6592SIngo Weinhold resume_thread(thread);
1073613bfc8SMichael Lotz
1083613bfc8SMichael Lotz add_debugger_command_etc("on_exit", &add_run_on_exit_command,
1093613bfc8SMichael Lotz "Adds a command to be run when leaving the kernel debugger",
1103613bfc8SMichael Lotz "<command> [<arguments>]\n"
1113613bfc8SMichael Lotz "Adds a command to be run when leaving the kernel debugger.\n", 0);
1123613bfc8SMichael Lotz
1133613bfc8SMichael Lotz return B_OK;
1143613bfc8SMichael Lotz } else if (op == B_MODULE_UNINIT) {
1153613bfc8SMichael Lotz remove_debugger_command("on_exit", &add_run_on_exit_command);
1163613bfc8SMichael Lotz // deleting the sem will also cause the thread to exit
1173613bfc8SMichael Lotz delete_sem(sRequestSem);
1183613bfc8SMichael Lotz sRequestSem = -1;
1193613bfc8SMichael Lotz return B_OK;
1203613bfc8SMichael Lotz }
1213613bfc8SMichael Lotz
1223613bfc8SMichael Lotz return B_BAD_VALUE;
1233613bfc8SMichael Lotz }
1243613bfc8SMichael Lotz
1253613bfc8SMichael Lotz
1263613bfc8SMichael Lotz static struct debugger_module_info sModuleInfo = {
1273613bfc8SMichael Lotz {
1283613bfc8SMichael Lotz "debugger/run_on_exit/v1",
1293613bfc8SMichael Lotz B_KEEP_LOADED,
1303613bfc8SMichael Lotz &std_ops
1313613bfc8SMichael Lotz },
1323613bfc8SMichael Lotz
1333613bfc8SMichael Lotz NULL,
1343613bfc8SMichael Lotz exit_debugger,
1353613bfc8SMichael Lotz NULL,
1363613bfc8SMichael Lotz NULL
1373613bfc8SMichael Lotz };
1383613bfc8SMichael Lotz
1393613bfc8SMichael Lotz module_info *modules[] = {
1403613bfc8SMichael Lotz (module_info *)&sModuleInfo,
1413613bfc8SMichael Lotz NULL
1423613bfc8SMichael Lotz };
143