Cannot link to BLAS/ATLAS when trying to compile HPCC benchmark - c

I am trying to compile the HPCC benchmark on a small RHEL desktop. Everything seems fine until linking. My link command is
mpicc -DAdd_ -DF77_INTEGER=int -DStringSunStyle -I../../../include \
-I../../../include/myarch -I/path/to/my/ATLAS_build/include \
-I/usr/include/openmpi-x86_64 -fomit-frame-pointer -O3 -funroll-loops \
-W -Wall -lm -o ../../../../hpcc ../../../lib/bugzilla/libhpl.a \
/path/to/my/ATLAS_build/lib/libcblas.a \
/path/to/my/ATLAS_build/lib/libatlas.a -L/usr/lib64/openmpi/lib
The link fails with several errors, all related to BLAS/ATLAS objects that the linker can't find. A few of them are:
../../../lib/myarch/libhpl.a(HPL_dcopy.o): In function `HPL_dcopy':
HPL_dcopy.c:(.text+0x1e): undefined reference to `dcopy_'
../../../lib/myarch/libhpl.a(HPL_daxpy.o): In function `HPL_daxpy':
HPL_daxpy.c:(.text+0x2f): undefined reference to `daxpy_'
../../../lib/myarch/libhpl.a(HPL_dscal.o): In function `HPL_dscal':
HPL_dscal.c:(.text+0x22): undefined reference to `dscal_'
../../../lib/myarch/libhpl.a(HPL_idamax.o): In function `HPL_idamax':
HPL_idamax.c:(.text+0x1a): undefined reference to `idamax_'
../../../lib/myarch/libhpl.a(HPL_dgemv.o): In function `HPL_dgemv':
HPL_dgemv.c:(.text+0xba): undefined reference to `dgemv_'
HPL_dgemv.c:(.text+0x136): undefined reference to `dgemv_'
Here's what I really don't understand. Take dgemv for instance. libhpl.a does indeed invoke it:
>$ nm libhpl.a | grep dgemv
HPL_dgemv.o:
U dgemv_
Now, libcblas.a has a reference to it, but needs the version in ATLAS:
>$ nm libcblas.a | grep dgemv
cblas_dgemv.o:
U ATL_dgemv
Finally, does ATLAS have ATL_dgemv?
ATL_dgemv.o:
0000000000000000 T ATL_dgemv
So, yes, it certainly does. So CBLAS has a dgemv that HPCC should (I would think) be able to plug into, but it needs ATL_dgemv. But ATLAS has ATL_dgemv. So why can't the linker find everything it needs for HPCC?
Thanks.

Your logs indicate that libhpl.a needs the dgemv_ symbol that is not provided either by libcblas.a nor libatlas.a (I assume your last command was nm libatlas.a | grep dgemv).
The trailing underscore in dgemv_ strongly suggests it requires the Fortran BLAS(and not the C BLAS) library, so you can simply replace libcblas.a with libblas.a.
IIRC, an other option is to tweak the HPL config and direct it to use cblas instead of (Fortran) BLAS.

Related

OCaml: Issues linking C and OCaml

I am able to wrap C code and access it from the OCaml interpreter, but cannot build a binary! I'm 98% sure it is some linking problem, but can't find the tools to explore the linkage.
Getting even to this point was a chore, (endless quantities of Error: The external function is not available messages) so I'll document everything I did.
A 'system' file stuff.c
#include <stdio.h>
int fun(int z) // Emulate a "real" subroutine
{
printf("duuude whoa z=%d\n", z);
return 42;
}
Compile above as
cc -fPIC -c stuff.c
ld -shared -o libstuff.so stuff.o
An OCaml wrapper around above, in ocmstuff.c:
#include <caml/mlvalues.h>
CAMLprim value yofun(value z) {
return Val_long(fun(Long_val(z)));
}
Build above as
cc -fPIC -c ocmstuff.c
ld -shared -o dllostuff.so ocmstuff.o -L . -lstuff -lc -rpath .
Yes, the rpath really is needed, else the next steps suffer. (Edit: If you don't use rpath, you'll need to use LD_LIBRARY_PATH=. instead. For the final 'production' version, you'd change the rpath to the actual library path, or do ld.so.conf trickery or install into 'standard' locations, or tell your users about LD_LIBRARY_PATH. This is just like what you'd do for any other system. The rpath solution seems to be the most stable and reliable solution.)
Next, a module declaration, stored in fapi.mli
module Fapi : sig
external ofun : int -> int = "yofun" ;;
end
Build above as:
ocamlc -a -o fapi.cma -intf fapi.mli -dllib -lostuff
Does it work? Yes it does:
$ rlwrap ocaml fapi.cma
OCaml version 4.11.1
open Fapi ;;
Fapi.ofun 33 ;;
duuude whoa z=33
- : int = 42
#
So the wrapper works fine. Now lets compile with it. Here's myprog.ml:
open Fapi ;;
Fapi.ofun 33 ;;
Compile it:
ocamlc -c myprog.ml
ocamlc -o myprog myprog.cmo fapi.cma
The very last command spews:
File "_none_", line 1:
Error: Required module `Fapi' is unavailable
I am 98% sure the above error is due to some silly linking error, but I cannot track it down. Why do I think this? Well, here's a related problem that provides a hint.
$ rlwrap ocaml
open Fapi ;;
# Fapi.ofun 33 ;;
Error: The external function `yofun' is not available
#
Well, that's odd. It clearly must have found fapi.cma because that is the only way it can know about yofun. But somehow, it doesn't know it needs to dig into dllostuff.so for that. Or possibly dllostuff.so is failing to correctly link/load libstuff.so ? Or maybe libc.so to get printf ? I'm pretty sure its one of these last few, but I just can't get it to work, and don't have the tools to debug it. (nm and ldd -r look healthy. Are there some similar tools for the assorted cma,cmo,cmi,cmx files?)
Interfacing with C is much easier if you use dune. You don't need to know the low-level details it is all handled for you.
Now, back to your example. This is definitely not how OCaml users are interfacing with C, but if you really want to learn about it here are a few notes.
The reason why you have the error is that:
you specified modules in an incorrect order, it should be topological, not reverse topological order, i.e., the dependency comes before dependent
you do not have the .ml file (the -intf option means very different)
The reason why the last snippet doesn't work is because you're not loading the library. The ocaml binary obviously doesn't have any fapi units linked into it, so you have to explicitly load it using either #load directive or by passing it in the command line.
Also the following line is not necessary,
ld -shared -o dllostuff.so ocstuff.o -L . -lstuff -lc -rpath .
First of all, there is no need to link a stub file into a shared library. It is counterproductive and doesn't really bring you anything. Second, passing -rpath . will render the end executable unusable, unless the shared objects are stored in the same folder as the executable. Just remove this.
Just to complete your exercise, here is how it could be built and run. First, let's fix the stub file. We need the ml file and we also need to remove an extra module definition,
$ cat fapi.{ml,mli}
external ofun : int -> int = "yofun" ;;
external ofun : int -> int = "yofun" ;;
Yes, they are the same. The mli file is not really needed here, but let's keep it for the sake of completeness.
The way how you build the pure C part is fine, as long as you get a relocatable .so file it works.
Now to build the ocstuff.c (which we conventionally call stubs) you just need to do,
ocamlc -c ocstuff.c
Don't turn it into a shared library, don't do anything else with it. Now let's build the fapi library,
ocamlc -c fapi.mli
ocamlc -c fapi.ml
Now let's build the library that contains both OCaml and C code,
ocamlmklib -o fapi fapi.cmo ocstuff.o -lstuff -L.
Now we can finally build the executable,
ocamlc -c myprog.ml
LD_LIBRARY_PATH=. ocamlc -o myprog fapi.cma myprog.cmo
and run it,
LD_LIBRARY_PATH=. ./myprog
duuude whoa z=33
Notice that we have to use the LD_LIBRARY_PATH to tell the system dynamic loader where to look for the external dependency libstuff.so. You can, of course, use rpath to specify its location (pass it to ocamlmklib via -ccopt) but in general it is assumed that the external library is installed at some location that the system loader knows.
Again, unless you're developing your own build system, please use dune or oasis for building OCaml programs. These systems will handle all low-level details in the best possible way.
P.S. It is also worth mentioning that you're not building a binary, but a bytecode executable. For binaries, you will have to use the ocamlopt compiler. And this would be a completely different story. Again, dune is the solution.
There is a lot to take in here, but these lines are suspicious:
ocamlc -c myprog.ml
ocamlc -o myprog myprog.cmo fapi.cma
OCaml expects modules in topologically sorted order, with a module appearing on the command line before the modules that refer to it.
So it would seem the last line should be this:
ocamlc -o myprog fapi.cma myprog.cmo
I hope this helps, it's just a quick response.
The answer provided by ivg works. It also provides enough hints to retrofit the original question to get the correct behavior. The changes to the original recipe are:
Create fapi.mli and fapi.ml which both have the same content: external ofun : int -> int = "yofun" ;;
Compile both the above with ocaml -c. The mli must be compiled first: it yields an interface file cmi which is needed before the ml file can be compiled into it's object file cmo.
The name dllostuff.so was wrong: it must be dllfapi.so to maintain naming consistency.
Build the cma archive/library as ocamlc -a -o fapi.cma fapi.cmo -dllib -lfapi
That's it! Other than these, the original instructions work. The answer from ivg suggests using
ocamlmklib -o fapi fapi.cmo ostuff.o -L. -lstuff
instead of
ld -shared -o dllfapi.so ostuff.o -L. -lstuff
Either of these work. The primary difference is that ocamlmklib also creates a static-linked library libfapi.a. Other than that, it creates the dllfapi.so as before. (That version also contains a motley assortment of typical gcc symbols, for handling exceptions, library ctors, etc. It's not clear why these are needed here, since they'll show up sooner or later anyway.)

dietlibc, lowfat, opentracker - compiling against alternative libc

I'm attempting to build opentracker. My system has the following:
| package | library | headers |
| lowfat | /usr/lib/libowfat.a | /usr/include/libowfat |
| dietlibc | /opt/diet/lib-x86_64/*.a | /usr/diet/include |
| glibc | /usr/lib/*.{a,so} | /usr/include |
Looking at the Makefile for opentracker, I see (essentially) the following:
PREFIX?=..
LIBOWFAT_HEADERS=$(PREFIX)/libowfat
LIBOWFAT_LIBRARY=$(PREFIX)/libowfat
CFLAGS+=-I$(LIBOWFAT_HEADERS) -Wall -pipe -Wextra
LDFLAGS+=-L$(LIBOWFAT_LIBRARY) -lowfat -pthread -lpthread -lz
opentrackers: $(OBJECTS) $(HEADERS)
cc -o $# $(OBJECTS) $(LDFLAGS)
I've not compiled against an alternative libc before, so I'm including this information in case I've done this part wrong. When I invoke make, I need to point it at where my system has dietlibc and lowfat live. I'm doing it like this:
$ LDFLAGS=-L/opt/diet/lib-x86_64 make PREFIX=/opt/diet LIBOWFAT_HEADERS=/usr/include/libowfat LIBOWFAT_LIBRARY=/usr/lib
...
...
cc -o opentracker opentracker.o trackerlogic.o scan_urlencoded_query.o ot_mutex.o ot_stats.o ot_vector.o ot_clean.o ot_udp.o ot_iovec.o ot_fullscrape.o ot_accesslist.o ot_http.o ot_livesync.o ot_rijndael.o -L/opt/diet/lib-x86_64 -L/usr/lib -lowfat -pthread -lpthread -lz
/usr/bin/ld: /usr/lib/libowfat.a(io_fd.o):(.bss+0xb0): multiple definition of `first_deferred'; /usr/lib/libowfat.a(io_close.o):(.data+0x0): first defined here
...
... lots of warnings ...
/usr/bin/ld: opentracker.o: undefined reference to symbol '__ctype_b_loc##GLIBC_2.3'
/usr/bin/ld: /usr/lib/libc.so.6: error adding symbols: DSO missing from command line
Looks like there's two issues going on in there.
Multiple definitions of first_deferred
I see references to first_deferred in both io_close and io_fd, but they are in different sections.
$ objdump -t /usr/lib/libowfat.a | egrep '^[^:]+.o:|first_deferred' | grep -B1 first_deferred
io_close.o: file format elf64-x86-64
0000000000000000 g O .data 0000000000000008 first_deferred
--
io_fd.o: file format elf64-x86-64
00000000000000b0 g O .bss 0000000000000008 first_deferred
--
io_waituntil2.o: file format elf64-x86-64
0000000000000000 *UND* 0000000000000000 first_deferred
In io/io_fd.c, there's an #include io_internal.h and in that header there's an extern long first_deferred;. In io/io_close.c it's defined as long first_deferred=-1. So it doesn't look like it's double defined in the libowfat code itself. Did I compile lowfat wrong?
DSO missing from command line / symbol '__ctype_b_loc##GLIBC_2.3'
Since the Makefile is trying to compile against dietlibc, I'm a bit surprised that there's a reference to glibc (but, to be honest, also not surprised at all).
Here's the recipe for opentracker.o:
cc -c -o opentracker.o -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -I/usr/include/libowfat -Wall -pipe -Wextra -O3 -DWANT_FULLSCRAPE opentracker.c
This doesn't appear to have the -L/opt/diet/lib-x86_64 argument from LDFLAGS that is used for the main executable. Should it? I don't think so as that's a linker argument so it would not make sense to add it to the compile command. I don't see any references to glibc in the object file:
$ objdump -t ./src/opentracker/opentracker.o | grep -c 'glib'
0
DSO missing from command line / symbol '__ctype_b_loc##GLIBC_2.3'
I found two permutations to solve this issue. Option one is to make sure the very first -L argument is the location of dietlibc's lib directory, so that all symbols are resolved from there first.
The other permutation was to invoke make via the /opt/diet/bin/diet wrapper program. From the dietlibc FAQ
Q: How do I install it? make install?
A: Yep. It will then install itself to /opt/diet, with the wrapper in
/opt/diet/bin/diet. Or you don't install it at all.
The diet libc comes with a wrapper called "diet", which can be found
in bin-$(ARCH)/diet, i.e. bin-i386/diet for most of us. Copy this
wrapper somewhere in your path (for example ~/bin) and then just
compile stuff by prepending diet to the command line, e.g. "diet gcc
-pipe -g -o t t.c".
Q: How do I compile programs using autoconf with the diet libc?
A: Set CC in the environment properly. For Bourne Shells:
$ CC="diet gcc -nostdinc" ./configure --disable-nls
That should be enough, but you might also want to set
--disable-shared and --enable-static for packages using libtool.
It's not explained anywhere on the website, as far as I can tell, what the wrapper program does. The code is annoying to read due to all the architecture specific #ifdefs, but the file comment indicates it just modifies the gcc command line in an architecture specific way. A quick scan suggests relevant args modifications include: -I/opt/diet/include when compiling, -nostdlib when linking, and possibly -Os.
Multiple definitions of first_deferred
I'm not happy with my workaround here. The symbol is defined in io_internal.h:
#ifndef my_extern
#define my_extern extern
#endif
my_extern long first_deferred;
Why is there a funny redefinition of the extern keyword? Read on. The initialization of this variable is in io_close.c:
#include "io_internal.h"
long first_deferred=-1;
And here's the interesting bit. In io_fd.c:
#define my_extern
#include "io_internal.h"
#undef my_extern
Why? Who knows. The author believes they are clever I guess and saved themselves some keystrokes? The effect of this is that my_extern is defined as an empty string, so when my_extern long first_deferred; is transcluded from the header, it appears as long first_deferred;. This is what leads there to be two locations for the symbol in the archive, as there are two files that reserve space for that symbol.
I'm not happy with my "solution", which was to remove the static initialization from io_close.c. Technically, that means the variable starts with random heap memory. A quick look at how it gets used suggests this is maybe not safe, but is probably safe enough. The variable is used as an index into an array. Thankfully iarray_get does a bounds check, so it's very likely that if(e) will be false and the variable will get set to -1 as it should be.
if (first_deferred!=-1) {
while (first_deferred!=-1) {
io_entry* e=iarray_get(&io_fds,first_deferred);
if (e) {
if (e->closed) {
e->closed=0;
close(first_deferred);
}
first_deferred=e->next_defer;
} else
first_deferred=-1; // can't happen
}
}
I can't provide a good explanation for those errors, but your post helped me to get it to compile so I figured I'd mention what I did.
The "first_deferred" error seems to come from using a newer version of libowfat, I got past that by using 0.31 instead.
I didn't come across the second error, but I was getting "__you_tried_to_link_a_dietlibc_object_against_glibc" errors which I got past by uninstalling dietlibc and compiling libowfat with glibc instead.
I compiled them the same way as the AUR packages:
https://aur.archlinux.org/packages/opentracker/
https://aur.archlinux.org/packages/libowfat/
Although, instead of installing libowfat, I just put it in the src directory and skipped fetching libowfat from CVS.

