I get these error messages compiling a program to use my library that
was separately compiled and linked on the same machine:

================================================== ===========================
phil@tanith:/home/phil 42$ gcc -O2 -o electric electric.c -lm -lh
/usr/bin/ld: electric: hidden symbol `__fixunsxfdi' in /usr/lib/gcc/i386-redhat-linux/4.1.1/libgcc.a(_fixunsxfdi.o) is referenced by DSO
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status
phil@tanith:/home/phil 43$
================================================== ===========================

I found that gcc was compiling in a reference to symbol __fixunsxfdi in
just one file of my large library. That file does involve converting
type long double to type uint64_t, so I'm not surprised that gcc would
make some kind of function call to handle it. But why would there be
something weird about this function that makes ld not be able to handle
it?

Here is the C code of the function in the library:

================================================== ===========================
{
long double ld_etime ;

ld_etime = (long double) arg_jd * 86400000000.0L + 43200000000.5L;
return ld_etime > (long double) ETIME_MAX ? ETIME_MAX
: ld_etime < (long double) ETIME_MIN ? ETIME_MIN
: (etime_t) ld_etime;
}
================================================== ===========================

The type (etime_t) is defined in a header file as follows:

================================================== ===========================
typedef uint64_t etime_t ;
================================================== ===========================

and the value symbols are defined like:

================================================== ===========================
#define ETIME_MIN (UINT64_C(0))
#define ETIME_MAX (INT64_MAX)
================================================== ===========================

The variable arg_jd is defined in the function prototype as:

================================================== ===========================
JD arg_jd
================================================== ===========================

And JD is defined to be a double with this in the header file:

================================================== ===========================
typedef double JD ;
================================================== ===========================

So basically the function takes a double argument, casts it to long double,
multiplies it by one long double constant and adds another long double
constant. That result is then compared to the range as defined by the
symbols in a ?: expression that yields the bounds constants in their
original types, or that calculated value cast to etime_t.

So would that validly result in a reference to __fixunsxfdi ?
And if so, why would that be a reference that cannot be linked by ld?

Note that the program being compiled to link against this library built
as a shared library does not call the function that seems to be causing
this strange reference. If the program is linked with the library's .a
file included on the command line instead of -lh then everything links
just fine and the program runs. Apparently the linker just does not like
something about __fixunsxfdi when it is referenced in my library.

The system this is being compiled on with problems is:
Fedora Core 8
gcc (GCC) 4.1.1 20061011 (Red Hat 4.1.1-30)
GNU ld version 2.17.50.0.3-6 20060715
GNU C Library stable release version 2.5, by Roland McGrath et al.

It works fine without these problems on various other systems such as
Slackware-9.0, Slackware-10.2, Slackwre-11.0, all of which have older
versions of these tools. It also works on an older Debian machine and
an older OpenBSD machine.

Is gcc broken? Or ld? Or glibc? Or FC?

--
|---------------------------------------/----------------------------------|
| Phil Howard KA9WGN (ka9wgn.ham.org) / Do not send to the address below |
| first name lower case at ipal.net / spamtrap-2006-12-28-1527@ipal.net |
|------------------------------------/-------------------------------------|