为SIGSEGV设置handler有用吗?

2023-05-16

背景

最近几天看到先辈们30年前留下了一块代码,为SIGSEGV设置了handler,所以心中有了两个疑问:

  1. 为SIGSEGV设置handler有没有用?
  2. 能否跳过引起崩溃的那一句指令?

答案是没有太多用处,信号处理函数返回后会再次执行出错的指令,从而再次引发调用信号处理函数,陷入无限循环。不过信号处理函数有能力改变RIP的值从而跳过出错的指令,但用处不大,因为跳过了出错指令会影响后面代码的执行结果。
以下试验只是为了玩玩,没有太多用处。

试验代码

#include<stdio.h>
#include <unistd.h>
#include <stdint.h>

#define __USE_GNU
#include <signal.h>

int handle_count=0;
void signal_seg_handler(int sig, siginfo_t* siginfo, void* context){
        char eye_chacher[16]="seg_handler";
        mcontext_t* mcontext = &((ucontext_t*)context)->uc_mcontext;
        write(STDERR_FILENO, "SIGSEGV caught\n", 15);
        if(++handle_count<5){
                uint8_t* code = (uint8_t*)mcontext->gregs[REG_RIP];
                printf("SIGSEGV instruction address:%p code:%02x%02x\n", code, code[0], code[1]);//此处不应该使用非重入函数printf,仅仅为了方便。
        }else{
                write(STDERR_FILENO, "SIGSEGV caught more than 5 times\n", 32);
                exit(-1);
        }
}

static void do_segv()
{
        char eye_chacher[16]="do_segv";
        int *segv;
        segv = 0; /* malloc(a_huge_amount); */
        *segv = 1;
        printf("Should not go here\n");
}

void main(){
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_sigaction = signal_seg_handler;
        act.sa_flags = SA_SIGINFO;
        sigaction(SIGSEGV, &act, NULL);
        do_segv();
        printf("exit\n");
}

给地址0处赋值,必然引起SEGV,从而触发信号处理函数signal_seg_handler。
运行结果如下:

SIGSEGV caught
SIGSEGV instruction address:0x400779 code:c700
SIGSEGV caught
SIGSEGV instruction address:0x400779 code:c700
SIGSEGV caught
SIGSEGV instruction address:0x400779 code:c700
SIGSEGV caught
SIGSEGV instruction address:0x400779 code:c700
SIGSEGV caught
SIGSEGV caught more than 5 times

正如预期, 不停地执行0x400779处的指令,使用GDB查看此处指令:

(gdb) x /3i 0x400779
   0x400779 <do_segv+42>:       movl   $0x1,(%rax)
   0x40077f <do_segv+48>:       mov    $0x4008e2,%edi
   0x400784 <do_segv+53>:       callq  0x400520 <puts@plt>
(gdb) x /6xb 0x400779
0x400779 <do_segv+42>:  0xc7    0x00    0x01    0x00    0x00    0x00
(gdb) f 3
#3  0x0000000000400779 in do_segv () at sigsegv.c:33
33              *segv = 1;
(gdb) disass /m
Dump of assembler code for function do_segv:
...
33              *segv = 1;
   0x0000000000400775 <+38>:    mov    -0x8(%rbp),%rax
=> 0x0000000000400779 <+42>:    movl   $0x1,(%rax)

所以说代码*segv = 1;一直没过去。

跳过出错指令

通过上面的分析,我们知道了出错指令的长度为6;信号处理函数signal_seg_handler中也能拿到一系列要恢复的寄存器的值,尤其是RIP。只要修改RIP=RIP+6即可。
代码修改如下:

