How to overrule default gcc options to the linker? - gcc

On my system when I compile something (with bfin-linux-uclibc-g++ but that is irrelevant), I get hundreds of warnings (not in my own code base) with respect to one of the compiler flags. I want to disable it.
fde encoding in src/SpiMessageUtil.o(.eh_frame) prevents .eh_frame_hdr table being created.
This orginates from a default gcc flag which is handed over to the linker, which is easy to check by adding '-v' to the compilation step:
COLLECT_GCC_OPTIONS=... --eh-frame-hdr ...
I would like to get rid of this option, which is indeed by default defined:
bfin-linux-uclibc-g++ -dumpspecs | grep frame-hdr
%{!static:--eh-frame-hdr}\
%{mfdpic: -m elf32bfinfd -z text} %{shared} %{pie} \
%{static:-dn -Bstatic} %{shared:-G -Bdynamic} \
%{!shared: %{!static: %{rdynamic:-export-dynamic} \
%{!dynamic-linker:-dynamic-linker \
%{mglibc:%{muclibc:%e-mglibc and -muclibc used together;:%e-mglibc not supported for this target};:/lib/ld-uClibc.so.0 \
}}}\
%{static}} -init __init -fini __fini
How can I override this option? I cannot use -Wl,--no-eh-frame-hdr, because there is nothing like that defined.

You can dynamically dump GCC's specs, remove this switch from there and use it when linking, i.e.:
g++ -dumpspecs | sed -e 's,--eh-frame-hdr,,g' > better_specs
g++ -specs=better_specs -o target file1.o file2.o -llib1...
This would replace the specs inline, while keeping original compiler intact.
If you keep your own Makefiles, this could also be handled with something like:
$(TARGET): $(OBJS) | better_specs
$(LINK.o) $(OUTPUT_OPTION) -specs=$| $^
better_specs:
$(CXX) -dumpspecs | sed -e 's,--eh-frame-hdr,,g' > $#
This approach could be also used with configure scripts, provided that you generate better_specs before, you could just use ./configure CXX='g++ -specs=/path/to/better_specs'.

I just got started with back-porting some code to an old system with a bfin controller and ran into the problem with these terribly annoying warnings - 1000s at a time. I didn't find a way to just deactivate the output.
But there are 2 "ways to go" that work:
Fix the source and rebuild the tool-chain:
Remove the code that creates the output in elf-eh-frame.c in the function _bfd_elf_discard_section_eh_frame:
(*info->callbacks->einfo)
(_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr"
" table being created.\n"), abfd, sec);
Patch the ld binary
Take a look at the ld-Binary and patch the binary directly.
I dumped the data segment (.rodata) with objdump to find the address of the string. Then (after creating a disassembly with objdump) I searched where that string was used and replaced the call to the function that creates the output with two NoOps (0xFF 0xD3 -> 0x90 0x90).
Linker still creates the same output, but no more messages.

Related

Cannot pass flags to Makefile to compile my code

I have a project that basically compiles from the command line in the following form:
g++ -o stack_raster stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
I made a Makefile, and this is the content:
CXX =g++
LDDFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
However I got a collect2: error: ld returned 1 exit status.
A second variation of my Makefile I tried was:
CXX = g++
CPPFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rem -f stack_raster
but I still receive the following message (even though the compile flags appear as they should for my program to compile successfully).
collect2: error: ld returned 1 exit status
<builtin>: recipe for target `stack_raster` failed
make: *** [stack_raster] Error 1
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
To begin with, you should have a look at the actual link command that make executed. It should have been echoed to make's output just before the error message from collect2. Understanding what's wrong with the command is the first step in determining how to fix your makefile.
In the first case, the command is probably something like
g++ stack_raster.cpp -o stack_raster
In the second, it is probably something like
g++ -lgdal -lboost_system -lboost_filesystem stack_raster.cpp -o stack_raster
The latter is probably also very similar to what you would get with the first makefile if you corrected the spelling of LDDFLAGS to LDFLAGS.
You will note that the library flags come in a different place in that command than they do in your manual command, and I assume you know that the order of objects and library flags on the linker command line is significant to Unix-style linkers such as GNU's (which is the one that the g++ driver will use).
You can certainly fix this by writing an explicit rule, as you describe in your own answer, but your makes' built-in rules may be up to the task, too. If you are using GNU make then they certainly are. For this purpose it is useful to know what the built-in rules actually are, and essential to know what the variables on which these rules depend mean.
Specifically,
LDFLAGS provides options to pass when invoking the linker, and conventionally, they appear on the command line before the objects being linked. As a result, this variable typically is not appropriate for specifying libraries (but it is fine for other link-specific options, such as -L to add directories to the library search path).
CPPFLAGS provides options for modulating the behavior of the C preprocessor (including when compiling C++). These do not typically appear at all in link(-only) commands executed by make, but they will appear (early) in commands for compiling object files from C or C++ sources, and in rules for building executables directly from C or C++ sources.
Neither of those is what you want, but if you are using GNU make, then its documentation for the former explicitly tells you what (with that make implementation) you should do instead:
Extra flags to give to compilers when they are supposed to invoke the
linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the
LDLIBS variable instead.
(emphasis added)
In GNU make, and perhaps some others, the LDLIBS variable serves exactly the purpose you need: to specify the libraries to link. These will appear at the end of the link command line from built-in rules, as you can confirm from GNU make's catalog of implicit rules, or from the list obtainable by running make -p in a directory containing no makefile.
So, with GNU make you can get the build you seem to want from the built-in rules, with this:
CXX = g++
LDLIBS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
In closing, I note that cleaning before building by default, as your examples do and mine imitates, largely defeats the purpose of using make instead of a simple script. Part of the point of make is to do the minimum work necessary, and if your target executable is present and not out of date with respect to its sources then there is no reason to force it to be rebuilt.
Check out the answer:
Set up my makefile to compile C with just "make"
YOu have to specify in the Makefile the file you want to create in this case stack_raster.exe and the objective file in this case stack_raster.cpp and specify the command line arguments you normally pass for compiling. So the Makefile would be something like:
CXX=g++
stack_raster.exe: stack_raster.cpp
g++ -o stack_raster.exe stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
all: clean stack_raster.exe
clean:
rm -f stack_raster.exe

