Named common block in a shared library - windows

I am encountering a problem when I include a Fortran
subroutine in a shared library. This subroutine has a
named common block.
I have a Fortran main program that uses this common block
and links with the shared library.
The behavior is that variables in the common block set in
either the subroutine or main program are not shared between
the two.
I am using gfortran 4.9.3 under MinGW on windows. Here are the pieces of
my very simple example.
Main program:
program mainp
common/whgc/ivar
ivar = 23
call sharedf
end
Subroutine:
subroutine sharedf
common/whgc/ivar
print *, 'ivar=', ivar
end
Makefile:
FC = gfortran
FFLAGS=-g
all: shltest.dll mainp.exe
shltest.dll: sharedf.o
$(FC) -shared -o shltest.dll sharedf.o
mainp.exe: mainp.o shltest.dll
$(FC) -o mainp.exe mainp.o shltest.dll
clean:
rm *.o mainp.exe shltest.dll
When mainp.exe is run, it produces ivar = 0 instead of the correct ivar=23
Here are the results of some experimentation I did with nm.
nm -g mainp.o shows:
...
00000004 C _whgc_
nm on sharedf.o shows the same.
nm -g shltest.dll shows:
...
71446410 B _whgc_
nm -g mainp.exe shows:
...
00406430 B _whgc_
This is the only _whgc_ symbol in mainp.exe.
However, when I run mainp.exe in gdb and set break points in both
mainp and sharedf, I can print the address of ivar at each break point. The addresses
are not the same.
From the behavior it seems clear that GNU ld is not correctly
matching the _whgc_ symbols but I'm unclear about what options
to pass either in the shared library build or the final link to
make it do so?
(Please don't suggest alternatives to common blocks. In my real
application I am dealing with legacy code that uses common blocks.)
EDIT:
I tried my example on Linux/x86 and there the behavior is correct.
Of course on Linux the shared library and executable are ELF format
objects and on Windows/MinGW the format is PE/COFF.

Related

Run two instances of the same C++ program simultaneously

I've got a C++ program with a Makefile, building (g++) and running on Windows cmd. Thing is, sometimes it takes a while to run and save the results, and I want to run it with different parameters at the same time so that I can do something else while I wait for the first instance to finish. It doesn't work though, because of the executable I guess:
>make
g++ -c -o main.o main.cpp
Assembler messages:
Fatal error: can't create main.o: Permission denied
make: *** [main.o] Error 1
You have two problems: The one you ask about, and the reason you ask this question in the first place.
Lets start with the problem you have...
Judging by the Makefile you show, you have it all wrong.
Rules are in the format
target: sources_the_target_depend_on
The target is usually a file that need to be created. For an object file that is the name of the actual object file itself. The source files that the object files then depend on should be on the right-hand side.
To take an example from you Makefile (before you edited it away):
graph2: graph2.o
g++ -g -c graph.cpp -o graph2.o
Here you tell make that the file graph2 depends on the file graph2.o, and then it creates the graph2.o file. That's wrong. The rule should be that the file graph2.o depends om the file graph.cpp and go on to generate the file graph2.o:
graph2.o: graph.cpp
g++ -g -c graph.cpp -o graph2.o
This indirectly leads to the problem you have, with this line (deduced from your error and the Makefile):
main: main.o utils.o graph.o heuristics.o
g++ -g main.cpp -o main.o utils.o graph.o heuristics.o
This contains the same error as discussed above: You say that the file main depends on main.o and then the rule create main.o. Your rule should be
main: main.cpp utils.o graph.o heuristics.o
g++ -g main.cpp -o main utils.o graph.o heuristics.o
Note also how I no longer name the executable file main.o, as that is supposed to be used for object files.
Now lets continue with the reason you have the problem in the first place: That you need to edit the code to change data or values.
This is a problem that you need to solve. One common way to solve it is through command line arguments. If your program parses the command line arguments passed to your program you can pass it the values that could change from run to run.
How to do this is whole chapter on its own, so I wont give you any more details. There are plenty of tutorials online.
Lastly, you can simplify your Makefile considerably, by using implicit rules and variables.
I would simply create the Makefile to look something like this
# The compiler to use
CXX = g++
# Flags to pass to the compiler (add warnings when building)
CXXFLAGS = -Wall
# The main executable file to generate
TARGET = main
# List the object files needed to generate the main executable file
OBJECTS = main.o utils.o graph.o heuristics.o
# The all target depends on your main executable file
# Also as the first target in the Makefile, if no specific target is specified
# this will be the one that is used (it's the "default" target for the Makefile)
all: $(TARGET)
# The main executable file depends on the object files
$(TARGET): $(OBJECTS)
This is really it. the object files will be built automatically from their respective source files, and then the executable program will be linked using the object files listed.

