home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / gcl-1.000 / gcl-1 / gcl-1.0 / c / NeXTunixfasl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-25  |  12.6 KB  |  460 lines

  1. /*
  2.  * FASL loader using rld() for NeXT
  3.  *
  4.  * Written by Noritake Yonezawa (yone@vcdew25.lsi.tmg.nec.CO.JP)
  5.  * February 14, 1992
  6.  *
  7.  */
  8.  
  9. #include <mach.h>
  10. #include <sys/loader.h>
  11. #include <rld.h>
  12.  
  13. #include <ar.h>
  14. #include <nlist.h>
  15. #include <sys/types.h>
  16. #include <sys/file.h>
  17. #include <strings.h>
  18.  
  19. static unsigned long object_size, object_start;
  20.  
  21. static unsigned long
  22. my_address_func(size)
  23.     unsigned long       size;
  24. {
  25.     return (object_start = (unsigned long)alloc_contblock(object_size = size));
  26. }
  27.  
  28. static void
  29. load_mach_o(filename)
  30.     char               *filename;
  31. {
  32.     FILE               *fp;
  33.     struct mach_header  header;
  34.     char               *hdrbuf;
  35.     struct load_command *load_command;
  36.     struct segment_command *segment_command;
  37.     struct section     *section;
  38.     int                 len, cmd, seg;
  39.  
  40.     if ((fp = fopen(filename, "r")) == NULL)
  41.     FEerror("Can't read Mach-O object file", 0);
  42.     len = fread((char *)&header, sizeof(struct mach_header), 1, fp);
  43.     if (len == 1 && header.magic == MH_MAGIC) {
  44.     hdrbuf = (char *)malloc(header.sizeofcmds);
  45.     len = fread(hdrbuf, header.sizeofcmds, 1, fp);
  46.     if (len != 1)
  47.         FEerror("failure reading Mach-O load commands", 0);
  48.     load_command = (struct load_command *) hdrbuf;
  49.     for (cmd = 0; cmd < header.ncmds; ++cmd) {
  50.         if (load_command->cmd == LC_SEGMENT) {
  51.         segment_command = (struct segment_command *) load_command;
  52.         section = (struct section *) ((char *)(segment_command + 1));
  53.         for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {
  54.             if (section->size != 0 && section->offset != 0) {
  55. #ifdef DEBUG
  56.             fprintf(stderr, "section: %s, addr: 0x%08x, size: %d\n",
  57.                section->sectname, section->addr, section->size);
  58.             fflush(stderr);
  59. #endif
  60.             fseek(fp, section->offset, 0);
  61.             fread((char *)section->addr, section->size, 1, fp);
  62.             }
  63.         }
  64.         }
  65.         load_command = (struct load_command *)
  66.           ((char *)load_command + load_command->cmdsize);
  67.     }
  68.     free(hdrbuf);
  69.     }
  70.     (void)fclose(fp);
  71. }
  72.  
  73. int
  74. seek_to_end_ofile(fp)
  75.     FILE               *fp;
  76. {
  77.     struct mach_header  mach_header;
  78.     char               *hdrbuf;
  79.     struct load_command *load_command;
  80.     struct segment_command *segment_command;
  81.     struct section     *section;
  82.     struct symtab_command *symtab_command;
  83.     struct symseg_command *symseg_command;
  84.     int                 len, cmd, seg;
  85.     int                 end_sec, end_ofile;
  86.  
  87.     end_ofile = 0;
  88.     fseek(fp, 0L, 0);
  89.     len = fread((char *)&mach_header, sizeof(struct mach_header), 1, fp);
  90.     if (len == 1 && mach_header.magic == MH_MAGIC) {
  91.     hdrbuf = (char *)malloc(mach_header.sizeofcmds);
  92.     len = fread(hdrbuf, mach_header.sizeofcmds, 1, fp);
  93.     if (len != 1) {
  94.         fprintf(stderr, "seek_to_end_ofile(): failure reading Mach-O load commands\n");
  95.         return 0;
  96.     }
  97.     load_command = (struct load_command *) hdrbuf;
  98.     for (cmd = 0; cmd < mach_header.ncmds; ++cmd) {
  99.         switch (load_command->cmd) {
  100.         case LC_SEGMENT:
  101.         segment_command = (struct segment_command *) load_command;
  102.         section = (struct section *) ((char *)(segment_command + 1));
  103.         for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {
  104.             end_sec = section->offset + section->size;
  105.             if (end_sec > end_ofile)
  106.             end_ofile = end_sec;
  107.         }
  108.         break;
  109.         case LC_SYMTAB:
  110.         symtab_command = (struct symtab_command *) load_command;
  111.         end_sec = symtab_command->symoff + symtab_command->nsyms * sizeof(struct nlist);
  112.         if (end_sec > end_ofile)
  113.             end_ofile = end_sec;
  114.         end_sec = symtab_command->stroff + symtab_command->strsize;
  115.         if (end_sec > end_ofile)
  116.             end_ofile = end_sec;
  117.         break;
  118.         case LC_SYMSEG:
  119.         symseg_command = (struct symseg_command *) load_command;
  120.         end_sec = symseg_command->offset + symseg_command->size;
  121.         if (end_sec > end_ofile)
  122.             end_ofile = end_sec;
  123.         break;
  124.         }
  125.         load_command = (struct load_command *)
  126.           ((char *)load_command + load_command->cmdsize);
  127.     }
  128.     free(hdrbuf);
  129.     fseek(fp, end_ofile, 0);
  130.     return 1;
  131.     }
  132.     return 0;
  133. }
  134.  
  135. static char        *library_search_path[] =
  136. {"/lib", "/usr/lib", "/usr/local/lib", NULL};
  137.  
  138. #define strdup(string)    strcpy((char *)malloc(strlen(string)+1),(string))
  139.  
  140. static char        *
  141. expand_library_filename(filename)
  142.     char               *filename;
  143. {
  144.     int                 fd;
  145.     char              **dir;
  146.     char                libname[256];
  147.     char                fullname[256];
  148.  
  149.     if (filename[0] == '-' && filename[1] == 'l') {
  150.     filename++;
  151.     filename++;
  152.     strcpy(libname, "lib");
  153.     strcat(libname, filename);
  154.     strcat(libname, ".a");
  155.     for (dir = library_search_path; *dir; dir++) {
  156.         strcpy(fullname, *dir);
  157.         strcat(fullname, "/");
  158.         strcat(fullname, libname);
  159. #ifdef DEBUG
  160.         fprintf(stderr, "%s\n", fullname);
  161.         fflush(stderr);
  162. #endif
  163.         if ((fd = open(fullname, O_RDONLY, 0)) > 0) {
  164.         close(fd);
  165.         return (strdup(fullname));
  166.         }
  167.     }
  168.     return (strdup(libname));
  169.     }
  170.     return (strdup(filename));
  171. }
  172.  
  173. static char       **
  174. make_ofile_list(faslfile, argstr)
  175.     char               *faslfile, *argstr;
  176. {
  177.     char                filename[256];
  178.     char               *dst;
  179.     int                 i;
  180.     char              **ofile_list;
  181.  
  182.     ofile_list = (char **)calloc(1, sizeof(char *));
  183.     ofile_list[0] = strdup(faslfile);
  184.     i = 1;
  185.     if (argstr != NULL) {
  186.     for (;; i++) {
  187.         while ((*argstr == ' ') && (*argstr != '\0'))
  188.         argstr++;
  189.         if (*argstr == '\0')
  190.         break;
  191.         dst = filename;
  192.         while ((*argstr != ' ') && (*argstr != '\0'))
  193.         *dst++ = *argstr++;
  194.         *dst = '\0';
  195.         ofile_list = (char **)realloc((void *)ofile_list,
  196.                       (i + 1) * sizeof(char *));
  197.         ofile_list[i] = expand_library_filename(filename);
  198.     }
  199.     }
  200.     ofile_list = (char **)realloc((void *)ofile_list, (i + 1) * sizeof(char *));
  201.     ofile_list[i] = NULL;
  202.     return (ofile_list);
  203. }
  204.  
  205. static void
  206. free_ofile_list(ofile_list)
  207.     char              **ofile_list;
  208. {
  209.     int                 i;
  210.  
  211.     for (i = 1;; i++) {
  212.     if (ofile_list[i] == NULL)
  213.         break;
  214.     (void)free(ofile_list[i]);
  215.     }
  216.     (void)free(ofile_list);
  217. }
  218.  
  219. #ifdef DEBUG
  220. static void
  221. print_ofile_list(ofile_list)
  222.     char              **ofile_list;
  223. {
  224.     int                 i;
  225.  
  226.     if (ofile_list == NULL)
  227.     return;
  228.     fprintf(stderr, "ofiles: ");
  229.     for (i = 0;; i++) {
  230.     if (ofile_list[i] == NULL)
  231.         break;
  232.     fprintf(stderr, "(%s)", ofile_list[i]);
  233.     }
  234.     fprintf(stderr, "\n");
  235.     fflush(stderr);
  236. }
  237.  
  238. #endif
  239.  
  240. int
  241. fasload(pathname)
  242.     object              pathname;
  243. {
  244.     FILE               *fp;
  245.     object             *old_vs_base = vs_base;
  246.     object             *old_vs_top = vs_top;
  247.     object              memory;
  248.     object              fasl_data;
  249.     object              stream;
  250.     char                entryname[100];
  251.     char                filename[256];
  252.     char                tempfilename[40];
  253.     char              **ofiles;
  254.     NXStream           *err_stream;
  255.     void                (*entry) ();
  256.     struct mach_header *hdr;
  257.  
  258.     stream = open_stream(pathname, smm_input, Cnil, Kerror);
  259.     fp = stream->sm.sm_fp;
  260.  
  261.     seek_to_end_ofile(fp);
  262.     fasl_data = read_fasl_vector(stream);
  263.     vs_push(fasl_data);
  264.  
  265.     pathname = coerce_to_pathname(stream);
  266.     coerce_to_filename(stream, filename);
  267.  
  268.     if ((err_stream = NXOpenFile(fileno(stderr), NX_WRITEONLY)) == 0)
  269.     FEerror("NXOpenFile() failed", 0);
  270.  
  271.     sprintf(tempfilename, "/tmp/fasltemp%d", getpid());
  272.     rld_address_func(my_address_func);
  273.     ofiles = make_ofile_list(filename, NULL);
  274. #ifdef DEBUG
  275.     print_ofile_list(ofiles);
  276. #endif
  277.     if (!rld_load(err_stream, &hdr, ofiles, tempfilename)) {
  278.     free_ofile_list(ofiles);
  279.     NXFlush(err_stream);
  280.     NXClose(err_stream);
  281.     FEerror("rld_load() failed", 0);
  282.     }
  283.     free_ofile_list(ofiles);
  284.     load_mach_o(tempfilename);
  285.     unlink(tempfilename);
  286.  
  287.     strcpy(entryname, "_init_code");
  288.     if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
  289.     strcpy(entryname, "_init_");
  290.     bcopy(pathname->pn.pn_name->st.st_self,
  291.           entryname + 6, pathname->pn.pn_name->st.st_fillp);
  292.     entryname[6 + pathname->pn.pn_name->st.st_fillp] = 0;
  293.     if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
  294.         NXFlush(err_stream);
  295.         NXClose(err_stream);
  296.         FEerror("Can't find init code", 0);
  297.     }
  298.     }
  299.     (void)rld_unload_all(err_stream, 0);
  300.     NXFlush(err_stream);
  301.     NXClose(err_stream);
  302.  
  303.  
  304. #ifdef DEBUG
  305.     {
  306.     extern char        *mach_brkpt, *mach_maplimit, *core_end;
  307.  
  308.     fprintf(stderr, "mach_brkpt    : 0x%08x\n", mach_brkpt);
  309.     fprintf(stderr, "mach_maplimit : 0x%08x\n", mach_maplimit);
  310.     fprintf(stderr, "core_end      : 0x%08x\n", core_end);
  311.     fprintf(stderr, "hdr           : 0x%08x\n", hdr);
  312.     fprintf(stderr, "object_start  : 0x%08x\n", object_start);
  313.     fprintf(stderr, "object_size   : %d\n", object_size);
  314.     fprintf(stderr, "&%s   : 0x%08x\n", entryname, entry);
  315.     fflush(stderr);
  316.     }
  317. #endif
  318.  
  319.     memory = alloc_object(t_cfdata);
  320.     memory->cfd.cfd_self = 0;
  321.     memory->cfd.cfd_fillp = 0;
  322.     memory->cfd.cfd_size = object_size;
  323.     memory->cfd.cfd_start = (char *)object_start;
  324.     vs_push(memory);
  325.  
  326.     asm("trap #2");        /* clear cache */
  327.     call_init(entry - object_start, memory, fasl_data);
  328.  
  329.     if (symbol_value(Vload_verbose) != Cnil)
  330.     printf("start address -T 0x%08x ", entry);
  331.  
  332.     vs_base = old_vs_base;
  333.     vs_top = old_vs_top;
  334.     close_stream(stream);
  335.     return object_size;
  336. }
  337.  
  338. int
  339. faslink(pathname, ldargstring)
  340.     object              pathname, ldargstring;
  341. {
  342.     FILE               *fp;
  343.     object             *old_vs_base = vs_base;
  344.     object             *old_vs_top = vs_top;
  345.     object              memory;
  346.     object              fasl_data;
  347.     object              stream;
  348.     char                entryname[100];
  349.     char                filename[256];
  350.     char                ldargstr[256];
  351.     char                tempfilename[40];
  352.     char              **ofiles;
  353.     NXStream           *err_stream;
  354.     void                (*entry) ();
  355.     struct mach_header *hdr;
  356.  
  357.     stream = open_stream(pathname, smm_input, Cnil, Kerror);
  358.     fp = stream->sm.sm_fp;
  359.  
  360.     seek_to_end_ofile(fp);
  361.     fasl_data = read_fasl_vector(stream);
  362.     vs_push(fasl_data);
  363.  
  364.     pathname = coerce_to_pathname(stream);
  365.     coerce_to_filename(stream, filename);
  366.     coerce_to_filename(ldargstring, ldargstr);
  367.  
  368.     if ((err_stream = NXOpenFile(fileno(stderr), NX_WRITEONLY)) == 0)
  369.     FEerror("NXOpenFile() failed", 0);
  370.  
  371.     sprintf(tempfilename, "/tmp/fasltemp%d", getpid());
  372.     rld_address_func(my_address_func);
  373.     ofiles = make_ofile_list(filename, ldargstr);
  374. #ifdef DEBUG
  375.     print_ofile_list(ofiles);
  376. #endif
  377.     if (!rld_load(err_stream, &hdr, ofiles, tempfilename)) {
  378.     free_ofile_list(ofiles);
  379.     NXFlush(err_stream);
  380.     NXClose(err_stream);
  381.     FEerror("rld_load() failed", 0);
  382.     }
  383.     free_ofile_list(ofiles);
  384.     load_mach_o(tempfilename);
  385.     unlink(tempfilename);
  386.  
  387.     strcpy(entryname, "_init_code");
  388.     if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
  389.     strcpy(entryname, "_init_");
  390.     bcopy(pathname->pn.pn_name->st.st_self,
  391.           entryname + 6, pathname->pn.pn_name->st.st_fillp);
  392.     entryname[6 + pathname->pn.pn_name->st.st_fillp] = 0;
  393.     if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
  394.         NXFlush(err_stream);
  395.         NXClose(err_stream);
  396.         FEerror("Can't find init code", 0);
  397.     }
  398.     }
  399.     (void)rld_unload_all(err_stream, 0);
  400.     NXFlush(err_stream);
  401.     NXClose(err_stream);
  402.  
  403.  
  404. #ifdef DEBUG
  405.     {
  406.     extern char        *mach_brkpt, *mach_maplimit, *core_end;
  407.  
  408.     fprintf(stderr, "mach_brkpt    : 0x%08x\n", mach_brkpt);
  409.     fprintf(stderr, "mach_maplimit : 0x%08x\n", mach_maplimit);
  410.     fprintf(stderr, "core_end      : 0x%08x\n", core_end);
  411.     fprintf(stderr, "hdr           : 0x%08x\n", hdr);
  412.     fprintf(stderr, "object_start  : 0x%08x\n", object_start);
  413.     fprintf(stderr, "object_size   : %d\n", object_size);
  414.     fprintf(stderr, "&%s   : 0x%08x\n", entryname, entry);
  415.     fflush(stderr);
  416.     }
  417. #endif
  418.  
  419.     memory = alloc_object(t_cfdata);
  420.     memory->cfd.cfd_self = 0;
  421.     memory->cfd.cfd_fillp = 0;
  422.     memory->cfd.cfd_size = object_size;
  423.     memory->cfd.cfd_start = (char *)object_start;
  424.     vs_push(memory);
  425.  
  426.     asm("trap #2");        /* clear cache */
  427.     call_init(entry - object_start, memory, fasl_data);
  428.  
  429.     if (symbol_value(Vload_verbose) != Cnil)
  430.     printf("start address -T 0x%08x \n", entry);
  431.  
  432.     vs_base = old_vs_base;
  433.     vs_top = old_vs_top;
  434.     close_stream(stream);
  435.     return object_size;
  436. }
  437.  
  438. siLfaslink()
  439. {
  440.     bds_ptr             old_bds_top;
  441.     int                 i;
  442.     object              package;
  443.  
  444.     check_arg(2);
  445.     check_type_or_pathname_string_symbol_stream(&vs_base[0]);
  446.     check_type_string(&vs_base[1]);
  447.     vs_base[0] = coerce_to_pathname(vs_base[0]);
  448.     vs_base[0]->pn.pn_type = FASL_string;
  449.     vs_base[0] = namestring(vs_base[0]);
  450.     package = symbol_value(Vpackage);
  451.     old_bds_top = bds_top;
  452.     bds_bind(Vpackage, package);
  453.     i = faslink(vs_base[0], vs_base[1]);
  454.     bds_unwind(old_bds_top);
  455.     vs_top = vs_base;
  456.     vs_push(make_fixnum(i));
  457. }
  458.  
  459. #define FASLINK
  460.