Remove a compiler / linker flag from autotools configure

There is a project (Antlr3 for C) that can be built with ./configure && make && make install.
One of the flags that are used in the compilation command is -Wl,-soname -Wl,libantlr3c.so. The whole command is:
libtool: link: gcc -shared .libs/antlr3baserecognizer.o .libs/antlr3basetree.o \
.libs/antlr3basetreeadaptor.o .libs/antlr3bitset.o .libs/antlr3collections.o \
.libs/antlr3commontoken.o .libs/antlr3commontree.o .libs/antlr3commontreeadaptor.o \
.libs/antlr3commontreenodestream.o .libs/antlr3convertutf.o .libs/antlr3cyclicdfa.o \
.libs/antlr3debughandlers.o .libs/antlr3encodings.o .libs/antlr3exception.o \
.libs/antlr3filestream.o .libs/antlr3inputstream.o .libs/antlr3intstream.o \
.libs/antlr3lexer.o .libs/antlr3parser.o .libs/antlr3rewritestreams.o \
.libs/antlr3string.o .libs/antlr3tokenstream.o .libs/antlr3treeparser.o \
-m64 -Wl,-soname -Wl,libantlr3c.so -o .libs/libantlr3c.so
How can I remove only the -Wl,-soname -Wl,libantlr3c.so part?
I understand that the compiler and linker flags can be overridden with CFLAGS and LDFLAGS in the configure command. According to this link, it's something like
./configure CFLAGS=blah LDFLAGS=blah
Although I understand that they can/should be used as environment variables, something like
CFLAGS=BLAH LDFLAGS=blah ./configure
However, I think that those uses would try to override all the CFLAGS or LDFLAGS. I only want to exclude the -soname flag (which, I understand, -Wl, means that the compiler passes a flag to the linker.
None of my attempts with things like LDFLAGS=-soname= or CFLAGS="-Wl,soname -Wl,", and variations of them, were successful so far.
From this question it looks as if it was possible to remove flags from within a Makefile, but I can't see that being applicable to overriding flags from the command line with the configure command. It's also possible to provide these variables to the make command instead of the configure command, but that wasn't successful either.
Note, it wouldn't make sense for me to change the Makefile, since it's generated out of the configure command.
You cannot remove -soname because it's part of the way you build a shared library with GCC, and comes straight from libtool. Since you can't really build a shared object for ELF without a soname (well, you can, but it's not really useful) libtool won't let you remove that.
You probably are better off declaring what you try to achieve, because I have a feeling it has nothing really to do with -soname in that case.

How to see exactly what make is doing

Ive got some large make files for a third party project that are not building due to linker issues.
From looking at the make files, I think it should be executing something like:
LIBS = -lm
CC = gcc
bin = bin
myapp: $(bin)/main.o $(bin)/other.o $(bin)/etc.o
$(CC) $(bin)/main.o $(bin)/other.o $(bin)/etc.o $(LIBS) -o myapp
gcc bin/main.o bin/other.o bin/etc.o -lm -o myapp
Instead from the error it seems to be failing on something like: It also didn't put any of the .o files in the expected bin/ location, but just left them in the source directory...
cc main.o -o myapp
But I cant locate anywhere that might come from. Is there some way to get some kind of stacktrace through the make files?
I am aware of -n and -d, but neither seems to tell me what target line and file yeilded that command, or which series of targets led there and the values of any $() expansions (The one im expecting is the only myapp: I can find in any of the makefiles...)
Check out the --debug option. From my manpage:
--debug[=FLAGS]
Print debugging information in addition to normal processing. If the
FLAGS are omitted, then the behavior is the same as if -d was specified.
FLAGS may be a for all debugging output (same as using -d), b for basic
debugging, v for more verbose basic debugging, i for showing implicit
rules, j for details on invocation of commands, and m for debugging
while remaking makefiles.
remake is a very good choice but in a pinch something like the following (saved as debug.mk) can be a good help too. It won't tell you as much as remake but it might tell you enough to start with.
# Use as: MAKEFILES=debug.mk make
OLD_SHELL := $(SHELL)
ifneq (undefined,$(origin X))
override X = -x
endif
SHELL = $(if $#,$(warning Running $#$(if $<, (from: $<))$(if $?, (newer: $?))))$(OLD_SHELL) $(X)
You can print out the other automatic variables there too if you wanted to see a bit more about what was going on.

Error: bad value for -march= switch

I wrote a Makefile and I can't get it to work. I have an option which is supposed to select which processor to compile to. However, when I run make from the commandline it says:
tandex#tandex-P-6860FX:~/emulators/nintendo sdks/3DS SDK [HomeBrew]$ make
gcc -march=arm7tdmi -static -fexceptions -fnon-call-exceptions -fstack-check test.c -c
test.c:1:0: error: bad value (arm7tdmi) for -march= switch
make: *** [ALL] Error 1
But in the man pages for gcc, it states that arm7tdmi is a permissible value. Am I missing something?
Makefile:
#3DS Compilation Makefile (c) TanDex (TEQ)RunawayFreelancers
#
#Version 0.99 (Alpha) For *nix Devices
#
#Please Check Back Soon for 3rd SDK
#SELECT THE COMPILER TO USE! GCC RECOMMENDED!
#FOR SANITY SAKE, USE C FILES WITH GCC AND CPP FILES WITH G++
CC=gcc
#CC=g++
#OBJECTCOPY REFERENCE, DO NOT REMOVE
OBJC=objcopy
OBJREFS= -O Binary
#SELECT THE PROCESSOR TO TUNE IT TO. ARMV7 (Nintendo DS) or ARMV9(Nintendo DS
(Graphical Support))
#or ARM11 Core ARM1176JZ-S and ARM1176JZF-S (3DS Processor? Not Sure if Correct. Try
and see if they Work?)
#
#NOTE: DS GAMES REQUIRE BOTH A ARM7 AND ARM9 BINARY. RUN THIS TWICE (ONCE FOR EACH)
#
#UNCOMMENT FOR PROCESOR
PROCESSOR=arm7tdmi
#PROCESSOR=arm946e-s
#PROCESSOR=arm1176jz-s
#PROCESSOR=arm1176jzf-s
#FILES
#
#PLACE ALL OF THE FILES HERE, THAT ARE BEING COMPILED!
FILES=test.c
#SET BIN FILE NAME BASED ON PROCESSOR SELECTED
ifeq($(PROCESSOR),arm7tdmi)\
NAME=ARM7.BIN
ifeq($(PROCESSOR), arm946e-s)\
NAME=ARM9.BIN
ifeq($(PROCESSOR), arm1176jz-s)\
NAME=ARM11.BIN
ifeq($(PROCESSOR), arm1176jzf-s)\
NAME=ARM11.BIN
#CREATE OBJECTS
ifeq($(CC), gcc)\
OBJECTS=$(FILES:.c=.o)
ifeq($(CC), g++)\
OBJECTS=$(FILES:.cpp=.o)
#FLAGS! DO NOT CHANGE THESE!!!!!!!!!!! THAT MEANS YOU!!!!!
#
#FOR THOSE WHO WANT TO KNOW WHAT THESE DO, HERE THEY ARE:
#-mtune=$(PROCESSOR) FORE THE COMPILER TO TUNE OUTPUT TO THE SPECIFIED
PROCESSOR
#-static REQUIRED FOR CLEAN BINARY OUTPUT?? (NOT SURE WHAT THIS
DOES, BUT WAS SUGESTED ON A POST ON STACKOVERFLOW)
#-fexceptions FORCE EXCEPTIONS
#-fnon-call-exceptions FORCE EXCEPTIONS TO ONLY BE RETURNED BY THE SYSTEM
(MEMORY AND FPU INSTRUTIONS FOR EXAMPLE)
#-fstack-check FORCE STACK CHECKING (DS / 3DS USE AWKWARD STACK
IMPLEMENTATION)
CFLAGS=-march=$(PROCESSOR) -static -fexceptions -fnon-call-exceptions -fstack-check
ALL:
$(CC) $(CFLAGS) $(FILES) -c
.c.o:
$(OBJC) $(OBJREFS) $(OBJECTS) $(NAME)
.cpp.o:
$(OBJC) $(OBJREFS) $(OBJECTS) $(NAME)
You are probably not calling the right gcc. You seem to be calling the gcc installed in your system, rather than the one that comes with the 3DS SDK.
It appears the problem is with -march=arm7tdmi.
I think the workaround is to avoid using -march=arm7tdmi; and use -march=cpu-type, where cpu-type is one of the ones listed at 3.17.4 ARM Options of the GCC manual.
Here's part of the page:
-march=name
This specifies the name of the target ARM architecture. GCC uses this name to determine what kind of instructions it can emit when
generating assembly code. This option can be used in conjunction with
or instead of the -mcpu= option. Permissible names are: ‘armv2’,
‘armv2a’, ‘armv3’, ‘armv3m’, ‘armv4’, ‘armv4t’, ‘armv5’, ‘armv5t’,
‘armv5e’, ‘armv5te’, ‘armv6’, ‘armv6j’, ‘armv6t2’, ‘armv6z’,
‘armv6kz’, ‘armv6-m’, ‘armv7’, ‘armv7-a’, ‘armv7-r’, ‘armv7-m’,
‘armv7e-m’, ‘armv7ve’, ‘armv8-a’, ‘armv8-a+crc’, ‘iwmmxt’, ‘iwmmxt2’,
‘ep9312’.

