Bug 179392 - odd x86 assembly emitted.
odd x86 assembly emitted.
Status: CLOSED NOTABUG
Product: Fedora
Classification: Fedora
Component: gcc (Show other bugs)
rawhide
All Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2006-01-30 16:29 EST by Dave Jones
Modified: 2015-01-04 17:24 EST (History)
1 user (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2006-02-17 04:20:13 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
preprocessor output for drivers/net/e1000/e1000_param.c (710.64 KB, text/plain)
2006-01-30 16:29 EST, Dave Jones
no flags Details

  None (edit)
Description Dave Jones 2006-01-30 16:29:06 EST
I've got a script that checks for functions using too much stack space in kernel
modules. This morning it triggered on the e1000 driver with this..

2000005 e1000_validate_option

The actual function looks fairly benign.
static int __devinit
e1000_validate_option(int *value, struct e1000_option *opt,
        struct e1000_adapter *adapter)
{
    if (*value == OPTION_UNSET) {
        *value = opt->def;
        return 0;
    }

    switch (opt->type) {
    case enable_option:
        switch (*value) {
        case OPTION_ENABLED:
            DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name);
            return 0;
        case OPTION_DISABLED:
            DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name);
            return 0;
        }
        break;
    case range_option:
        if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
            DPRINTK(PROBE, INFO,
                    "%s set to %i\n", opt->name, *value);
            return 0;
        }
        break;
    case list_option: {
        int i;
        struct e1000_opt_list *ent;

        for (i = 0; i < opt->arg.l.nr; i++) {
            ent = &opt->arg.l.p[i];
            if (*value == ent->i) {
                if (ent->str[0] != '\0')
                    DPRINTK(PROBE, INFO, "%s\n", ent->str);
                return 0;
            }
        }
    }
        break;
    default:
        BUG();
    }

    DPRINTK(PROBE, INFO, "Invalid %s specified (%i) %s\n",
           opt->name, *value, opt->err);
    *value = opt->def;
    return -1;
}

0000e368 <e1000_validate_option>:
    e368:       55                      push   %ebp
    e369:       57                      push   %edi
    e36a:       56                      push   %esi
    e36b:       53                      push   %ebx
    e36c:       89 c5                   mov    %eax,%ebp
    e36e:       89 d3                   mov    %edx,%ebx
    e370:       8b 10                   mov    (%eax),%edx
    e372:       83 fa ff                cmp    $0xffffffff,%edx
    e375:       75 0b                   jne    e382 <e1000_validate_option+0x1a>
    e377:       8b 43 0c                mov    0xc(%ebx),%eax
    e37a:       89 45 00                mov    %eax,0x0(%ebp)
    e37d:       e9 25 01 00 00          jmp    e4a7 <e1000_validate_option+0x13f>
    e382:       8b 03                   mov    (%ebx),%eax
    e384:       83 f8 01                cmp    $0x1,%eax
    e387:       74 73                   je     e3fc <e1000_validate_option+0x94>
    e389:       72 13                   jb     e39e <e1000_validate_option+0x36>
    e38b:       83 f8 02                cmp    $0x2,%eax
    e38e:       0f 85 d8 00 00 00       jne    e46c <e1000_validate_option+0x104>
    e394:       8b 7b 10                mov    0x10(%ebx),%edi
    e397:       31 f6                   xor    %esi,%esi
    e399:       e9 c8 00 00 00          jmp    e466 <e1000_validate_option+0xfe>
    e39e:       85 d2                   test   %edx,%edx
    e3a0:       74 2b                   je     e3cd <e1000_validate_option+0x65>
    e3a2:       83 fa 01                cmp    $0x1,%edx
    e3a5:       0f 85 c9 00 00 00       jne    e474 <e1000_validate_option+0x10c>
    e3ab:       f6 81 f4 05 00 00 02    testb  $0x2,0x5f4(%ecx)
    e3b2:       0f 84 ef 00 00 00       je     e4a7 <e1000_validate_option+0x13f>
    e3b8:       ff 73 04                pushl  0x4(%ebx)
    e3bb:       68 68 0f 00 00          push   $0xf68
    e3c0:       ff b1 b8 01 00 00       pushl  0x1b8(%ecx)
    e3c6:       68 b8 0b 00 00          push   $0xbb8
    e3cb:       eb 20                   jmp    e3ed <e1000_validate_option+0x85>
    e3cd:       f6 81 f4 05 00 00 02    testb  $0x2,0x5f4(%ecx)
    e3d4:       0f 84 cd 00 00 00       je     e4a7 <e1000_validate_option+0x13f>
    e3da:       ff 73 04                pushl  0x4(%ebx)
    e3dd:       68 68 0f 00 00          push   $0xf68
    e3e2:       ff b1 b8 01 00 00       pushl  0x1b8(%ecx)
    e3e8:       68 d6 0b 00 00          push   $0xbd6
    e3ed:       e8 fc ff ff ff          call   e3ee <e1000_validate_option+0x86>
    e3f2:       31 c0                   xor    %eax,%eax
    e3f4:       83 c4 10                add    $0x10,%esp
    e3f7:       e9 ad 00 00 00          jmp    e4a9 <e1000_validate_option+0x141>
    e3fc:       3b 53 10                cmp    0x10(%ebx),%edx
    e3ff:       7c 73                   jl     e474 <e1000_validate_option+0x10c>
    e401:       3b 53 14                cmp    0x14(%ebx),%edx
    e404:       7f 6e                   jg     e474 <e1000_validate_option+0x10c>
    e406:       f6 81 f4 05 00 00 02    testb  $0x2,0x5f4(%ecx)
    e40d:       0f 84 94 00 00 00       je     e4a7 <e1000_validate_option+0x13f>
    e413:       52                      push   %edx
    e414:       ff 73 04                pushl  0x4(%ebx)
    e417:       68 68 0f 00 00          push   $0xf68
    e41c:       ff b1 b8 01 00 00       pushl  0x1b8(%ecx)
    e422:       68 f5 0b 00 00          push   $0xbf5
    e427:       e8 fc ff ff ff          call   e428 <e1000_validate_option+0xc0>
    e42c:       31 c0                   xor    %eax,%eax
    e42e:       83 c4 14                add    $0x14,%esp
    e431:       eb 76                   jmp    e4a9 <e1000_validate_option+0x141>
    e433:       8d 04 f5 00 00 00 00    lea    0x0(,%esi,8),%eax
    e43a:       03 43 14                add    0x14(%ebx),%eax
    e43d:       3b 10                   cmp    (%eax),%edx
    e43f:       75 24                   jne    e465 <e1000_validate_option+0xfd>
    e441:       8b 40 04                mov    0x4(%eax),%eax
    e444:       80 38 00                cmpb   $0x0,(%eax)
    e447:       74 5e                   je     e4a7 <e1000_validate_option+0x13f>
    e449:       f6 81 f4 05 00 00 02    testb  $0x2,0x5f4(%ecx)
    e450:       74 55                   je     e4a7 <e1000_validate_option+0x13f>
    e452:       50                      push   %eax
    e453:       68 68 0f 00 00          push   $0xf68
    e458:       ff b1 b8 01 00 00       pushl  0x1b8(%ecx)
    e45e:       68 15 0c 00 00          push   $0xc15
    e463:       eb 88                   jmp    e3ed <e1000_validate_option+0x85>
    e465:       46                      inc    %esi
    e466:       39 fe                   cmp    %edi,%esi
    e468:       7c c9                   jl     e433 <e1000_validate_option+0xcb>
    e46a:       eb 08                   jmp    e474 <e1000_validate_option+0x10c>
    e46c:       0f 0b                   ud2a
    e46e:       0c 01                   or     $0x1,%al
    e470:       2b 0c 00                sub    (%eax,%eax,1),%ecx
    e473:       00 f6                   add    %dh,%dh
    e475:       81 f4 05 00 00 02       xor    $0x2000005,%esp
    e47b:       74 1f                   je     e49c <e1000_validate_option+0x134>
    e47d:       ff 73 08                pushl  0x8(%ebx)
    e480:       52                      push   %edx
    e481:       ff 73 04                pushl  0x4(%ebx)
    e484:       68 68 0f 00 00          push   $0xf68
    e489:       ff b1 b8 01 00 00       pushl  0x1b8(%ecx)
    e48f:       68 4b 0c 00 00          push   $0xc4b
    e494:       e8 fc ff ff ff          call   e495 <e1000_validate_option+0x12d>
    e499:       83 c4 18                add    $0x18,%esp
    e49c:       8b 43 0c                mov    0xc(%ebx),%eax
    e49f:       89 45 00                mov    %eax,0x0(%ebp)
    e4a2:       83 c8 ff                or     $0xffffffff,%eax
    e4a5:       eb 02                   jmp    e4a9 <e1000_validate_option+0x141>
    e4a7:       31 c0                   xor    %eax,%eax
    e4a9:       5b                      pop    %ebx
    e4aa:       5e                      pop    %esi
    e4ab:       5f                      pop    %edi
    e4ac:       5d                      pop    %ebp
    e4ad:       c3                      ret


