当前位置: 首页 > 面试题库 >

从信号处理程序中获取保存的指令指针地址

金晗日
2023-03-14
问题内容

我的问题与其他询问故障地址的问题有所不同。我正在尝试实施一个可怕的技巧,通过检查保存的指令指针处的代码并将其与主机体系结构的可能的syscall输入指令进行比较,从信号处理程序中确定信号是否中断了syscall或普通用户代码。运行。这是实现正确的POSIX线程取消的一部分,该操作不会受到我的旧问题中描述的竞争条件和资源泄漏的影响:

如果这种方法不可靠或其他错误,我也想听听原因。


问题答案:

/ sigsegv.c /
/*
* This source file is used to print out a stack-trace when your program
* segfaults. It is relatively reliable and spot-on accurate.
* * This code is in the public domain. Use it as you see fit, some credit
* would be appreciated, but is not a prerequisite for usage. Feedback
* on it’s use would encourage further development and maintenance.
* * Due to a bug in gcc-4.x.x you currently have to compile as C++ if you want
* demangling to work.
* * Please note that it’s been ported into my ULS library, thus the check for
* HAS_ULSLIB and the use of the sigsegv_outp macro based on that define.
* * Author: Jaco Kroon jaco@kroon.co.za
* * Copyright (C) 2005 - 2010 Jaco Kroon


/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

/* Bug in gcc prevents from using CPP_DEMANGLE in pure "C" */
#if !defined(__cplusplus) && !defined(NO_CPP_DEMANGLE)
#define NO_CPP_DEMANGLE
#endif

#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <ucontext.h>
#include <dlfcn.h>
#ifndef NO_CPP_DEMANGLE
#include <cxxabi.h>
#ifdef __cplusplus
using __cxxabiv1::__cxa_demangle;
#endif
#endif

#ifdef HAS_ULSLIB
#include "uls/logger.h"
#define sigsegv_outp(x)         sigsegv_outp(,gx)
#else
#define sigsegv_outp(x, ...)    fprintf(stderr, x "\n", ##__VA_ARGS__)
#endif

#if defined(REG_RIP)
# define SIGSEGV_STACK_IA64
# define REGFORMAT "%016lx"
#elif defined(REG_EIP)
# define SIGSEGV_STACK_X86
# define REGFORMAT "%08x"
#else
# define SIGSEGV_STACK_GENERIC
# define REGFORMAT "%x"
#endif

static void signal_segv(int signum, siginfo_t* info, void*ptr) {
    static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};

    int i, f = 0;
    ucontext_t *ucontext = (ucontext_t*)ptr;
    Dl_info dlinfo;
    void **bp = 0;
    void *ip = 0;

    sigsegv_outp("Segmentation Fault!");
    sigsegv_outp("info.si_signo = %d", signum);
    sigsegv_outp("info.si_errno = %d", info->si_errno);
    sigsegv_outp("info.si_code  = %d (%s)", info->si_code, si_codes[info->si_code]);
    sigsegv_outp("info.si_addr  = %p", info->si_addr);
    for(i = 0; i < NGREG; i++)
        sigsegv_outp("reg[%02d]       = 0x" REGFORMAT, i, ucontext->uc_mcontext.gregs[i]);

#ifndef SIGSEGV_NOSTACK
#if defined(SIGSEGV_STACK_IA64) || defined(SIGSEGV_STACK_X86)
#if defined(SIGSEGV_STACK_IA64)
    ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
    bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
#elif defined(SIGSEGV_STACK_X86)
    ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
    bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
#endif

    sigsegv_outp("Stack trace:");
    while(bp && ip) {
        if(!dladdr(ip, &dlinfo))
            break;

        const char *symname = dlinfo.dli_sname;

#ifndef NO_CPP_DEMANGLE
        int status;
        char * tmp = __cxa_demangle(symname, NULL, 0, &status);

        if (status == 0 && tmp)
            symname = tmp;
#endif

        sigsegv_outp("% 2d: %p <%s+%lu> (%s)",
                 ++f,
                 ip,
                 symname,
                 (unsigned long)ip - (unsigned long)dlinfo.dli_saddr,
                 dlinfo.dli_fname);

#ifndef NO_CPP_DEMANGLE
        if (tmp)
            free(tmp);
#endif

        if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
            break;

        ip = bp[1];
        bp = (void**)bp[0];
    }