rpath=$ORIGIN not having desired effect?

I've got a binary "CeeloPartyServer" that needs to find libFoundation.so at runtime, on a FreeBSD machine. They're both in the same directory. I compile (on another platform, using a cross compiler) CeeloPartyServer using linker flag -rpath=$ORIGIN.
> readelf -d CeeloPartyServer |grep -i rpath
0x0000000f (RPATH) Library rpath: [$ORIGIN]
> ls
CeeloPartyServer Contents Foundation.framework libFoundation.so
> ./CeeloPartyServer
/libexec/ld-elf.so.1: Shared object "libFoundation.so" not found, required by "CeeloPartyServer"
Why isn't it finding the library when I try to run it?
My exact linker line is: -lm -lmysql -rpath=$ORIGIN.
I am pretty sure I don't have to escape $ or anything like that since my readelf analysis does in fact show that library rpath is set to $ORIGIN. What am I missing?
I'm assuming you are using gcc and binutils.
If you do
readelf -d CeeloPartyServer | grep ORIGIN
You should get back the RPATH line you found above, but you should also see some entries about flags. The following is from a library that I built.
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib]
0x000000000000001e (FLAGS) ORIGIN
0x000000006ffffffb (FLAGS_1) Flags: ORIGIN
If you aren't seeing some sort of FLAGS entries, you probably haven't told the linker to mark the object as requiring origin processing. With binutils ld, you do this by passing the -z origin flag.
I'm guessing you are using gcc to drive the link though, so in that case you will need to pass flag through the compiler by adding -Wl,-z,origin to your gcc link line.
Depending on how many layers this flag passes through before the linker sees it, you may need to use $$ORIGIN or even \$$ORIGIN. You will know that you have it right when readelf shows an RPATH header that looks like $ORIGIN/../lib or similar. The extra $ and the backslash are just to prevent the $ from being processed by other tools in the chain.
\$\ORIGIN if you are using chrpath and \$\$ORIGIN if you are providing directly in LDFLAGS
using ldd CeeloPartyServer to check the dependency .so is starting with ./ or not. (e.g. libFoundation.so and ./libFoundation.so)
For common situation it should be libFoundation.so and without the prefix ./
if ./ prefix is necessary for some uncommon case, make sure the CWD is the same folder with libFoundation.so, and the $ORIGIN would be invalid.
=======
For example:
g++ --shared -Wl,--rpath="\$ORIGIN" ./libFoundation.so -o lib2.so
would got a library lib2.so with ./libFoundation.so
g++ --shared -Wl,--rpath="\$ORIGIN" libFoundation.so -o lib2.so
would got libFoundation.so instead.

Resources