summaryrefslogtreecommitdiff
path: root/extra/gcc-uClibc
diff options
context:
space:
mode:
Diffstat (limited to 'extra/gcc-uClibc')
-rw-r--r--extra/gcc-uClibc/gcc-uClibc.c107
1 files changed, 101 insertions, 6 deletions
diff --git a/extra/gcc-uClibc/gcc-uClibc.c b/extra/gcc-uClibc/gcc-uClibc.c
index 201f0ac20..7b48ef8dd 100644
--- a/extra/gcc-uClibc/gcc-uClibc.c
+++ b/extra/gcc-uClibc/gcc-uClibc.c
@@ -75,6 +75,8 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include "gcc-uClibc.h"
@@ -105,6 +107,41 @@ char *basename(const char *path)
return (char *) p;
}
+char *dirname(char *path)
+{
+ static const char null_or_empty_or_noslash[] = ".";
+ register char *s;
+ register char *last;
+ char *first;
+
+ last = s = path;
+
+ if (s != NULL) {
+
+ LOOP:
+ while (*s && (*s != '/')) ++s;
+ first = s;
+ while (*s == '/') ++s;
+ if (*s) {
+ last = first;
+ goto LOOP;
+ }
+
+ if (last == path) {
+ if (*last != '/') {
+ goto DOT;
+ }
+ if ((*++last == '/') && (last[1] == 0)) {
+ ++last;
+ }
+ }
+ *last = 0;
+ return path;
+ }
+ DOT:
+ return (char *) null_or_empty_or_noslash;
+}
+
extern void *xmalloc(size_t size)
{
@@ -156,6 +193,8 @@ int main(int argc, char **argv)
char *uClibc_inc[2];
char *our_lib_path[2];
char *crt0_path[2];
+ char *crtbegin_path[2];
+ char *crtend_path[2];
const char *application_name;
#ifdef __UCLIBC_CTOR_DTOR__
char *crti_path[2];
@@ -387,6 +426,61 @@ int main(int argc, char **argv)
i = 0; k = 0;
#ifdef __UCLIBC_CTOR_DTOR__
+ if (ctor_dtor) {
+ struct stat statbuf;
+ if (stat(LIBGCC_DIR, &statbuf)!=0 ||
+ !S_ISDIR(statbuf.st_mode))
+ {
+ /* Bummer, gcc has moved things on us... */
+ int status, gcc_pipe[2];
+ pid_t pid, wpid;
+
+ pipe(gcc_pipe);
+ if (!(pid = fork())) {
+ char *argv[4];
+ close(gcc_pipe[0]);
+ close(1);
+ close(2);
+ dup2(gcc_pipe[1], 1);
+ dup2(gcc_pipe[1], 2);
+ argv[0] = GCC_BIN;
+ argv[2] = "-print-libgcc-file-name";
+ argv[3] = NULL;
+ execvp(argv[0], argv);
+ close(gcc_pipe[1]);
+ _exit(-1);
+ }
+ wpid=0;
+ while (wpid != pid) {
+ wpid = wait(&status);
+ }
+ close(gcc_pipe[1]);
+ if (WIFEXITED(status)) {
+ char buf[1024], *dir;
+ status = read(gcc_pipe[0], buf, sizeof(buf));
+ if (status < 0) {
+ goto crash_n_burn;
+ }
+ dir = dirname(buf);
+ xstrcat(&(crtbegin_path[0]), dir, "crtbegin.o", NULL);
+ xstrcat(&(crtbegin_path[1]), dir, "crtbeginS.o", NULL);
+ xstrcat(&(crtend_path[0]), dir, "crtend.o", NULL);
+ xstrcat(&(crtend_path[1]), dir, "crtendS.o", NULL);
+ } else {
+crash_n_burn:
+ fprintf(stderr, "Unable to locale crtbegin.o provided by gcc");
+ exit(EXIT_FAILURE);
+ }
+ close(gcc_pipe[0]);
+
+ } else {
+ xstrcat(&(crtbegin_path[0]), LIBGCC_DIR, "crtbegin.o", NULL);
+ xstrcat(&(crtbegin_path[1]), LIBGCC_DIR, "crtbeginS.o", NULL);
+ xstrcat(&(crtend_path[0]), LIBGCC_DIR, "crtend.o", NULL);
+ xstrcat(&(crtend_path[1]), LIBGCC_DIR, "crtendS.o", NULL);
+ }
+ }
+
if (cplusplus && GPLUSPLUS_BIN)
gcc_argv[i++] = GPLUSPLUS_BIN;
else
@@ -466,9 +560,9 @@ int main(int argc, char **argv)
if (ctor_dtor) {
gcc_argv[i++] = crti_path[use_build_dir];
if (use_pic) {
- gcc_argv[i++] = LIBGCC_DIR "crtbeginS.o" ;
+ gcc_argv[i++] = crtbegin_path[1];
} else {
- gcc_argv[i++] = LIBGCC_DIR "crtbegin.o" ;
+ gcc_argv[i++] = crtbegin_path[0];
}
}
#endif
@@ -503,11 +597,12 @@ int main(int argc, char **argv)
}
#ifdef __UCLIBC_CTOR_DTOR__
if (ctor_dtor) {
- if (use_pic) {
- gcc_argv[i++] = LIBGCC_DIR "crtendS.o" ;
+ if (use_pic) {
+ gcc_argv[i++] = crtend_path[1];
} else {
- gcc_argv[i++] = LIBGCC_DIR "crtend.o" ;
- }
+ gcc_argv[i++] = crtend_path[0];
+ }
+
gcc_argv[i++] = crtn_path[use_build_dir];
}
#endif