如何确定线程栈的基址?

很早之前,我遇到过几个与栈相关的问题,当时总结过几篇关于线程栈的文章,分别是 《栈大小可以怎么改?》、《栈局部变量优化探究,意外发现了 vs 的一个 bug ?》、《栈又溢出了》、《有趣的异常》。在这几篇总结中,简单的总结了栈溢出的原因,设置线程栈大小的方法。但是还有一点没弄清楚:操作系统是怎么知道一个线程的栈大小的?一定记录在某个位置了,否则就不能正确的在栈溢出的时候抛出异常了。不能根据 PE 头中的字段判断,因为在创建线程的时候可以指定线程栈大小。TEB 中的 StackLimit 是真正的栈底吗?带着这些疑问一起来刨根问底吧~

友情提示:结论在文章末尾。

!teb 命令

相信,很多小伙伴儿都知道,可以使用 !teb 查看线程相关的信息。

 

其中的 StackBaseStackLimit 分别指示了栈顶和当前栈使用情况。因为栈是从上向下增长的,所以 StackBase 的值比较大。

我之前一直认为这两个字段分别指向了栈顶和栈底(线程栈可以到达的最低位置),可以通过这两个字段计算出线程栈大小。后来才发现 StackLimit 并没有指向栈底,而是指向了线程栈当前所到达的最低位置。

线程栈默认的大小是 1MB。如果计算一下 StackBase - StackLimit 的值即可知道,它们的差值是 256KB,而不是 1MB

那么当前线程栈的大小是不是 1MB 呢?该如何确认呢?可以通过 vmmap 确定。

vmmap

打开 vmmap.exe,并选择想要查看的进程,即可进行查看。

注意: 当选择的进程已经中断到调试器时,vmmap.exe 会一直等待,需要让目标进程运行起来。

 

可以看到,线程 9804 的线程栈大小确实是 1MB

根据以上信息,可以确定 StackLimit 并不是真正的线程栈栈底。那么,栈底位置到底记录在哪里了呢?

最近在重翻《软件调试》的时候,发现了一个关键函数。

栈空间自动增长的关键函数

在第 2222.8.1 节 栈空间的自动增长(P617)中提到了一个关键函数 MiCheckForUserStackOverflow。该函数是判断栈空间能否增长的关键函数。如果知道该函数是如何实现的,就能找到栈底了。

脑子里很快有了三个选项:google 搜索,ReactOSserver03 源码。正好电脑上有源码,不用考虑其它两个选项了。

参考源码

知道了函数名,但是还不知道这个函数在哪个文件中实现的。这个简单,在 File Locator 中输入 MiCheckForUserStackOverflow,很快就找到了关键的文件。

 

双击打开 accesschk.c,找到 MiCheckForUserStackOverflow。注释很清晰的解释了这个函数的作用。 

 

说明: 该函数的实现在 wrk 中也可以找到,地址是 https://github.com/mic101/windows/blob/master/WRK-v1.2/base/ntos/mm/acceschk.c。

整个函数虽然行数很多,但是有大部分是注释,而且考虑了各种情况。我截取了最关键的部分,如下图:

 

看样子 teb->DeallocationStack 记录了栈底。 StackBase 减去 teb->DeallocationStack 的值应该是栈大小(默认是 1MB)。在 windbg 中验证一下。

验证

windbg 中输入如下命令 dt _teb 0043f000 -y DeallocationStack -y NtTib.StackBase,只查看 DeallocationStackNtTib.StackBase 的值。然后计算差值,发现正好是 1MB0x100000)。

总结

  • _TEB 结构体的 DeallocationStack 指向线程栈底,而 NtTib.StackLimit 指向的是线程栈当前所到达的最低位置。

  • 可以在 dt 命令中通过 -y 选项来显示特定字段。

  • vmmap.exe 可以非常详细的展示进程虚拟内存情况。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/169634.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外星人笔记本键盘USB协议逆向

