Re: Request for implementation of KERN_PROC_SIGTRAMP sysctl

2021-10-27 Thread Jason Thorpe


> On Oct 27, 2021, at 4:01 PM, Jason Thorpe  wrote:
> 
> 
>> On Oct 27, 2021, at 3:44 PM, Valery Ushakov  wrote:
>> 
>> On Wed, Oct 27, 2021 at 07:50:55 -0700, Jason Thorpe wrote:
>> 
>> I was wondering if it might be easier to not put the onus onto the
>> caller and instead have a function that returns the interrupted
>> ucontext (or NULL, if the pc is not in a trampoline).
>> 
>> ucontext_t *__unwind_sigtramp(return_pc, return_sp)
> 
> That would certainly be a nicer API.

Thought about it a little more.

To make this really work, we’d definitely have to version sigaction() so that 
it fully de-supported sigcontext handlers.  Otherwise, it’s a toss-up whether 
you have a sigcontext or a ucontext on the stack.  I do think a 
__sigtramp_unwind() would also be a good addition.  But I also see some value 
in the basic check (which you need to have to __sigtramp_unwind() anyway…).

-- thorpej



Re: Request for implementation of KERN_PROC_SIGTRAMP sysctl

2021-10-27 Thread Jason Thorpe


> On Oct 27, 2021, at 3:44 PM, Valery Ushakov  wrote:
> 
> On Wed, Oct 27, 2021 at 07:50:55 -0700, Jason Thorpe wrote:
> 
> I was wondering if it might be easier to not put the onus onto the
> caller and instead have a function that returns the interrupted
> ucontext (or NULL, if the pc is not in a trampoline).
> 
> ucontext_t *__unwind_sigtramp(return_pc, return_sp)

That would certainly be a nicer API.

-- thorpej



Re: Request for implementation of KERN_PROC_SIGTRAMP sysctl

2021-10-27 Thread Valery Ushakov
On Wed, Oct 27, 2021 at 07:50:55 -0700, Jason Thorpe wrote:

> > On Oct 18, 2021, at 9:41 AM, John Marino (NetBSD)  wrote:
> > 
> > yes, it sounds like a __in_signal_trampoline function would work for
> > the GCC unwind, and I would think it would work for GDB as well.
> 
> Ok, I have implemented a new function with this signature:
> 
> /*
>  * __sigtramp_check_np --
>  *
>  *  Non-portable function that checks if the specified program
>  *  counter value is within the signal return trampoline.  Returns
>  *  the trampoline version numnber corresponding to what style of
>  *  trampoline it matches, or -1 if the program value is not within
>  *  the signal return trampoline.
>  */
> int __sigtramp_check_np(void *pc);
> 
> Usage would be like:
[... lots of code ...]

I was wondering if it might be easier to not put the onus onto the
caller and instead have a function that returns the interrupted
ucontext (or NULL, if the pc is not in a trampoline).

ucontext_t *__unwind_sigtramp(return_pc, return_sp)


-uwe


Re: Request for implementation of KERN_PROC_SIGTRAMP sysctl

2021-10-27 Thread John Marino (NetBSD)
Hi Jason,
For the purpose of supporting GCC stack unwinding, the __sigtramp_check_np
function would work as a solution.
Backporting to NetBSD-9 branch would definitely be nice as well.
Thanks,
John

On Wed, Oct 27, 2021 at 9:51 AM Jason Thorpe  wrote:

