Error[8]: Undefined offset: 6, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量. 由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题. #include <stdio.h>struct Foo { int x; int y;};__thread Foo 我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量.

由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题.

#include <stdio.h>struct Foo {    int x;    int y;};__thread Foo* volatile foo;voID bar() {    asm("nop");}voID f() {    foo->x = 5;    bar();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    foo->y = 7;}int main(){    foo = new Foo;    f();    delete foo;}

接下来,我们运行以下命令进行编译和反汇编.请注意,-fPIC标志似乎是重现此问题所必需的,并且对于我的用例也是必需的,因为我正在构建库.假设上面的代码在一个名为TL.cc的文件中

g++ -std=c++11 -O3  -fPIC  -Wall -g TL.cc   -o TL objdump -d TL

这是函数f()的汇编转储.

400760:       53                      push   %rbx  # Notice this computation happens only once.  400761:       64 48 8b 04 25 00 00    mov    %fs:0x0,%rax  400768:       00 00   40076a:       48 8d 80 f8 ff ff ff    lea    -0x8(%rax),%rax  400771:       48 89 c3                mov    %rax,%rbx  400774:       48 8b 00                mov    (%rax),%rax  400777:       c7 00 05 00 00 00       movl   
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609copyright (C) 2015 Free Software Foundation,Inc.This is free software; see the source for copying conditions.  There is NOwarranty; not even for MERCHANTABIliTY or fitness FOR A PARTIculaR PURPOSE.
x5,(%rax) 40077d: e8 ce ff ff ff callq 400750 <_Z3barv> # Observe that the value of rbx came from before the function call,# so if the function bar() actually returned on a different kernel # thread,we would be referencing the original kernel thread's # version of foo,instead of the new kernel thread's version. 400782: 48 8b 03 mov (%rbx),%rax 400785: c7 40 04 07 00 00 00 movl
#define SafeTLS(Typename,name) \struct name##_SafeClass { \    name##_SafeClass& \    __attribute__ ((noinline)) \    operator=(const Typename& other) { \        asm (""); \        name = const_cast<Typename&>(other); \        return *this; \    } \    Typename& \    __attribute__ ((noinline)) \    operator->() { \       asm (""); \        return get(); \    } \    operator Typename() { return get(); } \    Typename& \    __attribute__ ((noinline)) \    get() { \        asm (""); \        return name; \    } \   \    Typename* \    operator&() { \        asm (""); \        return &name; \    } \} name##_Safe
x7,0x4(%rax) 40078c: 5b pop %rbx 40078d: c3 retq 40078e: 66 90 xchg %ax,%ax

我们观察到寄存器rax正在从内存重新加载,但是在调用bar()之前确定了内存位置.

有没有办法强制重新加载变量的地址作为fs寄存器当前值的偏移量?

如果存在这些,我可以使用gcc特定的黑客攻击.

这是输出g –version

#include <stdio.h>#include "TLS.h"struct Foo {    int x;    int y;};__thread Foo* volatile foo;__thread int bar;SafeTLS(Foo* volatile,foo);SafeTLS(int,bar);voID f2() {    asm("nop");}voID f() {    foo_Safe->x = 5;    f2();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    (*foo_Safe).y = 7;    bar = 7;    printf("%d\n",bar);    printf("%d %d\n",foo->x,foo->y);    bar = 8;    printf("%d\n",bar_Safe.get());}int main(){    foo = new Foo;    f();    delete foo;}
解决方法 我编写了以下Hack,它强制在我测试的所有情况下重新加载TLS,但是会欣赏有关它可能被破坏的所有方式的反馈.

[+++]

这是一个使用它的更复杂的测试用例.

[+++] 总结

以上是内存溢出为你收集整理的c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?全部内容,希望文章能够帮你解决c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 7, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量. 由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题. #include <stdio.h>struct Foo { int x; int y;};__thread Foo 我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量.

由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题.