Can IAR produce a static library that GCC can link to?

There is a vendor whose software I'd like to work with. They have a code base which they can only compile using IAR Embedded Workbench (as far as I know, their code does not compile with GCC). Unfortunately their hardware only works with their software stack, so I don't really have a choice about whether or not I'd like to use it. They distribute this code as a .a static library file (and accompanying headers) compiled for the ARM Cortex-M4 CPU. (They don't want to distribute sources.) For the sake of this discussion, let's call it evil_sw_stack.a.
I'd like to use this piece of code but I don't have an IAR license and have zero expertise with IAR. I'd like to use GCC.
Is there a way to make IAR produce such a static library that GCC can link to? What kind of compiler option would the vendor need to use to produce such a binary?
(I would guess that the ABI of the resulting binary can be somehow specified and set to a setting which statisfies GCC. )
Example usage of GCC
Their default software stack is very GCC-friendly, this specific one is the only one in their offering which isn't. Generally, I can compile a simple piece of example code if I have the following:
startup_(devicename).S: GCC-specific assembly file
system_(devicename).c
(devicename).ld: linker script
Some header files for the specific device
For example, I can compile a simple piece of example like this:
$ arm-none-eabi-gcc helloworld.c startup_(devicename).S system_(devicename).c -T (devicename).ld -o helloworld -D(devicename) -I. -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mcpu=cortex-m4 -mthumb -mno-sched-prolog -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
So far, so good. No warnings, no errors.
How I try to use the static library
For the sake of this discussion, let's call it evil_sw_stack.a.
This is how I attempted to use it:
$ arm-none-eabi-gcc evil_sw_stack.a helloworld.c startup_(devicename).S system_(devicename).c -T (devicename).ld -o helloworld -D(devicename) -I. -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mcpu=cortex-m4 -mthumb -mno-sched-prolog -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
Unfortunately this complains about multiple definitions of a bunch of functions that are defined in system_(devicename).c. Maybe they accidentally compiled that into this library? Or maybe IAR just compiled it this way? Now, if I try to remove system_(devicename).c from the GCC command line and simply link to the .a file, I get these errors:
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: thelibrary.a(startup_chipname.o) uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
undefined reference to `__iar_program_start'
undefined reference to `CSTACK$$Limit'
undefined reference to `__iar_program_start'
Poking the file with readelf gets me nowhere:
$ readelf -h evil_sw_stack.a
readelf: Error: evil_sw_stack.a: did not find a valid archive header
Interestingly though, this seems to be getting somewhere:
$ arm-none-eabi-ar x evil_sw_stack.a
Now I've got a bunch of object files which do have ELF headers according to readelf, and yup, they did compile a startup file (of another of their devices) into the library... I'm wondering why, but I think this is a mistake.
This also works:
$ arm-none-eabi-objdump -t evil_sw_stack_objfile.o
So now the question is, is it safe to try to compile these object files into my own application using GCC? According to this other SO question, the object file formats are not compatible.
I assume that the startup code is mistakenly compiled into the library. I can delete it:
$ arm-none-eabi-ar d evil_sw_stack.a startup_(otherdevicename).o
$ arm-none-eabi-ar d evil_sw_stack.a system_(otherdevicename).o
Now I get an evil_sw_stack.a which gcc can accept as an input without complaining.
However, there is one thing that still worries me. When I use the object files instead of the static library, I get these warnings:
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: evil_objfile.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: evil_objfile.o uses 32-bit enums yet the output is to use variable-size enums; use of enum values across objects may fail
So it seems that evil_sw_stack.a was compiled with (the IAR equivalents of) -fno-short-enums and -fshort-wchar. GCC doesn't complain about this when I use evil_sw_stack.a at its command line but it does complain when I try to use any object file that I extracted from the library. Should I worry about this?
I don't use wchar_t in my code so I believe that one doesn't matter, but I would like to pass enums between my code and the library.
Update
Even though the linker doesn't complain, it doesn't work when I actually call some functions from the static library. In that case, make sure to put the libraries in the correct order when you call the linker. According to the accepted answer to this question, they need to be in reverse order of dependency. After doing this, it still misses some IAR crap:
undefined reference to `__aeabi_memclr4'
undefined reference to `__aeabi_memclr'
undefined reference to `__aeabi_memmove'
undefined reference to `__aeabi_memset4'
undefined reference to `__aeabi_memset'
undefined reference to `__iar_vla_alloc2'
undefined reference to `__iar_vla_dealloc2'
undefined reference to `__aeabi_memclr4'
I've found out that the __aeabi functions are defined in libgcc but even though I link to libgcc too, the definition in libgcc doesn't seem to be good enough for the function inside evil_sw_stack.a.
EDIT: after some googling around, it seems that arm-none-eabi-gcc doesn't support these specific __aeabi functions. Take a look at this issue.
Anyway, after taking a look at ARM's runtime ABI docs, the missing __aeabi functions can be trivially implemented using their standard C library equivalents. But I'm not quite sure how __iar_vla_alloc2 and __iar_vla_dealloc2 should work and couldn't find any documentation on them online. The only thing I found out is that VLA means "variable length array".
So, it seems that this will never work unless the chip vendor can compile their static library in such a way that it doesn't use these symbols. Is that right?
Disclaimer
I'd prefer not to disclose who the vendor is and not to disclose which product I work with. They are not proud that this thing doesn't work properly and asked me not to. I'm asking this question to help and not to discredit them.

gcc static library compilation

i have made a static library using the ar command after an object creation using gcc -o file.o -c file.c.
Now i'm trying to use the gcc to link this library in the compilation with a command similar to this
gcc -I /PathInclude -L /PathStaticLib -lm \
-std=c99 -o file file.o -lstatic_library_name
with static_library_name i mean that the file is named
libstatic_library_name.a
Since the files structure is quite complex (because basically in the compiling i also substitute some macro definition etc) i don't post all the code, do you have any thought on what is going on? if not what kind of info could i provide to you in order to help me?
PS. there aren't a lot o files, but the internal structure is a bit complicated to explain in few words, so... let me know what do you need.
I can give you the make file content if you need, is not complicated.
PS. The command is...
gcc -I../CModels -L../CModels/ -std=c99 -o ref_approx_bs3_log2_4_4_1ulp_arch1
ref_approx_bs3_log2_4_4_1ulp_arch1.o -lm -lmy_float
The error is
ref_approx_bs3_log2_4_4_1ulp_arch1.o: In function `cogen_fp_bs3_log2_4_4_1ulp_arch1':
ref_approx_log2.c:(.text+0x2229): undefined reference to `cast'
ref_approx_log2.c:(.text+0x22d0): undefined reference to `cast'
ref_approx_log2.c:(.text+0x22f7): undefined reference to `cast'
ref_approx_log2.c:(.text+0x232e): undefined reference to `sumFP'
ref_approx_log2.c:(.text+0x2350): undefined reference to `diffFP'
ref_approx_log2.c:(.text+0x2375): undefined reference to `mulFP'
ref_approx_log2.c:(.text+0x239c): undefined reference to `sumFP'
collect2: ld returned 1 exit status
Using
nm my_float.a
the output is
my_float.o:
0000000000000ca8 T _Z11castToFixedyPyyyy
0000000000000a0c T _Z12splitIntFracyPyS_yy
0000000000000324 T _Z28rightShift_and_round2NearestyyPyyy
000000000000005c T _Z3ldzy
0000000000000132 T _Z3mulyyy
000000000000048a T _Z4castyPyyyyy
0000000000000000 T _Z4maxuyy
000000000000002e T _Z4minuyy
00000000000014dc T _Z5mulFPyyPyyy
0000000000000cc2 T _Z5sumFPyyPyyy
000000000000147a T _Z6diffFPyyPyyy
0000000000000300 T _Z9ldzFormatyy
U __gxx_personality_v0
So i guess the library .a is ok...
As per the gcc manual, AFAIR, there should be no space in between -L or -I and the path. Change your command to
.. -I/PathInclude -L/PathStaticLib ...
Error says that the references to cast, sumFP, diffFP , mulFP are not defined. Need to make sure that they are defined in the library.

Undefined Symbol _memset although _memset nowhere used? [duplicate]

I asked a similar question, but I have some update which is really confusing me. Essentially, I want to link a number of object files with the linker as follows:
/usr/ccs/bin/ld -o q -e start_master -dn -z defs -M ../../../mapfile.q {list of object files}
I get the following error:
Undefined first referenced
symbol in file
_memset reconf.o
The interesting things is, that memset is not referenced in reconf.c and I also grep'ed the whole directory but there is also no reference in any of the other files to _memset. Therefore I am wondering why I get this error message from the linker, although nowhere in my source code _memset is actually used. Anyone an idea what could be going on here?
Thanks so much, this error is driving us mental!
EDIT:
I tried to add the path to the library of memset and linked it with -lc and run it in verbose mode:
/usr/ccs/bin/ld -o q -e start_master -dn -z defs -z verbose -L/usr/lib -M ../../../mapfile.q {list of object files} -lc
Then I get the following error:
ld: fatal: library -lc: not found
ld: fatal: File processing errors. No output written to q
And this although libc.so is clearly in /usr/lib ...
Confusing
EDIT II:
Doing some more research it seems that on Solaris 10 static linking disappeard as you can read here:
http://blogs.oracle.com/rie/entry/static_linking_where_did_it
Probably this is my problem. Has anyone an idea how I could rewrite my linker command for a workaround to this problem?
Many thanks!
Probably you did:
struct S v = { 0 };
or
struct S v;
v = (some const-variable).
or
uint8_t b[100] = { 0 };
.
Some compilers are putting implicitly the built-in memset (or memcpy) for such things. The built-in memset then is called _memset (in your case). Once you link and your libc (or what provides standard-function in your case) does not providie it, you are getting this link error.
Assuming you're on Solaris, you'll find memset in the libc.so library :
/usr/lib-> nm libc.so | grep memset
[7122] | 201876| 104|FUNC |GLOB |0 |9 |_memset
Simply add -lc to the command line
Memset is a library function from standard C library. If you don't use gcc for linking (which links your files with standard libraries by default) you should explicitly link your progrom with libc.
On the other option, probably you don't use libc. In this case memset call could be generated by gcc.
From man gcc:
-nodefaultlibs
Do not use the standard system libraries when linking. Only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The standard startup files are used normally, unless -nostartfiles is used. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
In this case simply write memset (it's trivial proc.) and supply it to linker.

Resources