#else
    sigsegv_outp("Stack trace (non-dedicated):");
    sz = backtrace(bt, 20);
    strings = backtrace_symbols(bt, sz);
    for(i = 0; i < sz; ++i)
        sigsegv_outp("%s", strings[i]);
#endif
    sigsegv_outp("End of stack trace.");
#else
    sigsegv_outp("Not printing stack strace.");
#endif
    _exit (-1);
}

static void __attribute__((constructor)) setup_sigsegv() {
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_sigaction = signal_segv;
    action.sa_flags = SA_SIGINFO;
    if(sigaction(SIGSEGV, &action, NULL) < 0)
        perror("sigaction");
}

$ g++ -fPIC -shared -o libsigsegv.so -ldl sigsegv

$ export LD_PRELOAD=/path/to/libsigsegv.so

我在一个LUG上找到了此代码。无法进入页面将URL指向此处,因此粘贴了整个代码。发生SIGSEGV时,此代码将打印一条小的堆栈跟踪。不知道是否还有其他不使用ucontext_t的方式。



 类似资料:
  • 假设有一个结构 我得到一个指向该结构的成员的指针,比如作为某个函数的参数: 如何获取指向包含对象的指针?最重要的是:在不违反标准中的某些规则的情况下,也就是说,我想要标准定义的行为,而不是未定义或实现定义的行为。 附带说明:我知道这规避了类型安全。

  • 问题内容: 我正在编写一个在x86-32和x86-64 Linux中使用和进行反汇编的工具。问题是,尽管我能够分解libopcode,但无法获得任何指令信息。为了演示起见,我举了一个最小的例子来重现我的问题。该程序应从入口点反汇编到第一个/ 。 该代码有点被全局变量所破坏,为简洁起见,省略了错误检查等,但是应该清楚地说明问题。 可以使用以下内容构建此源。要执行成功的链接,需要将该软件包安装在本地计

  • 问题内容: 我正在将Linux与x86(准确地说是64位)配合使用。有没有一种方法可以获取当前指令的地址。实际上,我想编写自己的简化版本 setjmp /longjmp 。,R ..发布了 longjmp 的简化版本。任何想法如何实现 setjmp 。简化版本,不考虑异常和信号等。 问题答案: 我相信只要使用64位代码即可。 32位习惯用法是:

  • 问题内容: 解释我的问题的最短方法是该代码: 但是,如果我尝试将指向Item的指针设置为i,代码将起作用: 但是我的函数接收对象,而不是指向它的指针。我可以得到它的类型(第一)。但是当我尝试指向它的指针时,我收到的是,而不是我的Object()的指针。 我可以指向该对象进行调用吗?或者可能是其他方式 问题答案: 切勿使用指向接口的指针。如果您需要一个指针来使用指针接收器调用方法,则必须将指针放入。

  • 问题内容: 将一些地图定义为: 我想要一个指向地图地址的变量(不要复制所有变量)。我尝试使用: 但在使用时,它显示 内部编译器错误:无类型的var,初始化:new 如何获得? 编辑 该错误由另一个问题显示。 问题答案: 映射是引用类型,因此它们总是通过引用传递。您不需要指针。转到文档

  • 问题内容: 我有两个Angular指令,一个嵌套在另一个内,如下所示。 的HTML responseGroup.template.html responseOption.template.html 的JavaScript 我希望子指令可以访问父指令中的“ response-group-id”字段。我该怎么做呢?我能够通过让子指令要求父指令,然后在子指令的“ link”方法中获取它来获取值,但是那时