This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Wrongfully compiled code


Hello,
Happy New Year.

I am encountered next phenomenon and I am very in deep trouble.
It happens when sending back TCP SYN-ACK packet to peer,
and it happens in packages\net\bsd_tcpip\current\src\sys\netinet\tcp_output.c
tcp_output()function.


I attach C source code,and corresponding mixed source code below.
Please refer to them.

I traced source code using ICE. (numbers are source line numbers)
First,on line 398 hdrlen becomes 0x28.And optlen becomes 4 on line 408.
Althoug it should execute
      512:     hdrlen += optlen;
but looks it passed in C code trace.

And on line
|      643:         m->m_len = hdrlen;      -- hdrlen is still 0x28
hdrlen is 0x28,although it should be 0x2c.

I could have traced same part in mixed source mode,and I discovered it was wrongfully compiled.
I explain in detail after the source code.
Below are C code source and corresponding mixed source(from 445 line onward in C source).
-- tcp_output() C source code
383: send:
384: /*
385: * Before ESTABLISHED, force sending of initial options
386: * unless TCP set not to do any options.
387: * NOTE: we assume that the IP/TCP header plus TCP options
388: * always fit in a single mbuf, leaving room for a maximum
389: * link header, i.e.
390: * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MCLBYTES
391: */
392: optlen = 0;
393: #ifdef INET6
394: if (isipv6)
395: hdrlen = sizeof (struct ip6_hdr) + sizeof (struct tcphdr);
396: else
397: #endif
-> 398: hdrlen = sizeof (struct tcpiphdr); -- here hdrlen becomes 0x28
| 399: if (flags & TH_SYN) {
| 400: tp->snd_nxt = tp->iss;
| 401: if ((tp->t_flags & TF_NOOPT) == 0) {
402: u_short mss;
403:
| 404: opt[0] = TCPOPT_MAXSEG;
| 405: opt[1] = TCPOLEN_MAXSEG;
| 406: mss = htons((u_short) tcp_mssopt(tp));
| 407: (void)memcpy(opt + 2, &mss, sizeof(mss));
| 408: optlen = TCPOLEN_MAXSEG;
409:
| 410: if ((tp->t_flags & TF_REQ_SCALE) && --428,É"n,Ô
411: ((flags & TH_ACK) == 0 ||
412: (tp->t_flags & TF_RCVD_SCALE))) {
413: *((u_int32_t *)(opt + optlen)) = htonl(
414: TCPOPT_NOP << 24 |
415: TCPOPT_WINDOW << 16 |
416: TCPOLEN_WINDOW << 8 |
417: tp->request_r_scale);
418: optlen += 4;
419: }
420: }
421: }
422:
423: /*
424: * Send a timestamp and echo-reply if this is a SYN and our side
425: * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
426: * and our peer have sent timestamps in our SYN's.
427: */
-> 428: if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
429: (flags & TH_RST) == 0 &&
430: ((flags & TH_ACK) == 0 ||
431: (tp->t_flags & TF_RCVD_TSTMP))) {
432: u_int32_t *lp = (u_int32_t *)(opt + optlen);
433:
434: /* Form timestamp option as shown in appendix A of RFC 1323. */
435: *lp++ = htonl(TCPOPT_TSTAMP_HDR);
436: *lp++ = htonl(ticks);
437: *lp = htonl(tp->ts_recent);
438: optlen += TCPOLEN_TSTAMP_APPA;
439: }
440:
441: /*
442: * Send `CC-family' options if our side wants to use them (TF_REQ_CC),
443: * options are allowed (!TF_NOOPT) and it's not a RST.
444: */
-> 445: if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
446: (flags & TH_RST) == 0) {
447: switch (flags & (TH_SYN|TH_ACK)) {
448: /*
449: * This is a normal ACK, send CC if we received CC before
450: * from our peer.
451: */
452: case TH_ACK:
453: if (!(tp->t_flags & TF_RCVD_CC))
454: break;
455: /*FALLTHROUGH*/
456:
457: /*
458: * We can only get here in T/TCP's SYN_SENT* state, when
459: * we're a sending a non-SYN segment without waiting for
460: * the ACK of our SYN. A check above assures that we only
461: * do this if our peer understands T/TCP.
462: */
463: case 0:
464: opt[optlen++] = TCPOPT_NOP;
465: opt[optlen++] = TCPOPT_NOP;
466: opt[optlen++] = TCPOPT_CC;
467: opt[optlen++] = TCPOLEN_CC;
468: *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
469:
470: optlen += 4;
471: break;
472:
473: /*
474: * This is our initial SYN, check whether we have to use
475: * CC or CC.new.
476: */
477: case TH_SYN:
478: opt[optlen++] = TCPOPT_NOP;
479: opt[optlen++] = TCPOPT_NOP;
480: opt[optlen++] = tp->t_flags & TF_SENDCCNEW ?
481: TCPOPT_CCNEW : TCPOPT_CC;
482: opt[optlen++] = TCPOLEN_CC;
483: *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
484: optlen += 4;
485: break;
486:
487: /*
488: * This is a SYN,ACK; send CC and CC.echo if we received
489: * CC from our peer.
490: */
491: case (TH_SYN|TH_ACK):
492: if (tp->t_flags & TF_RCVD_CC) {
493: opt[optlen++] = TCPOPT_NOP;
494: opt[optlen++] = TCPOPT_NOP;
495: opt[optlen++] = TCPOPT_CC;
496: opt[optlen++] = TCPOLEN_CC;
497: *(u_int32_t *)&opt[optlen] =
498: htonl(tp->cc_send);
499: optlen += 4;
500: opt[optlen++] = TCPOPT_NOP;
501: opt[optlen++] = TCPOPT_NOP;
502: opt[optlen++] = TCPOPT_CCECHO;
503: opt[optlen++] = TCPOLEN_CC;
504: *(u_int32_t *)&opt[optlen] =
505: htonl(tp->cc_recv);
506: optlen += 4;
507: }
508: break;
509: }
510: }
511:
512: hdrlen += optlen;