#include <stdio.h>struct Foo {    int x;    int y;};__thread Foo* volatile foo;voID bar() {    asm("nop");}voID f() {    foo->x = 5;    bar();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    foo->y = 7;}int main(){    foo = new Foo;    f();    delete foo;}

接下来,我们运行以下命令进行编译和反汇编.请注意,-fPIC标志似乎是重现此问题所必需的,并且对于我的用例也是必需的,因为我正在构建库.假设上面的代码在一个名为TL.cc的文件中

g++ -std=c++11 -O3  -fPIC  -Wall -g TL.cc   -o TL objdump -d TL

这是函数f()的汇编转储.

400760:       53                      push   %rbx  # Notice this computation happens only once.  400761:       64 48 8b 04 25 00 00    mov    %fs:0x0,%rax  400768:       00 00   40076a:       48 8d 80 f8 ff ff ff    lea    -0x8(%rax),%rax  400771:       48 89 c3                mov    %rax,%rbx  400774:       48 8b 00                mov    (%rax),%rax  400777:       c7 00 05 00 00 00       movl   
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609copyright (C) 2015 Free Software Foundation,Inc.This is free software; see the source for copying conditions.  There is NOwarranty; not even for MERCHANTABIliTY or fitness FOR A PARTIculaR PURPOSE.
x5,(%rax) 40077d: e8 ce ff ff ff callq 400750 <_Z3barv> # Observe that the value of rbx came from before the function call,# so if the function bar() actually returned on a different kernel # thread,we would be referencing the original kernel thread's # version of foo,instead of the new kernel thread's version. 400782: 48 8b 03 mov (%rbx),%rax 400785: c7 40 04 07 00 00 00 movl
#define SafeTLS(Typename,name) \struct name##_SafeClass { \    name##_SafeClass& \    __attribute__ ((noinline)) \    operator=(const Typename& other) { \        asm (""); \        name = const_cast<Typename&>(other); \        return *this; \    } \    Typename& \    __attribute__ ((noinline)) \    operator->() { \       asm (""); \        return get(); \    } \    operator Typename() { return get(); } \    Typename& \    __attribute__ ((noinline)) \    get() { \        asm (""); \        return name; \    } \   \    Typename* \    operator&() { \        asm (""); \        return &name; \    } \} name##_Safe
x7,0x4(%rax) 40078c: 5b pop %rbx 40078d: c3 retq 40078e: 66 90 xchg %ax,%ax

我们观察到寄存器rax正在从内存重新加载,但是在调用bar()之前确定了内存位置.

有没有办法强制重新加载变量的地址作为fs寄存器当前值的偏移量?

如果存在这些,我可以使用gcc特定的黑客攻击.

这是输出g –version

#include <stdio.h>#include "TLS.h"struct Foo {    int x;    int y;};__thread Foo* volatile foo;__thread int bar;SafeTLS(Foo* volatile,foo);SafeTLS(int,bar);voID f2() {    asm("nop");}voID f() {    foo_Safe->x = 5;    f2();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    (*foo_Safe).y = 7;    bar = 7;    printf("%d\n",bar);    printf("%d %d\n",foo->x,foo->y);    bar = 8;    printf("%d\n",bar_Safe.get());}int main(){    foo = new Foo;    f();    delete foo;}
解决方法 我编写了以下Hack,它强制在我测试的所有情况下重新加载TLS,但是会欣赏有关它可能被破坏的所有方式的反馈.

这是一个使用它的更复杂的测试用例.

[+++] 总结

以上是内存溢出为你收集整理的c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?全部内容,希望文章能够帮你解决c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?_C_内存溢出

c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?

c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?,第1张

概述我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量. 由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题. #include <stdio.h>struct Foo { int x; int y;};__thread Foo 我在内核和线程之上实现用户线程并观察到,当用户线程在内核线程之间迁移时,即使变量也被标记为volatile,也会从先前的内核位置读取thread_local变量.

