gcc -print-prog-name=??? doesn't work as I would expect - gcc

if I understand the gcc manuals right than the option -print-prog-name should print the name of the program used.
But it seems that this option only echoes the given argument
Examples:
gcc -print-prog-name=ld
--> ld
gcc -print-prog-name=xxxsome-funny-name
--> xxxsome-funny-name
Is this the expected behaviour? I think it should print something like
gcc -print-prog-name=ld
--> /usr/bin/ld
gcc -print-prog-name=xxxsome-funny-name
--> unknown program
EDIT: testing on Debian Lenny 64bit with gcc v4.2.4

Meanwhile I found another reason for the behaviour of
gcc -print-prog-name=ld
The ld command is not invoked directly by gcc.
gcc invokes collect. And it is collect which in turn invokes ld.

I think the -print-prog-name option only applies to a small set of tools that GCC
uses internally. For example,
$ gcc -print-prog-name=cc1
/usr/libexec/gcc/x86_64-redhat-linux/3.4.5/cc1
$ ls -L /usr/libexec/gcc/x86_64-redhat-linux/3.4.5/
cc1 cc1plus collect2 f771 jc1 jvgenmain
$ gcc -print-prog-name=f771
/usr/libexec/gcc/x86_64-redhat-linux/3.4.5/f771
So gcc -print-prog-name is aware of the tools that live in that directory. But:
$ gcc -print-prog-name=ld
ld
My guess is that if gcc -print-prog-name returns an absolute path, it's configured
to use that version of the program, no matter what's on your $PATH -- otherwise
it just echoes back what you gave it without resolving it to an absolute pathname.

Related

How can I automagically obtain a detailed script equivalent to a complex `gcc` invocation?

It is my understanding that, under the hood, a simple gcc invocation such as this:
% gcc -o hello hello.c
— May actually invoke several separate executables, perhaps hidden inside gcc installation. These may be:
The linker ld.
The assembler as.
An obscure executable cc1 that is actually a compiler.
An obscure executable collect2 with functionality that I find difficult to summarize.
Any number of other commands.
All of them will be invoked with an outrageous amount of command line parameters and environment variables. However, it is my understanding that the gcc executable does nothing by itself, that is, the whole run of gcc is completely described by the commands it runs, so any single invocation of gcc is equivalent to some shell script.
It is sometimes desirable to locate individual commands performed during a run of gcc, either to alter and perform them separately, trace a bug in the build process, or simply to document the particulars of a build. Furthermore, it is sometimes demanded that such effort is performed across several build configurations, target architectures, optimization parameters and so on.
A log of operation may be obtained from gcc by supplying a parameter -v, and redirecting to a file:
% gcc -o hello hello.c 2> gcc.log
Unfortunately, this method by itself does not provide a script that can readily be executed, altered, version controlled and so on. Rather, the log generated will contain a mixture of actual commands and arbitrary commentary, such as gcc version, all in a uniform list. It is then on the operator to manually mark the commentary as such or remove it altogether, in order to, hopefully, obtain a runnable shell script.
How can I (make ghc to) automagically generate such a script?
First of all note that command-line invocations alone are not sufficient - GCC passes additional options via environment variables (COMPILER_PATH, COLLECT_GCC_OPTIONS, etc.) and via temp files which contain compiler options inside them (the latter is AFAIK only used in LTO compilations).
You can easily extract compilation commands via sed:
$ gcc tmp.c -### 2>&1
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: ...
Thread model: posix
gcc version 6.4.0 (GCC)
COLLECT_GCC_OPTIONS='-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/cc1.exe -quiet -Dunix -idirafter /usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../lib/../include/w32api -idirafter /usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../x86_64-pc-cygwin/lib/../lib/../../include/w32api tmp.c -quiet -dumpbase tmp.c "-mtune=generic" "-march=x86-64" -auxbase tmp -o /tmp/cco2cExb.s
...
$ gcc tmp.c -### 2>&1 | sed -ne '/^[A-Z_0-9]\+=/{ s/^\([^=]\+\)=\(.*\)/export \1="\2"/; s/'\''//g; p}; /^ /{p}'
export COLLECT_GCC="gcc"
export COLLECT_LTO_WRAPPER="/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/lto-wrapper.exe"
export COLLECT_GCC_OPTIONS="-mtune=generic -march=x86-64"
/usr/lib/gcc/x86_64-pc-cygwin/6.4.0/cc1.exe -quiet -Dunix -idirafter /usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../lib/../include/w32api -idirafter /usr/lib/gcc/x86_64-pc-cygwin/6.4.0/../../../../x86_64-pc-cygwin/lib/../lib/../../include/w32api tmp.c -quiet -dumpbase tmp.c "-mtune=generic" "-march=x86-64" -auxbase tmp -o /tmp/ccZSUbZx.s
...

ld.exe: unrecognized option '-z'

