Statically Linking System Libraries, Libc, Pthreads, to Aid in Debugging

Statically linking system libraries, libc, pthreads, to aid in debugging


If I compile all the libraries statically will I avoid having to always gather the shared libraries when it core dumps

Yes.

However, contrary to popular belief, statically linked binaries are less portable than dynamically linked ones (at least on Linux).

In particular, if you use any of these functions: gethostbyname, gethostbyaddr, getpwent, getpwnam, getpwuid (and a whole lot more), you will get a warning at link time, similar to this:

Using 'getpwuid' in statically linked applications requires at runtime
the shared libraries from the glibc version used for linking.

What this warning means is that IF your customer has a different version of glibc installed from the one you used at link time (i.e. different from your system libc), THEN your program will likely crash. Since that is a clearly worse situation than your current one, I don't believe static linking is a good solution for you.

is pthread in glibc.so implemented by weak symbol to provide pthread stub functions?

Yes, glibc uses a stub implementation of various pthread functions, so that single threaded programs do not have to waste cycles doing things like locking and unlocking mutexes, and yet do not have to link to a different C library (like what is done in the Microsoft world, for instance).

For instance, according to POSIX, every time you call fputc(ch, stream), there is mutex lock and unlock. If you don't want that, you call fputc_unlocked. But when you do that, you're using a POSIX extension related to threading; it's not an appropriate workaround for programs that don't use POSIX or don't use the threading API.

The overriding of the stub pthread functions with the real ones (in the dynamic glibc) is not based on weak symbols. The shared library mechanism makes it possible to override non-weak definitions.

Weak symbols are a mechanism which allows for symbol overriding under static linking.

If you want a source for the above statement, here it is:

"Note that a definition in a DSO being weak has no effects. Weak definitions only play a role in static linking." [Ulrich Drepper, "How To Write Shared Libraries"].

If you run nm on the static glibc on your system (if you have one), libc.a, you will note that functions like pthread_mutex_lock are marked weak. In the dynamic version, libc.so.<whatetever>, the functions are not marked weak.

Note: you should use nm -D or nm --dynamic to look at the symbols in a shared library. nm will not produce anything on a shared library that is stripped. If it does, you're looking at the debug symbols, not the dynamic symbols.

Keeping the structure of a shared libraries plug-in system when compiling statically and linking

I do such things through those pesky static objects that call register in ctor.

The ordering problem is dodged by making the map itself a local static, so getting constructed on the first client call, wherever it comes from. (Threading and similar issues are dodged by restricting thread launch to until-main time, and by that time all important things are forced.)


class RegMap;  // the registry
RegMap& GetRegistry(); // the singleton access function; you can make a separate const/nonconst version or provide another wrapper for registering

// implementation in core.cpp:
RegMap& GetRegistry()
{
static RegMap m;
return m;
}

//in client ctor:
GetRegistry().Register( key, func);

Creating and linking static rust library and link to c

On Linux, std dynamically links to pthreads and libdl. You need to link these in as well to create the executable:

gcc main.o libCustomlib.a -lpthread -ldl

The result is a binary that links dynamically to a handful of fundamental libraries, but statically to Customlib.

If you want a purely statically linked binary, you will probably need to use no_std and enable only the specific features of core that do not depend on dynamically linked system libraries. (Certain libraries cannot be statically linked on Linux; read Statically linking system libraries, libc, pthreads, to aid in debugging) Just for a toy program like hello, world you may get away with simply passing -static to gcc, but for anything robust it's better to dynamically link these fundamental libraries.

g++ issues with shared libraries and libpthread.so


${compiler} ${arch} -static -g -o main.out ./main.o -lpthread -ldl -lc

This is a fully-static link.

On most OSes, no calls to dlopen can be made from a fully-static binary (dlopen is simply not provided in libdl.a, and the link fails).

GLIBC is an exception, but only so far as dlopen is needed to support /etc/nsswitch.conf. Almost certainly dynamic loading of libpthread.so.0 into a fully-static a.out that contains its own copy of libpthread.a is not supported. The short answer is: it hurts, don't do that.

Fully-static linking is in general a very bad idea on any modern UNIX system. Fully-static linking of multithreaded apps doubly so. Fully-static linking that then dynamically loads another copy of libpthread? Really bad idea.

Update:

GLIBC consists of many libraries (200+), and I would strongly advise against mixing static and dynamic linking for any such library. In other words, if you link against libc.a, then make it a completely static link. If you link against libc.so, then don't statically link libpthread.a, libdl.a, or any other part of GLIBC.

How to build a C program using a custom version of glibc and static linking?

Following a couple of suggestions from the glibc help mailing list (libc-help@sourceware.org), I have a solution. It turns out that this task is a bit tricky because you have to tell the linker to omit everything it would normally include automatically (and silently), and then include back everything that it needs, including a bunch of start and end files. Some of the start and end files come from libc and some come from gcc, so the make rule is a bit complicated. Below is a general sample makefile to illustrate the approach. I will assume that you are building a program called prog from a source file called prog.c and that you have installed your custom glibc in directory /home/my_acct/glibc_install.

TARGET = prog
OBJ = $(TARGET).o
SRC = $(TARGET).c
CC = gcc
CFLAGS = -g
LDFLAGS = -nostdlib -nostartfiles -static
GLIBCDIR = /home/my_acct/glibc_install/lib
STARTFILES = $(GLIBCDIR)/crt1.o $(GLIBCDIR)/crti.o `gcc --print-file-name=crtbegin.o`
ENDFILES = `gcc --print-file-name=crtend.o` $(GLIBCDIR)/crtn.o
LIBGROUP = -Wl,--start-group $(GLIBCDIR)/libc.a -lgcc -lgcc_eh -Wl,--end-group

$(TARGET): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $(STARTFILES) $^ $(LIBGROUP) $(ENDFILES)

$(OBJ): $(SRC)
$(CC) $(CFLAGS) -c $^

clean:
rm -f *.o *.~ $(TARGET)


Related Topics



Leave a reply



Submit