xref: /haiku/src/bin/debug/debug_utils.cpp (revision 475172337b217fc506feeec8d9fd8258c2d7c97c)
1 /*
2  * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2013, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "debug_utils.h"
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/stat.h>
12 
13 #include <string>
14 #include <string.h>
15 
16 #include <debugger.h>
17 
18 #include <libroot_private.h>
19 #include <syscalls.h>
20 #include <syscall_load_image.h>
21 
22 
23 extern const char* __progname;
24 static const char* kCommandName = __progname;
25 
26 
27 // find_program
28 static status_t
find_program(const char * programName,std::string & resolvedPath)29 find_program(const char* programName, std::string& resolvedPath)
30 {
31     // If the program name is absolute, then there's nothing to do.
32     // If the program name consists of more than one path element, then we
33     // consider it a relative path and don't search in PATH either.
34     if (*programName == '/' || strchr(programName, '/')) {
35         resolvedPath = programName;
36         return B_OK;
37     }
38 
39     // get the PATH environment variable
40     const char* paths = getenv("PATH");
41     if (!paths)
42         return B_ENTRY_NOT_FOUND;
43 
44     // iterate through the paths
45     do {
46         const char* pathEnd = strchr(paths, ':');
47         int pathLen = (pathEnd ? pathEnd - paths : strlen(paths));
48 
49         // We skip empty paths.
50         if (pathLen > 0) {
51             // get the program path
52             std::string path(paths, pathLen);
53             path += "/";
54             path += programName;
55 
56             // stat() the path to be sure, there is a file
57             struct stat st;
58             if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
59             	resolvedPath = path;
60                 return B_OK;
61             }
62         }
63 
64         paths = (pathEnd ? pathEnd + 1 : NULL);
65     } while (paths);
66 
67     // not found in PATH
68     return B_ENTRY_NOT_FOUND;
69 }
70 
71 
72 // #pragma mark -
73 
74 
75 // load_program
76 thread_id
load_program(const char * const * args,int32 argCount,bool traceLoading)77 load_program(const char* const* args, int32 argCount, bool traceLoading)
78 {
79 	// clone the argument vector so that we can change it
80 	const char** mutableArgs = new const char*[argCount];
81 	for (int i = 0; i < argCount; i++)
82 		mutableArgs[i] = args[i];
83 
84 	// resolve the program path
85 	std::string programPath;
86 	status_t error = find_program(args[0], programPath);
87 	if (error != B_OK) {
88 		delete[] mutableArgs;
89 		return error;
90 	}
91 	mutableArgs[0] = programPath.c_str();
92 
93 	// count environment variables
94 	int32 envCount = 0;
95 	while (environ[envCount] != NULL)
96 		envCount++;
97 
98 	// flatten the program args and environment
99 	char** flatArgs = NULL;
100 	size_t flatArgsSize;
101 	error = __flatten_process_args(mutableArgs, argCount, environ, &envCount,
102 		mutableArgs[0], &flatArgs, &flatArgsSize);
103 
104 	// load the program
105 	thread_id thread;
106 	if (error == B_OK) {
107 		thread = _kern_load_image(flatArgs, flatArgsSize, argCount, envCount,
108 			B_NORMAL_PRIORITY, (traceLoading ? 0 : B_WAIT_TILL_LOADED), -1, 0);
109 
110 		free(flatArgs);
111 	} else
112 		thread = error;
113 
114 	delete[] mutableArgs;
115 
116 	return thread;
117 }
118 
119 
120 // set_team_debugging_flags
121 status_t
set_team_debugging_flags(port_id nubPort,int32 flags)122 set_team_debugging_flags(port_id nubPort, int32 flags)
123 {
124 	debug_nub_set_team_flags message;
125 	message.flags = flags;
126 
127 	status_t error = B_OK;
128 	do {
129 		error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS,
130 			&message, sizeof(message));
131 	} while (error == B_INTERRUPTED);
132 
133 	if (error != B_OK) {
134 		fprintf(stderr, "%s: Failed to set team debug flags: %s\n",
135 			kCommandName, strerror(error));
136 	}
137 
138 	return error;
139 }
140 
141 
142 // set_thread_debugging_flags
143 status_t
set_thread_debugging_flags(port_id nubPort,thread_id thread,int32 flags)144 set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags)
145 {
146 	debug_nub_set_thread_flags message;
147 	message.thread = thread;
148 	message.flags = flags;
149 
150 	status_t error = B_OK;
151 	do {
152 		error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS,
153 			&message, sizeof(message));
154 	} while (error == B_INTERRUPTED);
155 
156 	if (error != B_OK) {
157 		fprintf(stderr, "%s: Failed to set thread debug flags: %s\n",
158 			kCommandName, strerror(error));
159 	}
160 
161 	return error;
162 }
163 
164 
165 // continue_thread
166 status_t
continue_thread(port_id nubPort,thread_id thread)167 continue_thread(port_id nubPort, thread_id thread)
168 {
169 	debug_nub_continue_thread message;
170 	message.thread = thread;
171 	message.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
172 	message.single_step = false;
173 
174 	status_t error = B_OK;
175 
176 	do {
177 		error = write_port(nubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD,
178 			&message, sizeof(message));
179 	} while (error == B_INTERRUPTED);
180 
181 	if (error != B_OK) {
182 		fprintf(stderr, "%s: Failed to run thread %" B_PRId32 ": %s\n",
183 			kCommandName, thread, strerror(error));
184 	}
185 
186 	return error;
187 }
188