Relay-Version: version B 2.10.3 alpha 4/15/85; site seismo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: seismo!harvard!talcott!panda!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: dynamic loading code for 4.2bsd Message-ID: <840@genrad.UUCP> Date: 17 May 85 20:28:34 GMT Sender: john@genrad.UUCP Organization: Microelectronics Center of NC Lines: 396 Approved: john@genrad.UUCP From: Stephen Daniel Having recieved the usual numerouse requests for this code, I am submitting it. This is a fast but simple dynamic loader for 4.2bsd. It handles everything except making linkages between the code being loaded and the running process image (sorry). Stephen Daniel decvax!mcnc!swd swd@mcnc (csnet) # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. -----cut here-----cut here-----cut here-----cut here----- #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # README # Makefile # dyload.c # main.c # test.c # This archive created: Thu May 16 14:01:14 1985 echo shar: extracting README '(282 characters)' sed 's/^XX//' << \SHAR_EOF > README XXThese files contain a dynamic loading routine (dyload.c) XXand a test program (main.c and test.c). XX XXTo run things, type make and then foo. XXYou should get XX Hello World XX routine returns 17 XXas output. XX XXThis dynamic loading code pretends to work under XXBerkeley Unix versions 4.1 and 4.2. SHAR_EOF if test 282 -ne "`wc -c README`" then echo shar: error transmitting README '(should have been 282 characters)' fi echo shar: extracting Makefile '(217 characters)' sed 's/^XX//' << \SHAR_EOF > Makefile XXCFLAGS= XX XXall : foo test XX XXfoo : main.o dyload.o XX cc -o foo main.o dyload.o XX XX# XX# Note: on a vax this line can be replaced by just "mv test.o test" XX# XXtest: test.o XX ld -r -d -o test test.o -lc XX XXclean: XX rm -f *.o test foo SHAR_EOF if test 217 -ne "`wc -c Makefile`" then echo shar: error transmitting Makefile '(should have been 217 characters)' fi echo shar: extracting dyload.c '(5168 characters)' sed 's/^XX//' << \SHAR_EOF > dyload.c XX/* XX XX DISCLAIMER AND NOTIFICATION OF RIGHTS XX May 16, 1985 XX XX This code was written by Phil Smith, Bert Sacks, and XX Stephen Daniel of the Microelectronics Center of NC. XX XX It appears to us that it works, but there are no XX guarentees of any kind expressed or implied. XX XX The Microelectronics Center of North Carolina XX hereby places this code into the public domain. XX XX We request that you keep this comment associated with XX this code. XX XX*/ XX XX XX/* XX * Dynamic loading routine. XX */ XX XX#include XX#include XX#include XX XXtypedef int (*pfi_t)(); /* pointer to function returning integer. */ XX XXstatic FILE *input; XXstatic char *f_name; XXstatic long string_offset; XXjmp_buf blow_out; XX XXpfi_t XXload_function(file_name) XX char *file_name; XX{ XX int size; XX int *data; XX struct exec header; XX char *ok_calloc(); XX FILE *fopen(); XX XX /* XX * Set up an error exit. XX */ XX f_name = file_name; XX if (setjmp(blow_out)) XX return ((pfi_t)0); XX XX /* XX * Open the file: return if unopened. XX */ XX if ((input = fopen(file_name, "r")) == NULL) XX error("cannot open file\n"); XX XX ok_fread (&header, sizeof(header), 1, input); XX ok_fseek (input, (long) N_TXTOFF(header), 0); XX XX string_offset = N_STROFF(header); XX size = header.a_text + header.a_data; XX XX /* XX * Read in the text and data segments XX * Use ok_calloc() to make sure bss segment zero'ed XX */ XX data = (int *)ok_calloc(size + header.a_bss, 1); XX XX ok_fread ((char *)data, 1, size, input); XX XX if (header.a_trsize + header.a_drsize > 0) XX relocate (header, data); XX XX fclose (input); XX return((pfi_t ) data); XX} XX XX/* XX * Relocate text and data XX */ XXstatic XXrelocate (header, text) XXstruct exec header; XXchar *text; XX{ XX int i; XX char *data; XX unsigned long no_reloc_items, XX no_reloc_text_items, XX no_reloc_data_items, XX no_symbols; XX struct relocation_info *rp, *relocate; XX struct nlist *symtab; XX char *ok_malloc(); XX XX data = text + header.a_text; XX XX /* XX * Read in the relocation information XX */ XX no_reloc_text_items = (header.a_trsize / sizeof (struct relocation_info)); XX no_reloc_data_items = (header.a_drsize / sizeof (struct relocation_info)); XX no_reloc_items = no_reloc_text_items + no_reloc_data_items; XX XX relocate = (struct relocation_info *) ok_malloc XX (header.a_trsize + header.a_drsize); XX ok_fread (relocate, sizeof (struct relocation_info), no_reloc_items, input); XX XX /* XX * Read in the symbol table XX */ XX symtab = (struct nlist *) ok_malloc (header.a_syms); XX no_symbols = header.a_syms / (sizeof (struct nlist)); XX ok_fread (symtab, sizeof (struct nlist), no_symbols, input); XX XX /* XX * Relocate text XX */ XX for (i = 0, rp = relocate; i < no_reloc_text_items; i++, rp++) XX adjust(text+rp->r_address, rp, symtab, text); XX XX /* XX * Relocate data XX */ XX for (i = 0; i < no_reloc_data_items; i++, rp++) XX adjust(data+rp->r_address, rp, symtab, text); XX XX ok_free(symtab); XX} XX XX/* XX * Add the offset to relocated items XX */ XXstatic XXadjust (word, reloc, symtab, text) XXchar *word; XXstruct relocation_info *reloc; XXstruct nlist *symtab; XXchar *text; XX{ XX long reloc_item; XX struct nlist *sp; XX XX if (reloc->r_length == 0) XX reloc_item = *(char *) word; XX else if (reloc->r_length == 1) XX reloc_item = *(short *) word; XX else if (reloc->r_length == 2) XX reloc_item = *(long *) word; XX else XX error("INTERNAL ERROR: bad r_length\n"); XX XX /* XX * Relocate a text or data item XX */ XX if (reloc->r_extern) { XX sp = symtab + reloc->r_symbolnum; XX if ((sp->n_type & N_TYPE) == N_UNDF) { XX warn("undefined symbol: "); XX print_symbol_name(sp->n_un.n_strx); XX } else XX reloc_item += sp->n_value; XX XX } else if (!reloc->r_pcrel) XX switch (reloc->r_symbolnum & N_TYPE) { XX case N_TEXT: XX case N_DATA: XX case N_BSS: XX reloc_item += (long)text; XX break; XX case N_ABS: XX break; XX default: XX error("INTERNAL ERROR: bad n_type\n"); XX } XX XX if (reloc->r_length == 0) XX *(char *) word = reloc_item; XX else if (reloc->r_length == 1) XX *(short *) word = reloc_item; XX else if (reloc->r_length == 2) XX *(long *) word = reloc_item; XX else XX error("INTERNAL ERROR: bad r_length\n"); XX} XX XXstatic XXprint_symbol_name(which) XXlong which; XX{ XX int c; XX XX if (which) { XX ok_fseek(input, string_offset + which, 0); XX while ((c = getc(input)) != '\0') XX putchar(c); XX putchar ('\n'); XX } else XX puts ("name undetermined"); XX} XX XXstatic XXok_fread(ptr, size, nitems, stream) XXchar *ptr; XXint size, nitems; XXFILE *stream; XX{ XX if (fread(ptr, size, nitems, stream) != nitems || XX feof(stream) || ferror(stream)) XX error("error while reading disk file\n"); XX} XX XXstatic XXok_fseek(stream, offset, ptrname) XXFILE *stream; XXlong offset; XXint ptrname; XX{ XX if (fseek(stream, offset, ptrname) < 0) XX error("error while seeking on disk file\n"); XX} XX XXstatic char * XXok_calloc(nelem, elsize) XXint nelem, elsize; XX{ XX register char *ret; XX char *calloc(); XX XX if ((ret = calloc((unsigned)nelem, (unsigned)elsize)) == (char *)0) XX error("insufficient memory\n"); XX return(ret); XX} XX XXstatic char * XXok_malloc(n) XXint n; XX{ XX register char *ret; XX char *malloc(); XX XX if ((ret = malloc((unsigned)n)) == (char *)0) XX error("insufficient memory\n"); XX return(ret); XX} XX XXstatic XXok_free(s) XXchar *s; XX{ XX free(s); XX} XX XXstatic XXerror(s) XXchar *s; XX{ XX warn(s); XX longjmp(blow_out, 1); XX} XX XX XXstatic XXwarn(s) XXchar *s; XX{ XX fprintf(stderr, "load_function(%s): %s", f_name, s); XX} SHAR_EOF if test 5168 -ne "`wc -c dyload.c`" then echo shar: error transmitting dyload.c '(should have been 5168 characters)' fi echo shar: extracting main.c '(437 characters)' sed 's/^XX//' << \SHAR_EOF > main.c XX#include XX XXtypedef int (*pfi_t)(); /* pointer to function returning integer. */ XX XXmain(argc, argv) XXint argc; XXchar **argv; XX{ XX int ret; XX char *f_name; XX pfi_t routine, load_function(); XX int printf(); XX XX if (argc > 1) XX f_name = argv[1]; XX else XX f_name = "test"; XX XX if (!(routine = load_function(f_name))) { XX fprintf(stderr, "Cannot load %s\n", f_name); XX exit(1); XX } XX XX ret = routine(printf); XX printf("routine returns %d\n", ret); XX} SHAR_EOF if test 437 -ne "`wc -c main.c`" then echo shar: error transmitting main.c '(should have been 437 characters)' fi echo shar: extracting test.c '(110 characters)' sed 's/^XX//' << \SHAR_EOF > test.c XX/* XX * routine that gets called by main(). XX */ XX XXfoo(pf) XXint (*pf)(); XX{ XX (*pf)("Hello World\n"); XX return(17); XX} SHAR_EOF if test 110 -ne "`wc -c test.c`" then echo shar: error transmitting test.c '(should have been 110 characters)' fi # End of shell archive exit 0