home *** CD-ROM | disk | FTP | other *** search
- Date: Thu, 16 May 85 14:10:49 edt
- From: Stephen Daniel <decvax!mcnc!swd>
- Subject: dynamic loading code for 4.2bsd
- Newsgroups: mod.sources
- Organization: Microelectronics Center of NC
-
- 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 <stdio.h>
- XX#include <a.out.h>
- XX#include <setjmp.h>
- 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 <stdio.h>
- 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
-
-