2015-07-13 10 views
5

मुझे एक सीजीएफॉल्ट के कारण का निर्धारण करने में परेशानी हो रही है जब एक कार्यक्रम -O3 के साथ जीसीसी 4.8/4.9/5.1 के साथ संकलित किया जाता है। जीसीसी 4.9.एक्स के लिए, मैंने इसे सिगविन, डेबियन 8 (x64) और फेडोरा 21 (x64) पर देखा है। अन्य ने इसे GCC 4.8 and 5.1 पर अनुभव किया है।-O3 का उपयोग करते समय segfault का कारण निर्धारित करें?

कार्यक्रम -O2 के तहत ठीक है, जीसीसी के अन्य संस्करणों के साथ ठीक है, और अन्य कंपाइलर्स (जैसे एमएसवीसी, आईसीसी और क्लैंग) के तहत ठीक है।

नीचे जीडीबी के तहत दुर्घटना है, लेकिन मुझ पर कुछ भी कूद नहीं रहा है। misc.cpp:26 से स्रोत कोड के नीचे है, लेकिन इसकी एक सरल XOR:

((word64*)buf)[i] ^= ((word64*)mask)[i]; 

64-बिट शब्द संरेखण पहले कलाकारों के लिए सवाल की जाँच में कोड। -O3 तहत disassembly से, मैं जानता हूँ कि यह vmovdqa अनुदेश के साथ कुछ है:

(gdb) disass 0x0000000000539fc3 
... 

    0x0000000000539fbc <+220>: vxorps 0x0(%r13,%r10,1),%ymm0,%ymm0 
=> 0x0000000000539fc3 <+227>: vmovdqa %ymm0,0x0(%r13,%r10,1) 
    0x0000000000539fca <+234>: add $0x20,%r10 

ऐसा प्रतीत होता है जीसीसी -O3 पर SSE वैक्टर उपयोग कर रहा है, और नहीं उन्हें -O2 पर इस्तेमाल करते हैं। (सुझाव के लिए Alejandro के लिए धन्यवाद)।

मैं भोलेपन पूछने के लिए जा रहा हूँ: करता vmovdqa 64-बिट शब्द से अधिक संरेखण आवश्यकताओं है? ऐसा है, जब जीसीसी 128-बिट गठबंधन नहीं होता है तो जीसीसी इसका चयन क्यों कर रहा है?

यहां सेगफॉल्ट का कारण क्या है? मैं इसे और समस्या निवारण कैसे करूं?


यह भी देखें Bug 66852 - vmovdqa instructions issued on 64-bit aligned array, causes segfault। यह इस मुद्दे के जवाब में दायर किया गया था, इसलिए इस समय इसकी पुष्टि नहीं हुई।


$ gdb ./cryptest.exe 
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1 
... 
(gdb) r v 
... 
Testing MessageDigest algorithm SHA-3-224. 
..... 
Program received signal SIGSEGV, Segmentation fault. 
0x0000000000539fc3 in CryptoPP::xorbuf (buf=0x98549a "efghijde", 
    [email protected]=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., [email protected]=0x5e) at misc.cpp:26 
26     ((word64*)buf)[i] ^= ((word64*)mask)[i]; 

(gdb) where 
#0 0x0000000000539fc3 in CryptoPP::xorbuf (buf=0x98549a "efghijde", 
    [email protected]=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., [email protected]=0x5e) at misc.cpp:26 
#1 0x0000000000561eb0 in CryptoPP::SHA3::Update (this=0x985480, 
    input=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., 
    length=0x5e) at sha3.cpp:264 
#2 0x00000000005bac1a in CryptoPP::HashVerificationFilter::NextPutMultiple (
    this=0x7fffffffd390, 
    inString=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., 
    length=0x5e) at filters.cpp:786 
#3 0x00000000005bd8a2 in NextPutMaybeModifiable (modifiable=<optimized out>, 
    length=0x5e, 
    inString=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., 
    this=0x7fffffffd390) at filters.h:200 
