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