Makefile: Link several *.a to executable

I try to write a Makefile that takes several static libraries that have been created before and link the to an executable. Although one libary has a main-routine.
I get the error:
/lib/../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [dockSIM_gcc_release] Error 1
I tried it with just linking the library that has the main routine but the error stays the same and comes directly after invoking make.
The Makefile:
SHELL = /bin/sh
RM=/bin/rm -f
CXX=g++
PROGNAME=dockSIM_gcc_release
DEFINES=-DDOCKSIM_VERBOSE=FALSE -DNDEBUG -DPRINT_LOG_MSG=0 -DPRINT_DEBUG_MSG=0
LDFLAGS = -fopenmp -g -O3 -std=c++11 -mavx -mstackrealign -fstrict-aliasing
LIBS= -lnagc_mkl -lm -L../externalCode -lpardiso500-GNU481-X86-64 -lacml
FILENAMES = commandInterpreter_lib.a
OBJNAMES =
all: $(PROGNAME)
$(PROGNAME): $(FILENAMES)
$(CXX) $(LDFLAGS) $(DEFINES) -o $(PROGNAME) $(FILENAMES)
clean:
$(RM) *.mo *.ho *.o $(PROGNAME) core *~
test:
echo $(FILENAMES)
showlibs:
echo $(LIBS)
The flags are compatible with those that were used to compile the code.
g++ 4.9.3 is used.
Signature of the main-Routine:
int main(int argc, char* argv[])
Thanks for help and kind regards.
I can only guess what's wrong.
There is more to linking a static library than just a convenient bundle of object files to reduce command line length. In addition to that, the linker only links in object files which it thinks are needed. An object file is needed if there's some undefined symbol that the linker is looking for, that is contained in that object. If there's no symbol that the linker needs in the object, then the linker ignores the object and doesn't link it.
The normal way to build a program is to have the main program listed as object files on the command line: the linker always links every object file. This gives the linker a set of symbols which are defined (by the object files) and undefined (things the object files use but that aren't defined by them). Then the linker will go through the libraries on the link line and add in object files that resolve undefined symbols. These object files in turn may have other undefined symbols that the linker will need to resolve later, etc.
All I can guess is that by not having any object files on your link line, the linker doesn't see the object file in the library containing main as needed and so it doesn't link it.
I don't know why building with debug vs. non-debug makes a difference.
I didn't understand your comment about why you need to do things this way: even if the person who knew about this left, someone will need to learn about it to maintain the software.
In any event you have a few options.
One simple one is to use the "ar" program to extract out the object file containing main and link it directly: in addition to adding objects to libraries ar can extract them. Then you can link that object directly. See the man page for ar.
Another would be to look at the documentation for your compiler and linker and find flags that will force it to include the entire library, not just the unresolved symbols in the library. For the GCC/binutils linker, for example, you can pass -Wl,--whole-archive before the libraries you want to be fully included on the command line, then -Wl,--no-whole-archive after them to turn off that feature.

Discard unused functions in GCC [duplicate]

This question already has answers here:
How to remove unused C/C++ symbols with GCC and ld?
(11 answers)
Closed 6 years ago.
I need some help for compiling with GCC under MinGW.
Say I have two files:
File a.c contains two functions, a1 and a2
File b.c contains two functions, b1 and b2.
Then I link the two objects into a shared library. The command used are like:
gcc -c a.c
gcc -c b.c
gcc -shared -Wl, --version-script v.ver -Wl, -Map=out.map -Wl, --strip-all -o mydll.dll a.o b.o
File v.ver looks like:
mylib {
global: a1;
a2;
local: *;
}
which is used to control which functions to be exported.
By checking the mapfile I can see that the two functions in b.c are also included into the .text section of the DLL file.
Because this DLL file only exports a1 and a2, and b1 and b2 are only defined in b.c, but never used anywhere. Is there an option I could add in GCC or ld so that b1 and b2 are not built into the DLL file so that I can save some space in the DLL file?
Yes, this is possible. To do this, add the following two flags when compiling your C source code to objects:
-ffunction-sections -fdata-sections
This will generate bigger object files, but will add a lot of information for the linker.
When calling the linker add the following flag:
--gc-sections
The linker will now throw away all functions and sections that are not used. Note that this might incur a performance penalty:
Only use these options when there are significant benefits from doing
so. When you specify these options, the assembler and linker create
larger object and executable files and are also slower. These options
affect code generation. They prevent
optimizations by the compiler and assembler using relative locations inside a translation unit since the locations are unknown
until link time. An example of such an optimization is relaxing calls
to short call instructions.
(man gcc)
See also this question: Query on -ffunction-section & -fdata-sections options of gcc for more information.

Including a separate binary into an ELF executable

I am developing an operating system. I would like to include a small asm program into my main kernel elf that can serve as the first process to load. I am having trouble getting this to work. The program is initcode.s. I using the following Makefile which I modified from the xv6 operating system source for this task:
initcode:
$(AS) $(ASFLAGS) initcode.s -o initcode.o
ld $(LDFLAGS) -N -e start -Ttext 0 -o initcode initcode.o
objcopy --input binary --output elf32-i386 --binary-architecture i386 initcode.out initcode
kernel.elf: $(OBJECTS) initcode
ld -T link.ld -melf_i386 $(OBJECTS) -o kernel.elf initcode
The kernel compiles and links fine. objcopy also creates markers which enable me to find the binary from within the kernel code. However the contents of initcode is trashed. The contents does not resemble what the assembler step produced within initcode.out.
How can I achieve including initcode.s as a separate binary somewhere in my main kernel.elf with some markers generated so I can find it from within my kernel? Any suggestions?
I can think of 2 simple methods. There are certainly more complex methods if you prefer.
Write a small utility to convert the initcode binary to an asm file (or even C file) containing a GAS data section. Then assemble that file and link it with your kernel. Your initcode will than appear as a variable in your kernel.
OR
Simply 'cat' the initcode binary to the end of your kernel elf after the link step. This method will depend on whether your loader is happy to support this.

gcc/ld: undefined reference to unused function

I'm using gcc 4.3.4 and ld 2.20.51 in Cygwin under Windows 7. Here's a simplified version of my problem:
foo.o contains function foo_bar() which calls bar() in bar.o
bar.o contains function bar()
main.c calls functions in foo.o, but foo_bar() is not in the call chain
If I try to compile main.c and link it to foo.o, I get an undefined reference to _foo_bar error from ld. As you can see from my Makefile except below, I've tried using flags for putting each function in its own section and having the linker discard unused sections.
COMPILE_CYGWIN = gcc -iquote$(INCDIR)
COMPILE = $(COMPILE_CYGWIN) -g -MMD -MP -Wall -ffunction-sections -Wl,-gc-sections $(DEFINE)
main_OBJECTS = main.o foo.o
main.exe : $(main_OBJECTS)
$(COMPILE) -o main.exe $(main_OBJECTS)
The function foo_bar() is a short function that provides a connection between two networking layers in a protocol stack. Some programs don't need it, so they won't link in the other object files related to the upper layer of the stack. It's a small function, and seems inappropriate to put it into its own .o file.
I don't understand why ld throws the error -- nothing is calling foo_bar(), so there's no need to include bar() in the final executable. A coworker has just told me that ld is not a "smart linker", so maybe what I'm trying to do isn't possible?
Unless the linker is from Cyberdyne Systems it has no way to know exactly which functions will actually be called. It only knows which ones are referenced. Even Skynet's linker can't predict what run-time decisions will be made or what will happen if you load a module dynamically at run-time and it starts calling various global functions1.
So, if you link in module m and it references function f, you will need to link with whatever module has f.
1. This problem is related to the Halting Problem and has been proven undecidable.
I hit the similar issue and I find this page:
http://lists.gnu.org/archive/html/bug-gnu-utils/2004-09/msg00098.html
Highligt:
The GNU linker still works at .o file granularity.
Gcc pulls in foo.o and then find bar() was undefined.
You'd better put foo_bar() into another .o file.

Resources