由于编译器仅将用户级swapcontext视为函数调用,下面的示例演示了简单函数调用的问题.

#include <stdio.h>struct Foo {    int x;    int y;};__thread Foo* volatile foo;voID bar() {    asm("nop");}voID f() {    foo->x = 5;    bar();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    foo->y = 7;}int main(){    foo = new Foo;    f();    delete foo;}

接下来,我们运行以下命令进行编译和反汇编.请注意,-fPIC标志似乎是重现此问题所必需的,并且对于我的用例也是必需的,因为我正在构建库.假设上面的代码在一个名为TL.cc的文件中

g++ -std=c++11 -O3  -fPIC  -Wall -g TL.cc   -o TL objdump -d TL

这是函数f()的汇编转储.

400760:       53                      push   %rbx  # Notice this computation happens only once.  400761:       64 48 8b 04 25 00 00    mov    %fs:0x0,%rax  400768:       00 00   40076a:       48 8d 80 f8 ff ff ff    lea    -0x8(%rax),%rax  400771:       48 89 c3                mov    %rax,%rbx  400774:       48 8b 00                mov    (%rax),%rax  400777:       c7 00 05 00 00 00       movl   
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609copyright (C) 2015 Free Software Foundation,Inc.This is free software; see the source for copying conditions.  There is NOwarranty; not even for MERCHANTABIliTY or fitness FOR A PARTIculaR PURPOSE.
x5,(%rax) 40077d: e8 ce ff ff ff callq 400750 <_Z3barv> # Observe that the value of rbx came from before the function call,# so if the function bar() actually returned on a different kernel # thread,we would be referencing the original kernel thread's # version of foo,instead of the new kernel thread's version. 400782: 48 8b 03 mov (%rbx),%rax 400785: c7 40 04 07 00 00 00 movl
#define SafeTLS(Typename,name) \struct name##_SafeClass { \    name##_SafeClass& \    __attribute__ ((noinline)) \    operator=(const Typename& other) { \        asm (""); \        name = const_cast<Typename&>(other); \        return *this; \    } \    Typename& \    __attribute__ ((noinline)) \    operator->() { \       asm (""); \        return get(); \    } \    operator Typename() { return get(); } \    Typename& \    __attribute__ ((noinline)) \    get() { \        asm (""); \        return name; \    } \   \    Typename* \    operator&() { \        asm (""); \        return &name; \    } \} name##_Safe
x7,0x4(%rax) 40078c: 5b pop %rbx 40078d: c3 retq 40078e: 66 90 xchg %ax,%ax

我们观察到寄存器rax正在从内存重新加载,但是在调用bar()之前确定了内存位置.

有没有办法强制重新加载变量的地址作为fs寄存器当前值的偏移量?

如果存在这些,我可以使用gcc特定的黑客攻击.

这是输出g –version

#include <stdio.h>#include "TLS.h"struct Foo {    int x;    int y;};__thread Foo* volatile foo;__thread int bar;SafeTLS(Foo* volatile,foo);SafeTLS(int,bar);voID f2() {    asm("nop");}voID f() {    foo_Safe->x = 5;    f2();    asm volatile("":::"memory");    // We desire a second computation of the address of foo here as an offset    // from the FS register.    (*foo_Safe).y = 7;    bar = 7;    printf("%d\n",bar);    printf("%d %d\n",foo->x,foo->y);    bar = 8;    printf("%d\n",bar_Safe.get());}int main(){    foo = new Foo;    f();    delete foo;}
解决方法 我编写了以下Hack,它强制在我测试的所有情况下重新加载TLS,但是会欣赏有关它可能被破坏的所有方式的反馈.

这是一个使用它的更复杂的测试用例.

总结

以上是内存溢出为你收集整理的c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?全部内容,希望文章能够帮你解决c – 是否可以在跨内核线程迁移后强制重新加载thread_local变量?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1225030.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存