I followed this Buffer Overflow Exploit tutorial and wrote a small application to compile with gcc in my mingw32.exe. However, when I did, I got the following errors:
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$ gcc vuln.c -o vuln -fno-stack-protector -m32 -z execstack
C:/msys32/mingw32/bin/../lib/gcc/i686-w64-mingw32/7.3.0/../../../../i686-w64-mingw32/bin/ld.exe: unrecognized option '-z'
C:/msys32/mingw32/bin/../lib/gcc/i686-w64-mingw32/7.3.0/../../../../i686-w64-mingw32/bin/ld.exe: use the --help option for usage information
collect2.exe: error: ld returned 1 exit status
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$ gcc -c vuln.c -o vuln -fno-stack-protector -m32 -z execstack
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$ ld -z execstack vuln.o -o vuln
C:\msys32\mingw32\bin\ld.exe: unrecognized option '-z'
C:\msys32\mingw32\bin\ld.exe: use the --help option for usage information
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$ ld -v
GNU ld (GNU Binutils) 2.30
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$ C:/msys32/mingw32/bin/../lib/gcc/i686-w64-mingw32/7.3.0/../../../../i686-w64-mingw32/bin/ld.exe -v
GNU ld (GNU Binutils) 2.30
Liu.D.H#DESKTOP-KA8TQF4 MINGW32 ~
$
I could find the execstack options in man ld and the version matched above.
The -z options are just not supported for Windows versions of ld. Check with ld --help. For Cygwin, it should not list -z options that are present when running the same command on a Linux system. I believe this is because options here are really only meaningful on Linux.
The -z execstack option (not the Linux tool of the same name) tells the Linux version of ld to turn off Data Execution Prevention (DEP) on the executable. This is done with flags in the ELF.
Windows DEP policy, on the other hand, is built into the OS nowadays. Here are some options to manage this yourself:
For individual programs on Windows 10:
Look for "Adjust the appearance and performance of Windows" in the Start Menu. (You can type "performance" and it will appear). This gives you a new dialog box.
Go to the third tab, "Data Execution Prevention".
Add/remove exceptions here
Call the WinAPI's SetProcessDEPPolicy depending on the OS's DEP setting. However, this has to be done in the program itself.
Use bcdedit via CMD to globally turn on/off DEP, but this is a bad idea. To quote the article:
Important DEP is a highly effective security feature that should not be disabled unless you have no alternative.
In short, when following tutorials for exploit exercises, often these are meant to be done on Linux machines. Run it on the proper OS, or for extra safety, run it on a VM. The same exploits can't be expected to work on Windows in the same way.
More on Windows DEP policy: See
How to make my program DEP-compatible?

GCC ver 7.3.0 preprocessor fails if output file doesn't exist

I tried to build the FreeIPMI on a box with GCC 7.3.0 and got stuck - the preprocessor complained that output file was missing:
nekto#ubuntu:~/freeipmi-1.6.1/man$ /usr/bin/cpp -nostdinc -w -C -P -I../man libipmiconsole.3.pre libipmiconsole.3
cpp: error: libipmiconsole.3: No such file or directory
That's output file, its existence shouldn't be checked I think.
BTW, the same command worked flawlessly on another box with GCC 6.
Is it issue with the GCC 7.3.0 preprocessor?
I'm answering my own question.
The invocation format for the GCC 7.3.0 preprocessor has been changed - the output filename has to be prepended by the -o option, and all the free-standing filenames on the command line are considered input files.
Also the preprocessor became more strict about input formats it supports, so it can't be used to generate man-pages for the FreeIPMI anymore.

Can't output anything using cygwin 1.7 gcc under windows

I just installed cygwin 1.7, and wrote a simple Hello world in test.c
but when I complie, nothing happens, even no error messages
gcc-4 -o test.exe test.c
And there's nothing generated under my folder.
I have included C:\cygwin;C:\cygwin\bin in my PATH
Did I miss something?
EDIT:
for more information, I installed Qt4, tortoiseHg, and mingw before.
Now I had removed mingw. but still got Qt4 and tortoiseHg, is this a problem?
Try doing this from the Cygwin Terminal, not cmd.exe:
$ cd `cygpath -u "$USERPROFILE"`/Desktop/UT
$ gcc -o foo foo.c
$ ls -l foo
-rwxr-xr-x+ 1 yourlogin None 19618 May 10 05:15 foo*
If that works, there's some bogus remnant lying around.
You'll find that the Cygwin experience is generally better running under Bash, in a MinTTY terminal anyway. cmd.exe doesn't understand Cygwinisms, and is a DOS throwback besides.
Note that you don't need to say gcc-4 to get GCC 4.x. gcc is GCC 4.x on Cygwin, and has been for quite some time now.
Also note that you don't need to include .exe in the GCC -o flag, because Cygwin GCC knows to add that already.

Force gcc to use one linker over another

Lately I have been working on OS X. Things were going pretty peachy for a while until somehow ld got on my system and now gcc won't use dyld. Furthermore, all of my shared libraries are in *.dylib format, and ld is stubornly ignoring there existance. If I mv ld from PATH, gcc just complains it cant find ld.
Please help me to get gcc back on track and using what it should.
You can try some gcc options. From the man page:
-c Compile or assemble the source files, but do not link. The linking
stage simply is not done. The ultimate output is in the form of an
object file for each source file.
You could then link explicitly using whatever linker you want.
Does it help to symlink ld to dyld?
mv /usr/bin/ld /usr/bin/ld.old
ln -s /usr/bin/dyld /usr/bin/ld
Edit: fixed ld params order
This isn't your exact question, but I had a need to switch to ld.gold, and for that, the -fuse-ld=gold option to gcc was very useful.
look at -Xlinker option
I got it from man gcc
you can double check using some verbose options like -v

Resources