内联汇编中的弱符号和自定义部分
weak symbols and custom sections in inline assembly
我遇到了以下 g++ 代码所说明的问题:
frob.hpp:
template<typename T> T frob(T x);
template<> inline int frob<int>(int x) {
asm("1: nop\n"
".pushsection \"extra\",\"a\"\n"
".quad 1b\n"
".popsection\n");
return x+1;
}
foo.cpp:
#include "frob.hpp"
extern int bar();
int foo() { return frob(17); }
int main() { return foo() + bar(); }
bar.cpp:
#include "frob.hpp"
int bar() { return frob(42); }
我正在做这些古怪的自定义部分的事情作为模仿 the mechanism here in the linux kernel 的一种方式(但是以用户空间和 C++ 的方式)。
我的问题是 frob<int>
的实例化被识别为弱符号,这很好,两者之一最终被链接器省略,这也很好。除了链接器不会因为 extra
部分引用了该符号(通过 .quad 1b
)这一事实而受到干扰,并且链接器希望在本地解析它们。我得到:
localhost /tmp $ g++ -O3 foo.cpp bar.cpp
localhost /tmp $ g++ -O0 foo.cpp bar.cpp
`.text._Z4frobIiET_S0_' referenced in section `extra' of /tmp/ccr5s7Zg.o: defined in discarded section `.text._Z4frobIiET_S0_[_Z4frobIiET_S0_]' of /tmp/ccr5s7Zg.o
collect2: error: ld returned 1 exit status
(-O3
很好,因为没有符号完全发出)。
我不知道如何解决这个问题。
- 是否有办法告诉链接器也注意
extra
部分中的符号解析?
也许可以将本地标签换成 .weak
全局标签?例如。比如:
asm(".weak exception_handler_%=\n"
"exception_handler_%=: nop\n"
".pushsection \"extra\",\"a\"\n"
".quad exception_handler_%=\n"
".popsection\n"::);
但是我担心如果我这样做,不同编译单元中的不同 asm 语句可能会通过这种机制获得相同的符号(可能吗?)。
有没有我忽略的解决方法?
g++(至少5,6)编译一个带有外部链接的内联函数——比如
template<> inline int frob<int>(int x)
- 全球疲软
[COMDAT] [function-section] 中的符号
它自己的部分组。参见:-
g++ -S -O0 bar.cpp
bar.s
.file "bar.cpp"
.section .text._Z4frobIiET_S0_,"axG",@progbits,_Z4frobIiET_S0_,comdat
.weak _Z4frobIiET_S0_
.type _Z4frobIiET_S0_, @function
_Z4frobIiET_S0_:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
#APP
# 8 "frob.hpp" 1
1: nop
.pushsection "extra","a"
.quad 1b
.popsection
# 0 "" 2
#NO_APP
movl -4(%rbp), %eax
addl , %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
...
...
相关指令为:
.section .text._Z4frobIiET_S0_,"axG",@progbits,_Z4frobIiET_S0_,comdat
.weak _Z4frobIiET_S0_
(编译器生成的 #APP
和 #NO_APP
分隔您的内联程序集)。
通过使 extra
同样成为 COMDAT 部分来像编译器一样做
一个分区组:
frob.hpp(固定)
template<typename T> T frob(T x);
template<> inline int frob<int>(int x) {
asm("1: nop\n"
".pushsection \"extra\", \"axG\", @progbits,extra,comdat" "\n"
".quad 1b\n"
".popsection\n");
return x+1;
}
联动错误将得到解决:
$ g++ -O0 foo.cpp bar.cpp
$ ./a.out; echo $?
61
我遇到了以下 g++ 代码所说明的问题:
frob.hpp:
template<typename T> T frob(T x);
template<> inline int frob<int>(int x) {
asm("1: nop\n"
".pushsection \"extra\",\"a\"\n"
".quad 1b\n"
".popsection\n");
return x+1;
}
foo.cpp:
#include "frob.hpp"
extern int bar();
int foo() { return frob(17); }
int main() { return foo() + bar(); }
bar.cpp:
#include "frob.hpp"
int bar() { return frob(42); }
我正在做这些古怪的自定义部分的事情作为模仿 the mechanism here in the linux kernel 的一种方式(但是以用户空间和 C++ 的方式)。
我的问题是 frob<int>
的实例化被识别为弱符号,这很好,两者之一最终被链接器省略,这也很好。除了链接器不会因为 extra
部分引用了该符号(通过 .quad 1b
)这一事实而受到干扰,并且链接器希望在本地解析它们。我得到:
localhost /tmp $ g++ -O3 foo.cpp bar.cpp
localhost /tmp $ g++ -O0 foo.cpp bar.cpp
`.text._Z4frobIiET_S0_' referenced in section `extra' of /tmp/ccr5s7Zg.o: defined in discarded section `.text._Z4frobIiET_S0_[_Z4frobIiET_S0_]' of /tmp/ccr5s7Zg.o
collect2: error: ld returned 1 exit status
(-O3
很好,因为没有符号完全发出)。
我不知道如何解决这个问题。
- 是否有办法告诉链接器也注意
extra
部分中的符号解析? 也许可以将本地标签换成
.weak
全局标签?例如。比如:asm(".weak exception_handler_%=\n" "exception_handler_%=: nop\n" ".pushsection \"extra\",\"a\"\n" ".quad exception_handler_%=\n" ".popsection\n"::);
但是我担心如果我这样做,不同编译单元中的不同 asm 语句可能会通过这种机制获得相同的符号(可能吗?)。
有没有我忽略的解决方法?
g++(至少5,6)编译一个带有外部链接的内联函数——比如
template<> inline int frob<int>(int x)
- 全球疲软
[COMDAT] [function-section] 中的符号
它自己的部分组。参见:-
g++ -S -O0 bar.cpp
bar.s
.file "bar.cpp"
.section .text._Z4frobIiET_S0_,"axG",@progbits,_Z4frobIiET_S0_,comdat
.weak _Z4frobIiET_S0_
.type _Z4frobIiET_S0_, @function
_Z4frobIiET_S0_:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
#APP
# 8 "frob.hpp" 1
1: nop
.pushsection "extra","a"
.quad 1b
.popsection
# 0 "" 2
#NO_APP
movl -4(%rbp), %eax
addl , %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
...
...
相关指令为:
.section .text._Z4frobIiET_S0_,"axG",@progbits,_Z4frobIiET_S0_,comdat
.weak _Z4frobIiET_S0_
(编译器生成的 #APP
和 #NO_APP
分隔您的内联程序集)。
通过使 extra
同样成为 COMDAT 部分来像编译器一样做
一个分区组:
frob.hpp(固定)
template<typename T> T frob(T x);
template<> inline int frob<int>(int x) {
asm("1: nop\n"
".pushsection \"extra\", \"axG\", @progbits,extra,comdat" "\n"
".quad 1b\n"
".popsection\n");
return x+1;
}
联动错误将得到解决:
$ g++ -O0 foo.cpp bar.cpp
$ ./a.out; echo $?
61