The 'badness' the script hits seems to be a false positive coming from this..

    e475:       81 f4 05 00 00 02       xor    $0x2000005,%esp

But that seems like a really odd thing to be doing, and I can't figure out
why that was emitted.  Any clues ?

build flags are..

gcc -m32 -Wp,-MD,drivers/net/e1000/.e1000_param.o.d  -nostdinc -isystem
/usr/lib/gcc/i386-redhat-linux/4.1.0/include -D__KERNEL__ -Iinclude  -include
include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs
-fno-strict-aliasing -fno-common -ffreestanding -Os     -fomit-frame-pointer -g
-pipe -msoft-float -fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts 
-mpreferred-stack-boundary=2  -march=i686 -mtune=pentium4 -mregparm=3
-Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -Wno-pointer-sign
  -DMODULE -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(e1000_param)" 
-D"KBUILD_MODNAME=KBUILD_STR(e1000)" -c -o drivers/net/e1000/.tmp_e1000_param.o
drivers/net/e1000/e1000_param.c

preprocessor output attached.
Comment 1 Dave Jones 2006-01-30 16:29:06 EST
Created attachment 123885 [details]
preprocessor output for drivers/net/e1000/e1000_param.c
Comment 2 Jakub Jelinek 2006-02-17 04:20:13 EST
This is the result of BUG() macro.
       e46c:       0f 0b                   ud2a
       e46e:       0c 01                   or     $0x1,%al
       e470:       2b 0c 00                sub    (%eax,%eax,1),%ecx
       e473:       00 f6                   add    %dh,%dh
       e475:       81 f4 05 00 00 02       xor    $0x2000005,%esp
       e47b:       74 1f                   je     e49c
<e1000_validate_option+0x134>

The ud2a insn is the start of BUG() asm, which is followed by a 16-bit value
and one 32-bit value.
So it is actually:
       e46c:       0f 0b                   ud2a
       e46e:       0c 01                   .word 0x10c
       e470:       2b 0c 00 00             .long 0xc2b
       e474:       f6 81 f4 05 00 00 02    testb  $0x2,0x5f4(%ecx)
       e47b:       74 1f                   je     e49c
<e1000_validate_option+0x134>

but the disassembler has no way to find that out that kernel puts data in the
instruction stream.

Note You need to log in before you can comment on or make changes to this bug.