it's me again. I am working on a tool can that disassemble/reassemble stripped binaries and now I am sucked in a (external) symbol reuse issue.
The test is on 32-bit Linux x86 platform.
Suppose I am working on a C++ program, in the GCC
compiler produced assembly code, there exists some instructions like this:
call _ZNSt8ios_baseC2Ev
movl _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+4, %ebx
movb $0, 312(%esp)
movl _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+8, %ecx
....
Please pay special attention to symbol _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE
.
After the compilation, suppose I get an unstripped
binary, and i checked this symbol like this:
readelf -s a.out | grep "_ZTTSt14basic"
69: 080a7390 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
72: 080a7220 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ofstreamIcS@GLIBCXX_3.4 (3)
705: 080a7220 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ofstreamIcS
1033: 080a7390 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ifstreamIcS
See, this is my first question, why the name of symbol _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE
modified to _ZTTSt14basic_ifstreamIcS
and _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
?
What is _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
though?
Then I stripped the binary like this:
strip a.out
readelf -s a.out | grep "_ZTTSt14basic"
69: 080a7390 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
72: 080a7220 16 OBJECT WEAK DEFAULT 27 _ZTTSt14basic_ofstreamIcS@GLIBCXX_3.4 (3)
Then after I disassemble the binary, and the corresponding disassembled assembly instructions are :
8063ee7: e8 84 54 fe ff call 8049370 <_ZNSt8ios_baseC2Ev@plt>
8063eec: 8b 1d 94 73 0a 08 mov 0x80a7394,%ebx
8063ef2: c6 84 24 38 01 00 00 movb $0x0,0x138(%esp)
8063ef9: 00
8063efa: 8b 0d 98 73 0a 08 mov 0x80a7398,%ecx
At this point we can figure out that 0x80a7394 equals to _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+4
.
In order to reuse these instructions, I modified the code:
call _ZNSt8ios_baseC2Ev
mov _ZTTSt14basic_ifstreamIcS+4,%ebx
movb $0x0,0x138(%esp)
mov _ZTTSt14basic_ifstreamIcS+8,%ecx
And did some update like these (please see this question for reference):
echo ""_ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)" = 0x080a7390;" > symbolfile
g++ -Wl,--just-symbols=symbolfile final.s
readelf -s a.out | grep "_ZTTSt14basic"
3001: 080a7390 0 NOTYPE LOCAL DEFAULT 27 _ZTTSt14basic_ifstreamIcS
8412: 080a7390 0 NOTYPE GLOBAL DEFAULT ABS _ZTTSt14basic_ifstreamIcS
I debugged the newly produced binary, and to my surprise, in the newly produced binary, symbol _ZTTSt14basic_ifstreamIcS
does not get any value after the function call of _ZNSt8ios_baseC2Ev
, while in the original binary, after the function call, _ZTTSt14basic_ifstreamIcS
do get some memory address referring to library section. Which means:
call _ZNSt8ios_baseC2Ev
mov _ZTTSt14basic_ifstreamIcS+4,%ebx <--- %ebx gets zero!
movb $0x0,0x138(%esp)
mov _ZTTSt14basic_ifstreamIcS+8,%ecx <--- %ecx gets zero!
I must state that in these lines of the original binary, registers %ebx and %ecx both gets some addresses referring to the libc section.
This is my second question, why does symbol _ZTTSt14basic_ifstreamIcS
didn't get any value after function call _ZNSt8ios_baseC2Ev
? I also tried with symbol name _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE
. But that does not work also.
Am I clear enough? Could anyone save my ass? thank you!