[ECOS] Wrongfully compiled code

ariga masahiro ariga@link-lab.co.jp
Mon Jan 7 01:36:00 GMT 2008


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



More information about the Ecos-discuss mailing list