#include <stdio.h>
#include <string.h>
#define CONFDIR "/opt/hp9300/pov64_IworkspaceIdocpv989Ieightonews-r7.6-dev_tests-000001"
#define NEW_CONFDIR "/etc" CONFDIR
// test.c
int foo() {
char confdir[127+1]; // plz ignore the buffer checks
strcpy(confdir, NEW_CONFDIR);
// strncpy(confdir, NEW_CONFDIR, sizeof(confdir));
return 0;
}
// output when strcpy
// objdump -s test.so
// no .rodata section, only .text
Contents of section .text:
1040 488d3dc1 2f000048 8d05ba2f 00004839 H.=./..H.../..H9
1050 f8741548 8b056e2f 00004885 c07409ff .t.H..n/..H..t..
1060 e00f1f80 00000000 c30f1f80 00000000 ................
1070 488d3d91 2f000048 8d358a2f 00004829 H.=./..H.5./..H)
1080 fe4889f0 48c1ee3f 48c1f803 4801c648 .H..H..?H...H..H
1090 d1fe7414 488b053d 2f000048 85c07408 ..t.H..=/..H..t.
10a0 ffe0660f 1f440000 c30f1f80 00000000 ..f..D..........
10b0 f30f1efa 803d4d2f 00000075 2b554883 .....=M/...u+UH.
10c0 3d1a2f00 00004889 e5740c48 8d3d2e2d =./...H..t.H.=.-
10d0 0000e859 ffffffe8 64ffffff c605252f ...Y....d.....%/
10e0 0000015d c30f1f00 c30f1f80 00000000 ...]............
10f0 f30f1efa e977ffff ff554889 e54883ec .....w...UH..H..
1100 08488d45 8048ba2f 6574632f 6f707448 .H.E.H./etc/optH
1110 b92f6870 39333030 2f488910 48894808 ./hp9300/H..H.H.
1120 48be706f 7636345f 497748bf 6f726b73 H.pov64_IwH.orks
1130 70616365 48897010 48897818 48ba4964 paceH.p.H.x.H.Id
1140 6f637076 393848b9 39496569 6768746f ocpv98H.9Ieighto
1150 48895020 48894828 48be6e65 77732d72 H.P H.H(H.news-r
1160 372e48bf 362d6465 765f7465 48897030 7.H.6-dev_teH.p0
1170 48897838 48ba6576 5f746573 747348b9 H.x8H.ev_testsH.
1180 2d303030 30303100 4889503b 48894843 -000001.H.P;H.HC
1190 b8000000 00c9c3 .......
// output when strncpy
// objdump -s test.so
// readelf -p ".rodata" test.so
Contents of section .rodata:
2000 2f657463 2f6f7074 2f687039 3330302f /etc/opt/hp9300/
2010 706f7636 345f4977 6f726b73 70616365 pov64_Iworkspace
2020 49646f63 70763938 39496569 6768746f Idocpv989Ieighto
2030 6e657773 2d72372e 362d6465 765f7465 news-r7.6-dev_te
2040 7374732d 30303030 303100 sts-000001.
// output when strncpy
// readelf -p ".rodata" test.so
String dump of section '.rodata':
[ 0] /etc/opt/hp9300/pov64_IworkspaceIdocpv989Ieightonews-r7.6-dev_tests-000001
when I compile it on Linux using gcc -o test.so -fPIC -shared -g and inspect the string constants of shared lib test.so using objdump or strings, I see a sub-string of NEW_CONFDIR, truncated to multiple of 16 bytes.
But, if I change the code to use strncpy (as shown in the code above) and compile again with the same set of flags, it shows full string with no truncation.
Is this expected, does compiler do any optimization with string constants ? Or there is an issues with using strcpy and strncpy in this case and their effect on rodata of shared object files ?
I am only concerned about the compilation phase and generation of shared objects not actual execution of code. The tool searches rodata of shared libs for NEW_CONFDIR.
I reproduced this behavior: take the OP's source, compile with
gcc -o test.so -fPIC -shared -g, runstrings test.so:So let's figure out what's going on.
objdump -d test.soshows:This explains why the string is broken up into 8-byte chunks, but where does the (9-th)
Hcome from?Look at the byte following the "string" constant starting at 0x1122. The
MOVABS ..., %rcxinstruction code is0x480xbf, and0x48just happens to "spell"H, and that's why there is anHthere.Also,
0xbfjust happens to not beASCII, thus breaking the string.If the opcode for
MOVABS ..., %rcxwas0x48 0x5finstead, your "string" would look like/etc/optH_/hp9300/....Related answer about
AWAVAUATUSHand similar strings.So what happens when you use
strncpy?The compiler decides to call external version instead of inlining the
strncpy:P.S. You can ask GCC to not inline
strcpywith-fno-builtin-strcpy, and that will "restore" the full string (because GCC will call externalstrcpyfromlibcwith that flag).