]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/report-wait.c
elf: Add ld.so test with non-existing program name
[thirdparty/glibc.git] / hurd / report-wait.c
CommitLineData
a482b5a5 1/* Report on what a thread in our task is waiting for.
dff8da6b 2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
c84142e8
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
c84142e8
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
c84142e8 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
a482b5a5
RM
18
19#include <hurd.h>
20#include <hurd/signal.h>
21#include <hurd/fd.h>
22#include <string.h>
23#include <assert.h>
24#include <hurd/msg_server.h>
8f480b4b
RM
25#include <thread_state.h>
26#include <intr-msg.h>
a482b5a5 27
0bd01927 28static char *
76ea70c6 29describe_number (char *description, const char *flavor, long int i, size_t size)
a482b5a5 30{
cf725107 31 unsigned long int j;
76ea70c6
ST
32 char *limit = description + size;
33 char *p = flavor == NULL ? description : __stpncpy (description, flavor, size);
0bd01927
RM
34 char *end;
35
76ea70c6
ST
36 if (p == limit)
37 return p;
38
0bd01927
RM
39 /* Handle sign. */
40 if (i < 0)
41 {
42 i = -i;
43 *p++ = '-';
44 }
d3dc731b 45
76ea70c6
ST
46 if (p == limit)
47 return p;
48
d3dc731b
MB
49 /* Allocate space for the number at the end of DESCRIPTION. */
50 for (j = i; j >= 10; j /= 10)
51 p++;
0bd01927 52 end = p + 1;
76ea70c6
ST
53
54 if (end < limit)
55 *end = '\0';
56 else
57 end = limit;
d3dc731b 58
a482b5a5
RM
59 do
60 {
76ea70c6
ST
61 if (p < limit)
62 *p = '0' + i % 10;
63 p--;
a482b5a5
RM
64 i /= 10;
65 } while (i != 0);
0bd01927
RM
66
67 return end;
a482b5a5
RM
68}
69
0bd01927 70static char *
76ea70c6 71describe_port (char *description, mach_port_t port, size_t size)
a482b5a5
RM
72{
73 int i;
74
0bd01927 75 if (port == MACH_PORT_NULL)
76ea70c6 76 return __stpncpy (description, "(null)", size);
0bd01927 77 if (port == MACH_PORT_DEAD)
76ea70c6 78 return __stpncpy (description, "(dead)", size);
0bd01927 79
a482b5a5 80 if (port == __mach_task_self ())
76ea70c6 81 return __stpncpy (description, "task-self", size);
a482b5a5
RM
82
83 for (i = 0; i < _hurd_nports; ++i)
84 if (port == _hurd_ports[i].port)
76ea70c6 85 return describe_number (description, "init#", i, size);
a482b5a5
RM
86
87 if (_hurd_init_dtable)
88 {
89 for (i = 0; i < _hurd_init_dtablesize; ++i)
90 if (port == _hurd_init_dtable[i])
76ea70c6 91 return describe_number (description, "fd#", i, size);
a482b5a5 92 }
dba88fb3 93 if (_hurd_dtable)
a482b5a5
RM
94 {
95 for (i = 0; i < _hurd_dtablesize; ++i)
96 if (_hurd_dtable[i] == NULL)
97 continue;
98 else if (port == _hurd_dtable[i]->port.port)
76ea70c6 99 return describe_number (description, "fd#", i, size);
a482b5a5 100 else if (port == _hurd_dtable[i]->ctty.port)
76ea70c6 101 return describe_number (description, "bgfd#", i, size);
a482b5a5
RM
102 }
103
76ea70c6 104 return describe_number (description, "port#", port, size);
a482b5a5
RM
105}
106
107
6bac11d9
MB
108/* We want _HURD_ITIMER_THREAD, but don't want to link in the itimer code
109 unnecessarily. */
6bac11d9
MB
110extern thread_t _hurd_itimer_thread; /* XXX */
111weak_extern (_hurd_itimer_thread)
c3352e62 112
a482b5a5
RM
113kern_return_t
114_S_msg_report_wait (mach_port_t msgport, thread_t thread,
cca6915e 115 string_t description, mach_msg_id_t *msgid)
a482b5a5 116{
76ea70c6
ST
117 char *limit = description + 1024; /* XXX */
118 char *cur = description;
a482b5a5
RM
119 *msgid = 0;
120
121 if (thread == _hurd_msgport_thread)
122 /* Cute. */
76ea70c6 123 cur = __stpncpy (cur, "msgport", limit - cur);
72e1a750 124 else if (&_hurd_itimer_thread && thread == _hurd_itimer_thread)
76ea70c6 125 cur = __stpncpy (cur, "itimer", limit - cur);
a482b5a5
RM
126 else
127 {
128 /* Make sure this is really one of our threads. */
129
130 struct hurd_sigstate *ss;
131
132 __mutex_lock (&_hurd_siglock);
133 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
134 if (ss->thread == thread)
135 break;
136 __mutex_unlock (&_hurd_siglock);
137 if (ss == NULL)
138 /* To hell with you. */
139 return EINVAL;
140
141 if (ss->suspended != MACH_PORT_NULL)
76ea70c6 142 cur = __stpncpy (cur, "sigsuspend", limit - cur);
a482b5a5
RM
143 else
144 {
145 /* Examine the thread's state to see if it is blocked in an RPC. */
146
147 struct machine_thread_state state;
148 mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
149 error_t err;
150
151 err = __thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR,
8ad684db 152 (natural_t *) &state, &count);
a482b5a5
RM
153 if (err)
154 return err;
155 assert (count == MACHINE_THREAD_STATE_COUNT);
156 if (SYSCALL_EXAMINE (&state, msgid))
157 {
0bd01927
RM
158 mach_port_t send_port, rcv_port;
159 mach_msg_option_t option;
160 mach_msg_timeout_t timeout;
161
a482b5a5 162 /* Blocked in a system call. */
0bd01927
RM
163 if (*msgid == -25
164 /* mach_msg system call. Examine its parameters. */
c57fe546 165 && MSG_EXAMINE (&state, msgid, &rcv_port, &send_port,
0bd01927
RM
166 &option, &timeout) == 0)
167 {
0bd01927
RM
168 if (send_port != MACH_PORT_NULL && *msgid != 0)
169 {
170 /* For the normal case of RPCs, we consider the
171 destination port to be the interesting thing
172 whether we are in fact sending or receiving at the
173 moment. That tells us who we are waiting for the
174 reply from. */
175 if (send_port == ss->intr_port)
176 {
177 /* This is a Hurd interruptible RPC.
178 Mark it by surrounding the port description
179 string with [...] brackets. */
76ea70c6
ST
180 if (cur < limit)
181 *cur++ = '[';
182 cur = describe_port (cur, send_port, limit - cur);
183 if (cur < limit)
184 *cur++ = ']';
0bd01927
RM
185 }
186 else
76ea70c6 187 cur = describe_port (cur, send_port, limit - cur);
0bd01927
RM
188 }
189 else if (rcv_port != MACH_PORT_NULL)
190 {
191 /* This system call had no send port, but had a
192 receive port. The msgid we extracted is then just
193 some garbage or perhaps the msgid of the last
194 message this thread received, but it's not a
195 helpful thing to return. */
76ea70c6
ST
196 cur = describe_port (cur, rcv_port, limit - cur);
197 cur = __stpncpy (cur, ":rcv", limit - cur);
0bd01927
RM
198 *msgid = 0;
199 }
200 else if ((option & (MACH_RCV_MSG|MACH_RCV_TIMEOUT))
201 == (MACH_RCV_MSG|MACH_RCV_TIMEOUT))
202 {
203 /* A receive with no valid port can be used for a
204 pure timeout. Report the timeout value (counted
205 in milliseconds); note this is the original total
206 time, not the time remaining. */
76ea70c6
ST
207 cur = describe_number (cur, 0, timeout, limit - cur);
208 cur = __stpncpy (cur, "ms", limit - cur);
0bd01927
RM
209 *msgid = 0;
210 }
211 else
212 {
76ea70c6 213 cur = __stpncpy (cur, "mach_msg", limit - cur);
0bd01927
RM
214 *msgid = 0;
215 }
216 }
217 else /* Some other system call. */
218 {
76ea70c6 219 cur = describe_number (cur, "syscall#", *msgid, limit - cur);
0bd01927
RM
220 *msgid = 0;
221 }
a482b5a5 222 }
a482b5a5
RM
223 }
224 }
225
226 __mach_port_deallocate (__mach_task_self (), thread);
76ea70c6
ST
227
228 if (cur == limit)
229 return ENOMEM;
230
231 *cur = '\0';
a482b5a5
RM
232 return 0;
233}
0e3426bb
RM
234
235kern_return_t
236_S_msg_describe_ports (mach_port_t msgport, mach_port_t refport,
0eb230cc 237 const mach_port_t *ports, mach_msg_type_number_t nports,
0e3426bb
RM
238 char **desc, mach_msg_type_number_t *desclen)
239{
240 char *p, *end;
241
242 if (__USEPORT (AUTH, msgport != port))
243 return EPERM;
244
245 end = *desc + *desclen;
246 p = *desc;
247 while (nports-- > 0)
248 {
249 char this[200];
76ea70c6 250 describe_port (this, *ports++, sizeof this);
0e3426bb
RM
251 p = __stpncpy (p, this, end - p);
252 if (p == end && p[-1] != '\0')
253 return ENOMEM;
254 }
255
256 *desclen = p - *desc;
257 return 0;
258}