* [RFA] solib-svr4.c fetch link map address
@ 2002-10-01 19:30 Elena Zannoni
2002-10-01 21:52 ` Daniel Jacobowitz
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Elena Zannoni @ 2002-10-01 19:30 UTC (permalink / raw)
To: gdb-patches
This function is used by thread_db.c. Gdb needs to pass the address of
the link map to glibc. Glibc will compute the address of a thread
local variable, given such address and the offset within the thread
local storage at which the variable is stored (gdb gets the offset out
of the debug info).
The interface for the glibc function is like this:
extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
void *__map_address, size_t __offset,
void **__address);
The function loops through the link maps, and returns the address of
the one corresponding to the given objfile. Note that this function
takes into account that objfile can be the main executable, not just a
shared library. The main executable has always an empty name field in
the linkmap.
Elena
2002-10-01 Elena Zannoni <ezannoni@redhat.com>
* solib-svr4.c (svr4_fetch_objfile_link_map): New function.
* solib-svr4.h (svr4_fetch_objfile_link_map): Export.
Index: solib-svr4.h
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.h,v
retrieving revision 1.3
diff -u -p -r1.3 solib-svr4.h
--- solib-svr4.h 26 Sep 2001 07:03:13 -0000 1.3
+++ solib-svr4.h 2 Oct 2002 02:28:55 -0000
@@ -72,6 +72,10 @@ struct link_map_offsets
extern void set_solib_svr4_fetch_link_map_offsets
(struct gdbarch *gdbarch, struct link_map_offsets *(*func) (void));
+/* This function is called by thread_db.c. Return the address of the
+ link map for the given objfile. */
+extern CORE_ADDR svr4_fetch_objfile_link_map (struct objfile *objfile);
+
/* legacy_svr4_fetch_link_map_offsets_hook is a pointer to a function
which is used to fetch link map offsets. It will only be set
by solib-legacy.c, if at all. */
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.26
diff -u -p -r1.26 solib-svr4.c
--- solib-svr4.c 9 Jun 2002 16:39:00 -0000 1.26
+++ solib-svr4.c 2 Oct 2002 02:27:19 -0000
@@ -762,6 +762,75 @@ svr4_current_sos (void)
return head;
}
+/* Get the address of the link_map for a given OBJFILE. Loop through
+ the link maps, and return the address of the one corresponding to
+ the given objfile. Note that this function takes into account that
+ objfile can be the main executable, not just a shared library. The
+ main executable has always an empty name field in the linkmap. */
+
+CORE_ADDR
+svr4_fetch_objfile_link_map (struct objfile *objfile)
+{
+ CORE_ADDR lm;
+
+ if ((debug_base = locate_base ()) == 0)
+ return 0; /* failed somehow... */
+
+ /* Position ourselves on the first link map. */
+ lm = first_link_map_member ();
+ while (lm)
+ {
+ /* Get info on the layout of the r_debug and link_map structures. */
+ struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ int errcode;
+ char *buffer;
+ struct lm_info objfile_lm_info;
+ struct cleanup *old_chain;
+ CORE_ADDR name_address;
+ char *l_name_buf = xmalloc (lmo->l_name_size);
+
+ /* Set up the buffer to contain the portion of the link_map
+ structure that gdb cares about. Note that this is not the
+ whole link_map structure. */
+ objfile_lm_info.lm = xmalloc (lmo->link_map_size);
+ old_chain = make_cleanup (xfree, objfile_lm_info.lm);
+ memset (objfile_lm_info.lm, 0, lmo->link_map_size);
+
+ /* Read the link map into our internal structure. */
+ read_memory (lm, objfile_lm_info.lm, lmo->link_map_size);
+
+ /* Read address of name from target memory to GDB. */
+ read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
+
+ /* Extract this object's name. */
+ name_address = extract_address (l_name_buf,
+ lmo->l_name_size);
+ target_read_string (name_address, &buffer,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ {
+ warning ("svr4_fetch_objfile_link_map: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ }
+ else
+ {
+ /* Is this the linkmap for the file we want? */
+ /* If the file is not a shared library and has no name,
+ we are sure it is the main executable, so we return that. */
+ if ((buffer && strcmp (buffer, objfile->name) == 0)
+ || (!(objfile->flags & OBJF_SHARED) && (strcmp (buffer, "") == 0)))
+ {
+ discard_cleanups (old_chain);
+ return lm;
+ }
+ }
+ /* Not the file we wanted, continue checking. */
+ lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
+ lmo->l_next_size);
+ discard_cleanups (old_chain);
+ }
+ return 0;
+}
/* On some systems, the only way to recognize the link map entry for
the main executable file is by looking at its name. Return
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [RFA] solib-svr4.c fetch link map address
2002-10-01 19:30 [RFA] solib-svr4.c fetch link map address Elena Zannoni
@ 2002-10-01 21:52 ` Daniel Jacobowitz
2002-10-02 6:50 ` Elena Zannoni
2002-10-02 10:28 ` Kevin Buettner
2002-10-21 11:43 ` Elena Zannoni
2 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2002-10-01 21:52 UTC (permalink / raw)
To: gdb-patches
On Tue, Oct 01, 2002 at 10:28:01PM -0400, Elena Zannoni wrote:
>
> This function is used by thread_db.c. Gdb needs to pass the address of
> the link map to glibc. Glibc will compute the address of a thread
> local variable, given such address and the offset within the thread
> local storage at which the variable is stored (gdb gets the offset out
> of the debug info).
>
> The interface for the glibc function is like this:
>
> extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
> void *__map_address, size_t __offset,
> void **__address);
>
> The function loops through the link maps, and returns the address of
> the one corresponding to the given objfile. Note that this function
> takes into account that objfile can be the main executable, not just a
> shared library. The main executable has always an empty name field in
> the linkmap.
How is the interface in thread_db going to look?
Having finally gotten gdbserver thread support going, I don't want it
to lose features; so I'm going to need to communicate the necessary
information for these libthread_db queries to/from it somehow. I'm not
clear how that should look yet.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-01 21:52 ` Daniel Jacobowitz
@ 2002-10-02 6:50 ` Elena Zannoni
0 siblings, 0 replies; 9+ messages in thread
From: Elena Zannoni @ 2002-10-02 6:50 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Daniel Jacobowitz writes:
> On Tue, Oct 01, 2002 at 10:28:01PM -0400, Elena Zannoni wrote:
> >
> > This function is used by thread_db.c. Gdb needs to pass the address of
> > the link map to glibc. Glibc will compute the address of a thread
> > local variable, given such address and the offset within the thread
> > local storage at which the variable is stored (gdb gets the offset out
> > of the debug info).
> >
> > The interface for the glibc function is like this:
> >
> > extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
> > void *__map_address, size_t __offset,
> > void **__address);
> >
> > The function loops through the link maps, and returns the address of
> > the one corresponding to the given objfile. Note that this function
> > takes into account that objfile can be the main executable, not just a
> > shared library. The main executable has always an empty name field in
> > the linkmap.
>
> How is the interface in thread_db going to look?
>
> Having finally gotten gdbserver thread support going, I don't want it
> to lose features; so I'm going to need to communicate the necessary
> information for these libthread_db queries to/from it somehow. I'm not
> clear how that should look yet.
>
I am preparing the rest of the patch. Hold on. I eventually fell
asleep last night...:-(
Elena
> --
> Daniel Jacobowitz
> MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-01 19:30 [RFA] solib-svr4.c fetch link map address Elena Zannoni
2002-10-01 21:52 ` Daniel Jacobowitz
@ 2002-10-02 10:28 ` Kevin Buettner
2002-10-02 11:42 ` Elena Zannoni
2002-10-02 18:45 ` Elena Zannoni
2002-10-21 11:43 ` Elena Zannoni
2 siblings, 2 replies; 9+ messages in thread
From: Kevin Buettner @ 2002-10-02 10:28 UTC (permalink / raw)
To: Elena Zannoni, gdb-patches
On Oct 1, 10:28pm, Elena Zannoni wrote:
> + discard_cleanups (old_chain);
> + return lm;
> + }
> + }
> + /* Not the file we wanted, continue checking. */
> + lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
> + lmo->l_next_size);
> + discard_cleanups (old_chain);
> + }
Why are the cleanups being discarded? Won't this result in a memory
leak?
Another concern is that there appears to be some duplication of code
between svr4_current_sos() and the function that you've just written.
I'm wondering if some sort of factoring could be done to minimize
duplication.
Finally, I'm curious about how often we'll be fetching the link
map address. Is it the case that it'll be fetched once (per
objfile) and never fetched again? Or will it be fetched repeatedly?
If it's the former, I think your approach is fine. If the latter, we
should consider saving the link map address so that it can be supplied
to glibc without having to read the target.
Kevin
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-02 10:28 ` Kevin Buettner
@ 2002-10-02 11:42 ` Elena Zannoni
2002-10-02 18:45 ` Elena Zannoni
1 sibling, 0 replies; 9+ messages in thread
From: Elena Zannoni @ 2002-10-02 11:42 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
Kevin Buettner writes:
> On Oct 1, 10:28pm, Elena Zannoni wrote:
>
> > + discard_cleanups (old_chain);
> > + return lm;
> > + }
> > + }
> > + /* Not the file we wanted, continue checking. */
> > + lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
> > + lmo->l_next_size);
> > + discard_cleanups (old_chain);
> > + }
>
> Why are the cleanups being discarded? Won't this result in a memory
> leak?
>
Whoops, yes. Left over from a previous version of the function.
We need to *do* the cleanups before returning, instead. I realized I
also need to add to the cleanups the freeing of l_name_buf and buffer...
> Another concern is that there appears to be some duplication of code
> between svr4_current_sos() and the function that you've just written.
> I'm wondering if some sort of factoring could be done to minimize
> duplication.
>
The problem is that I need to check the main executable and not ignore
it like the solib stuff does. I tried to not skip the main executable
and include that in the list of so's. However that got too convoluted
pretty soon, because now all the shlibs ops would require to skip over
the main executable. I think I ran into problems because a lot of
solib operations assume that there are only solibs in the list. I also
didn't like the idea of introducing inconsistencies between svr4 and
other flavors. So I didn't pursue it.
> Finally, I'm curious about how often we'll be fetching the link
> map address. Is it the case that it'll be fetched once (per
> objfile) and never fetched again? Or will it be fetched repeatedly?
> If it's the former, I think your approach is fine. If the latter, we
> should consider saving the link map address so that it can be supplied
> to glibc without having to read the target.
>
It gets triggered by read_var_value when a variable is in thread
local storage. So it happens whenever the variable needs to be
printed.
> Kevin
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-02 10:28 ` Kevin Buettner
2002-10-02 11:42 ` Elena Zannoni
@ 2002-10-02 18:45 ` Elena Zannoni
2002-10-02 20:24 ` Kevin Buettner
1 sibling, 1 reply; 9+ messages in thread
From: Elena Zannoni @ 2002-10-02 18:45 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
I think I am doing the correct cleanups now.
Elena
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.26
diff -u -p -r1.26 solib-svr4.c
--- solib-svr4.c 9 Jun 2002 16:39:00 -0000 1.26
+++ solib-svr4.c 3 Oct 2002 01:44:14 -0000
@@ -762,6 +762,77 @@ svr4_current_sos (void)
return head;
}
+/* Get the address of the link_map for a given OBJFILE. Loop through
+ the link maps, and return the address of the one corresponding to
+ the given objfile. Note that this function takes into account that
+ objfile can be the main executable, not just a shared library. The
+ main executable has always an empty name field in the linkmap. */
+
+CORE_ADDR
+svr4_fetch_objfile_link_map (struct objfile *objfile)
+{
+ CORE_ADDR lm;
+
+ if ((debug_base = locate_base ()) == 0)
+ return 0; /* failed somehow... */
+
+ /* Position ourselves on the first link map. */
+ lm = first_link_map_member ();
+ while (lm)
+ {
+ /* Get info on the layout of the r_debug and link_map structures. */
+ struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ int errcode;
+ char *buffer;
+ struct lm_info objfile_lm_info;
+ struct cleanup *old_chain;
+ CORE_ADDR name_address;
+ char *l_name_buf = xmalloc (lmo->l_name_size);
+ old_chain = make_cleanup (xfree, l_name_buf);
+
+ /* Set up the buffer to contain the portion of the link_map
+ structure that gdb cares about. Note that this is not the
+ whole link_map structure. */
+ objfile_lm_info.lm = xmalloc (lmo->link_map_size);
+ make_cleanup (xfree, objfile_lm_info.lm);
+ memset (objfile_lm_info.lm, 0, lmo->link_map_size);
+
+ /* Read the link map into our internal structure. */
+ read_memory (lm, objfile_lm_info.lm, lmo->link_map_size);
+
+ /* Read address of name from target memory to GDB. */
+ read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
+
+ /* Extract this object's name. */
+ name_address = extract_address (l_name_buf,
+ lmo->l_name_size);
+ target_read_string (name_address, &buffer,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ make_cleanup (xfree, buffer);
+ if (errcode != 0)
+ {
+ warning ("svr4_fetch_objfile_link_map: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ }
+ else
+ {
+ /* Is this the linkmap for the file we want? */
+ /* If the file is not a shared library and has no name,
+ we are sure it is the main executable, so we return that. */
+ if ((buffer && strcmp (buffer, objfile->name) == 0)
+ || (!(objfile->flags & OBJF_SHARED) && (strcmp (buffer, "") == 0)))
+ {
+ do_cleanups (old_chain);
+ return lm;
+ }
+ }
+ /* Not the file we wanted, continue checking. */
+ lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
+ lmo->l_next_size);
+ do_cleanups (old_chain);
+ }
+ return 0;
+}
/* On some systems, the only way to recognize the link map entry for
the main executable file is by looking at its name. Return
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [RFA] solib-svr4.c fetch link map address
2002-10-02 18:45 ` Elena Zannoni
@ 2002-10-02 20:24 ` Kevin Buettner
2002-10-02 21:28 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: Kevin Buettner @ 2002-10-02 20:24 UTC (permalink / raw)
To: Elena Zannoni; +Cc: gdb-patches
On Oct 2, 9:42pm, Elena Zannoni wrote:
> +/* Get the address of the link_map for a given OBJFILE. Loop through
> + the link maps, and return the address of the one corresponding to
> + the given objfile. Note that this function takes into account that
> + objfile can be the main executable, not just a shared library. The
> + main executable has always an empty name field in the linkmap. */
Since this is all sort of experimental at the moment, your patch is
okay. I think we should revisit it at a later time so that we (re)use the
information that's already being fetched by solib-svr4.c. (We'll need
to allocate some space for the link map address though.)
With regard to the main executable, it can either be saved separately,
or put on the so_list chain.
BTW, have you answered Daniel's question about how a gdbserver (or
some other debug agent) should fetch the link map address? I.e,
is something like the qSymbol packet going to be needed?
Kevin
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-02 20:24 ` Kevin Buettner
@ 2002-10-02 21:28 ` Daniel Jacobowitz
0 siblings, 0 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2002-10-02 21:28 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Elena Zannoni, gdb-patches
On Wed, Oct 02, 2002 at 08:24:40PM -0700, Kevin Buettner wrote:
> On Oct 2, 9:42pm, Elena Zannoni wrote:
>
> > +/* Get the address of the link_map for a given OBJFILE. Loop through
> > + the link maps, and return the address of the one corresponding to
> > + the given objfile. Note that this function takes into account that
> > + objfile can be the main executable, not just a shared library. The
> > + main executable has always an empty name field in the linkmap. */
>
> Since this is all sort of experimental at the moment, your patch is
> okay. I think we should revisit it at a later time so that we (re)use the
> information that's already being fetched by solib-svr4.c. (We'll need
> to allocate some space for the link map address though.)
>
> With regard to the main executable, it can either be saved separately,
> or put on the so_list chain.
>
> BTW, have you answered Daniel's question about how a gdbserver (or
> some other debug agent) should fetch the link map address? I.e,
> is something like the qSymbol packet going to be needed?
Yes. We're going to have to find a way to give the link map offset to
the server; I'm not sure if the qSymbol model is best or not but I need
to think about the control flow. When I have time I'll come back to
this; I'd like it to work :)
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFA] solib-svr4.c fetch link map address
2002-10-01 19:30 [RFA] solib-svr4.c fetch link map address Elena Zannoni
2002-10-01 21:52 ` Daniel Jacobowitz
2002-10-02 10:28 ` Kevin Buettner
@ 2002-10-21 11:43 ` Elena Zannoni
2 siblings, 0 replies; 9+ messages in thread
From: Elena Zannoni @ 2002-10-21 11:43 UTC (permalink / raw)
To: gdb-patches
Elena Zannoni writes:
>
> This function is used by thread_db.c. Gdb needs to pass the address of
> the link map to glibc. Glibc will compute the address of a thread
> local variable, given such address and the offset within the thread
> local storage at which the variable is stored (gdb gets the offset out
> of the debug info).
>
> The interface for the glibc function is like this:
>
> extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
> void *__map_address, size_t __offset,
> void **__address);
>
> The function loops through the link maps, and returns the address of
> the one corresponding to the given objfile. Note that this function
> takes into account that objfile can be the main executable, not just a
> shared library. The main executable has always an empty name field in
> the linkmap.
>
> Elena
>
> 2002-10-01 Elena Zannoni <ezannoni@redhat.com>
>
> * solib-svr4.c (svr4_fetch_objfile_link_map): New function.
> * solib-svr4.h (svr4_fetch_objfile_link_map): Export.
>
I committed the following.
Elena
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.26
diff -u -p -r1.26 solib-svr4.c
--- solib-svr4.c 9 Jun 2002 16:39:00 -0000 1.26
+++ solib-svr4.c 21 Oct 2002 14:55:53 -0000
@@ -762,6 +762,77 @@ svr4_current_sos (void)
return head;
}
+/* Get the address of the link_map for a given OBJFILE. Loop through
+ the link maps, and return the address of the one corresponding to
+ the given objfile. Note that this function takes into account that
+ objfile can be the main executable, not just a shared library. The
+ main executable has always an empty name field in the linkmap. */
+
+CORE_ADDR
+svr4_fetch_objfile_link_map (struct objfile *objfile)
+{
+ CORE_ADDR lm;
+
+ if ((debug_base = locate_base ()) == 0)
+ return 0; /* failed somehow... */
+
+ /* Position ourselves on the first link map. */
+ lm = first_link_map_member ();
+ while (lm)
+ {
+ /* Get info on the layout of the r_debug and link_map structures. */
+ struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ int errcode;
+ char *buffer;
+ struct lm_info objfile_lm_info;
+ struct cleanup *old_chain;
+ CORE_ADDR name_address;
+ char *l_name_buf = xmalloc (lmo->l_name_size);
+ old_chain = make_cleanup (xfree, l_name_buf);
+
+ /* Set up the buffer to contain the portion of the link_map
+ structure that gdb cares about. Note that this is not the
+ whole link_map structure. */
+ objfile_lm_info.lm = xmalloc (lmo->link_map_size);
+ make_cleanup (xfree, objfile_lm_info.lm);
+ memset (objfile_lm_info.lm, 0, lmo->link_map_size);
+
+ /* Read the link map into our internal structure. */
+ read_memory (lm, objfile_lm_info.lm, lmo->link_map_size);
+
+ /* Read address of name from target memory to GDB. */
+ read_memory (lm + lmo->l_name_offset, l_name_buf, lmo->l_name_size);
+
+ /* Extract this object's name. */
+ name_address = extract_address (l_name_buf,
+ lmo->l_name_size);
+ target_read_string (name_address, &buffer,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ make_cleanup (xfree, buffer);
+ if (errcode != 0)
+ {
+ warning ("svr4_fetch_objfile_link_map: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ }
+ else
+ {
+ /* Is this the linkmap for the file we want? */
+ /* If the file is not a shared library and has no name,
+ we are sure it is the main executable, so we return that. */
+ if ((buffer && strcmp (buffer, objfile->name) == 0)
+ || (!(objfile->flags & OBJF_SHARED) && (strcmp (buffer, "") == 0)))
+ {
+ do_cleanups (old_chain);
+ return lm;
+ }
+ }
+ /* Not the file we wanted, continue checking. */
+ lm = extract_address (objfile_lm_info.lm + lmo->l_next_offset,
+ lmo->l_next_size);
+ do_cleanups (old_chain);
+ }
+ return 0;
+}
/* On some systems, the only way to recognize the link map entry for
the main executable file is by looking at its name. Return
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2002-10-21 18:43 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-01 19:30 [RFA] solib-svr4.c fetch link map address Elena Zannoni
2002-10-01 21:52 ` Daniel Jacobowitz
2002-10-02 6:50 ` Elena Zannoni
2002-10-02 10:28 ` Kevin Buettner
2002-10-02 11:42 ` Elena Zannoni
2002-10-02 18:45 ` Elena Zannoni
2002-10-02 20:24 ` Kevin Buettner
2002-10-02 21:28 ` Daniel Jacobowitz
2002-10-21 11:43 ` Elena Zannoni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox