首页
论坛
课程
招聘
关tls回调线程?
2010-3-1 16:40 12615

关tls回调线程?

2010-3-1 16:40
12615
链接 http://bbs.pediy.com/showthread.php?t=81543

下程序我编译运行不对,

恳请高手指点一下,是不是在vc下要做什么编译和链接设置,还是需要对程序进行修改才能运行tls回调线程

谢谢了

// TLS_CallBack_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <winnt.h>
//下面这行告诉链接器在PE文件中要创建TLS目录
#pragma comment(linker, "/INCLUDE:__tls_used")
/*这是PIMAGE_TLS_CALLBACK()函数的原型,其中第一个和第三个参数保留,第二个参数决定函数在那种情况下*/
void NTAPI my_tls_callback(PVOID h, DWORD reason, PVOID pv)
{
/*一共有四个选项DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH和DLL_PROCESS_DETACH。详见微软发布的《Microsoft Portable Executable and Common Object File Format Specification v8》*/
//仅在进程初始化创建主线程时执行的代码
if( reason == DLL_PROCESS_ATTACH ){
   MessageBox(NULL,L"hi,this is tls callback",L"title",MB_OK);
}
return;
}
/*下面这段是创建一个tls段
".CRT$XLB"的含义是:
.CRT表明是使用C RunTime机制
$后面的XLB中
X表示随机的标识
L表示是TLS callback section
B可以被换成B到Y的任意一个字母,但是不能使用".CRT$XLA"和".CRT$XLZ"
因为".CRT$XLA"和".CRT$XLZ"是用于tlssup.obj的
*/
#pragma data_seg(".CRT$XLB")
/*如果要定义多个TLS_CallBack函数,可以把下面这句写成:
PIMAGE_TLS_CALLBACK p_thread_callback [] = {tls_callback_A, tls_callback_B, tls_callback_C,0};
其中tls_callback_B和tls_callback_C应该是你定义好的其他TLS_callBack函数
*/
PIMAGE_TLS_CALLBACK p_thread_callback = my_tls_callback;
#pragma data_seg()

int main(void)
{
MessageBox(NULL,L"hi,this is main()",L"title",MB_OK);
return 0;
}
---------------------------------------------------------------------

【公告】 [2022大礼包]《看雪论坛精华22期》发布!收录近1000余篇精华优秀文章!

收藏
点赞1
打赏
分享
最新回复 (19)
雪    币: 460
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Akihyou 活跃值 2010-3-1 17:38
2
0
试了下可以正确运行

你那是运行结果不对,还是其他什么错误?
雪    币: 129
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
archy 活跃值 2010-3-1 17:46
3
0
我在vc6下测试的,没有弹出两个对话框。。。
雪    币: 460
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Akihyou 活跃值 2010-3-1 17:53
4
0
我刚是用VS2005试的。