>
> > On Oct 18, 2021, at 9:41 AM, John Marino (NetBSD) 
> wrote:
> >
> > yes, it sounds like a __in_signal_trampoline function would work for
> > the GCC unwind, and I would think it would work for GDB as well.
>
> Ok, I have implemented a new function with this signature:
>
> /*
>  * __sigtramp_check_np --
>  *
>  *  Non-portable function that checks if the specified program
>  *  counter value is within the signal return trampoline.  Returns
>  *  the trampoline version numnber corresponding to what style of
>  *  trampoline it matches, or -1 if the program value is not within
>  *  the signal return trampoline.
>  */
> int __sigtramp_check_np(void *pc);
>
> Usage would be like:
>
> /*
>  * If you need access to “struct sigcontext” to perform the unwind, you
> must
>  * define _LIBC before including .
>  */
> #define _LIBC
> #include 
>
> .
> .
> .
>
> int rv = __sigtramp_check_np((void *)context->return_address);
>
> if (rv == -1) {
> /* address was not within a signal return trampoline. */
> }
>
> if (rv == __SIGTRAMP_SIGCODE_VERSION) {
> /*
>  * ultra-legacy — this will never be returned for modern
> binaries.
>  *  in fact, the current implementation of
> __sigtramp_check_np()
>  * will never return it and there is no reason to add
> support for it.
>  */
> }
>
> if (rv >= __SIGTRAMP_SIGCONTEXT_VERSION_MIN &&
> rv <= __SIGTRAMP_SIGCONTEXT_VERSION_MAX) {
> #ifdef __HAVE_STRUCT_SIGCONTEXT
> /* do sigcontext stuff, distinguishing between versions,
> as needed */
> #else
> /*
>  * no sigcontext structure is available here, so none of
> these values
>  * should have been returned.
>  */
> #endif
> }
>
> if (rv >= __SIGTRAMP_SIGINFO_VERSION_MIN &&
> rv <= __SIGTRAMP_SIGINFO_VERSION_MAX) {
> /* do siginfo stuff, distinguishing between versions, as
> needed */
> }
>
> /*
>  * Address was within a signal return trampoline, but it’s not a
> version
>  * that this program knows how to decode so *shrug*.
>  */
>
> For the most part, the MIN and MAX values will be the same (currently only
> the VAX has multiple versions of either kind of signal trampoline, and it’s
> for the “sigcontext” type).
>
> Again, to be clear, this can query the current process ONLY.
>
> Is this suitable for your needs?  Looking at your GCC unwinder for FreeBSD
> (link in your original email), it seems it would work fine (that unwinder
> uses getpid() to pass to the sysctl).
>
> You would be able to test for the availability of __sigtramp_check_np() by
> testing for __SIGTRAMP_SIGCODE_VERSION being defined:
>
> #ifdef __SIGTRAMP_SIGCODE_VERSION
> /*
>  * Code to check if we’re in a NetBSD signal trampoline.
>  */
> ...
> #endif /* __SIGTRAMP_SIGCODE_VERSION */
>
> It’s not the prettiest API in the world, but you’re by definition diving
> into implementation details here, and the API does provide all the info
> needed to do the work.
>
> Any other comments?  Christos?
>
> …and while there was a flurry of activity lately around this area, the
> minimal changes to support __sigtramp_check_np() are easily isolated and
> could be back ported to the netbsd-9 branch without much trouble.
>
> -- thorpej
>
>


Re: Request for implementation of KERN_PROC_SIGTRAMP sysctl

2021-10-27 Thread Jason Thorpe


> On Oct 18, 2021, at 9:41 AM, John Marino (NetBSD)  wrote:
> 
> yes, it sounds like a __in_signal_trampoline function would work for
> the GCC unwind, and I would think it would work for GDB as well.

Ok, I have implemented a new function with this signature:

/*
 * __sigtramp_check_np --
 *
 *  Non-portable function that checks if the specified program
 *  counter value is within the signal return trampoline.  Returns
 *  the trampoline version numnber corresponding to what style of
 *  trampoline it matches, or -1 if the program value is not within
 *  the signal return trampoline.
 */
int __sigtramp_check_np(void *pc);

Usage would be like:

/*
 * If you need access to “struct sigcontext” to perform the unwind, you must
 * define _LIBC before including .
 */
#define _LIBC
#include 

.
.
.

int rv = __sigtramp_check_np((void *)context->return_address);

if (rv == -1) {
/* address was not within a signal return trampoline. */
}

if (rv == __SIGTRAMP_SIGCODE_VERSION) {
/*
 * ultra-legacy — this will never be returned for modern 
binaries.
 *  in fact, the current implementation of __sigtramp_check_np()
 * will never return it and there is no reason to add support 
for it.
 */
}

if (rv >= __SIGTRAMP_SIGCONTEXT_VERSION_MIN &&
rv <= __SIGTRAMP_SIGCONTEXT_VERSION_MAX) {
#ifdef __HAVE_STRUCT_SIGCONTEXT
/* do sigcontext stuff, distinguishing between versions, as 
needed */
#else
/*
 * no sigcontext structure is available here, so none of these 
values
 * should have been returned.
 */
#endif
}

if (rv >= __SIGTRAMP_SIGINFO_VERSION_MIN &&
rv <= __SIGTRAMP_SIGINFO_VERSION_MAX) {
/* do siginfo stuff, distinguishing between versions, as needed 
*/
}

/*
 * Address was within a signal return trampoline, but it’s not a version
 * that this program knows how to decode so *shrug*.
 */

For the most part, the MIN and MAX values will be the same (currently only the 
VAX has multiple versions of either kind of signal trampoline, and it’s for the 
“sigcontext” type).

Again, to be clear, this can query the current process ONLY.

Is this suitable for your needs?  Looking at your GCC unwinder for FreeBSD 
(link in your original email), it seems it would work fine (that unwinder uses 
getpid() to pass to the sysctl).

You would be able to test for the availability of __sigtramp_check_np() by 
testing for __SIGTRAMP_SIGCODE_VERSION being defined:

#ifdef __SIGTRAMP_SIGCODE_VERSION
/*
 * Code to check if we’re in a NetBSD signal trampoline.
 */
...
#endif /* __SIGTRAMP_SIGCODE_VERSION */

It’s not the prettiest API in the world, but you’re by definition diving into 
implementation details here, and the API does provide all the info needed to do 
the work.

Any other comments?  Christos?

…and while there was a flurry of activity lately around this area, the minimal 
changes to support __sigtramp_check_np() are easily isolated and could be back 
ported to the netbsd-9 branch without much trouble.

-- thorpej