* gdb on macOS 10.12 "Sierra"
@ 2016-10-01 12:08 Jonas Maebe
2016-10-04 11:42 ` Tristan Gingold
0 siblings, 1 reply; 10+ messages in thread
From: Jonas Maebe @ 2016-10-01 12:08 UTC (permalink / raw)
To: gdb
Hi,
Has anyone succeeded yet in getting gdb to work on macOS 10.12?
Reportedly, it works when you disable SIP (which is understandable,
given
https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut
it.
With gdb 7.11.1, I occasionally get this when I try to start an inferior:
During startup program terminated with signal SIG113, Real-time event 113.
and usually (with darwin_debug_flag set to 100 -- didn't manage to get
the SIG113 anymore after I recompiled gdb with that variable set to
100):
***
Starting program: textthr
[632 inferior]: inferior task: 0x300b, pid: 701
[632 inferior]: new_ix:0/1, old_ix:0/0, new_id:0x3203 old_id:0x0
[632 inferior]: darwin_wait: waiting for a message pid=701 thread=0
[701 inferior]: ptrace (PT_TRACE_ME, 0, 0x0, 0): 0 (no error)
[701 inferior]: ptrace (PT_SIGEXC, 0, 0x0, 0): 0 (no error)
message header:
bits: 0x1200
size: 0x24
remote-port: 0x0
local-port: 0xf87
reserved: 0x0
id: 0x48
data: 00000000 00000001 0000300b
[632 inferior]: darwin_wait: pid=701 exit, status=0x5
[632 inferior]: task=0x300b, prev=0x0, notify_port=0xf87
During startup program terminated with signal SIGTRAP, Trace/breakpoint trap.
***
gdb is code signed, the code signing certificate is the System
keychain and set to "Trust always".
Thanks,
Jonas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-01 12:08 gdb on macOS 10.12 "Sierra" Jonas Maebe
@ 2016-10-04 11:42 ` Tristan Gingold
2016-10-04 13:47 ` Tedeschi, Walfred
2016-10-31 11:54 ` Jonas Maebe
0 siblings, 2 replies; 10+ messages in thread
From: Tristan Gingold @ 2016-10-04 11:42 UTC (permalink / raw)
To: Jonas Maebe; +Cc: gdb
> On 01 Oct 2016, at 14:08, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>
> Hi,
>
> Has anyone succeeded yet in getting gdb to work on macOS 10.12? Reportedly, it works when you disable SIP (which is understandable, given https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut it.
No, I haven't tried yet. Did you investigate if lldb has updated its build instructions ?
Tristan.
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: gdb on macOS 10.12 "Sierra"
2016-10-04 11:42 ` Tristan Gingold
@ 2016-10-04 13:47 ` Tedeschi, Walfred
2016-10-31 11:54 ` Jonas Maebe
1 sibling, 0 replies; 10+ messages in thread
From: Tedeschi, Walfred @ 2016-10-04 13:47 UTC (permalink / raw)
To: Tristan Gingold, Jonas Maebe; +Cc: gdb
Hello All,
It looks like Apple has increased security. We have got it to work with a workaround.
In case the signature is not from Apple the System Integrity protection has to be changed.
In this case reboot the machine enter in the recovery mode, start a terminal and issue the command:
$ csrutil enable --without debug
Reboot the system and the debug session will be able to proceed.
Cheers,
/Fred
-----Original Message-----
From: gdb-owner@sourceware.org [mailto:gdb-owner@sourceware.org] On Behalf Of Tristan Gingold
Sent: Tuesday, October 4, 2016 12:43 PM
To: Jonas Maebe <jonas-devlists@watlock.be>
Cc: gdb@sourceware.org
Subject: Re: gdb on macOS 10.12 "Sierra"
> On 01 Oct 2016, at 14:08, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>
> Hi,
>
> Has anyone succeeded yet in getting gdb to work on macOS 10.12? Reportedly, it works when you disable SIP (which is understandable, given https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut it.
No, I haven't tried yet. Did you investigate if lldb has updated its build instructions ?
Tristan.
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-04 11:42 ` Tristan Gingold
2016-10-04 13:47 ` Tedeschi, Walfred
@ 2016-10-31 11:54 ` Jonas Maebe
2016-10-31 12:00 ` Jack Howarth
2016-10-31 23:24 ` Jason Molenda
1 sibling, 2 replies; 10+ messages in thread
From: Jonas Maebe @ 2016-10-31 11:54 UTC (permalink / raw)
To: Tristan Gingold; +Cc: gdb
Tristan Gingold wrote:
>> On 01 Oct 2016, at 14:08, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>>
>> Has anyone succeeded yet in getting gdb to work on macOS 10.12? Reportedly, it works when you disable SIP (which is understandable, given https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut it.
>
> No, I haven't tried yet. Did you investigate if lldb has updated its build instructions ?
I finally got time to look into this. lldb's codesigning instructions
are at
https://llvm.org/svn/llvm-project/lldb/trunk/docs/code-signing.txt .
They have not been updated recently, but they do differ from gdb's.
However, the result is exactly the same: SIG113.
I've also asked on the darwin-dev@apple list, but did not get any
replies there.
...
I've now tried building lldb, and regardless of whether I use the GDB or
LLDB-style codesigning certificate to sign debugserver (lldb itself does
not need codesigning), it works. So it seems like the problem is not
necessarily related to codesigning per se.
Jonas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-31 11:54 ` Jonas Maebe
@ 2016-10-31 12:00 ` Jack Howarth
2016-10-31 12:11 ` Jonas Maebe
2016-10-31 23:24 ` Jason Molenda
1 sibling, 1 reply; 10+ messages in thread
From: Jack Howarth @ 2016-10-31 12:00 UTC (permalink / raw)
To: Jonas Maebe; +Cc: Tristan Gingold, gdb
On Mon, Oct 31, 2016 at 7:54 AM, Jonas Maebe <jonas-devlists@watlock.be> wrote:
> Tristan Gingold wrote:
>>> On 01 Oct 2016, at 14:08, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>>>
>>> Has anyone succeeded yet in getting gdb to work on macOS 10.12? Reportedly, it works when you disable SIP (which is understandable, given https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut it.
>>
>> No, I haven't tried yet. Did you investigate if lldb has updated its build instructions ?
>
> I finally got time to look into this. lldb's codesigning instructions
> are at
> https://llvm.org/svn/llvm-project/lldb/trunk/docs/code-signing.txt .
> They have not been updated recently, but they do differ from gdb's.
> However, the result is exactly the same: SIG113.
>
> I've also asked on the darwin-dev@apple list, but did not get any
> replies there.
>
It has been reported that the hardened security in Sierra requires the
additional step of executing
csrutil enable --without debug
from within the Terminal application when booted under the Recovery Partition.
I don't have access to a machine that can run Sierra to verify it though.
> ...
>
> I've now tried building lldb, and regardless of whether I use the GDB or
> LLDB-style codesigning certificate to sign debugserver (lldb itself does
> not need codesigning), it works. So it seems like the problem is not
> necessarily related to codesigning per se.
>
>
> Jonas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-31 12:00 ` Jack Howarth
@ 2016-10-31 12:11 ` Jonas Maebe
0 siblings, 0 replies; 10+ messages in thread
From: Jonas Maebe @ 2016-10-31 12:11 UTC (permalink / raw)
To: Jack Howarth; +Cc: Tristan Gingold, gdb
Jack Howarth wrote:
> It has been reported that the hardened security in Sierra requires the
> additional step of executing
>
> csrutil enable --without debug
>
> from within the Terminal application when booted under the Recovery Partition.
> I don't have access to a machine that can run Sierra to verify it though.
Yes, someone else on the gdb list also answered that when I asked my
original question. However, that does not explain why that is not
necessary for a self-built and custom-codesigned lldb/debugserver, as I
wrote below:
>> I've now tried building lldb, and regardless of whether I use the GDB or
>> LLDB-style codesigning certificate to sign debugserver (lldb itself does
>> not need codesigning), it works. So it seems like the problem is not
>> necessarily related to codesigning per se.
Jonas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-31 11:54 ` Jonas Maebe
2016-10-31 12:00 ` Jack Howarth
@ 2016-10-31 23:24 ` Jason Molenda
2016-11-03 16:00 ` Tristan Gingold
1 sibling, 1 reply; 10+ messages in thread
From: Jason Molenda @ 2016-10-31 23:24 UTC (permalink / raw)
To: Jonas Maebe; +Cc: Tristan Gingold, gdb, Tedeschi, Walfred
[-- Attachment #1: Type: text/plain, Size: 269 bytes --]
Hi Jonas, there was a change in macOS 10.12.1 that may be impacting gdb. After an exec, you need to refresh the task port that gdb uses in its mach calls. You can see the lldb change here:
http://llvm.org/viewvc/llvm-project?view=revision&revision=282632
or
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 3933 bytes --]
------------------------------------------------------------------------
r282632 | gclayton | 2016-09-28 14:07:34 -0700 (Wed, 28 Sep 2016) | 4 lines
Add the ability for the task port to change when a process execs.
<rdar://problem/28476369>
------------------------------------------------------------------------
Index: source/MacOSX/MachException.cpp
===================================================================
--- source/MacOSX/MachException.cpp (revision 282631)
+++ source/MacOSX/MachException.cpp (revision 282632)
@@ -106,15 +106,30 @@ catch_mach_exception_raise(mach_port_t exc_port, m
(uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
(uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
}
+ g_message->exc_type = 0;
+ g_message->exc_data.clear();
if (task_port == g_message->task_port) {
g_message->task_port = task_port;
g_message->thread_port = thread_port;
g_message->exc_type = exc_type;
- g_message->exc_data.resize(exc_data_count);
- ::memcpy(&g_message->exc_data[0], exc_data,
- g_message->exc_data.size() * sizeof(mach_exception_data_type_t));
+ for (mach_msg_type_number_t i=0; i<exc_data_count; ++i)
+ g_message->exc_data.push_back(exc_data[i]);
return KERN_SUCCESS;
+ } else if (!MachTask::IsValid(g_message->task_port)) {
+ // Our original exception port isn't valid anymore check for a SIGTRAP
+ if (exc_type == EXC_SOFTWARE && exc_data_count == 2 &&
+ exc_data[0] == EXC_SOFT_SIGNAL && exc_data[1] == SIGTRAP) {
+ // We got a SIGTRAP which indicates we might have exec'ed and possibly
+ // lost our old task port during the exec, so we just need to switch over
+ // to using this new task port
+ g_message->task_port = task_port;
+ g_message->thread_port = thread_port;
+ g_message->exc_type = exc_type;
+ for (mach_msg_type_number_t i=0; i<exc_data_count; ++i)
+ g_message->exc_data.push_back(exc_data[i]);
+ return KERN_SUCCESS;
+ }
}
return KERN_FAILURE;
}
Index: source/MacOSX/MachTask.mm
===================================================================
--- source/MacOSX/MachTask.mm (revision 282631)
+++ source/MacOSX/MachTask.mm (revision 282632)
@@ -867,6 +867,16 @@ void *MachTask::ExceptionThread(void *arg) {
// TODO: notify of error?
} else {
if (exception_message.CatchExceptionRaise(task)) {
+ if (exception_message.state.task_port != task) {
+ if (exception_message.state.IsValid()) {
+ // We exec'ed and our task port changed on us.
+ DNBLogThreadedIf(LOG_EXCEPTIONS,
+ "task port changed from 0x%4.4x to 0x%4.4x",
+ task, exception_message.state.task_port);
+ task = exception_message.state.task_port;
+ mach_task->TaskPortChanged(exception_message.state.task_port);
+ }
+ }
++num_exceptions_received;
mach_proc->ExceptionMessageReceived(exception_message);
}
@@ -984,3 +994,8 @@ nub_bool_t MachTask::DeallocateMemory(nub_addr_t a
}
nub_size_t MachTask::PageSize() { return m_vm_memory.PageSize(m_task); }
+
+void MachTask::TaskPortChanged(task_t task)
+{
+ m_task = task;
+}
Index: source/MacOSX/MachTask.h
===================================================================
--- source/MacOSX/MachTask.h (revision 282631)
+++ source/MacOSX/MachTask.h (revision 282632)
@@ -82,6 +82,7 @@ class MachTask {
bool IsValid() const;
static bool IsValid(task_t task);
static void *ExceptionThread(void *arg);
+ void TaskPortChanged(task_t task);
task_t TaskPort() const { return m_task; }
task_t TaskPortForProcessID(DNBError &err, bool force = false);
static task_t TaskPortForProcessID(pid_t pid, DNBError &err,
[-- Attachment #3: Type: text/plain, Size: 1486 bytes --]
I skimmed this email thread and someone said that disabling launch-with-shell worked around the issue. That would be in line with this OS change.
Jason
> On Oct 31, 2016, at 4:54 AM, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>
> Tristan Gingold wrote:
>>> On 01 Oct 2016, at 14:08, Jonas Maebe <jonas-devlists@watlock.be> wrote:
>>>
>>> Has anyone succeeded yet in getting gdb to work on macOS 10.12? Reportedly, it works when you disable SIP (which is understandable, given https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html ), but plain code signing no longer seems to cut it.
>>
>> No, I haven't tried yet. Did you investigate if lldb has updated its build instructions ?
>
> I finally got time to look into this. lldb's codesigning instructions
> are at
> https://llvm.org/svn/llvm-project/lldb/trunk/docs/code-signing.txt .
> They have not been updated recently, but they do differ from gdb's.
> However, the result is exactly the same: SIG113.
>
> I've also asked on the darwin-dev@apple list, but did not get any
> replies there.
>
> ...
>
> I've now tried building lldb, and regardless of whether I use the GDB or
> LLDB-style codesigning certificate to sign debugserver (lldb itself does
> not need codesigning), it works. So it seems like the problem is not
> necessarily related to codesigning per se.
>
>
> Jonas
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
2016-10-31 23:24 ` Jason Molenda
@ 2016-11-03 16:00 ` Tristan Gingold
0 siblings, 0 replies; 10+ messages in thread
From: Tristan Gingold @ 2016-11-03 16:00 UTC (permalink / raw)
To: Jason Molenda; +Cc: Jonas Maebe, gdb, Tedeschi, Walfred
> On 01 Nov 2016, at 00:23, Jason Molenda <jmolenda@apple.com> wrote:
>
> Hi Jonas, there was a change in macOS 10.12.1 that may be impacting gdb. After an exec, you need to refresh the task port that gdb uses in its mach calls. You can see the lldb change here:
>
> http://llvm.org/viewvc/llvm-project?view=revision&revision=282632
>
> or
>
> <patch.txt>
>
> I skimmed this email thread and someone said that disabling launch-with-shell worked around the issue. That would be in line with this OS change.
Thank you Jason, that's very useful.
Tristan.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
@ 2016-11-03 22:05 David Jenkins
0 siblings, 0 replies; 10+ messages in thread
From: David Jenkins @ 2016-11-03 22:05 UTC (permalink / raw)
To: gdb
I can confirm that refreshing the task port after exec does allow gdb to
work. Here is a patch that I made against 7.12 that allows gdb to run
on Sierra. I cannot speak to the complete quality of the patch as this
is my first dive into gdb code. We just starting using the patched gdb
and it does allows us to break, step, and view variables in the Lazarus IDE.
Patch is inlined below
David Jenkins
Scooter Software
--- gdb-7.12/gdb/darwin-nat.c 2016-10-07 12:09:21.000000000 -0500
+++ gdb-7.12-dfj/gdb/darwin-nat.c 2016-11-03 15:56:49.000000000 -0500
@@ -171,6 +171,9 @@
"</dict>\n"
"</plist>\n";
+static kern_return_t darwin_save_exception_ports (darwin_inferior *inf);
+static kern_return_t darwin_restore_exception_ports (darwin_inferior *inf);
+
static void inferior_debug (int level, const char *fmt, ...)
ATTRIBUTE_PRINTF (2, 3);
@@ -401,6 +404,12 @@
}
static int
+find_inferior_pid_it (struct inferior *inf, void *pid_ptr)
+{
+ return inf->pid == *(int *)pid_ptr;
+}
+
+static int
find_inferior_task_it (struct inferior *inf, void *port_ptr)
{
return inf->priv->task == *(task_t*)port_ptr;
@@ -412,6 +421,13 @@
return inf->priv->notify_port == *(task_t*)port_ptr;
}
+/* Return an inferior by pid. */
+static struct inferior *
+darwin_find_inferior_by_pid (int pid)
+{
+ return iterate_over_inferiors (&find_inferior_pid_it, &pid);
+}
+
/* Return an inferior by task port. */
static struct inferior *
darwin_find_inferior_by_task (task_t port)
@@ -572,6 +588,7 @@
thread_t thread_port;
kern_return_t kret;
int i;
+ int task_pid;
/* Check message destination. */
if (hdr->msgh_local_port != darwin_ex_port)
@@ -606,6 +623,7 @@
task_port = desc[1].name;
thread_port = desc[0].name;
+ pid_for_task(task_port, &task_pid);
/* We got new rights to the task, get rid of it. Do not get rid of
thread
right, as we will need it to find the thread. */
@@ -617,25 +635,61 @@
*pinf = inf;
if (inf == NULL)
{
- /* Not a known inferior. This could happen if the child fork, as
- the created process will inherit its exception port.
- FIXME: should the exception port be restored ? */
- kern_return_t kret;
- mig_reply_error_t reply;
+ if MACH_PORT_VALID(task_port)
+ {
+ //int task_pid;
+ mach_port_name_t new_task;
+ mach_port_t prev_not;
+ exception_mask_t mask;
+
+ inf = darwin_find_inferior_by_pid(task_pid);
+ if (inf == NULL)
+ return 0;
- /* Free thread port (we don't know it). */
- kret = mach_port_deallocate (mach_task_self (), thread_port);
- MACH_CHECK_ERROR (kret);
+ kret = mach_port_deallocate (mach_task_self (), inf->priv->task);
+ MACH_CHECK_ERROR (kret);
- darwin_encode_reply (&reply, hdr, KERN_SUCCESS);
+ task_for_pid(gdb_task, task_pid, &new_task);
- kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
- reply.Head.msgh_size, 0,
- MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
- MACH_CHECK_ERROR (kret);
+ inf->priv->task = new_task;
+ *pinf = inf;
+
+ mach_port_request_notification (gdb_task, inf->priv->task,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ inf->priv->notify_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &prev_not);
+
+ darwin_restore_exception_ports(inf->priv);
+ if (enable_mach_exceptions)
+ mask = EXC_MASK_ALL;
+ else
+ mask = EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT;
+ task_set_exception_ports (inf->priv->task, mask, darwin_ex_port,
+ EXCEPTION_DEFAULT, THREAD_STATE_NONE);
+ }
+ else
+ {
+ /* Not a known inferior. This could happen if the child fork, as
+ the created process will inherit its exception port.
+ FIXME: should the exception port be restored ? */
+ kern_return_t kret;
+ mig_reply_error_t reply;
+
+ /* Free thread port (we don't know it). */
+ kret = mach_port_deallocate (mach_task_self (), thread_port);
+ MACH_CHECK_ERROR (kret);
- return 0;
+ darwin_encode_reply (&reply, hdr, KERN_SUCCESS);
+
+ kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
+ reply.Head.msgh_size, 0,
+ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ MACH_CHECK_ERROR (kret);
+
+ return 0;
+ }
}
/* Find thread by port. */
@@ -900,6 +954,7 @@
{
darwin_thread_t *thread;
struct inferior *inf;
+
/* Exception message. 2401 == 0x961 is exc. */
if (hdr->msgh_id == 2401)
@@ -992,6 +1047,14 @@
inf = darwin_find_inferior_by_notify (hdr->msgh_local_port);
if (inf != NULL)
{
+ mach_dead_name_notification_t *notif;
+ mach_port_t dead_port;
+
+ notif = (mach_dead_name_notification_t *)(hdr);
+ dead_port = notif->not_port;
+ if (dead_port != inf->priv->task)
+ return ptid_build (inf->pid, 0, 0);
+
if (!inf->priv->no_ptrace)
{
pid_t res;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: gdb on macOS 10.12 "Sierra"
@ 2016-10-31 23:14 C Western
0 siblings, 0 replies; 10+ messages in thread
From: C Western @ 2016-10-31 23:14 UTC (permalink / raw)
To: gdb
An additional note on this - I have been having similar problems with
running gdb under Sierra, and it seems the problem is more subtle than a
simple permissions problem. I am able to attach to a running process,
but not start a new process with gdb. This is even after using:
set startup-with-shell off
which I have seen suggested elsewhere.
Colin
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-11-03 22:05 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-01 12:08 gdb on macOS 10.12 "Sierra" Jonas Maebe
2016-10-04 11:42 ` Tristan Gingold
2016-10-04 13:47 ` Tedeschi, Walfred
2016-10-31 11:54 ` Jonas Maebe
2016-10-31 12:00 ` Jack Howarth
2016-10-31 12:11 ` Jonas Maebe
2016-10-31 23:24 ` Jason Molenda
2016-11-03 16:00 ` Tristan Gingold
2016-10-31 23:14 C Western
2016-11-03 22:05 David Jenkins
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox