Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #69203 > unrolled thread

[clang] -Os invalid content of argc+argv

Started bym.labanowicz@gmail.com
First post2015-09-03 13:28 -0700
Last post2015-09-04 20:48 +0200
Articles 8 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  [clang] -Os invalid content of argc+argv m.labanowicz@gmail.com - 2015-09-03 13:28 -0700
    Re: [clang] -Os invalid content of argc+argv Melzzzzz <mel@zzzzz.com> - 2015-09-03 23:31 +0200
      Re: [clang] -Os invalid content of argc+argv Keith Thompson <kst-u@mib.org> - 2015-09-03 16:43 -0700
        Re: [clang] -Os invalid content of argc+argv Melzzzzz <mel@zzzzz.com> - 2015-09-04 01:53 +0200
        Re: [clang] -Os invalid content of argc+argv Philip Lantz <prl@canterey.us> - 2015-09-03 20:15 -0700
          Re: [clang] -Os invalid content of argc+argv Keith Thompson <kst-u@mib.org> - 2015-09-04 09:15 -0700
            Re: [clang] -Os invalid content of argc+argv m.labanowicz@gmail.com - 2015-09-04 10:33 -0700
              Re: [clang] -Os invalid content of argc+argv Noob <root@127.0.0.1> - 2015-09-04 20:48 +0200

#69203 — [clang] -Os invalid content of argc+argv

Fromm.labanowicz@gmail.com
Date2015-09-03 13:28 -0700
Subject[clang] -Os invalid content of argc+argv
Message-ID<68a9e68b-dc3b-4c5e-8d01-bc91daaeb0f2@googlegroups.com>
Hello,

I have found an unexpected result of application compiled with clang.

'argc' + 'argv' values are incorrect.

Main conditions where issue is observed:
  a) compilation under system: Windows 10 + Cygwin64
     (Ubuntu.14.04.64bit on the same machine issue is not observed)
  b) enabled optimisation for size flag: -Os
  c) clang or clang++ compilator
     (not observed with gcc/g++)

Following is an example that demonstrates the issue:

--{example:beg}--------------------------------------

# gawk '{printf("/*%04d*/ %s\n", NR, $0);}' main.c
/*0001*/ #include <stdio.h>
/*0002*/ #include <stdlib.h>
/*0003*/ #ifdef __cplusplus
/*0004*/ extern "C" {
/*0005*/ #endif
/*0006*/ int bar(int argc, char * argv [])
/*0007*/ {
/*0008*/   printf("argc=%d, argv=%p\n", argc, (void *)(argv));
/*0009*/   if (argv) {
/*0010*/     int i = 0;
/*0011*/     while (argv[i]) {
/*0012*/       printf("argv[%d] = %p", i, (void *)(argv[i]));
/*0013*/       if (argv[i]) {
/*0014*/         printf(" = \"%s\"", argv[i]);
/*0015*/       }
/*0016*/       printf("\n");
/*0017*/       ++i;
/*0018*/     }
/*0019*/   }
/*0020*/   return EXIT_SUCCESS;
/*0021*/ }
/*0022*/ int main(int argc, char * argv [])
/*0023*/ {
/*0024*/   return bar(argc, argv);
/*0025*/ }
/*0026*/ #ifdef __cplusplus
/*0027*/ }
/*0028*/ #endif

