Trouble understanding gcc linker options - gcc

I have recently been reading up on linkers and I'm having trouble understanding this compilation code. If I were to run gcc -Wl,--hash-style=both example.c, what difference will it make as opposed to me simply running gcc example.c. And also, what does --hash-style means

what does --hash-style means
--hash-style allows you to change the format of hashtable which is used for runtime symbol resolution (see Drepper's article, section "The GNU-style Hash Table" for details). The GNU hashtable format is said to be slightly faster.
If I were to run gcc -Wl,--hash-style=both example.c,
what difference will it make as opposed to me simply running gcc example.c
It depends on how your distro's GCC was configured. AFAIK most use either both or gnu styles by default. Both simply means that linked files will include, um, both gnu and sysv hashtables. This shouldn't matter unless you try to run your program on a system with dynamic linker which does not understand GNU hashtables. In that case, if program was built with -Wl,--hash-style=gnu, you'll get an error at startup about unsupported hashtable format.

Related

How to change the default-search-path values for GNU GCC for regular usage?

GNU GCC Compiler Environment Variables Default-Search-Path — I am trying to change default values of GCC environment variables to new custom values so that the default search path will contain any needed additional libraries or include header files that I would like to use on a regular basis.
My version of GNU GCC is: gcc (MinGW.org GCC Build-2) 9.2.0
Include directories for .h header files for this <…> not "…" which would be in the same directory as .c file extension.
Include Header Directories:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Library File Directories:
LIBRARY_PATH
I realized that these are Windows Environment Variables.
And That I could Simply just create Windows User Environment Variables.
Here is a command which will show default search paths for GNU GCC Compiler.
cpp -v
This shows include directory default search path.
gcc -print-search-dirs
This shows library directory default search path.
This Command Prompt Command tells me the default-search-paths which are set during installation of GNU GCC Compiler I assume these are considered Environment Variables and I am looking to see if anyone on the web could give me any urls in regards to changing this default search path value.
Here are a few links related to what I am doing. I used that information although I was still unable to accomplish what I was intending to accomplish.
GCC environment variables
C Preprocessor search path
C preprocessor environment variables
GCC configuration
Recent GCC compilers have some (optional) .spec files.
You could edit yours, and that file drives the actual compilation processes. As you know, gcc is mostly starting some cc1 / cc1plus internal program (then ld)
But I recommend to not edit your .spec file.
Instead of that, configure your build procedure, e.g. edit your Makefile for GNU make or your build.ninja file (actually, the generator of that file) for ninja builder.
Of course, read the chapter about Invoking GCC.
BTW, GNU make has a lot of built-in rules. Use make -p to understand them.
You could also take inspiration from GNU autoconf.
You could also code your own GCC plugin, implementing your own #pragma which would customize the behavior of gcc. I am not sure it is a good idea.
How to change the default-search-path values?
don't do that, learn to use GCC instead
You might want, from time to time, to compile your code with Clang, to check that your code base is not tied to one particular compiler.
You could use Frama-C or the Clang static analyzer on your C code. In some cases, some bugs could be found at compile time. You certainly want to pass explicitly both -Wall and -Wextra to gcc (and notice that clang accepts them also)
PS. This is from a GNU/Linux perspective. Adapt that to your proprietary operating system. Or consider getting the permission to switch to Linux (see also this draft report funded by the CHARIOT European project).

GCC error with -mcpu32 flag, CPU32 compiler needed

I am patching code into my car's ECU. This has a Motorola MC68376 processor, so I'm using the appropriate CPU32 instruction set.
I want to continue to write in assembly code so that I can explicitly manage control registers, RAM access and allocation, as well as copying code structures which are already in use.
My first patch was successfully compiled in EASy68k, but that program does not support the full instruction set for the CPU32. For example, the DIVS.L command is not supported, so I cannot take a quotient of a 32-bit value.
Thus, before writing my own compiler out of sheer incompetence with available tools, I'm looking for an easier path. I read that gcc has the capability to compile code for the CPU32, but I have failed to get it to work.
I'm using MinGW's gcc (6.3.0) and Eclipse (2020-03). I added the '-mcpu32' or '-march=cpu32' flags to the compiler call, according to:
https://gcc.gnu.org/onlinedocs/gcc/M680x0-Options.html
Unfortunately this returns an error:
gcc: error: unrecognized command line option '-mcpu32'; did you mean '-mcpu='?
or
error: bad value (cpu32) for -march= switch
May I please have some advice for making this work? Does anyone know of a better CPU32 compiler that works with Eclipse?
I did not understand that gcc is conventionally distributed as binary files that are compiled with different functionality to suit the needs of a given user.
There seem to be two paths forward:
1) compile my own cross-compiler version of GCC
2) download a pre-compiled cross-compiler version of GCC
I chose to follow route 2).
I began the process of installing the 'Windows Subsystem for Linux' and Ubuntu 20.04 Focal Fossa, because I found a pre-made compiler that should be capable of performing cross compilation for the m68k processor: "gobjc-10-m68k-linux-gnu"
https://ubuntu.pkgs.org/20.04/ubuntu-universe-i386/gobjc-10-m68k-linux-gnu_10-20200411-0ubuntu1cross1_i386.deb.html
While I was installing that, I also found an m68k-elf gcc toolchain that is pre-compiled for windows 10:
https://gnutoolchains.com/m68k-elf/
I played with the latter for much of today. Although I was unable to get the toolchain integrated well with Eclipse, it works from the command line to compile a *.s assembly code file. This includes compatibility with the '-mcpu32' flag that I wanted at the outset.
There is still a lot for me to figure out, even after floundering through learning gcc's assembler directives (https://www.eecs.umich.edu/courses/eecs373/readings/Assembler.pdf) and the differences in gcc's assembly syntax compared to the MC68k reference manual (https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf).
I can even convert the code section of the output file to be a proper s-record by using objcopy with the '-O srec' and '--only-section=.text' flags. This helps me patch the code into my ECU.
Thus I've answered my original question.

