diff options
authorRich Felker <>2011-02-24 16:37:21 -0500
committerRich Felker <>2011-02-24 16:37:21 -0500
commit41d518360fd2da0f19d6a2f8d8c5f226b201c1e9 (patch)
parent73d310e1d2b76cd14b9913bbc3d8e75be91be5a6 (diff)
various changes in preparation for dynamic linking support
prefer using visibility=hidden for __libc internal data, rather than an accessor function, if the compiler has visibility. optimize with -O3 for PIC targets (shared library). without heavy inlining, reloading the GOT register in small functions kills performance. 20-30% size increase for a single is not a big deal, compared to comparaible size increase in every static binaries. use -Bsymbolic-functions, not -Bsymbolic. global variables are subject to COPY relocations, and thus binding their addresses in the library at link time will cause library functions to read the wrong (original) copies instead of the copies made in the main program's bss section. add entry point, _start, for dynamic linker.
4 files changed, 24 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index a47439b8..5c176423 100644
--- a/Makefile
+++ b/Makefile
@@ -21,16 +21,16 @@ LOBJS = $(OBJS:.o=.lo)
GENH = include/bits/alltypes.h
CFLAGS = -Os -nostdinc -ffreestanding -std=c99 -D_XOPEN_SOURCE=700 -pipe
-LDFLAGS = -nostdlib -shared -Wl,-Bsymbolic
+LDFLAGS = -nostdlib -shared -fPIC -Wl,-e,_start -Wl,-Bsymbolic-functions
INC = -I./include -I./src/internal -I./arch/$(ARCH)
-PIC = -fPIC
+PIC = -fPIC -O3
ALL_INCLUDES = $(sort $(wildcard include/*.h include/*/*.h) $(GENH))
-EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv
+EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
CRT_LIBS = lib/crt1.o lib/crti.o lib/crtn.o
LIBC_LIBS = lib/libc.a
diff --git a/src/internal/libc.c b/src/internal/libc.c
index 954efedf..5f12e295 100644
--- a/src/internal/libc.c
+++ b/src/internal/libc.c
@@ -1,6 +1,6 @@
#include "libc.h"
-#ifdef __PIC__
struct __libc *__libc_loc()
static struct __libc __libc;
diff --git a/src/internal/libc.h b/src/internal/libc.h
index 8a84be0b..e81ef760 100644
--- a/src/internal/libc.h
+++ b/src/internal/libc.h
@@ -17,12 +17,20 @@ struct __libc {
void (*fork_handler)(int);
-#ifdef __PIC__
-extern struct __libc *__libc_loc(void) __attribute__((const));
-#define libc (*__libc_loc())
+#if 100*__GNUC__+__GNUC_MINOR__ >= 303 || defined(__PCC__) || defined(__TINYC__)
+extern struct __libc __libc __attribute__((visibility("hidden")));
+#define libc __libc
+#elif !defined(__PIC__)
extern struct __libc __libc;
#define libc __libc
+extern struct __libc *__libc_loc(void) __attribute__((const));
+#define libc (*__libc_loc())
diff --git a/src/ldso/start.c b/src/ldso/start.c
new file mode 100644
index 00000000..f6ae7cd2
--- /dev/null
+++ b/src/ldso/start.c
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+/* stub for archs that lack dynamic linker support */
+void _start()
+ _Exit(1);