前言 我朋友一台 dell g16 购买时直接安装了linux系统,但是linux上没有官方的键盘控制中心,所以无法控制键盘灯光,于是我就想着能不能逆向一下键盘的协议,然后自己写一个控制键盘灯光的程序。我自己的外星人笔记本是m16&#xff…

音视频基础知识

图像(YUV RGB) ​​​​​​​​​​​​​​这个讲的比较好 RGB颜色编码 图像显示主要是由像素组成,每个像素点的颜色组成都是采用RGB格式,RGB就是红、绿、蓝,RGB分别取不同的值,展示不同的颜色。 YUV…

OpenMMlab导出yolov3的onnx模型并推理

手动导出 直接使用脚本 import torch from mmdet.apis import init_detector, inference_detectorconfig_file ./configs/yolo/yolov3_mobilenetv2_8xb24-ms-416-300e_coco.py checkpoint_file yolov3_mobilenetv2_mstrain-416_300e_coco_20210718_010823-f68a07b3.pth mod…

SPC 的一些小知识

在生产管理系统种,经常回涉及到质量管理分,我们经常听说SPC、SPC控制图等和SPC相关的词汇,那么SPC是什么意思呢?它有什么作用呢?在这里通俗一点介绍一下SPC。 SPC是统计过程控制(Statistical Process Cont…

Android—幸运抽奖火箭发射倒计时(第六次作业)

Android—幸运抽奖&&点火发射(第六次作业) 创建项目 准备工作 修改按钮的颜色,如果不修改这行代码,那么后期给按钮添加background属性的时候,按钮并不会发生变化。 设置按钮的样式文件btn_press_blue.xml&am…

学习OpenCV(蝴蝶书/C++)相关——2.MacOS下使用LLDB调试cpp程序

文章目录 1. VScode中的调试2. 配置VSCode中C++的调试(以OpenCV为例)2.1 创建适用于C++的.launch文件2.2 常见参数说明2.3 调试OpenCV的.launch文件示例2.3.1 .launch文件demo2.3.2 Debug模式的可执行文件3. 联合task.json文件一起使用3.1 创建tasks.json和launch.json文件3.2 …

数字化仪的超声波应用

超声波是频率大于人类听觉范围上限的声学声压(声学)波。超声波设备的工作频率为 20 kHz 至几千 MHz。表 1 总结了一些更常见的超声波应用的特征。每个应用中使用的频率范围都反映了实际情况下的平衡。提高工作频率可以通过提高分辨率来检测较小的伪影&am…

【紫光同创国产FPGA教程】——PDS安装教程

本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 一:软件简介 PangoDesign Suite是紫光同创基于多年FPGA开发软件技术攻关与工程实践经验而研发的一款拥有国产自主知识产权的大规模FPGA开…

【yolov5】onnx的INT8量化engine

GitHub上有大佬写好代码,理论上直接克隆仓库里下来使用 git clone https://github.com/Wulingtian/yolov5_tensorrt_int8_tools.git 然后在yolov5_tensorrt_int8_tools的convert_trt_quant.py 修改如下参数 BATCH_SIZE 模型量化一次输入多少张图片 BATCH 模型量化…

智能一体化管网水位监测仪怎么样?

城市排水管网是城市正常运行的关键环节,这是地上和地下通道的连接点,一旦出现问题便会影响城市生命线建设的工程进展。在复杂的地下管道内想要了解水位数据,对于政府部门来讲是一个管理难题。如果可以采取智能产品在其中发挥作用,…

threejs(12)-着色器打造烟雾水云效果

一、自己封装水波纹效果 src/main/main01.js import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import gsap from "gsap"; import * as dat from "dat.gui"; import ver…

江西开放大学引领学习新时代:电大搜题助力学子迈向成功

江西开放大学(简称江西电大)一直以来致力于为学子提供灵活便捷的学习服务。近年来,携手电大搜题微信公众号,江西开放大学以其卓越的教学质量和创新的教学手段,为广大学子开启了一扇通向成功的大门。 作为一家知名的远…