GNU GCC/LD : Which libraries are linked by default?

I am a regular C programmer, and there's something I have wondered for some time about GNU GCC/LD internals.
I have noticed that, when passing a sequence of object files to GCC (e.g gcc main.o otherfile.o), GCC automatically links libc.a library file without my explicitly specifying -lc in the options. Similarly, when I compile a program using ncurses, I just need to specify -lncurses and libtinfo.a gets linked automatically (no need to specify -ltinfo). In other words, even though ncurses functions use functions from libtinfo (for instance, unctrl()), I don't need to explicitly link libtinfo.
How can it be possible?
Does GCC/LD have a list of "default libraries" where it looks for missing symbols when linking? If such a table exists, where is it and how can it be configured?
A direct answer is that you can see what libraries are linked by command line options by adding -v to the linking command line. This will show you the commands as they are executed.
The C library and the GCC support library or libraries are linked automatically; other libraries have to be specified manually.
The case of -lncurses and libtinfo.a (libtinfo.so?) is rather different. There, the link command used to build libncurses.so tells the linker that this library also needs -ltinfo, so it automatically picks up the extra library.

What flags or environment variables can I pass to Clang to get maximum debugging on both BSD and Linux?

I'm interested in answers, approaches, and ideas out of the box. At a high level, the main page is pretty sparse and they mainly list -g, with one level, suggesting that -O0 is also either very helpful or essential.
But I'm wondering what other clang flags can be given to give maximum debugging. Is there an equivalent to gcc's -ggdb3 which includes some of the source or annotations directly in the object output? Or could there be? Is it possible and helpful to recompile the OS and its original libraries to have debugging (and if so, if I'm using Debian, can I have it write the debugging into the main .deb package instead of putting a separate debugged .deb package which stores debugging data in /usr/lib/debug?)? Will a static build of a binary affect the ability to see a good stacktrace? And is there anything that needs to be done to ensure that addr2line works well? Is it needed to compile all libraries (even glibc) with clang to get the maximum debugging benefit? I note that there is a project to recompile Debian with clang, and otherwise am open to a distribution that does so or otherwise places emphasis on debugging.
On Linux there are also options like an LD_PRELOAD set to /lib/libSegFault.so, or a set of LD_LIBRARY_PATH reassignments to /usr/lib/debug instead of the usual /usr/lib location (including redirecting libc itself to the debugged version). Is there a central place or external sources for answers to this question of how to enhance debuggability of a binary? The bigger mystery is clang, since I see in the long gcc man page that there are various options which can increase debugging (or reduce optimisations), but on the other hand the documentation for clang only shows a smaller set. It's possible that clang will accept more options than given, including gcc flags (which may either translate to a no-op or to more debugging - hard to tell without a canonical source of information).
Also from a package build perspective, since an external package may not respect CFLAGS, I've redirected /usr/bin/strip to be a no-op command that always succeeds, but other ideas on ensuring compliance are suggested (I believe that pkgsrc does a good job of wrapping gcc and the linker in shell scripts - useful to insert mandatory flags). Also there may be various ld options that can be passed to increase debugging of the outputted target. Also, it's quite possible that BSD (including FreeBSD 10, based upon clang) may have a different linking architecture which could make it easier to request and find debugged symbols in the generated libraries and executables.
To take debugging more broadly defined, I've set LD_WARN=yes, LD_DEBUG=unused, SEGFAULT_SIGNALS="all", LD_PRELOAD=.../libSegFault.so (as mentioned above), and LD_BIND_NOW=yes. Also I believe I can prefer that gcc search for libraries in /usr/lib/debug - above the standard search paths using strategic -Bs. Also, using --whole-archive for a static build might ensure that more objects are included in the linked output. There's also ulimit -c unlimited, and on Linux a nice way to differentiate core files like:
sysctl -w kernel.core_pattern="core.%t.SIG-%s.PID-%p.ID-%g-%u.%h.%E"
For gcc I've used and seen flags like: -O0 -fno-omit-frame-pointer -fverbose-asm -ggdb3 -mno-omit-leaf-frame-pointer -mtune=generic -fvar-tracking -D_GLIBCXX_DEBUG=1 -frecord-gcc-switches -femit-class-debug-always -fmath-errno -fno-eliminate-unused-debug-symbols -fno-eliminate-unused-debug-types -fno-merge-debug-strings -mieee-fp -mtune=generic -static-libgcc -fexceptions -fvar-tracking -fbounds-check -rdynamic -UNDEBUG -DDEBUG=1 (-ffreestanding -static-libgcc -pass-exit-codes) -fno-stack-check (since I believe I've read that the latter can interfere with debugging)
Other flags are there for other reasons but the emphasis is to be on maximum debugging. With all or most of the above, it's unclear to what extent clang would support or use there, or whether there are other options.
Clang does not support the -ggdb3 flag, only -g, as you have noticed. If you try to use it, you'll get the message:
clang: warning: argument unused during compilation: '-ggdb3'
so you can run your entire command line through Clang and it will tell you which of those GCC flags it supports and which it does not, some will print warnings, others may error out, but Clang will not silently ignore them. Here are the ones that Clang rejected when I tried your long command: -static-libgcc and -pass-exit-codes.
As pointed out in another SO answer, clang -cc1 --help can be used to list supported compilation flags, where we see the following which may be of interest to you:
-disable-llvm-optzns: Don't run LLVM optimization passes
-fno-elide-constructors: Disable C++ copy constructor elision
-mdisable-fp-elim: Disable frame pointer elimination optimization

