> On Oct 18, 2021, at 9:41 AM, John Marino (NetBSD) <net...@marino.st> 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 <signal.h>.
 */
#define _LIBC
#include <signal.h>

.
.
.

        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

Reply via email to