and try to convert m->m_len,
->     642:         m->m_data += max_linkhdr;
|      643:         m->m_len = hdrlen;        -- hdrlen is still 0x28

--- Mix source code corresponding to C code
tcp_output.c (445): if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
8C048BA4 51AA MOV.L @(28,R10 tp ),R1
8C048BA6 9214 MOV.W 8C048BD2,R2
8C048BA8 2129 AND R2,R1
8C048BAA 72F8 ADD #F8,R2
8C048BAC 3120 CMP/EQ R2,R1
8C048BAE 8F51 BF/S 4 ->1
8C048BB0 60D3 MOV R13 flags ,R0
8C048BB2 C904 AND #4,R0
8C048BB4 2008 TST R0,R0
8C048BB6 8F4D BF/S 8C048C54
8C048BB8 E212 MOV #12,R2
tcp_output.c (447): switch (flags & (TH_SYN|TH_ACK)) {
8C048BBA 22D9 AND R13 flags ,R2
8C048BBC E112 MOV #12,R1
8C048BBE 3216 CMP/HI R1,R2
8C048BC0 8948 BT 8C048C54
8C048BC2 C70A MOVA 8C048BEC,R0
8C048BC4 322C ADD R2,R2
8C048BC6 012D MOV.W @(R0,R2),R1
8C048BC8 0123 BRAF R1
8C048BCA 0009 NOP
8C048BCC 00AC MOV.B @(R0,R10 tp ),R0
8C048BCE 0080 ???
8C048BD0 0100 ???
8C048BD2 2008 TST R0,R0
8C048BD4 8C02 ???
8C048BD6 9D60 MOV.W 8C048C9A,R13 flags
8C048BD8 8C04 ???
8C048BDA 94A0 MOV.W 8C048D1E,R4
8C048BDC 8C04 ???
8C048BDE 8600 ???
8C048BE0 0103 BSRF R1
8C048BE2 0300 ???
8C048BE4 0101 ???
8C048BE6 080A STS MACH,R8 error
8C048BE8 8C02 ???
8C048BEA 8BF0 BF 8C048BCE
8C048BEC 005C MOV.B @(R0,R5),R0
8C048BEE 0124 MOV.B R2,@(R0,R1)
8C048BF0 0094 MOV.B R9,@(R0,R0)
8C048BF2 0124 MOV.B R2,@(R0,R1)
8C048BF4 0124 MOV.B R2,@(R0,R1)
8C048BF6 0124 MOV.B R2,@(R0,R1)
8C048BF8 0124 MOV.B R2,@(R0,R1)
8C048BFA 0124 MOV.B R2,@(R0,R1)
8C048BFC 0124 MOV.B R2,@(R0,R1)
8C048BFE 0124 MOV.B R2,@(R0,R1)
8C048C00 0124 MOV.B R2,@(R0,R1)
8C048C02 0124 MOV.B R2,@(R0,R1)
8C048C04 0124 MOV.B R2,@(R0,R1)
8C048C06 0124 MOV.B R2,@(R0,R1)
8C048C08 0124 MOV.B R2,@(R0,R1)
8C048C0A 0124 MOV.B R2,@(R0,R1)
8C048C0C 0054 MOV.B R5,@(R0,R0)
8C048C0E 0124 MOV.B R2,@(R0,R1)
8C048C10 00D4 MOV.B R13 flags ,@(R0,R0)
8C048C12 0009 NOP
8C048C14 0009 NOP
8C048C16 0009 NOP
8C048C18 0009 NOP
8C048C1A 0009 NOP
8C048C1C 0009 NOP
8C048C1E 0009 NOP
tcp_output.c (453): if (!(tp->t_flags & TF_RCVD_CC))
8C048C20 52AA MOV.L @(28,R10 tp ),R2
8C048C22 91B2 MOV.W 8C048D8A,R1
8C048C24 2218 TST R1,R2
8C048C26 8963 BT 8C048CF0
tcp_output.c (464): opt[optlen++] = TCPOPT_NOP;
8C048C28 E101 MOV #1,R1
8C048C2A E048 MOV #48,R0
8C048C2C 00EE MOV.L @(R0,R14),R0
8C048C2E 0E14 MOV.B R1,@(R0,R14)
8C048C30 7001 ADD #1,R0
8C048C32 E240 MOV #40,R2
8C048C34 32EC ADD R14,R2
tcp_output.c (465): opt[optlen++] = TCPOPT_NOP;
8C048C36 0E14 MOV.B R1,@(R0,R14)
8C048C38 7001 ADD #1,R0
tcp_output.c (466): opt[optlen++] = TCPOPT_CC;
8C048C3A E10B MOV #B,R1
8C048C3C 0E14 MOV.B R1,@(R0,R14)
8C048C3E 7001 ADD #1,R0
tcp_output.c (467): opt[optlen++] = TCPOLEN_CC;
8C048C40 E106 MOV #6,R1
8C048C42 0E14 MOV.B R1,@(R0,R14)
8C048C44 7001 ADD #1,R0
8C048C46 1202 MOV.L R0,@(8,R2)
tcp_output.c (468): *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
8C048C48 90A0 MOV.W 8C048D8C,R0
8C048C4A 01AE MOV.L @(R0,R10 tp ),R1
8C048C4C 5022 MOV.L @(8,R2),R0
8C048C4E 0E16 MOV.L R1,@(R0,R14)
tcp_output.c (470): optlen += 4;
8C048C50 7004 ADD #4,R0
8C048C52 1202 MOV.L R0,@(8,R2)
->1 8C048C54 A04D BRA 8C048CF2 ->2
tcp_output.c (471): break;
8C048C56 E740 MOV #40,R7
8C048C58 0009 NOP
8C048C5A 0009 NOP
8C048C5C 0009 NOP
8C048C5E 0009 NOP
tcp_output.c (478): opt[optlen++] = TCPOPT_NOP;
8C048C60 E101 MOV #1,R1
8C048C62 E048 MOV #48,R0
8C048C64 00EE MOV.L @(R0,R14),R0
8C048C66 0E14 MOV.B R1,@(R0,R14)
8C048C68 7001 ADD #1,R0
tcp_output.c (479): opt[optlen++] = TCPOPT_NOP;
8C048C6A 0E14 MOV.B R1,@(R0,R14)
8C048C6C 7001 ADD #1,R0
tcp_output.c (480): opt[optlen++] = tp->t_flags & TF_SENDCCNEW ?
8C048C6E 6303 MOV R0,R3 ipoptlen
8C048C70 33EC ADD R14,R3 ipoptlen
8C048C72 7001 ADD #1,R0
8C048C74 52AA MOV.L @(28,R10 tp ),R2
8C048C76 D146 MOV.L 8C048D90,R1
8C048C78 2218 TST R1,R2
8C048C7A 0129 MOVT R1
8C048C7C 611B NEG R1,R1
8C048C7E 710C ADD #C,R1
8C048C80 2310 MOV.B R1,@R3 ipoptlen
tcp_output.c (482): opt[optlen++] = TCPOLEN_CC;
8C048C82 E106 MOV #6,R1
8C048C84 0E14 MOV.B R1,@(R0,R14)
8C048C86 7001 ADD #1,R0
8C048C88 E640 MOV #40,R6
8C048C8A 36EC ADD R14,R6
8C048C8C 1602 MOV.L R0,@(8,R6)
tcp_output.c (483): *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
8C048C8E 907D MOV.W 8C048D8C,R0
8C048C90 01AE MOV.L @(R0,R10 tp ),R1
8C048C92 A029 BRA 8C048CE8
tcp_output.c (485): break;
8C048C94 5062 MOV.L @(8,R6),R0
8C048C96 0009 NOP
8C048C98 0009 NOP
8C048C9A 0009 NOP
8C048C9C 0009 NOP
8C048C9E 0009 NOP
tcp_output.c (492): if (tp->t_flags & TF_RCVD_CC) {
8C048CA0 52AA MOV.L @(28,R10 tp ),R2
8C048CA2 9172 MOV.W 8C048D8A,R1
8C048CA4 2218 TST R1,R2
8C048CA6 8D24 BT/S 8C048CF2
8C048CA8 E740 MOV #40,R7
tcp_output.c (493): opt[optlen++] = TCPOPT_NOP;
8C048CAA E201 MOV #1,R2
8C048CAC E048 MOV #48,R0
8C048CAE 00EE MOV.L @(R0,R14),R0
8C048CB0 0E24 MOV.B R2,@(R0,R14)
8C048CB2 7001 ADD #1,R0
tcp_output.c (494): opt[optlen++] = TCPOPT_NOP;
8C048CB4 0E24 MOV.B R2,@(R0,R14)
8C048CB6 7001 ADD #1,R0
tcp_output.c (495): opt[optlen++] = TCPOPT_CC;
8C048CB8 E10B MOV #B,R1
8C048CBA 0E14 MOV.B R1,@(R0,R14)
8C048CBC 7001 ADD #1,R0
8C048CBE E640 MOV #40,R6
8C048CC0 36EC ADD R14,R6
tcp_output.c (496): opt[optlen++] = TCPOLEN_CC;
8C048CC2 E706 MOV #6,R7
8C048CC4 0E74 MOV.B R7,@(R0,R14)
8C048CC6 7001 ADD #1,R0
tcp_output.c (497): *(u_int32_t *)&opt[optlen] =
8C048CC8 9160 MOV.W 8C048D8C,R1
8C048CCA 63A3 MOV R10 tp ,R3 ipoptlen
8C048CCC 331C ADD R1,R3 ipoptlen
8C048CCE 5130 MOV.L @(0,R3 ipoptlen ),R1
8C048CD0 0E16 MOV.L R1,@(R0,R14)
tcp_output.c (499): optlen += 4;
8C048CD2 7004 ADD #4,R0
tcp_output.c (500): opt[optlen++] = TCPOPT_NOP;
8C048CD4 0E24 MOV.B R2,@(R0,R14)
8C048CD6 7001 ADD #1,R0
tcp_output.c (501): opt[optlen++] = TCPOPT_NOP;
8C048CD8 0E24 MOV.B R2,@(R0,R14)
8C048CDA 7001 ADD #1,R0
tcp_output.c (502): opt[optlen++] = TCPOPT_CCECHO;
8C048CDC E10D MOV #D,R1
8C048CDE 0E14 MOV.B R1,@(R0,R14)
8C048CE0 7001 ADD #1,R0
tcp_output.c (503): opt[optlen++] = TCPOLEN_CC;
8C048CE2 0E74 MOV.B R7,@(R0,R14)
8C048CE4 7001 ADD #1,R0
tcp_output.c (504): *(u_int32_t *)&opt[optlen] =
8C048CE6 5131 MOV.L @(4,R3 ipoptlen ),R1
8C048CE8 0E16 MOV.L R1,@(R0,R14)
tcp_output.c (506): optlen += 4;
8C048CEA 7004 ADD #4,R0
8C048CEC 1602 MOV.L R0,@(8,R6)
8C048CEE 0009 NOP
tcp_output.c (512): hdrlen += optlen;
8C048CF0 E740 MOV #40,R7
->2 8C048CF2 37EC ADD R14,R7
8C048CF4 5073 MOV.L @(C,R7),R0
8C048CF6 5772 MOV.L @(8,R7),R7
8C048CF8 307C ADD R7,R0
8C048CFA 1703 MOV.L R0,@(C,R7)
tcp_output.c (520): if (tp->t_inpcb->inp_options) {
8C048CFC 51A8 MOV.L @(20,R10 tp ),R1
8C048CFE 9046 MOV.W 8C048D8E,R0
8C048D00 011E MOV.L @(R0,R1),R1
8C048D02 2118 TST R1,R1
8C048D04 8904 BT 8C048D10
8C048D06 5113 MOV.L @(C,R1),R1
tcp_output.c (521): ipoptlen = tp->t_inpcb->inp_options->m_len -


In detail.
Like I said,at line-445 hdrlen is 0x28,and optlen is 4.
After that it jump to address 8C048CF2(->2).

About @(disp:4,Rn) assembler operation,next is from SH assembler manual,
"The effective address is Rn plus a 4-bit displacement
(disp). The value of disp is zero-extended, and
remains the same for a byte operation, is doubled for
a word operation, and is quadrupled for a longword
operation."

When jumped to 8C048CF2, R14=8c081458,R7=00000040.
Added,R7 becomes 8c081498.
After executing (MOV.L @(C,R7),R0),R0 becomes 0x28.
But here it acts qeerly,according to manual,0x28 should be retrieved
from 8c081498+c*4=8c0814c8, but really it was retreived from 8c0814a4.
It looks there's no extension according to operand size.But this is minor point.
Anyway,after executing next line(MOV.L @(8,R7),R7),R7 becomes 4.
By (ADD R7,R0),R0 becomes 0x2c,this is expected value for hdrlen.
But,by (MOV.L R0,@(C,R7)),content of R0 is reserved into 0x00000010.(really it can't be written).
Content of hdrlen(8c0814a4) remains 0x28.


I executed without ICE but resulted in IP packet size being 0x28,although it should be 0x2c.

I am perplexed why this phenomenon happens.
Please enlighten me what do you think causes this mishappening.

My target CPU is SH7709S.
I am developing on Cygwin environment.
I checked sh-elf-gcc version and it was version 3.2.1.

$ sh-elf-gcc -v
Reading specs from /opt/ecos/gnutools/sh-elf/bin/../lib/gcc-lib/sh-elf/3.2.1/spe
cs
Configured with: /local/demonweb/tools/ecos-gnutools-v1.4/r2/sh-elf/cygwin/tar_b
z2/source/gcc-3.2.1/configure --target=sh-elf --prefix=/local/demonweb/tools/eco
s-gnutools-v1.4/r2/sh-elf/cygwin/tar_bz2/opt/ecos/gnutools/sh-elf --enable-langu
ages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-gxx-include-dir=/loc
al/demonweb/tools/ecos-gnutools-v1.4/r2/sh-elf/cygwin/tar_bz2/opt/ecos/gnutools/
sh-elf/sh-elf/include
Thread model: single
gcc version 3.2.1


My compile option is same as CVS downloaded version for se77x9,
cdl_option CYGBLD_GLOBAL_CFLAGS {
display "Global compiler flags"
flavor data
no_define
default_value { CYGHWR_HAL_SH_BIGENDIAN ? "-D_KERNEL -D__ECOS -mb -m3 -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -ggdb -O1 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" : "-D_KERNEL -D__ECOS -ml -m3 -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -ggdb -O1 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" }
description "
This option controls the global compiler flags which
are used to compile all packages by
default. Individual packages may define
options which override these global flags."
}


cdl_option CYGBLD_GLOBAL_LDFLAGS {
display "Global linker flags"
flavor data
no_define
default_value { CYGHWR_HAL_SH_BIGENDIAN ? "-mb -m3 -ggdb -nostdlib -Wl,--gc-sections -Wl,-static" : "-ml -m3 -ggdb -nostdlib -Wl,--gc-sections -Wl,-static" }
description "
This option controls the global linker flags. Individual
packages may define options which override these global flags."
}


CYGHWR_HAL_SH_BIGENDIAN is valid.

My ICE works on Windows so I would like to develop on Cygwin environment.

I bessech you to help me.
Thanks in advance.

Masahiro Ariga



--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]