How to choose the assembler GCC uses?

Is there an option to GCC that changes the path of the assembler it uses? I'm getting errors from Solaris /usr/ccs/bin/as when using GCC to attempt to compile Haskell, but I've got a copy of GNU as in my path so when I type which as and as --version they use the GNU version, not the Solaris version. Unfortunately it seems GCC ignores the GNU version in the path and goes to the Solaris version. I'm trying to build Haskell on Solaris and I don't think it sits well with the Solaris assembler. I hope I can change this behaviour with a simple wrapper script so I don't have to recompile GCC.
Specifying the assembler to be used is not possible at run time. It has to be done when configuring gcc:
--with-gnu-as
Specify that the compiler should assume that the assembler it finds is the GNU
assembler. However, this does not modify the rules to find an assembler and will
result in confusion if the assembler found is not actually the GNU assembler.
(Confusion may also result if the compiler finds the GNU assembler but has not
been configured with --with-gnu-as.)
Note the part I've put in italics. Of course you could temporarily change /usr/ccs/bin/as to call the gnu assembler (provided you have the necessary permissions), but the above seems to suggest that you'll very likely run into problems. The gcc build process actually checks the features the assembler supports and generates code for exactly that assembler.
I suggest you build a new version of gcc first (configured to use the gnu tools), and then use that to build ghc.

Resources