#4 CryptoPP::FilterWithBufferedInput::PutMaybeModifiable (
    this=0x7fffffffd390, 
    inString=0x7fffffffbfeb "efghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 'a' <repeats 106 times>..., 
    length=<optimized out>, messageEnd=0x0, blocking=<optimized out>, 
... 

-O3 disassembly और रजिस्टर मूल्यों।

(gdb) disass 0x0000000000539fc3 
Dump of assembler code for function CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long): 
    0x0000000000539ee0 <+0>: lea 0x8(%rsp),%r10 
    0x0000000000539ee5 <+5>: and $0xffffffffffffffe0,%rsp 
    0x0000000000539ee9 <+9>: mov %rdx,%rax 
    0x0000000000539eec <+12>: pushq -0x8(%r10) 
    0x0000000000539ef0 <+16>: push %rbp 
    0x0000000000539ef1 <+17>: shr $0x3,%rax 
    0x0000000000539ef5 <+21>: mov %rsp,%rbp 
    0x0000000000539ef8 <+24>: push %r15 
    0x0000000000539efa <+26>: push %r14 
    0x0000000000539efc <+28>: push %r13 
    0x0000000000539efe <+30>: push %r12 
    0x0000000000539f00 <+32>: push %r10 
    0x0000000000539f02 <+34>: push %rbx 
    0x0000000000539f03 <+35>: je  0x53a00a <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+298> 
    0x0000000000539f09 <+41>: lea 0x20(%rdi),%rcx 
    0x0000000000539f0d <+45>: cmp %rcx,%rsi 
    0x0000000000539f10 <+48>: lea 0x20(%rsi),%rcx 
    0x0000000000539f14 <+52>: setae %r8b 
    0x0000000000539f18 <+56>: cmp %rcx,%rdi 
    0x0000000000539f1b <+59>: setae %cl 
    0x0000000000539f1e <+62>: or  %cl,%r8b 
    0x0000000000539f21 <+65>: je  0x53a300 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+1056> 
    0x0000000000539f27 <+71>: cmp $0x8,%rax 
    0x0000000000539f2b <+75>: jbe 0x53a300 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+1056> 
    0x0000000000539f31 <+81>: mov %rdi,%rcx 
    0x0000000000539f34 <+84>: and $0x1f,%ecx 
    0x0000000000539f37 <+87>: shr $0x3,%rcx 
    0x0000000000539f3b <+91>: neg %rcx 
    0x0000000000539f3e <+94>: and $0x3,%ecx 
    0x0000000000539f41 <+97>: cmp %rax,%rcx 
    0x0000000000539f44 <+100>: cmova %rax,%rcx 
    0x0000000000539f48 <+104>: xor %r8d,%r8d 
    0x0000000000539f4b <+107>: test %rcx,%rcx 
    0x0000000000539f4e <+110>: je  0x539f80 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+160> 
    0x0000000000539f50 <+112>: mov (%rsi),%r8 
    0x0000000000539f53 <+115>: xor %r8,(%rdi) 
    0x0000000000539f56 <+118>: cmp $0x1,%rcx 
    0x0000000000539f5a <+122>: je  0x53a371 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+1169> 
    0x0000000000539f60 <+128>: mov 0x8(%rsi),%r8 
    0x0000000000539f64 <+132>: xor %r8,0x8(%rdi) 
    0x0000000000539f68 <+136>: cmp $0x3,%rcx 
    0x0000000000539f6c <+140>: jne 0x53a366 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+1158> 
    0x0000000000539f72 <+146>: mov 0x10(%rsi),%r8 
    0x0000000000539f76 <+150>: xor %r8,0x10(%rdi) 
    0x0000000000539f7a <+154>: mov $0x3,%r8d 
    0x0000000000539f80 <+160>: mov %rax,%r11 
    0x0000000000539f83 <+163>: xor %r10d,%r10d 
    0x0000000000539f86 <+166>: sub %rcx,%r11 
    0x0000000000539f89 <+169>: shl $0x3,%rcx 
    0x0000000000539f8d <+173>: xor %ebx,%ebx 
    0x0000000000539f8f <+175>: lea -0x4(%r11),%r9 
    0x0000000000539f93 <+179>: lea (%rdi,%rcx,1),%r13 
    0x0000000000539f97 <+183>: shr $0x2,%r9 
    0x0000000000539f9b <+187>: add %rsi,%rcx 
    0x0000000000539f9e <+190>: add $0x1,%r9 
    0x0000000000539fa2 <+194>: lea 0x0(,%r9,4),%r12 
    0x0000000000539faa <+202>: add $0x1,%rbx 
    0x0000000000539fae <+206>: vmovdqu (%rcx,%r10,1),%xmm0 
    0x0000000000539fb4 <+212>: vinsertf128 $0x1,0x10(%rcx,%r10,1),%ymm0,%ymm0 
    0x0000000000539fbc <+220>: vxorps 0x0(%r13,%r10,1),%ymm0,%ymm0 