void signal_seg_handler(int sig, siginfo_t* siginfo, void* context){
        char eye_chacher[16]="seg_handler";
        mcontext_t* mcontext = &((ucontext_t*)context)->uc_mcontext;
        write(STDERR_FILENO, "SIGSEGV caught\n", 15);
        mcontext->gregs[REG_RIP] += 6; // skip it!
        return;

编译运行:

[mzhai@dendevmvascen05 cprograms]$ ./a.out
SIGSEGV caught
Should not go here
exit

打印了不应该打印的Should not go here,搞定!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为SIGSEGV设置handler有用吗? 的相关文章

  • C# 事件删除语法

    我对 C 中删除事件处理程序的语法感到困惑 Something new MyHandler HandleSomething add Something new MyHandler HandleSomething remove new 在每一
  • 如何在Android Studio中正确使用postDelayed()?

    我有一个 countDownTimer 如果用户在第 12 秒内没有点击 gameButton 我希望调用 gameOver 方法 问题在于 当 countDownTimer 为 12 时 游戏函数会立即被调用 或者计时器会继续倒计时 所以
  • char 设备捕获多个(int)ioctl 参数

    我必须编写一个linux char设备 它处理每个unlock ioctl的ioctl 没有BKL 函数 目前 我可以从用户空间 ioctl 命令接收一个参数 get user myint int user arg 我如何接收多个 int
  • 单击按钮启动计时器

    我是 Android 编程新手 但我了解 Java 我的问题是 Android 中的计时器如何工作 我读过最好使用处理程序 我想做的是 您单击一个按钮 计时器就会启动 到单击按钮的那一刻 我一切都清楚了 但如何启动计时器 Android 中
  • 停止 handler.postDelayed()

    我通过 new Handler postDelayed new Runnable 调用多个处理程序 当我点击返回时如何停止它 public class MyActivity extends AppCompatActivity impleme
  • `无法在继承的 Activity 中创建处理程序...Looper.prepare()`

    我有一个游戏Activity 活动 A 适用于所有代码 然后我创建一个新的Activity 活动 B 对于我的新游戏模式 extendsActivity A 然而 当遇到 Toast 行时 Activity B 突然抛出异常 Activit
  • Web API - 405 - 请求的资源不支持 http 方法“PUT”

    我有一个 Web API 项目 但无法对其启用 PUT Patch 请求 我从 fiddler 得到的回应是 HTTP 1 1 405 Method Not Allowed Cache Control no cache Pragma no
  • 处理程序与线程

    我想知道一次 我读过很多地方 当我想做一些 长时间操作 时 我应该使用Handler 但我不明白为什么 我所有的 长时间操作 都用常规线程包围 并且工作正常 我为什么要使用Handler为了这 我唯一需要使用的时间Handler是 当我必须
  • UINavigationController“pushViewController:animated”的完成处理程序?

    我正在使用创建一个应用程序UINavigationController呈现下一个视图控制器 iOS5 提供了一种新的呈现方法UIViewControllers presentViewController animated completio
  • 通过线程中的处理程序更新主活动中的 UI (Android)

    我尝试在一个类中建立多个连接并更新主屏幕中的多个进度条 但我在尝试在 android 中使用线程时遇到以下错误 代码 05 06 13 13 11 092 错误 ConnectionManager 22854 错误 无法在未调用 Loope
  • Android - 延迟加载图像

    我正在尝试伪造某种进度条 我有 X 张图片并想要一张ImageView以一定的延迟向他们展示 我尝试过做这样的事情 for i 2 i
  • 如何向标准信号处理程序添加代码?

    我有一个在 Linux 上运行的 C 应用程序 我需要向标准信号处理程序添加一些代码 我的想法是设置我的处理程序 将指针保存到标准处理程序 并从我的代码中调用保存的处理程序 不幸的是 signal 和 sigaction 都没有返回指向标准
  • 找不到记录器的处理程序

    我是Python新手 我正在尝试登录 python 我遇到了找不到记录器的处理程序尝试通过记录器实例打印一些警告时出错 下面是我尝试过的代码 import logging logger logging getLogger logger lo
  • Android 中的处理程序和内存泄漏

    请看下面的代码 public class MyGridFragment extends Fragment Handler myhandler new Handler Override public void handleMessage Me
  • 为什么要使用 Handlers 而 runOnUiThread 会做同样的事情?

    我都遇到过Handlers http developer android com reference android os Handler html and 在UiThread上运行 http developer android com r
  • Python 日志记录:为什么 __init__ 被调用两次?

    我正在尝试将 python 日志记录与配置文件和自己的处理程序一起使用 这在某种程度上是有效的 真正让我困惑的是 init 被叫两次并且 del 被调用一次 当我删除整个配置文件内容并直接在代码中创建处理程序时 init 被调用一次并且 d
  • 处理程序/可运行延迟有时会产生不同步的事件

    当尝试学习如何创建延迟时 我研究并发现主要答案是使用 Handler Runnable postDelayed Handler handler new Handler final Runnable r new Runnable public
  • JQuery - 使用变量处理多个元素的一个处理程序

    我有两个这样定义的变量 var a a b b 如何使用 a 和 b 重写以下行 a b click function e a get 0 b get 0 click function e
  • 如何使用应用程序接口将蓝牙套接字传递给另一个活动

    因此 根据我收集的信息 套接字连接既不可序列化 也不可分割 但我需要将蓝牙连接传递给另一个活动 我不想作为中间人编写服务 所以请不要将此作为解决方案发布 我听说有一种方法可以使用自定义应用程序接口来传递这些类型的对象 但我一生都找不到这样的
  • Session_set_save_handler 未设置

    我在设置 session set save handler 时遇到问题 我将 php ini 配置为 session handler user 这个简单的测试失败了 Define custom session handler if sess

随机推荐

  • C语言之网络编程(服务器和客户端)

    Linux网络编程 1 套接字 xff1a 源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字 其用于标识客户端请求的服务器和服务 常用的TCP IP协议的3种套接字类型如下所示 xff08 1 xff09 流套接字 xff0
  • 无监督学习论文阅读

    无监督学习论文阅读 刚开始接触这方面的内容 xff0c 仅供参考 Diversity Transfer Network for Few Shot Learning xff08 AAAI2020 xff09 1 这篇文章提出了一种新的深度聚类
  • 控制教程 —— 介绍篇:3.PID控制器设计

    承接上一篇 控制教程 介绍篇 xff1a 2 系统分析 介绍完系统建模和基本的系统分析后 xff0c 我们已经了解了被控对象的特性 xff0c 这时 xff0c 就需要用一个合理的控制器 xff0c 让这个被控对象在该控制器下按照指定的给定
  • FreeRTOS —— 4.队列管理

    4 1 本章介绍与适用范围 队列 提供了任务到任务 xff0c 任务到中断以及中断到任务的通信机制 范围 本章旨在使读者更好地理解 xff1a 如何创建队列 队列如何管理其包含的数据 如何将数据发送到队列 如何从队列接收数据 阻塞队列意味着
  • LSTM一般最多堆叠多少层

    一 LSTM一般最多堆叠多少层 在大规模翻译任务的经验中 简单的堆叠LSTM层最多可以工作4层 很少工作6层 超过8层就很差了 Redisual connection有助于梯度的反向传播 xff0c 能够帮助lstm堆叠更多层 xff0c
  • 华为机试在线训练-牛客网(23)判断两个IP是否属于同一子网

    题目描述 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据 子网掩码与IP地址结构相同 xff0c 是32位二进制数 xff0c 其中网络号部分全为 1 和主机号部分全为 0 利用子网掩码可以判断两台主机是否中同一子网中
  • APISIX Dashboard中文文档(二)

    2022年7月6日14 31 51 APISIX Dashboard中文文档 一 APISIX Dashboard中文文档 二 APISIX Dashboard中文文档 三 基本部署 在 Linux 上安装 Apache APISIX Da
  • FreeRTOS 任务调度原理(基于cortexM内核)

    目录 默认FreeRTOS调度策略 xff08 单核 xff09 FreeRTOS调度策略的实现 任务创建 任务调度的4种情景 xff1a 1 第一次启动任务调度器 2 任务主动触发调度 3 SystemTick时钟触发调度 4 因为中断而
  • Centos7命令行安装图形用户界面

    安装完成Centos7后 xff0c 重启后发现是命令行界面 xff0c 于是就想改成图形用户界面 安装了图形用户界面的话 xff1a 1 查看系统里是否已经安装了图形用户界面 使用ctrl 43 alt 43 fx xff0c x为123
  • STM32G070 DMA+SPI+LCD显示

    SPI HandleTypeDef hspi1 DMA HandleTypeDef hdma spi1 tx 描述 xff1a LCD的SPI引脚初始化 参数 xff1a 无 返回 xff1a 无 void LCD SPI Init voi
  • Linux 开启VNCSERVER

    尽管我们可以使用 SSH连接远程通过字符界面来操作Linux xff0c 但是对于更多熟悉图形人来说是很不方便的 xff0c 因此开启Linux的远程桌面还是很有必要的 目前有两种比较流行的方式 xff1a XDM X display ma
  • Ubuntu 代号引发的“崩溃”

    写这篇文章主要是因为在前几天 xff0c 因为向来不关心ubuntu代号的我而引发的一次 崩溃 xff08 人崩溃 xff09 xff0c 正如我们所知Ubuntu 每半年都会更新一个版本 xff0c 每两年都会发布一个TLS xff08
  • Prometheus(二)部署Prometheus和node_exporter

    软件包列表 Prometheus安装 解压部署 rm rf prometheus 2 28 1 linux amd64 tar xvf prometheus 2 28 1 linux amd64 tar gz rm usr local pr
  • Python学习之路_day_02(编程语言介绍及变量)

    一 编程语言介绍 1 机器语言 直接用二进制编程 xff0c 直接控制硬件 xff0c 需要掌握硬件的操作细节 优点 xff1a 执行效率高 缺点 xff1a 开发效率低 2 汇编语言 xff1a 用英文标签取代二进制指令去编写程序 xff
  • 解决linux系统read only system 解决办法

    首先确认系统属于非硬盘物理坏道引起 其次确认是否有root权限 下面我要阐述一个恢复实例 xff1a 一现象 xff1a 1 没有root权限 2 由于磁盘空间满溢导致分区表损坏 xff08 非物理坏道引起 xff09 3 重启后已经无法进
  • 哈希查找效率及应用场景

    数组的特点是 xff1a 寻址容易 xff0c 插入和删除困难 xff1b 而链表的特点是 xff1a 寻址困难 xff0c 插入和删除容易 那么我们能不能综合两者的特性 xff0c 做出一种寻址容易 xff0c 插入删除也容易的数据结构
  • 四位比较器

    四位比较器 一 xff0c 实验目的 通过使用比较四位二进制判断它的相对大小 二 xff0c 实验内容 四位比较器的实验 三 xff0c 实验代码 module Comp 2 str output A gt B A lt B A eq B
  • 程序员玩游戏之三--天天爱消除非暴力脚本

    评论 xff1a 此款游戏成功在其好友排名上 好友的分数超过了你无疑会增加你的斗志 中级策略 xff1a 七手八脚多人一起点 这相当于多个CPU处理一个大任务了 xff0c 哈哈 终极策略 xff1a 自动化 机器总是比人快的多 你两个人一
  • 程序员玩游戏之四--娱网棋牌大连打滚子记牌器

    话说大连人都爱打滚子 xff0c 所以本人就做了一个打滚子记牌器 基本原理同 程序员玩游戏之一 自动对对碰 xff0c 故此处不再赘述 xff0c 只留下一张截图吧 代码请见资源地址 xff1a http download csdn net
  • 为SIGSEGV设置handler有用吗?

    背景 最近几天看到先辈们30年前留下了一块代码 xff0c 为SIGSEGV设置了handler xff0c 所以心中有了两个疑问 xff1a 为SIGSEGV设置handler有没有用 xff1f 能否跳过引起崩溃的那一句指令 xff1f