OK, the dirty deed is finally done. AIX needs a coupl'a patches to
make it work. The stuff attached is relative to scsh-0.2, but should
also work for vanilla Scheme48. I'm sending the scsh-specific AIX
code in a separate message, just to scsh.
The one thing I'm not sure how to do properly is how to teach autoconf
to generate a special command for linking the VM. It looks like this
for gcc:
$(VM): main.o $(OBJS)
rm -f exportlist.aix; \
for f in $(OBJS); do \
/usr/ccs/bin/nm -e $$f | grep '^\..*|extern|' | sed -e
's/^\.//;s/|//' \
| awk '{print $$1}' >> exportlist.aix; \
done; \
$(CC) $(LDFLAGS) -Xlinker -bexport:exportlist.aix -o $@ main.o $(OBJS)
$(LIBS)
... for cc, the "-Xlinker" needs to be omitted. Great, isn't it? :-}
I'm sure you developers know a proper way to do this.
The patches for configure.in and sysdep.h.in are probably off by a few
lines; I've hacked some other stuff which is not used anymore.
I'm really sorry this is so ugly.
Cheers =8-} Chipsy
*** configure.in.orig Wed Nov 16 04:40:34 1994
--- configure.in Thu Dec 1 16:14:16 1994
***************
*** 53,58 ****
--- 63,69 ----
AC_HAVE_LIBRARY(m, [LIBS="$LIBS -lm"])
AC_HAVE_LIBRARY(dl, [LIBS="$LIBS -ldl"])
AC_HAVE_LIBRARY(mld, [LIBS="$LIBS -lmld"])
+ AC_HAVE_LIBRARY(ld, [LIBS="$LIBS -lld"])
AC_HAVE_LIBRARY(nsl, [LIBS="$LIBS -lnsl"])
AC_HAVE_LIBRARY(gen, [LIBS="$LIBS -lgen"])
AC_HAVE_LIBRARY(socket, [LIBS="$LIBS -lsocket"])
***************
*** 61,67 ****
S48_POSIX_LIBC
AC_CONST
AC_RETSIGTYPE
! AC_HAVE_HEADERS(libgen.h sys/timeb.h posix/time.h)
AC_HAVE_FUNCS(dlopen gettimeofday ftime nlist select setitimer sigaction)
AC_HAVE_FUNCS(socket chroot)
AC_COMPILE_CHECK([n_name], [#include <nlist.h>],
--- 72,78 ----
S48_POSIX_LIBC
AC_CONST
AC_RETSIGTYPE
! AC_HAVE_HEADERS(libgen.h sys/timeb.h posix/time.h sys/select.h)
AC_HAVE_FUNCS(dlopen gettimeofday ftime nlist select setitimer sigaction)
AC_HAVE_FUNCS(socket chroot)
AC_COMPILE_CHECK([n_name], [#include <nlist.h>],
*** sysdep.h.in.orig Wed Nov 16 04:10:46 1994
--- sysdep.h.in Thu Dec 1 15:14:06 1994
***************
*** 69,78 ****
--- 69,81 ----
the standard <time.h>. (MIPS RISC/OS) */
#undef POSIX_TIME_H
+
/* Define this if /bin/ld exists and accepts a BSD-style -A argument
(for dynamic loading of .o files). */
#undef ANCIENT_DYNLOAD
+ /* Define this if fd_set and friends need sys/select.h */
+ #undef HAVE_SYS_SELECT_H
#if !defined(HAVE_SIGACTION)
struct sigaction {
*** unix.c.orig Sun Oct 23 19:23:29 1994
--- unix.c Fri Dec 2 13:51:57 1994
***************
*** 30,35 ****
--- 30,39 ----
widespread, but everyone wants to phase it out because it's not
very abstract.
+ Access to a COFF symbol table via ldtbread is even less abstract,
+ really sucks in general, and should be banned from earth.
+ Probably only AIX needs it because of the broken nlist.
+
Posix/ANSI C things used:
feof fopen fprintf perror strlen strncpy etc.
time (if gettimeofday and ftime are unavailable)
***************
*** 77,82 ****
--- 81,89 ----
#if defined(HAVE_SELECT)
# include <sys/types.h> /* for FD_SET and friends (BSD) */
+ #if defined(HAVE_SYS_SELECT_H)
+ # include <sys/select.h>
+ #endif
#endif
#if defined(HAVE_SYS_TIMEB_H)
***************
*** 416,421 ****
--- 423,567 ----
** - On failure, returns 0.
*/
+ #if defined(_AIX)
+
+ /* The problem with AIX is threefold:
+ - AIX throws away unused symbols during linking.
+ Since the externals only get referenced at runtime, ld throws them out.
+ This can, in theory, be turned off by the "nogc" option, but when
+ that is used, all hell breaks lose.
+ - AIX nlist lies: if you ask for "foobar", and there is a symbol "foo" in
+ the symbol table before "foobar", it will give you the value for "foo".
+ - AIX function pointers from the symbol table cannot be used directly:
+ Rather, all jumps are indirect. Therefore, the externals mechanism needs
+ to set up an "activation record" which contains the actual pointer,
followed
+ by a toc value which is loaded into r2 in function activation. I'm not
sure what
+ the third one is for. Even then, an offset is involved which is
calculated using
+ the data of the "main" procedure. */
+
+ #include <filehdr.h>
+ #include <syms.h>
+ #include <ldfcn.h>
+
+ struct s_symbol_table {
+ char *name;
+ void *value;
+ struct s_symbol_table *next;
+ };
+
+ static struct s_symbol_table *the_table = NULL;
+
+ #define MALLOC_TO(name, size) \
+ if (((name) = malloc(size)) == NULL) { \
+ fprintf(stderr, "Malloc error during external name lookup\n"); \
+ return; \
+ }
+
+ static void
+ fill_the_table(void)
+ {
+ extern char *get_reloc_file();
+ char *reloc_info_file;
+ LDFILE *f;
+ SYMENT entry;
+ long i;
+ struct s_symbol_table *cur_entry;
+
+ reloc_info_file = get_reloc_file();
+
+ if (reloc_info_file == NULL) {
+ fprintf(stderr, "Error during external name lookup\n");
+ return;
+ }
+
+ if ((f = ldopen(reloc_info_file, NULL)) == NULL) {
+ fprintf(stderr, "Error during external name lookup\n");
+ return;
+ }
+
+ if (!ldtbseek(f)) {
+ ldclose(f);
+ fprintf(stderr, "Error during external name lookup\n");
+ return;
+ }
+
+ cur_entry = the_table;
+
+
+ for (;;) {
+ i = ldtbindex(f);
+ if (!ldtbread(f, i, &entry))
+ break;
+ if (entry.n_sclass == C_EXT &&
+ entry.n_scnum != N_UNDEF &&
+ entry.n_scnum != N_DEBUG)
+ {
+ extern char *ldgetname(LDFILE *, SYMENT *);
+ char *p = ldgetname(f, &entry);
+
+ if (p != NULL && p[0] == '.') {
+ struct s_symbol_table *last_entry = cur_entry;
+
+ MALLOC_TO(cur_entry, sizeof(struct s_symbol_table));
+ MALLOC_TO(cur_entry->name, strlen(p));
+ strcpy(cur_entry->name, p+1); /* skip the dot */
+ cur_entry->value = (void *) entry.n_value;
+ if (!last_entry)
+ the_table = cur_entry;
+ else
+ last_entry->next = cur_entry;
+ }
+ }
+ }
+
+ if (cur_entry)
+ cur_entry->next = NULL;
+
+ ldclose(f);
+ }
+
+ static long
+ really_lookup_external_name(char *name)
+ {
+ struct s_symbol_table *entry = the_table;
+
+ while (entry) {
+ if (!strcmp(entry->name, name))
+ return((long) entry->value);
+ entry = entry->next;
+ }
+ return(0);
+ }
+
+ long
+ lookup_external_name(char *name, long *location)
+ {
+ long r;
+ static long val_offset;
+ extern int main();
+
+ if (!the_table) {
+ fill_the_table();
+ val_offset =
+ *((unsigned long *) ((void (*)()) main)) -
really_lookup_external_name("main");
+ }
+
+ r = really_lookup_external_name(name);
+
+ if (r) {
+ unsigned long *activate;
+
+ MALLOC_TO(activate, 3 * sizeof(unsigned long));
+ memcpy(activate, (void *) main, 3 * sizeof(unsigned long));
+ ((unsigned long *)activate)[0] = r + val_offset;
+ *location = (long) activate;
+ return(1);
+ } else
+ return(0);
+ }
+
+ #else /* i.e. #if !defined(_AIX) */
+
#if !defined(NLIST_HAS_N_NAME)
#define n_name n_un.n_name
#endif
***************
*** 481,486 ****
--- 627,634 ----
return 0;
#endif /*! HAVE_DLOPEN */
}
+
+ #endif /* !defined(AIX) */
extern char *object_file; /* specified via a command line argument */
extern char *reloc_file; /* dynamic loading will set this */
|