=> 0x0000000000539fc3 <+227>: vmovdqa %ymm0,0x0(%r13,%r10,1) 
    0x0000000000539fca <+234>: add $0x20,%r10 
    0x0000000000539fce <+238>: cmp %r9,%rbx 
    0x0000000000539fd1 <+241>: jb  0x539faa <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+202> 
    0x0000000000539fd3 <+243>: lea (%r8,%r12,1),%rcx 
    0x0000000000539fd7 <+247>: cmp %r12,%r11 
    0x0000000000539fda <+250>: je  0x53a006 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+294> 
    0x0000000000539fdc <+252>: mov (%rsi,%rcx,8),%r8 
    0x0000000000539fe0 <+256>: xor %r8,(%rdi,%rcx,8) 
    0x0000000000539fe4 <+260>: lea 0x1(%rcx),%r8 
    0x0000000000539fe8 <+264>: cmp %r8,%rax 
    0x0000000000539feb <+267>: jbe 0x53a006 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+294> 
    0x0000000000539fed <+269>: add $0x2,%rcx 
    0x0000000000539ff1 <+273>: mov (%rsi,%r8,8),%r9 
    0x0000000000539ff5 <+277>: xor %r9,(%rdi,%r8,8) 
    0x0000000000539ff9 <+281>: cmp %rcx,%rax 
    0x0000000000539ffc <+284>: jbe 0x53a006 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+294> 
    0x0000000000539ffe <+286>: mov (%rsi,%rcx,8),%r8 
    0x000000000053a002 <+290>: xor %r8,(%rdi,%rcx,8) 
    0x000000000053a006 <+294>: shl $0x3,%rax 

और:

(gdb) info r ymm0 r13 r10 
ymm0   {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
    v4_double = {0x8000000000000000, 0x8000000000000000, 0x8000000000000000, 
    0x8000000000000000}, v32_int8 = {0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x65, 
    0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x66, 0x67, 0x68, 0x69, 0x6a, 
    0x6b, 0x6c, 0x6d, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x68, 
    0x69}, v16_int16 = {0x6766, 0x6968, 0x6b6a, 0x6665, 0x6867, 0x6a69, 
    0x6c6b, 0x6766, 0x6968, 0x6b6a, 0x6d6c, 0x6867, 0x6a69, 0x6c6b, 0x6e6d, 
    0x6968}, v8_int32 = {0x69686766, 0x66656b6a, 0x6a696867, 0x67666c6b, 
    0x6b6a6968, 0x68676d6c, 0x6c6b6a69, 0x69686e6d}, v4_int64 = { 
    0x66656b6a69686766, 0x67666c6b6a696867, 0x68676d6c6b6a6968, 
    0x69686e6d6c6b6a69}, v2_int128 = {0x67666c6b6a69686766656b6a69686766, 
    0x69686e6d6c6b6a6968676d6c6b6a6968}} 
r13   0x9854a2 0x9854a2 
r10   0x0 0x0 

जब -O2 साथ संकलित और प्रश्न में लाइन पर एक ब्रेकपाइंट, यहाँ disassembly है। ((word64*)buf)[i] ^= ((word64*)mask)[i]; 31 लाइन में ले जाया गया:

Breakpoint 1, CryptoPP::xorbuf (buf=0x985488 "", 
    [email protected]=0x7fffffffc01d "The quick brown fox", 'a' <repeats 181 times>..., [email protected]=0x13) at misc.cpp:31 
31     ((word64*)buf)[i] ^= ((word64*)mask)[i]; 
(gdb) disass 
Dump of assembler code for function CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long): 
    0x0000000000532150 <+0>: mov %rdx,%rcx 
    0x0000000000532153 <+3>: shr $0x3,%rcx 
    0x0000000000532157 <+7>: je  0x532170 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+32> 
    0x0000000000532159 <+9>: xor %eax,%eax 
=> 0x000000000053215b <+11>: mov (%rsi,%rax,8),%r8 
    0x000000000053215f <+15>: xor %r8,(%rdi,%rax,8) 
    0x0000000000532163 <+19>: add $0x1,%rax 
    0x0000000000532167 <+23>: cmp %rcx,%rax 
    0x000000000053216a <+26>: jne 0x53215b <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+11> 
    0x000000000053216c <+28>: shl $0x3,%rcx 
    0x0000000000532170 <+32>: sub %rcx,%rdx 
    0x0000000000532173 <+35>: je  0x5321d0 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+128> 
    0x0000000000532175 <+37>: mov %rdx,%r8 
    0x0000000000532178 <+40>: add %rcx,%rdi 
    0x000000000053217b <+43>: add %rcx,%rsi 
    0x000000000053217e <+46>: shr $0x2,%r8 
    0x0000000000532182 <+50>: je  0x5321a8 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+88> 
    0x0000000000532184 <+52>: xor %eax,%eax 
    0x0000000000532186 <+54>: nopw %cs:0x0(%rax,%rax,1) 
    0x0000000000532190 <+64>: mov (%rsi,%rax,4),%ecx 
    0x0000000000532193 <+67>: xor %ecx,(%rdi,%rax,4) 
    0x0000000000532196 <+70>: add $0x1,%rax 
    0x000000000053219a <+74>: cmp %r8,%rax 
    0x000000000053219d <+77>: jne 0x532190 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+64> 
    0x000000000053219f <+79>: shl $0x2,%r8 
    0x00000000005321a3 <+83>: sub %r8,%rdx 
    0x00000000005321a6 <+86>: je  0x5321d8 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+136> 
    0x00000000005321a8 <+88>: lea (%rdi,%r8,1),%rcx 
    0x00000000005321ac <+92>: xor %eax,%eax 
    0x00000000005321ae <+94>: lea (%rsi,%r8,1),%rdi 
    0x00000000005321b2 <+98>: nopw 0x0(%rax,%rax,1) 
    0x00000000005321b8 <+104>: movzbl (%rdi,%rax,1),%esi 
    0x00000000005321bc <+108>: xor %sil,(%rcx,%rax,1) 
    0x00000000005321c0 <+112>: add $0x1,%rax 
    0x00000000005321c4 <+116>: cmp %rdx,%rax 
    0x00000000005321c7 <+119>: jb  0x5321b8 <CryptoPP::xorbuf(unsigned char*, unsigned char const*, unsigned long)+104> 
    0x00000000005321c9 <+121>: retq 
    0x00000000005321ca <+122>: nopw 0x0(%rax,%rax,1) 
    0x00000000005321d0 <+128>: retq 
    0x00000000005321d1 <+129>: nopl 0x0(%rax) 
    0x00000000005321d8 <+136>: retq 
End of assembler dump. 

misc.cpp से, लाइन 26 ((word64*)buf)[i] ^= ((word64*)mask)[i]; है।

void xorbuf(byte *buf, const byte *mask, size_t count) 
{ 
    size_t i; 

    if (IsAligned<word32>(buf) && IsAligned<word32>(mask)) 
    { 
     if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask)) 
     { 
      for (i=0; i<count/8; i++) 
       ((word64*)buf)[i] ^= ((word64*)mask)[i]; 
      count -= 8*i; 
      if (!count) 
       return; 
      buf += 8*i; 
      mask += 8*i; 
     } 

     for (i=0; i<count/4; i++) 
      ((word32*)buf)[i] ^= ((word32*)mask)[i]; 
     count -= 4*i; 
     if (!count) 
      return; 
     buf += 4*i; 
     mask += 4*i; 
    } 

    for (i=0; i<count; i++) 
     buf[i] ^= mask[i]; 
} 
+0

