* Hardware watchpoints; dealing with false triggers?
@ 2001-11-29 6:25 Orjan Friberg
2001-11-19 11:58 ` Orjan Friberg
2001-11-19 12:06 ` Eli Zaretskii
0 siblings, 2 replies; 11+ messages in thread
From: Orjan Friberg @ 2001-11-29 6:25 UTC (permalink / raw)
To: gdb-patches
I'm wondering how/if gdb deals with false hardware watchpoint triggers.
Depending on how your hardware watchpoints are implemented, you could
run the risk of having to watch a larger area than what the watched
variable actually occupies in memory.
I've looked at the i386 hardware watchpoint implementation in gdb, and
read chapter 15 of the Intel Architecture Software Developer's Manual
Volume 3 about the debug registers, but I can't tell if it's susceptible
to false triggers. The i386 breakpoint registers can only deal with 1,
2, and 4-byte sized areas, so watching a 4-byte aligned 3-byte struct
seems to use two of the i386's debug registers (watching 2 and 1 bytes,
respectively).
But consider the following: say your watchpoint registers can only watch
4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an
unaligned variable of size 4 bytes. You'd have to use two watchpoint
registers, both covering too much, like this:
Variable to watch: | 0 1 2 3 |
Watchpoints: | 0 1 2 3 | 0 1 2 3 |
wp1 wp2
Now, say a there's a read of wp1's byte 0. The hardware would trigger,
but it would be a false trigger. Gdb would somehow have to find out the
actual address that was read and if it was found to be outside of the
variable's range it would not trigger the watchpoint. (For the current
write watchpoint implementation in gdb, false triggers wouldn't be a
problem, since the value of the variable wouldn't change.)
I guess some new target hooks could be needed, but besides that: are
there any major obstacles for implementing such target-dependent false
trigger handling in gdb?
--
Orjan Friberg
Axis Communications AB
^ permalink raw reply [flat|nested] 11+ messages in thread* Hardware watchpoints; dealing with false triggers? 2001-11-29 6:25 Hardware watchpoints; dealing with false triggers? Orjan Friberg @ 2001-11-19 11:58 ` Orjan Friberg 2001-11-19 12:06 ` Eli Zaretskii 1 sibling, 0 replies; 11+ messages in thread From: Orjan Friberg @ 2001-11-19 11:58 UTC (permalink / raw) To: gdb-patches I'm wondering how/if gdb deals with false hardware watchpoint triggers. Depending on how your hardware watchpoints are implemented, you could run the risk of having to watch a larger area than what the watched variable actually occupies in memory. I've looked at the i386 hardware watchpoint implementation in gdb, and read chapter 15 of the Intel Architecture Software Developer's Manual Volume 3 about the debug registers, but I can't tell if it's susceptible to false triggers. The i386 breakpoint registers can only deal with 1, 2, and 4-byte sized areas, so watching a 4-byte aligned 3-byte struct seems to use two of the i386's debug registers (watching 2 and 1 bytes, respectively). But consider the following: say your watchpoint registers can only watch 4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an unaligned variable of size 4 bytes. You'd have to use two watchpoint registers, both covering too much, like this: Variable to watch: | 0 1 2 3 | Watchpoints: | 0 1 2 3 | 0 1 2 3 | wp1 wp2 Now, say a there's a read of wp1's byte 0. The hardware would trigger, but it would be a false trigger. Gdb would somehow have to find out the actual address that was read and if it was found to be outside of the variable's range it would not trigger the watchpoint. (For the current write watchpoint implementation in gdb, false triggers wouldn't be a problem, since the value of the variable wouldn't change.) I guess some new target hooks could be needed, but besides that: are there any major obstacles for implementing such target-dependent false trigger handling in gdb? -- Orjan Friberg Axis Communications AB ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-29 6:25 Hardware watchpoints; dealing with false triggers? Orjan Friberg 2001-11-19 11:58 ` Orjan Friberg @ 2001-11-19 12:06 ` Eli Zaretskii 2001-11-29 7:01 ` Eli Zaretskii 2001-11-30 8:44 ` Orjan Friberg 1 sibling, 2 replies; 11+ messages in thread From: Eli Zaretskii @ 2001-11-19 12:06 UTC (permalink / raw) To: Orjan Friberg; +Cc: gdb-patches On Thu, 29 Nov 2001, Orjan Friberg wrote: > I'm wondering how/if gdb deals with false hardware watchpoint triggers. In general, there shouldn't be any. If you have lots of false triggers, you will be in trouble, since the higher-level code of GDB cannot cope with that very well. So the low-level watchpoint support should do whatever it takes to eliminate the possibility of false hits. > I've looked at the i386 hardware watchpoint implementation in gdb, and > read chapter 15 of the Intel Architecture Software Developer's Manual > Volume 3 about the debug registers, but I can't tell if it's susceptible > to false triggers. AFAIK, the x86 watchpoint support doesn't cause false triggers, except in one case: if you use `rwatch'. x86 debug support doesn't support read-only watchpoints, only read-write or write-only watchpoints. To emulate rwatch, GDB's higher-level code has some kludgey work-arounds (it checks whether the value changed or not), which I had hard time convincing Michael Snyder to accept, and rightfully so. > The i386 breakpoint registers can only deal with 1, > 2, and 4-byte sized areas, so watching a 4-byte aligned 3-byte struct > seems to use two of the i386's debug registers (watching 2 and 1 bytes, > respectively). Yes. > But consider the following: say your watchpoint registers can only watch > 4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an > unaligned variable of size 4 bytes. You'd have to use two watchpoint > registers, both covering too much, like this: > > Variable to watch: | 0 1 2 3 | > Watchpoints: | 0 1 2 3 | 0 1 2 3 | > wp1 wp2 This shouldn't happen, and it indeed does not happen with x86. x86 uses 2 debug registers in this case, like so: Variable to watch: | 0 1 2 3 | Watchpoints: | 0 1 | 0 1 | wp1 wp2 If the variable is only single-byte aligned, x86 would use 3 debug registers to cover it: the first one watching 1 byte, and two others watching 2 bytes each. > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > but it would be a false trigger. Gdb would somehow have to find out the > actual address that was read and if it was found to be outside of the > variable's range it would not trigger the watchpoint. You can't do that, at least not with x86 debug registers: when a watchpoint triggers, you don't know what byte of its covered memory was written to. All you know is that memory covered by a specific register was written. In other words, the Debug Status register has only one bit for each of the 4 debug registers, to tell you which of the registers' watchpoints triggered; but it doesn't tell you what bytes were modified. > are > there any major obstacles for implementing such target-dependent false > trigger handling in gdb? IIRC, no. If you cannot do something similar to what x86 does, I think you are in for a bumpy ride, as GDB doesn't handle such problems very well. Your best bet would be to solve this in the target-specific low-level code. Do you really have such a strange target? Can you tell the details? ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-19 12:06 ` Eli Zaretskii @ 2001-11-29 7:01 ` Eli Zaretskii 2001-11-30 8:44 ` Orjan Friberg 1 sibling, 0 replies; 11+ messages in thread From: Eli Zaretskii @ 2001-11-29 7:01 UTC (permalink / raw) To: Orjan Friberg; +Cc: gdb-patches On Thu, 29 Nov 2001, Orjan Friberg wrote: > I'm wondering how/if gdb deals with false hardware watchpoint triggers. In general, there shouldn't be any. If you have lots of false triggers, you will be in trouble, since the higher-level code of GDB cannot cope with that very well. So the low-level watchpoint support should do whatever it takes to eliminate the possibility of false hits. > I've looked at the i386 hardware watchpoint implementation in gdb, and > read chapter 15 of the Intel Architecture Software Developer's Manual > Volume 3 about the debug registers, but I can't tell if it's susceptible > to false triggers. AFAIK, the x86 watchpoint support doesn't cause false triggers, except in one case: if you use `rwatch'. x86 debug support doesn't support read-only watchpoints, only read-write or write-only watchpoints. To emulate rwatch, GDB's higher-level code has some kludgey work-arounds (it checks whether the value changed or not), which I had hard time convincing Michael Snyder to accept, and rightfully so. > The i386 breakpoint registers can only deal with 1, > 2, and 4-byte sized areas, so watching a 4-byte aligned 3-byte struct > seems to use two of the i386's debug registers (watching 2 and 1 bytes, > respectively). Yes. > But consider the following: say your watchpoint registers can only watch > 4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an > unaligned variable of size 4 bytes. You'd have to use two watchpoint > registers, both covering too much, like this: > > Variable to watch: | 0 1 2 3 | > Watchpoints: | 0 1 2 3 | 0 1 2 3 | > wp1 wp2 This shouldn't happen, and it indeed does not happen with x86. x86 uses 2 debug registers in this case, like so: Variable to watch: | 0 1 2 3 | Watchpoints: | 0 1 | 0 1 | wp1 wp2 If the variable is only single-byte aligned, x86 would use 3 debug registers to cover it: the first one watching 1 byte, and two others watching 2 bytes each. > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > but it would be a false trigger. Gdb would somehow have to find out the > actual address that was read and if it was found to be outside of the > variable's range it would not trigger the watchpoint. You can't do that, at least not with x86 debug registers: when a watchpoint triggers, you don't know what byte of its covered memory was written to. All you know is that memory covered by a specific register was written. In other words, the Debug Status register has only one bit for each of the 4 debug registers, to tell you which of the registers' watchpoints triggered; but it doesn't tell you what bytes were modified. > are > there any major obstacles for implementing such target-dependent false > trigger handling in gdb? IIRC, no. If you cannot do something similar to what x86 does, I think you are in for a bumpy ride, as GDB doesn't handle such problems very well. Your best bet would be to solve this in the target-specific low-level code. Do you really have such a strange target? Can you tell the details? ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-19 12:06 ` Eli Zaretskii 2001-11-29 7:01 ` Eli Zaretskii @ 2001-11-30 8:44 ` Orjan Friberg 2001-11-21 17:14 ` Orjan Friberg 2001-11-22 13:19 ` Eli Zaretskii 1 sibling, 2 replies; 11+ messages in thread From: Orjan Friberg @ 2001-11-30 8:44 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii wrote: > > On Thu, 29 Nov 2001, Orjan Friberg wrote: > > > But consider the following: say your watchpoint registers can only watch > > 4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an > > unaligned variable of size 4 bytes. You'd have to use two watchpoint > > registers, both covering too much, like this: > > > > Variable to watch: | 0 1 2 3 | > > Watchpoints: | 0 1 2 3 | 0 1 2 3 | > > wp1 wp2 > > This shouldn't happen, and it indeed does not happen with x86. x86 uses > 2 debug registers in this case, like so: Eli, Many thanks for your detailed response. Maybe I should clarify that I'm not talking about the x86, but a hypothetical target whose watchpoint mechanism would function this way. I was only using the i386 hardware watchpoint implementation as a reference and a basis for discussion. > > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > > but it would be a false trigger. Gdb would somehow have to find out the > > actual address that was read and if it was found to be outside of the > > variable's range it would not trigger the watchpoint. > > You can't do that, at least not with x86 debug registers: when a > watchpoint triggers, you don't know what byte of its covered memory was > written to. All you know is that memory covered by a specific register > was written. Ok, but say that the actual address is shipped with the register packet when the target stops so that gdb in fact knows what address was actually read/written. I'm thinking gdb could compare that address with the watchpoints, and just send the target on its way if the address is outside the watched ranges. I'm thinking of the implementation of this in a cross-environment, and while you could do it on the target side, say in the kernel, I'd rather not since I could potentially have several stubs. Handling it on the host side would allow me to handle it in one place only. > > are > > there any major obstacles for implementing such target-dependent false > > trigger handling in gdb? > > IIRC, no. If you cannot do something similar to what x86 does, I think > you are in for a bumpy ride, as GDB doesn't handle such problems very > well. Your best bet would be to solve this in the target-specific > low-level code. And this is the key issue: could the interface to the target-specific code be extended to handle the concept of "actual watchpoint address"? Or rather, could it be made to fit in nicely with the existing framework, or would it require a horrible kludge? (Maybe this question is on a too general level, and I just have to dig deeper into the code to see what would actually be needed.) > Do you really have such a strange target? Can you tell the details? No, I don't actually have such a target, so I'm sorry; I can't tell any details. -- Orjan Friberg Axis Communications AB ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-30 8:44 ` Orjan Friberg @ 2001-11-21 17:14 ` Orjan Friberg 2001-11-22 13:19 ` Eli Zaretskii 1 sibling, 0 replies; 11+ messages in thread From: Orjan Friberg @ 2001-11-21 17:14 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii wrote: > > On Thu, 29 Nov 2001, Orjan Friberg wrote: > > > But consider the following: say your watchpoint registers can only watch > > 4-byte aligned areas of 4 bytes, but you want to rwatch (or awatch) an > > unaligned variable of size 4 bytes. You'd have to use two watchpoint > > registers, both covering too much, like this: > > > > Variable to watch: | 0 1 2 3 | > > Watchpoints: | 0 1 2 3 | 0 1 2 3 | > > wp1 wp2 > > This shouldn't happen, and it indeed does not happen with x86. x86 uses > 2 debug registers in this case, like so: Eli, Many thanks for your detailed response. Maybe I should clarify that I'm not talking about the x86, but a hypothetical target whose watchpoint mechanism would function this way. I was only using the i386 hardware watchpoint implementation as a reference and a basis for discussion. > > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > > but it would be a false trigger. Gdb would somehow have to find out the > > actual address that was read and if it was found to be outside of the > > variable's range it would not trigger the watchpoint. > > You can't do that, at least not with x86 debug registers: when a > watchpoint triggers, you don't know what byte of its covered memory was > written to. All you know is that memory covered by a specific register > was written. Ok, but say that the actual address is shipped with the register packet when the target stops so that gdb in fact knows what address was actually read/written. I'm thinking gdb could compare that address with the watchpoints, and just send the target on its way if the address is outside the watched ranges. I'm thinking of the implementation of this in a cross-environment, and while you could do it on the target side, say in the kernel, I'd rather not since I could potentially have several stubs. Handling it on the host side would allow me to handle it in one place only. > > are > > there any major obstacles for implementing such target-dependent false > > trigger handling in gdb? > > IIRC, no. If you cannot do something similar to what x86 does, I think > you are in for a bumpy ride, as GDB doesn't handle such problems very > well. Your best bet would be to solve this in the target-specific > low-level code. And this is the key issue: could the interface to the target-specific code be extended to handle the concept of "actual watchpoint address"? Or rather, could it be made to fit in nicely with the existing framework, or would it require a horrible kludge? (Maybe this question is on a too general level, and I just have to dig deeper into the code to see what would actually be needed.) > Do you really have such a strange target? Can you tell the details? No, I don't actually have such a target, so I'm sorry; I can't tell any details. -- Orjan Friberg Axis Communications AB ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-30 8:44 ` Orjan Friberg 2001-11-21 17:14 ` Orjan Friberg @ 2001-11-22 13:19 ` Eli Zaretskii 2001-11-30 10:33 ` Eli Zaretskii 2001-12-04 3:09 ` Orjan Friberg 1 sibling, 2 replies; 11+ messages in thread From: Eli Zaretskii @ 2001-11-22 13:19 UTC (permalink / raw) To: orjan.friberg; +Cc: gdb-patches > Date: Fri, 30 Nov 2001 17:42:38 +0100 > From: Orjan Friberg <orjan.friberg@axis.com> > > Maybe I should clarify that I'm not talking about the x86, but a > hypothetical target whose watchpoint mechanism would function this way. Yes, I guessed that much. > > > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > > > but it would be a false trigger. Gdb would somehow have to find out the > > > actual address that was read and if it was found to be outside of the > > > variable's range it would not trigger the watchpoint. > > > > You can't do that, at least not with x86 debug registers: when a > > watchpoint triggers, you don't know what byte of its covered memory was > > written to. All you know is that memory covered by a specific register > > was written. > > Ok, but say that the actual address is shipped with the register packet > when the target stops so that gdb in fact knows what address was > actually read/written. I'm thinking gdb could compare that address with > the watchpoints, and just send the target on its way if the address is > outside the watched ranges. This can be done. The low-level target end is repsonsible to tell GDB whether a watchpoint triggered, and at what address. So given enough information from your target, you could write the low-level watchpoint code to DTRT. > And this is the key issue: could the interface to the target-specific > code be extended to handle the concept of "actual watchpoint address"? We already have this: it's called target_stopped_data_address. breakpoint.c uses this macro to see which watchpoint, if any, triggered. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-22 13:19 ` Eli Zaretskii @ 2001-11-30 10:33 ` Eli Zaretskii 2001-12-04 3:09 ` Orjan Friberg 1 sibling, 0 replies; 11+ messages in thread From: Eli Zaretskii @ 2001-11-30 10:33 UTC (permalink / raw) To: orjan.friberg; +Cc: gdb-patches > Date: Fri, 30 Nov 2001 17:42:38 +0100 > From: Orjan Friberg <orjan.friberg@axis.com> > > Maybe I should clarify that I'm not talking about the x86, but a > hypothetical target whose watchpoint mechanism would function this way. Yes, I guessed that much. > > > Now, say a there's a read of wp1's byte 0. The hardware would trigger, > > > but it would be a false trigger. Gdb would somehow have to find out the > > > actual address that was read and if it was found to be outside of the > > > variable's range it would not trigger the watchpoint. > > > > You can't do that, at least not with x86 debug registers: when a > > watchpoint triggers, you don't know what byte of its covered memory was > > written to. All you know is that memory covered by a specific register > > was written. > > Ok, but say that the actual address is shipped with the register packet > when the target stops so that gdb in fact knows what address was > actually read/written. I'm thinking gdb could compare that address with > the watchpoints, and just send the target on its way if the address is > outside the watched ranges. This can be done. The low-level target end is repsonsible to tell GDB whether a watchpoint triggered, and at what address. So given enough information from your target, you could write the low-level watchpoint code to DTRT. > And this is the key issue: could the interface to the target-specific > code be extended to handle the concept of "actual watchpoint address"? We already have this: it's called target_stopped_data_address. breakpoint.c uses this macro to see which watchpoint, if any, triggered. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-11-22 13:19 ` Eli Zaretskii 2001-11-30 10:33 ` Eli Zaretskii @ 2001-12-04 3:09 ` Orjan Friberg 2001-12-04 3:43 ` Eli Zaretskii 1 sibling, 1 reply; 11+ messages in thread From: Orjan Friberg @ 2001-12-04 3:09 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii wrote: > > > Date: Fri, 30 Nov 2001 17:42:38 +0100 > > From: Orjan Friberg <orjan.friberg@axis.com> > > > > Ok, but say that the actual address is shipped with the register packet > > when the target stops so that gdb in fact knows what address was > > actually read/written. I'm thinking gdb could compare that address with > > the watchpoints, and just send the target on its way if the address is > > outside the watched ranges. > > This can be done. The low-level target end is repsonsible to tell > GDB whether a watchpoint triggered, and at what address. So given > enough information from your target, you could write the low-level > watchpoint code to DTRT. Ah, great. > > And this is the key issue: could the interface to the target-specific > > code be extended to handle the concept of "actual watchpoint address"? > > We already have this: it's called target_stopped_data_address. > breakpoint.c uses this macro to see which watchpoint, if any, > triggered. Also great. Thank you very much for your comments on this, Eli. -- Orjan Friberg Axis Communications AB ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-12-04 3:09 ` Orjan Friberg @ 2001-12-04 3:43 ` Eli Zaretskii 2001-12-04 5:51 ` Orjan Friberg 0 siblings, 1 reply; 11+ messages in thread From: Eli Zaretskii @ 2001-12-04 3:43 UTC (permalink / raw) To: Orjan Friberg; +Cc: gdb-patches On Tue, 4 Dec 2001, Orjan Friberg wrote: > > > And this is the key issue: could the interface to the target-specific > > > code be extended to handle the concept of "actual watchpoint address"? > > > > We already have this: it's called target_stopped_data_address. > > breakpoint.c uses this macro to see which watchpoint, if any, > > triggered. > > Also great. Thank you very much for your comments on this, Eli. I need to correct myself: there's a subtle point I forgot to mention. The current code only calls target_stopped_data_address for read and access watchpoints (those set by `rwatch' and `awatch' commands), but not for regular, i.e. data-write, hardware watchpoints (those set by `watch' command). Instead, GDB compares the previous and the current value of the watched expression, and if they differ, it decides that the corresponding watchpoint triggered, without ever considering the address! I think it's a bug to do that with hardware watchpoints (as opposed to software watchpoints), so I'm trying to convince The Powers That Be to change that (in another thread called "Re: [RFC] Possible bug with i386 watchpoints on several targets", which see). But for now, that's how the code works. Sorry I failed to mention that in my original message. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Hardware watchpoints; dealing with false triggers? 2001-12-04 3:43 ` Eli Zaretskii @ 2001-12-04 5:51 ` Orjan Friberg 0 siblings, 0 replies; 11+ messages in thread From: Orjan Friberg @ 2001-12-04 5:51 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii wrote: > > I need to correct myself: there's a subtle point I forgot to mention. > The current code only calls target_stopped_data_address for read and > access watchpoints (those set by `rwatch' and `awatch' commands), but not > for regular, i.e. data-write, hardware watchpoints (those set by `watch' > command). Instead, GDB compares the previous and the current value of > the watched expression, and if they differ, it decides that the > corresponding watchpoint triggered, without ever considering the address! Hm, I explicitly considered that a non-problem. (In my original post in this thread I wrote: "For the current [data-]write watchpoint implementation in gdb, false triggers wouldn't be a problem, since the value of the variable wouldn't change.") The way hardware data-write watchpoints work now, the lack of a target_stopped_data_address wouldn't matter, since gdb only cares about whether the expression changed and not whether it was written. I realise now their functioning is more software-like (and even inconsistent with respect to awatch, which you'd think would be the union of watch and rwatch). Thanks for the clarification. -- Orjan Friberg Axis Communications AB ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2001-12-04 13:51 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-11-29 6:25 Hardware watchpoints; dealing with false triggers? Orjan Friberg 2001-11-19 11:58 ` Orjan Friberg 2001-11-19 12:06 ` Eli Zaretskii 2001-11-29 7:01 ` Eli Zaretskii 2001-11-30 8:44 ` Orjan Friberg 2001-11-21 17:14 ` Orjan Friberg 2001-11-22 13:19 ` Eli Zaretskii 2001-11-30 10:33 ` Eli Zaretskii 2001-12-04 3:09 ` Orjan Friberg 2001-12-04 3:43 ` Eli Zaretskii 2001-12-04 5:51 ` Orjan Friberg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox