scsh-users
[Top] [All Lists]

AIX support / externals

To: scsh@martigny.ai.mit.edu, scheme-48@martigny.ai.mit.edu
Subject: AIX support / externals
From: sperber@informatik.uni-tuebingen.de
Date: Fri, 02 Dec 94 14:03:06 +0100
Cc: sperber@informatik.uni-tuebingen.de
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 */

<Prev in Thread] Current Thread [Next in Thread>