'buf' बिंदु कितना स्थान करता है? क्या आपने सुनिश्चित किया है कि आप अंत में लिख नहीं रहे हैं? ऐसा लगता है कि यह 8-चार लंबी सीस्ट्रिंग है ... अजीब बात यह है कि त्रुटि तब होती है जब यह 8 बाइट्स लिखने वाला है, जो शून्य टर्मिनेटर हो सकता है ... – user657267

+1

@ user657267 - हाँ, कोड सम्मान कर रहा है बफर आकार। परीक्षण के दौरान इसे सत्यापित करने के लिए मेरे पास प्रक्रियाएं भी होती हैं। अर्थात्, क्लैंग sanitizers और Valgrind। मैं कवरिटी जोड़ने के लिए तैयार हो रहा हूं क्योंकि यह एक ओपन सोर्स प्रोजेक्ट है। (मैं स्थिर और गतिशील विश्लेषण पूजा करता हूं)। – jww

+0

@jww क्या आप शुरुआती ब्लॉक को पूरी तरह अक्षम कर सकते हैं और अंत में केवल अंतिम "बाइट-एट-ए-टाइम" लूप छोड़ सकते हैं? फिर फिर से 'ओओ 3' के साथ संकलित करें? हो सकता है कि यह कार्य स्वयं कुछ अजीब नहीं कर रहा हो - शायद जिस तरह से तर्क मिलते हैं वह सही नहीं है। – viraptor

उत्तर

4

आप g++ -Wall -Wextra -O3 -g के साथ संकलित कर सकते हैं; आप चेतावनियां सक्षम करना चाहते हैं, क्योंकि उनमें से कुछ संभवतः केवल GCC पास -O3 के साथ सक्षम हैं; आप gdb का उपयोग करने के लिए डिबगिंग जानकारी (-g) सक्षम करना चाहते हैं, लेकिन ध्यान रखें कि डीबगिंग जानकारी हमेशा मजबूत अनुकूलन के साथ विश्वसनीय नहीं होती है।

आपके पास कुछ pointer aliasing समस्या हो सकती हैं। शायद restrict कीवर्ड का उपयोग करें (या हटाएं)।

undefined behavior से बचने के लिए सुनिश्चित रहें। आप -fsanitize= विकल्प (विशेष रूप से -fsanitize=address और -fsanitize=undefined ....) g++ कंपाइलर (संस्करण 5 अधिमानतः) valgrind का उपयोग कर सकते हैं।

बीटीडब्ल्यू, आप g++ के आंतरिक व्यवहार को समझने के लिए -fdump-tree-all (चेतावनी, वे सैकड़ों फाइलें उत्पन्न करते हैं) डंप विकल्प का उपयोग कर सकते हैं; और आप अपने जीसीसी कंपाइलर को MELT के साथ भी अनुकूलित कर सकते हैं।

इसके अलावा, उत्पादन कोडांतरक को देख, g++ -Wall -S -O3 -fverbose-asm साथ संकलन के बाद से -fverbose-asm जीसीसी पूछता है कुछ कोडांतरक टिप्पणी "समझा" फेंकना यदि (बहुत ज्यादा नहीं है, लेकिन एक छोटा सा) संकलित कोड।

+0

हाँ, मुझे वास्तव में क्लैंग और इसके सैनिटाइज़र पसंद हैं। मुझे पता है कि i386 और x86_64 पर * 'ALLOW_UNALIGNED_DATA_ACCESS' * नामक एक परिभाषा के कारण अपरिभाषित व्यवहार है। लेकिन यह 64-बिट शब्दों के लिए 'vmovdqa' के उपयोग की व्याख्या नहीं करता है। – jww

+0

हां, परिभाषा के अनुसार अपरिभाषित व्यवहार विचित्र संकलन आउटपुट बताता है। –

+0

जीसीसी में सैनिटाइजर्स भी हैं .... मैं 'clang ++' –

संबंधित मुद्दे