# gcc --version && gcc -Os main.c -o a.exe && ./a.exe 1 2 3
gcc (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

argc=4, argv=0x24cb50
argv[0] = 0x18032a770 = "./a"
argv[1] = 0x18032b7b8 = "1"
argv[2] = 0x18032b808 = "2"
argv[3] = 0x18032b7e0 = "3"

# g++ --version && g++ -Os main.c -o a.exe && ./a.exe 1 2 3
g++ (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

argc=4, argv=0x24cb50
argv[0] = 0x18032a770 = "./a"
argv[1] = 0x18032b7b8 = "1"
argv[2] = 0x18032b808 = "2"
argv[3] = 0x18032b7e0 = "3"

# clang --version && clang -Os main.c -o a.exe && ./a.exe 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
argc=1, argv=0x0

# clang++ --version && clang++ -Os main.c -o a.exe && ./a.exe 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
argc=1, argv=0x0

--{example:eof}--------------------------------------

Is there any reasonable explanation of that ?

Regards

-- 
Maciek

[toc] | [next] | [standalone]


#69222

FromMelzzzzz <mel@zzzzz.com>
Date2015-09-03 23:31 +0200
Message-ID<20150903233124.38258cdb@maxa-pc>
In reply to#69203
On Thu, 3 Sep 2015 13:28:33 -0700 (PDT)
m.labanowicz@gmail.com wrote:

> Hello,
> 
> I have found an unexpected result of application compiled with clang.
> 
> 'argc' + 'argv' values are incorrect.
> 
> Main conditions where issue is observed:
>   a) compilation under system: Windows 10 + Cygwin64
>      (Ubuntu.14.04.64bit on the same machine issue is not observed)
>   b) enabled optimisation for size flag: -Os
>   c) clang or clang++ compilator
>      (not observed with gcc/g++)
> 
> Following is an example that demonstrates the issue:
> 
> --{example:beg}--------------------------------------
> 
> # gawk '{printf("/*%04d*/ %s\n", NR, $0);}' main.c
> /*0001*/ #include <stdio.h>
> /*0002*/ #include <stdlib.h>
> /*0003*/ #ifdef __cplusplus
> /*0004*/ extern "C" {
> /*0005*/ #endif
> /*0006*/ int bar(int argc, char * argv [])
> /*0007*/ {
> /*0008*/   printf("argc=%d, argv=%p\n", argc, (void *)(argv));
> /*0009*/   if (argv) {
> /*0010*/     int i = 0;
> /*0011*/     while (argv[i]) {
> /*0012*/       printf("argv[%d] = %p", i, (void *)(argv[i]));
> /*0013*/       if (argv[i]) {
> /*0014*/         printf(" = \"%s\"", argv[i]);
> /*0015*/       }
> /*0016*/       printf("\n");
> /*0017*/       ++i;
> /*0018*/     }
> /*0019*/   }
> /*0020*/   return EXIT_SUCCESS;
> /*0021*/ }
> /*0022*/ int main(int argc, char * argv [])
> /*0023*/ {
> /*0024*/   return bar(argc, argv);
> /*0025*/ }
> /*0026*/ #ifdef __cplusplus
> /*0027*/ }
> /*0028*/ #endif
> 
> # gcc --version && gcc -Os main.c -o a.exe && ./a.exe 1 2 3
> gcc (GCC) 4.9.3
> Copyright (C) 2015 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There
> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
> 
> argc=4, argv=0x24cb50
> argv[0] = 0x18032a770 = "./a"
> argv[1] = 0x18032b7b8 = "1"
> argv[2] = 0x18032b808 = "2"
> argv[3] = 0x18032b7e0 = "3"
> 
> # g++ --version && g++ -Os main.c -o a.exe && ./a.exe 1 2 3
> g++ (GCC) 4.9.3
> Copyright (C) 2015 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There
> is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
> 
> argc=4, argv=0x24cb50
> argv[0] = 0x18032a770 = "./a"
> argv[1] = 0x18032b7b8 = "1"
> argv[2] = 0x18032b808 = "2"
> argv[3] = 0x18032b7e0 = "3"
> 
> # clang --version && clang -Os main.c -o a.exe && ./a.exe 1 2 3
> clang version 3.5.2 (tags/RELEASE_352/final)
> Target: x86_64-unknown-windows-cygnus
> Thread model: posix
> argc=1, argv=0x0
> 
> # clang++ --version && clang++ -Os main.c -o a.exe && ./a.exe 1 2 3
> clang version 3.5.2 (tags/RELEASE_352/final)
> Target: x86_64-unknown-windows-cygnus
> Thread model: posix
> clang: warning: treating 'c' input as 'c++' when in C++ mode, this
> behavior is deprecated argc=1, argv=0x0
> 
> --{example:eof}--------------------------------------
> 
> Is there any reasonable explanation of that ?

I don't know about cygwin but argc/argv values are parsed with crt 
on Linux. That is if you link with c runtime and write main in assembler
you get already parsed values eg Linux passes values on stack but crt
parses them into rdi,rsi registers...
Probably on cygwin compiler parses those values therefore bug.


> 
> Regards
> 

[toc] | [prev] | [next] | [standalone]


#69242

FromKeith Thompson <kst-u@mib.org>
Date2015-09-03 16:43 -0700
Message-ID<lnbndjqda9.fsf@kst-u.example.com>
In reply to#69222
Melzzzzz <mel@zzzzz.com> writes:
[...]
> I don't know about cygwin but argc/argv values are parsed with crt 
> on Linux. That is if you link with c runtime and write main in assembler
> you get already parsed values eg Linux passes values on stack but crt
> parses them into rdi,rsi registers...
> Probably on cygwin compiler parses those values therefore bug.

The command line is parsed by the shell, which then passes them to your
program using one of the exec*() functions.

The compiler doesn't parse your program's command line arguments
(because they don't exist yet).  It merely generates code that is able
to receive those arguments via the argc and argv parameters.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#69243

FromMelzzzzz <mel@zzzzz.com>
Date2015-09-04 01:53 +0200
Message-ID<20150904015342.411a46af@maxa-pc>
In reply to#69242
On Thu, 03 Sep 2015 16:43:58 -0700
Keith Thompson <kst-u@mib.org> wrote:

> Melzzzzz <mel@zzzzz.com> writes:
> [...]
> > I don't know about cygwin but argc/argv values are parsed with crt 
> > on Linux. That is if you link with c runtime and write main in
> > assembler you get already parsed values eg Linux passes values on
> > stack but crt parses them into rdi,rsi registers...
> > Probably on cygwin compiler parses those values therefore bug.
> 
> The command line is parsed by the shell, which then passes them to
> your program using one of the exec*() functions.
> 
> The compiler doesn't parse your program's command line arguments
> (because they don't exist yet).  It merely generates code that is able
> to receive those arguments via the argc and argv parameters.
> 

Hm, when I don't link with crt, rather make assembly executable
independently, I don;t have argc,argv parameters as function
arguments at all, rather they are laid down on stack... at least on
x86-64 Linux...
Of course shell parses command line but what I actually meant is that
crt parses stack and forms argc,argv as standard function parameters
(rdi->argc (first function parameter),rsi->argv (second function
parameter).

[toc] | [prev] | [next] | [standalone]


#69250

FromPhilip Lantz <prl@canterey.us>
Date2015-09-03 20:15 -0700
Message-ID<MPG.3052aca464f49aad5a@news.eternal-september.org>
In reply to#69242
Keith Thompson wrote:
> Melzzzzz writes:
> > I don't know about cygwin but argc/argv values are parsed with crt 
> > on Linux. That is if you link with c runtime and write main in assembler
> > you get already parsed values eg Linux passes values on stack but crt
> > parses them into rdi,rsi registers...
> > Probably on cygwin compiler parses those values therefore bug.
> 
> The command line is parsed by the shell, which then passes them to your
> program using one of the exec*() functions.
> 
> The compiler doesn't parse your program's command line arguments
> (because they don't exist yet).  It merely generates code that is able
> to receive those arguments via the argc and argv parameters.

Actually, Melzzzzz is right, although I can see why his description was 
confusing.

On Unix, execv doesn't create the values for argc and argv; it just 
passes to the program the strings needed to populate argv. The C runtime 
needs to interpret (or "parse") the strings received from the kernel and 
create the values for argc and argv.

On Windows, the operating system passes the entire command line as a 
single string, so the C runtime does need to parse it (in the usual 
sense) as well as construct the argc and argv values.

You're right that in neither case is it done by the compiler, per se, 
but the C runtime is part of the compiler package, not part of the 
operating system.

[toc] | [prev] | [next] | [standalone]


#69325

FromKeith Thompson <kst-u@mib.org>
Date2015-09-04 09:15 -0700
Message-ID<ln4mjaqhyr.fsf@kst-u.example.com>
In reply to#69250
Philip Lantz <prl@canterey.us> writes:
> Keith Thompson wrote:
>> Melzzzzz writes:
>> > I don't know about cygwin but argc/argv values are parsed with crt 
>> > on Linux. That is if you link with c runtime and write main in assembler
>> > you get already parsed values eg Linux passes values on stack but crt
>> > parses them into rdi,rsi registers...
>> > Probably on cygwin compiler parses those values therefore bug.
>> 
>> The command line is parsed by the shell, which then passes them to your
>> program using one of the exec*() functions.
>> 
>> The compiler doesn't parse your program's command line arguments
>> (because they don't exist yet).  It merely generates code that is able
>> to receive those arguments via the argc and argv parameters.
>
> Actually, Melzzzzz is right, although I can see why his description was 
> confusing.
>
> On Unix, execv doesn't create the values for argc and argv; it just 
> passes to the program the strings needed to populate argv. The C runtime 
> needs to interpret (or "parse") the strings received from the kernel and 
> create the values for argc and argv.

There are several steps between typing a command line at a shell prompt
and providing the arguments to the program via argc and argv.  On
Unix-like systems, the only one of those steps that IMHO can reasonably
be called "parsing" is done by the shellf

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#69341

Fromm.labanowicz@gmail.com
Date2015-09-04 10:33 -0700
Message-ID<919a1e84-602a-4555-97a4-5b497d9c49b0@googlegroups.com>
In reply to#69325
Ok, after adding a 'printf' in main function,
arguments which are passed to bar seems to have correct values.
But there is still invalid 'argv' in 'main' function.

Ok, this value is not important for this particular program,
but optimizer shouldn't change the program behavior
or perhaps optimizer in clang is so clever that it knows better what program should do :).

--{diff:beg}---------------------------------------------
@@ -21,6 +21,7 @@
 }
 int main(int argc, char * argv [])
 {
+  printf("::::argv=%p\n", (void *)argv);
   return bar(argc, argv);
 }
 #ifdef __cplusplus
--{diff:eof}---------------------------------------------

# clang --version && clang -Os main2.c -o a && ./a 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
::::argv=0x0
argc=4, argv=0x24cb50
argv[0] = 0x18032a748 = "./a"
argv[1] = 0x18032a770 = "1"
argv[2] = 0x18032b7b8 = "2"
argv[3] = 0x18032b7e0 = "3"

# clang --version && clang main2.c -o a && ./a 1 2 3
clang version 3.5.2 (tags/RELEASE_352/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
::::argv=0x24cb50
argc=4, argv=0x24cb50
argv[0] = 0x18032a748 = "./a"
argv[1] = 0x18032a770 = "1"
argv[2] = 0x18032b7b8 = "2"
argv[3] = 0x18032b7e0 = "3"

Regards

-- 
Maciek

[toc] | [prev] | [next] | [standalone]


#69344

FromNoob <root@127.0.0.1>
Date2015-09-04 20:48 +0200
Message-ID<mscott$ten$1@dont-email.me>
In reply to#69341
On 04/09/2015 19:33, m.labanowicz wrote:

> Ok, after adding a 'printf' in main function,
> arguments which are passed to bar seems to have correct values.
> But there is still invalid 'argv' in 'main' function.

If you're trying to get a bug fixed in clang/llvm, I think you
need to go through the proper channels.

Maybe you can reach out on IRC first:
irc://irc.oftc.net/llvm

Or report a bug:
http://llvm.org/docs/HowToSubmitABug.html
http://clang.llvm.org/get_involved.html
https://llvm.org/bugs/

Regards.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web