自己调试跟踪进去看啊。。
雪    币: 294
活跃值: 活跃值 (122)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
blueapplez 活跃值 14 2010-3-1 17:58
5
0
强烈关注!
我存在同样的疑问  关于tls的也试过好多次都没成功 也不知道是为什么
我VC 6.0编译的 不成功!
雪    币: 611
活跃值: 活跃值 (373)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
zzage 活跃值 1 2010-3-2 11:12
6
0
VC6编译不了tls,好像说是VC6编译器的BUG,编译时会把TLS的回调函数地址被覆盖,用VS2005或VS2008就可以~
雪    币: 923
活跃值: 活跃值 (20)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
不问年少 活跃值 15 2010-3-2 17:26
7
0
嗯,VC6编译不成功……!用VC6以后的版本能行
雪    币: 4990
活跃值: 活跃值 (661)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
littlewisp 活跃值 2 2010-3-2 22:10
8
0
vc6的一个Bug.
雪    币: 923
活跃值: 活跃值 (20)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
不问年少 活跃值 15 2010-3-3 08:13
9
0
也不是没办法解决,自己PEDIY就行了
雪    币: 294
活跃值: 活跃值 (122)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
blueapplez 活跃值 14 2010-3-4 09:37
10
0
VS2005的Debug版本是正常的   Release版本依然不会调用TLS的回调   用LordPE查了下
TLS的信息如下,忘记说明一下是控制台的程序
上传的附件:
雪    币: 705
活跃值: 活跃值 (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半道出家 活跃值 2010-3-4 12:38
11
0
这个问题可以说是VC6的BUG,但也可以解决,关键在于VC6提供的tlssup.obj上,它已定义了回调表的第一项,且该项为0,意味着回调表结束,p_thread_callback放在了回调表的第2项上,永远调不到。知道了问题所在,也就可以解决,使用VC2008带的tlssup.obj,将它加到你的工程中,以取代LIBC中的实现。但仍有一个问题是VS2008中的tlssup.obj中的CRT$XLA和CRT$XLZ的节属性要改成和VC6带的tlssup.obj中的一致,否则仍然不行。
雪    币: 705
活跃值: 活跃值 (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半道出家 活跃值 2010-3-5 09:23
12
0
我来对这个问题进行一下总结,并给出新的解决方法。
TLS回调问题,网上已有人给出了解决方案,但总是有一些问题,基本如下:
  1、VC6不支持。
  2、VS2005的Debug版正常,Release版不正常。
  3、VS2005的Release版正常,Debug版不正常。
VC6不支持的原因是VC6带的TLSSUP.OBJ有问题,它已定义了回调表的第一项,并且为0,0意味着回调表的结束,因此我们加的函数都不会被调用。对于第2个问题,我没遇到,倒是遇到了第3个问题。对这个问题进行了一下研究,发现问题所在:在Link过程中节.CRT$XLA和.CRT$XLB合并时,应该是按字母顺序无间隙合并,但在DEBUG版的输出中实事并非如此,顺序没错,但却产生了很大的间隙,间隙填0,相当于在我们的回调表前加0若干个0,又是回调表提前结束,这也许是BUG。针对第二种情况,我没有遇到,不知道是否是这个原因,如果是,则我想应是LINK的BUG。
    针对上述问题,本来我想可以使用VS2008的tlssup.obj,但是它与VC6的不兼容,改起来比较麻烦,后来我突然想到,也许我们可以自己创建一个tlssup.obj,基于这个思路,写了自己的tlssup,目前测试结果显示,它可以兼容VC6,VS2005,VS2008,代码如下:

       /*文件名:tlssup.c, 要求以C方式编译, 如果你的工程是CPP工程,请针对此源文件取消预编译头*/
  #include <windows.h>
  #include <winnt.h>

  int _tls_index=0;

  #pragma data_seg(".tls")
  int _tls_start=0;
  #pragma data_seg(".tls$ZZZ")
  int _tls_end=0;
  #pragma data_seg(".CRT$XLA")
  int __xl_a=0;
  #pragma data_seg(".CRT$XLZ")
  int __xl_z=0;

  #pragma data_seg(".rdata$T")

  extern PIMAGE_TLS_CALLBACK my_tls_callbacktbl[];

  IMAGE_TLS_DIRECTORY32 _tls_used[]={(DWORD)&_tls_start,(DWORD)&_tls_end,(DWORD)&_tls_index,(DWORD)my_tls_callbacktbl,0,0};

  /*tlssup.c结束*/

    然后,我们在其它CPP文件中定义my_tls_callbacktbl如下即可:
  extern "C" PIMAGE_TLS_CALLBACK my_tls_callbacktbl[] = {my_tls_callback1,0};  //可以有多个回调,但一定要在最后加一个空项,否则很可能出错。
    当然下面一行也不能少:
#pragma comment(linker, "/INCLUDE:__tls_used")
雪    币: 923
活跃值: 活跃值 (20)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
不问年少 活跃值 15 2010-3-5 10:12
13
0
嗯,非常不错,测试很好用,在文件中加入警告禁止更好:

#include <windows.h>
#include <winnt.h>
#pragma warning(disable:4047)
int _tls_index=0;

#pragma data_seg(".tls")
int _tls_start=0;
#pragma data_seg(".tls$ZZZ")
int _tls_end=0;
#pragma data_seg(".CRT$XLA")
int __xl_a=0;
#pragma data_seg(".CRT$XLZ")
int __xl_z=0;

#pragma data_seg(".rdata$T")

extern PIMAGE_TLS_CALLBACK my_tls_callbacktbl[];

IMAGE_TLS_DIRECTORY32 _tls_used[]={(DWORD)&_tls_start,(DWORD)&_tls_end,(DWORD)&_tls_index,(DWORD)my_tls_callbacktbl,0,0};

/*tlssup.c结束*/
雪    币: 705
活跃值: 活跃值 (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半道出家 活跃值 2010-3-5 11:10
14
0
谢谢楼上的反馈,有没有人愿意给我增加“声望值”呀,想升级成变通用户
雪    币: 129
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
archy 活跃值 2010-3-5 11:43
15
0
谢谢半道出家,,

测试成功了。。
雪    币: 705
活跃值: 活跃值 (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半道出家 活跃值 2010-3-5 12:04
16
0
不客气,不过有一点我当时糊涂了,就是_tls_used不需要定义成数组,虽然结果一样,但不想误导大家。
雪    币: 196
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
邹志勇 活跃值 2010-5-15 12:20
17
0
找了很就了,终于找到了解决的方法,真的非常感谢 半道出家
雪    币: 274
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
hejiwen 活跃值 2 2010-5-15 13:51
18
0
Mark Mark
雪    币: 146
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
nsso 活跃值 2010-12-5 13:19
19
0
tls回调 mark
雪    币: 208
活跃值: 活跃值 (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
一只小猴子 活跃值 2019-10-7 16:39
20
0
9年后的小白前来打卡
游客
登录 | 注册 方可回帖
返回