home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume1
/
dynamic
< prev
next >
Wrap
Internet Message Format
|
1986-11-30
|
9KB
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