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

  1. Date: Thu, 16 May 85 14:10:49 edt
  2. From: Stephen Daniel <decvax!mcnc!swd>
  3. Subject: dynamic loading code for 4.2bsd
  4. Newsgroups: mod.sources
  5. Organization: Microelectronics Center of NC
  6.  
  7. Having recieved the usual numerouse requests for this code,
  8. I am submitting it.
  9.  
  10. This is a fast but simple dynamic loader for 4.2bsd.
  11. It handles everything except making linkages between
  12. the code being loaded and the running process image (sorry).
  13.  
  14.     Stephen Daniel
  15.     decvax!mcnc!swd
  16.     swd@mcnc (csnet)
  17.  
  18.  
  19. #    This is a shell archive.
  20. #    Remove everything above and including the cut line.
  21. #    Then run the rest of the file through sh.
  22. -----cut here-----cut here-----cut here-----cut here-----
  23. #!/bin/sh
  24. # shar:    Shell Archiver
  25. #    Run the following text with /bin/sh to create:
  26. #    README
  27. #    Makefile
  28. #    dyload.c
  29. #    main.c
  30. #    test.c
  31. # This archive created: Thu May 16 14:01:14 1985
  32. echo shar: extracting README '(282 characters)'
  33. sed 's/^XX//' << \SHAR_EOF > README
  34. XXThese files contain a dynamic loading routine (dyload.c)
  35. XXand a test program (main.c and test.c).
  36. XX
  37. XXTo run things, type make and then foo.
  38. XXYou should get
  39. XX    Hello World
  40. XX    routine returns 17
  41. XXas output.
  42. XX
  43. XXThis dynamic loading code pretends to work under
  44. XXBerkeley Unix versions 4.1 and 4.2.
  45. SHAR_EOF
  46. if test 282 -ne "`wc -c README`"
  47. then
  48. echo shar: error transmitting README '(should have been 282 characters)'
  49. fi
  50. echo shar: extracting Makefile '(217 characters)'
  51. sed 's/^XX//' << \SHAR_EOF > Makefile
  52. XXCFLAGS=
  53. XX
  54. XXall : foo test
  55. XX
  56. XXfoo : main.o dyload.o
  57. XX    cc -o foo main.o dyload.o
  58. XX
  59. XX#
  60. XX# Note: on a vax this line can be replaced by just "mv test.o test"
  61. XX#
  62. XXtest: test.o
  63. XX    ld -r -d -o test test.o -lc
  64. XX
  65. XXclean:
  66. XX    rm -f *.o test foo
  67. SHAR_EOF
  68. if test 217 -ne "`wc -c Makefile`"
  69. then
  70. echo shar: error transmitting Makefile '(should have been 217 characters)'
  71. fi
  72. echo shar: extracting dyload.c '(5168 characters)'
  73. sed 's/^XX//' << \SHAR_EOF > dyload.c
  74. XX/*
  75. XX
  76. XX        DISCLAIMER AND NOTIFICATION OF RIGHTS
  77. XX            May 16, 1985
  78. XX
  79. XX    This code was written by Phil Smith, Bert Sacks, and
  80. XX    Stephen Daniel of the Microelectronics Center of NC.
  81. XX
  82. XX    It appears to us that it works, but there are no
  83. XX    guarentees of any kind expressed or implied.
  84. XX
  85. XX    The Microelectronics Center of North Carolina
  86. XX    hereby places this code into the public domain.
  87. XX
  88. XX    We request that you keep this comment associated with
  89. XX    this code.
  90. XX
  91. XX*/
  92. XX
  93. XX
  94. XX/*
  95. XX * Dynamic loading routine.
  96. XX */
  97. XX
  98. XX#include <stdio.h>
  99. XX#include <a.out.h>
  100. XX#include <setjmp.h>
  101. XX
  102. XXtypedef int (*pfi_t)();    /* pointer to function returning integer. */
  103. XX
  104. XXstatic FILE *input;
  105. XXstatic char *f_name;
  106. XXstatic long string_offset;
  107. XXjmp_buf blow_out;
  108. XX
  109. XXpfi_t
  110. XXload_function(file_name)
  111. XX  char *file_name;
  112. XX{
  113. XX    int size;
  114. XX    int *data;
  115. XX    struct exec header;
  116. XX    char *ok_calloc();
  117. XX    FILE *fopen();
  118. XX
  119. XX    /*
  120. XX     * Set up an error exit.
  121. XX     */
  122. XX    f_name = file_name;
  123. XX    if (setjmp(blow_out))
  124. XX        return ((pfi_t)0);
  125. XX
  126. XX    /*
  127. XX     *    Open the file:  return if unopened.
  128. XX     */
  129. XX    if ((input = fopen(file_name, "r")) == NULL)
  130. XX        error("cannot open file\n");
  131. XX
  132. XX    ok_fread (&header, sizeof(header), 1, input);
  133. XX    ok_fseek (input, (long) N_TXTOFF(header), 0);
  134. XX
  135. XX    string_offset = N_STROFF(header);
  136. XX    size = header.a_text + header.a_data;
  137. XX
  138. XX    /*
  139. XX     *    Read in the text and data segments
  140. XX     *    Use ok_calloc() to make sure bss segment zero'ed
  141. XX     */
  142. XX    data = (int *)ok_calloc(size + header.a_bss, 1);
  143. XX
  144. XX    ok_fread ((char *)data, 1, size, input);
  145. XX
  146. XX    if (header.a_trsize + header.a_drsize > 0)
  147. XX        relocate (header, data);
  148. XX
  149. XX    fclose (input);
  150. XX    return((pfi_t ) data);
  151. XX}
  152. XX
  153. XX/*
  154. XX *    Relocate text and data
  155. XX */
  156. XXstatic
  157. XXrelocate (header, text)
  158. XXstruct exec header;
  159. XXchar *text;
  160. XX{
  161. XX    int i; 
  162. XX    char *data;
  163. XX    unsigned long    no_reloc_items,
  164. XX            no_reloc_text_items,
  165. XX            no_reloc_data_items,
  166. XX            no_symbols;
  167. XX    struct relocation_info *rp, *relocate;
  168. XX    struct nlist *symtab;
  169. XX    char *ok_malloc();
  170. XX
  171. XX    data = text + header.a_text;
  172. XX
  173. XX    /*
  174. XX     *    Read in the relocation information
  175. XX     */
  176. XX    no_reloc_text_items = (header.a_trsize / sizeof (struct relocation_info));
  177. XX    no_reloc_data_items = (header.a_drsize / sizeof (struct relocation_info));
  178. XX    no_reloc_items = no_reloc_text_items + no_reloc_data_items;
  179. XX
  180. XX    relocate = (struct relocation_info *) ok_malloc
  181. XX                (header.a_trsize + header.a_drsize);
  182. XX    ok_fread (relocate, sizeof (struct relocation_info), no_reloc_items, input);
  183. XX
  184. XX    /*
  185. XX     *    Read in the symbol table
  186. XX     */
  187. XX    symtab = (struct nlist *) ok_malloc (header.a_syms);
  188. XX    no_symbols = header.a_syms / (sizeof (struct nlist));
  189. XX    ok_fread (symtab, sizeof (struct nlist), no_symbols, input);
  190. XX
  191. XX    /*
  192. XX     *    Relocate text
  193. XX     */
  194. XX    for (i = 0, rp = relocate; i < no_reloc_text_items; i++, rp++) 
  195. XX        adjust(text+rp->r_address, rp, symtab, text);
  196. XX
  197. XX    /*
  198. XX     *    Relocate data
  199. XX     */
  200. XX    for (i = 0; i < no_reloc_data_items; i++, rp++) 
  201. XX        adjust(data+rp->r_address, rp, symtab, text);
  202. XX
  203. XX    ok_free(symtab);
  204. XX}
  205. XX
  206. XX/*
  207. XX *    Add the offset to relocated items
  208. XX */
  209. XXstatic
  210. XXadjust (word, reloc, symtab, text)
  211. XXchar *word;
  212. XXstruct relocation_info *reloc;
  213. XXstruct nlist *symtab;
  214. XXchar *text;
  215. XX{
  216. XX    long reloc_item;
  217. XX    struct nlist *sp;
  218. XX
  219. XX    if (reloc->r_length == 0) 
  220. XX        reloc_item = *(char *) word;
  221. XX    else if (reloc->r_length == 1) 
  222. XX        reloc_item = *(short *) word;
  223. XX    else if (reloc->r_length == 2) 
  224. XX        reloc_item = *(long *) word;
  225. XX    else
  226. XX        error("INTERNAL ERROR: bad r_length\n");
  227. XX
  228. XX    /*
  229. XX     *    Relocate a text or data item 
  230. XX     */
  231. XX    if (reloc->r_extern) {
  232. XX        sp = symtab + reloc->r_symbolnum;
  233. XX        if ((sp->n_type & N_TYPE) == N_UNDF) {
  234. XX            warn("undefined symbol: ");
  235. XX            print_symbol_name(sp->n_un.n_strx);
  236. XX        } else 
  237. XX            reloc_item += sp->n_value;
  238. XX
  239. XX    } else if (!reloc->r_pcrel)
  240. XX        switch (reloc->r_symbolnum & N_TYPE) {
  241. XX            case N_TEXT:
  242. XX            case N_DATA:
  243. XX            case N_BSS:
  244. XX                reloc_item += (long)text;
  245. XX                break;
  246. XX            case N_ABS:
  247. XX                break;
  248. XX            default:
  249. XX                error("INTERNAL ERROR: bad n_type\n");
  250. XX        }
  251. XX
  252. XX    if (reloc->r_length == 0)
  253. XX        *(char *) word = reloc_item;
  254. XX    else if (reloc->r_length == 1)
  255. XX        *(short *) word = reloc_item;
  256. XX    else if (reloc->r_length == 2)
  257. XX        *(long *) word = reloc_item;
  258. XX    else
  259. XX        error("INTERNAL ERROR: bad r_length\n");
  260. XX}
  261. XX
  262. XXstatic
  263. XXprint_symbol_name(which)
  264. XXlong which;
  265. XX{
  266. XX    int c;
  267. XX
  268. XX    if (which) {
  269. XX        ok_fseek(input, string_offset + which, 0);
  270. XX        while ((c = getc(input)) != '\0')
  271. XX            putchar(c);
  272. XX        putchar ('\n');
  273. XX    } else 
  274. XX        puts ("name undetermined");
  275. XX}
  276. XX
  277. XXstatic
  278. XXok_fread(ptr, size, nitems, stream)
  279. XXchar *ptr;
  280. XXint size, nitems;
  281. XXFILE *stream;
  282. XX{
  283. XX    if (fread(ptr, size, nitems, stream) != nitems ||
  284. XX        feof(stream) || ferror(stream))
  285. XX        error("error while reading disk file\n");
  286. XX}
  287. XX
  288. XXstatic
  289. XXok_fseek(stream, offset, ptrname)
  290. XXFILE *stream;
  291. XXlong offset;
  292. XXint ptrname;
  293. XX{
  294. XX    if (fseek(stream, offset, ptrname) < 0)
  295. XX        error("error while seeking on disk file\n");
  296. XX}
  297. XX
  298. XXstatic char *
  299. XXok_calloc(nelem, elsize)
  300. XXint nelem, elsize;
  301. XX{
  302. XX    register char *ret;
  303. XX    char *calloc();
  304. XX
  305. XX    if ((ret = calloc((unsigned)nelem, (unsigned)elsize)) == (char *)0)
  306. XX        error("insufficient memory\n");
  307. XX    return(ret);
  308. XX}
  309. XX
  310. XXstatic char *
  311. XXok_malloc(n)
  312. XXint n;
  313. XX{
  314. XX    register char *ret;
  315. XX    char *malloc();
  316. XX
  317. XX    if ((ret = malloc((unsigned)n)) == (char *)0)
  318. XX        error("insufficient memory\n");
  319. XX    return(ret);
  320. XX}
  321. XX
  322. XXstatic
  323. XXok_free(s)
  324. XXchar *s;
  325. XX{
  326. XX    free(s);
  327. XX}
  328. XX
  329. XXstatic
  330. XXerror(s)
  331. XXchar *s;
  332. XX{
  333. XX    warn(s);
  334. XX    longjmp(blow_out, 1);
  335. XX}
  336. XX
  337. XX
  338. XXstatic
  339. XXwarn(s)
  340. XXchar *s;
  341. XX{
  342. XX    fprintf(stderr, "load_function(%s): %s", f_name, s);
  343. XX}
  344. SHAR_EOF
  345. if test 5168 -ne "`wc -c dyload.c`"
  346. then
  347. echo shar: error transmitting dyload.c '(should have been 5168 characters)'
  348. fi
  349. echo shar: extracting main.c '(437 characters)'
  350. sed 's/^XX//' << \SHAR_EOF > main.c
  351. XX#include <stdio.h>
  352. XX
  353. XXtypedef int (*pfi_t)();    /* pointer to function returning integer. */
  354. XX
  355. XXmain(argc, argv)
  356. XXint argc;
  357. XXchar **argv;
  358. XX{
  359. XX    int ret;
  360. XX    char *f_name;
  361. XX    pfi_t routine, load_function();
  362. XX    int printf();
  363. XX
  364. XX    if (argc > 1)
  365. XX        f_name = argv[1];
  366. XX    else
  367. XX        f_name = "test";
  368. XX    
  369. XX    if (!(routine = load_function(f_name))) {
  370. XX        fprintf(stderr, "Cannot load %s\n", f_name);
  371. XX        exit(1);
  372. XX    }
  373. XX
  374. XX    ret = routine(printf);
  375. XX    printf("routine returns %d\n", ret);
  376. XX}
  377. SHAR_EOF
  378. if test 437 -ne "`wc -c main.c`"
  379. then
  380. echo shar: error transmitting main.c '(should have been 437 characters)'
  381. fi
  382. echo shar: extracting test.c '(110 characters)'
  383. sed 's/^XX//' << \SHAR_EOF > test.c
  384. XX/*
  385. XX * routine that gets called by main().
  386. XX */
  387. XX
  388. XXfoo(pf)
  389. XXint (*pf)();
  390. XX{
  391. XX    (*pf)("Hello World\n");
  392. XX    return(17);
  393. XX}
  394. SHAR_EOF
  395. if test 110 -ne "`wc -c test.c`"
  396. then
  397. echo shar: error transmitting test.c '(should have been 110 characters)'
  398. fi
  399. #    End of shell archive
  400. exit 0
  401.  
  402.