home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / cdl / part02 < prev    next >
Internet Message Format  |  1991-04-14  |  30KB

  1. From: mauro@netcom.COM (Mauro DePalma)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i018:  cdl - COFF Dynamic Loader, Part02/02
  4. Message-ID: <1991Apr13.212620.15975@sparky.IMD.Sterling.COM>
  5. Date: 13 Apr 91 21:26:20 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: b9b54dac fd95c06f eb5c16ad 90a27ccb
  8.  
  9. Submitted-by: Mauro DePalma <mauro@netcom.COM>
  10. Posting-number: Volume 18, Issue 18
  11. Archive-name: cdl/part02
  12.  
  13. #!/bin/sh
  14. # This is part 02 of CDL-1.2
  15. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  16.  then TOUCH=touch
  17.  else TOUCH=true
  18. fi
  19. # ============= loader.c ==============
  20. echo "x - extracting loader.c (Text)"
  21. sed 's/^X//' << 'SHAR_EOF' > loader.c &&
  22. X
  23. X#ifndef lint
  24. Xstatic char sccsid[] = "@(#) loader.c 1.5 1/18/91 by DePalma SoftCraft";
  25. X#endif
  26. X
  27. X/* UNIX System V/386 COFF Dynamic Loader (CDL).
  28. X*/
  29. X#ifndef PORTAR
  30. X#  define PORTAR yes
  31. X#endif
  32. X
  33. X#include <errno.h>
  34. X#include <stdio.h>
  35. X#include <sys/stat.h>
  36. X#include <sys/fcntl.h>
  37. X#include <a.out.h>
  38. X#include <ldfcn.h>
  39. X
  40. X#include "craft.h"
  41. X#include "loader.h"
  42. X
  43. X
  44. X/*
  45. X   NAME
  46. X       assort(CDL) -- adjust and sort out symbols.
  47. X
  48. X   SYNOPSIS
  49. X*/
  50. X       int assort(source, seed, name, symndx, dynamic)
  51. X       buffer_t   source;
  52. X       caddr_t *  seed;
  53. X       char *     name;
  54. X       int        symndx;
  55. X       loader_t   dynamic;
  56. X/*
  57. X   DESCRIPTION
  58. X       The goal here is to provide correct values for symbols and
  59. X       and place those which are defined in the 'seed' structure.
  60. X*/
  61. X{
  62. X  SYMENT *  symbol = (SYMENT *) (dynamic->table + symndx * SYMESZ);
  63. X  caddr_t   item;
  64. X
  65. X/* object archive support
  66. X*/
  67. X  if (AVLsearch(*seed, (caddr_t) name, &item, strcmp) == SUCCESS)
  68. X    {
  69. X      collect_t parcel = (collect_t) item;
  70. X
  71. X      if (symbol->n_scnum || (symbol->n_scnum == N_UNDEF && symbol->n_value))
  72. X        {
  73. X          if (symbol->n_scnum == N_UNDEF && symbol->n_value)
  74. X            {
  75. X              if (symbol->n_value = (long) allocate(NIL, symbol->n_value))
  76. X                symbol->n_sclass = (char) 0;
  77. X              else
  78. X                return ELDNOMEM;
  79. X            }
  80. X
  81. X          parcel->sector  = sectarian(symbol->n_scnum);
  82. X          parcel->segment = source->base;
  83. X          parcel->site    = symbol->n_value;
  84. X        }
  85. X
  86. X      return SUCCESS;
  87. X    }
  88. X
  89. X/* see if it's a global symbol
  90. X*/
  91. X  if (AVLsearch(Global, (caddr_t) name, &item, strcmp) == SUCCESS)
  92. X    if (symbol->n_scnum == N_UNDEF)
  93. X      {
  94. X        collect_t parcel = (collect_t) item;
  95. X
  96. X        symbol->n_value = parcel->site;
  97. X
  98. X        if (parcel->sector == N_DATA || parcel->sector == N_BSS)
  99. X          symbol->n_sclass = (char) 0;
  100. X
  101. X        return SUCCESS;
  102. X      }
  103. X
  104. X/* see if it's uninitialized data
  105. X*/
  106. X  if (symbol->n_scnum == N_UNDEF && symbol->n_value)
  107. X    {
  108. X      if (symbol->n_value = (long) allocate(NIL, symbol->n_value))
  109. X        symbol->n_sclass = (char) 0;
  110. X      else
  111. X        return ELDNOMEM;
  112. X    }
  113. X
  114. X  return collect(source, seed, name, symbol, dynamic);
  115. X} /* assort */
  116. X
  117. X
  118. X
  119. X/*
  120. X   NAME
  121. X       collect(CDL) -- collect symbols.
  122. X
  123. X   SYNOPSIS
  124. X*/
  125. X       static int collect(source, seed, name, symbol, dynamic)
  126. X       buffer_t   source;
  127. X       caddr_t *  seed;
  128. X       char *     name;
  129. X       SYMENT *   symbol;
  130. X       loader_t   dynamic;
  131. X/*
  132. X   DESCRIPTION
  133. X*/
  134. X{
  135. X  collect_t  parcel = (collect_t) 0;
  136. X  int        status;
  137. X
  138. X  if (! (parcel = (collect_t) allocate(NIL, sizeof(struct _collect))))
  139. X    return ELDNOMEM;
  140. X
  141. X  if (symbol)
  142. X    {
  143. X      parcel->sector  = sectarian(symbol->n_scnum);
  144. X      parcel->segment = source->base;
  145. X      parcel->site    = symbol->n_value;
  146. X    }
  147. X  else
  148. X    {
  149. X      parcel->sector  = N_FILE;
  150. X      parcel->segment = (dynamic) ? dynamic->segment : (char *) 0;
  151. X      parcel->site    = source->mark;
  152. X    }
  153. X
  154. X  status = AVLinsert(seed, (caddr_t) name, (caddr_t) parcel, strcmp);
  155. X
  156. X  if (status != SUCCESS)
  157. X    {
  158. X      deallocate((caddr_t) parcel);
  159. X      status = DUBIOUS(status);
  160. X    }
  161. X
  162. X  return status;
  163. X} /* collect */
  164. X
  165. X
  166. X
  167. X/*
  168. X   NAME
  169. X       destruct(CDL) -- dispose of a single stored symbol.
  170. X
  171. X   SYNOPSIS
  172. X*/
  173. X       static int destruct(key, item)
  174. X       caddr_t  key;
  175. X       caddr_t  item;
  176. X/*
  177. X   DESCRIPTION
  178. X*/
  179. X{
  180. X  deallocate(item);
  181. X  deallocate(key);
  182. X
  183. X  return SUCCESS;
  184. X} /* destruct */
  185. X
  186. X
  187. X
  188. X/*
  189. X   NAME
  190. X       initialize(CDL) -- dynamic loader initialization.
  191. X
  192. X   SYNOPSIS
  193. X*/
  194. X       static int initialize(pid)
  195. X       int pid;
  196. X/*
  197. X   DESCRIPTION
  198. X       Initialization consists on a "ps -fp `echo $$`" using the 8th
  199. X       field of the last line of output from that command.
  200. X*/
  201. X{
  202. X  if (Global == (caddr_t) 0)               /* initialization required  */
  203. X    {
  204. X      FILE *    stream;
  205. X      LDFILE *  ldptr;
  206. X      char      line[BUFSIZ];
  207. X      char *    image;
  208. X      int       status;
  209. X      short     scan;
  210. X
  211. X      (void) sprintf(line, "ps -fp %d", pid);
  212. X
  213. X      if (stream = popen(line, "r"))
  214. X        while (fgets(line, BUFSIZ, stream))
  215. X          ;
  216. X
  217. X      for (scan = 0; scan < 8; scan++)     /* 'image' is the 8th field */
  218. X        image = strtok((scan) ? NULL : line, " ");
  219. X
  220. X      ldptr  = ldopen(image = which(image), NULL);
  221. X      status = (ldptr) ? SUCCESS : ERROR(sys_errlist, errno);
  222. X
  223. X      if (status == SUCCESS)
  224. X        {
  225. X          struct _buffer    record;
  226. X          struct _buffer *  source = &record;
  227. X
  228. X          if ((status = quantum(ldptr, source, image)) == SUCCESS)
  229. X            status = prospect(ldptr, source, &Global, NIL);
  230. X
  231. X          (void) ldclose(ldptr);
  232. X        }
  233. X
  234. X      return status;
  235. X    }
  236. X
  237. X  return SUCCESS;
  238. X} /* initialize */
  239. X
  240. X
  241. X
  242. X/*
  243. X   NAME
  244. X       process(CDL) -- driver for loading a module.
  245. X
  246. X   SYNOPSIS
  247. X*/
  248. X       static int process(ldptr, source, seed, card)
  249. X       LDFILE *   ldptr;
  250. X       buffer_t   source;
  251. X       caddr_t *  seed;
  252. X       caddr_t *  card;
  253. X/*
  254. X   DESCRIPTION
  255. X*/
  256. X{
  257. X  int       status;
  258. X  loader_t  dynamic;
  259. X
  260. X  if (! (dynamic = (loader_t) allocate(NIL, sizeof(struct _loader))))
  261. X    return ELDNOMEM;
  262. X
  263. X  if ((status = profile(ldptr, dynamic)) == SUCCESS)
  264. X    if ((status = prospect(ldptr, source, seed, dynamic)) == SUCCESS)
  265. X      if (Stack(card, (caddr_t) dynamic) == (caddr_t) 0)
  266. X        status = ELDNOMEM;
  267. X
  268. X  if (status != SUCCESS)
  269. X    {
  270. X      deallocate((caddr_t) dynamic->reloc.base);
  271. X      deallocate((caddr_t) dynamic->segment);
  272. X      deallocate((caddr_t) dynamic->table);
  273. X      deallocate((caddr_t) dynamic);
  274. X    }
  275. X
  276. X  return status;
  277. X} /* process */
  278. X
  279. X
  280. X
  281. X/*
  282. X   NAME
  283. X       profile(CDL) -- read relevant information.
  284. X
  285. X   SYNOPSIS
  286. X*/
  287. X       static int profile(ldptr, dynamic)
  288. X       LDFILE *  ldptr;
  289. X       loader_t  dynamic;
  290. X/*
  291. X   DESCRIPTION
  292. X       Sufficient memory is allocated for combined section data,
  293. X       relocation information, and symbol table; each of these parts
  294. X       are read from the LDFILE* 'ldptr' into their respective
  295. X       loader_t (see, loader.h) 'dynamic' component.
  296. X*/
  297. X{
  298. X  FILHDR *  header = &HEADER(ldptr);
  299. X  SCNHDR    scnhdr;
  300. X  SCNHDR *  section = &scnhdr;
  301. X  long      region = (long) 0;
  302. X  ushort    nreloc = (ushort) 0;
  303. X  ushort    scnum;
  304. X
  305. X  if (! ISCOFF(header->f_magic))
  306. X    return ELDBADHDR;
  307. X
  308. X/* read section headers and track size of combined section data
  309. X   along with the number of relocation entries
  310. X*/
  311. X  for (scnum = 1; scnum <= header->f_nscns; scnum++)
  312. X    {
  313. X      if (ldshread(ldptr, scnum, section) == FAILURE)
  314. X        return ELDSCNHDR;
  315. X
  316. X      nreloc += section->s_nreloc;
  317. X      region += section->s_size;
  318. X    }
  319. X
  320. X/* allocate and read combined section data
  321. X*/
  322. X  if (! (dynamic->segment = (char *) allocate(NIL, region)))
  323. X    return ELDNOMEM;
  324. X
  325. X  if (ldsseek(ldptr, N_TEXT) == FAILURE && errno > 0)
  326. X    return ERROR(sys_errlist, errno);
  327. X
  328. X  if (FREAD(dynamic->segment, sizeof(char), region, ldptr) != region)
  329. X    return ELDSECTION;
  330. X
  331. X/* allocate and read combined relocation entries
  332. X*/
  333. X  region = (long) nreloc * RELSZ;
  334. X
  335. X  if (! (dynamic->reloc.base = (char *) allocate(NIL, region)))
  336. X    return ELDNOMEM;
  337. X
  338. X  dynamic->reloc.mark = (long) nreloc;
  339. X
  340. X  if (FREAD(dynamic->reloc.base, sizeof(char), region, ldptr) != region)
  341. X    return ELDRELOC;
  342. X
  343. X/* allocate and read the symbol table (assume: AUXESZ == SYMESZ)
  344. X*/
  345. X  region = header->f_nsyms * SYMESZ;
  346. X
  347. X  if (! (dynamic->table = (char *) allocate(NIL, region)))
  348. X    return ELDNOMEM;
  349. X
  350. X  if (ldtbseek(ldptr) == FAILURE)
  351. X    return ERROR(sys_errlist, errno);
  352. X
  353. X  if (FREAD(dynamic->table, sizeof(char), region, ldptr) != region)
  354. X    return ELDSYMBOL;
  355. X
  356. X  return SUCCESS;
  357. X} /* profile */
  358. X
  359. X
  360. X
  361. X/*
  362. X   NAME
  363. X       prospect(CDL) -- store global symbols.
  364. X
  365. X   SYNOPSIS
  366. X*/
  367. X       static int prospect(ldptr, source, seed, dynamic)
  368. X       LDFILE *   ldptr;
  369. X       buffer_t   source;
  370. X       caddr_t *  seed;
  371. X       loader_t   dynamic;
  372. X/*
  373. X   DESCRIPTION
  374. X*/
  375. X{
  376. X  SYMENT   syment;
  377. X  SYMENT * symbol = &syment;
  378. X  int      status = SUCCESS;
  379. X  ushort   symndx;
  380. X  ushort   nsyms;
  381. X
  382. X  for (nsyms = HEADER(ldptr).f_nsyms, symndx = 0; symndx < nsyms; )
  383. X    {
  384. X      if (ldtbread(ldptr, symndx, symbol) == FAILURE)
  385. X        break;
  386. X
  387. X      if (symbol->n_sclass == C_EXT && symbol->n_scnum >= 0)
  388. X        {
  389. X          char *  name = strdup(ldgetname(ldptr, symbol));
  390. X
  391. X          if (dynamic)
  392. X            status = assort(source, seed, name, symndx, dynamic);
  393. X          else
  394. X            status = collect(source, seed, name, symbol, dynamic);
  395. X
  396. X          if (status != SUCCESS)
  397. X            break;
  398. X        }
  399. X      
  400. X      symndx += symbol->n_numaux + 1;
  401. X    }
  402. X
  403. X  if (status == SUCCESS)
  404. X    status = collect(source, seed, source->base, NULL, dynamic);
  405. X
  406. X  return status;
  407. X} /* prospect */
  408. X
  409. X
  410. X
  411. X/*
  412. X   NAME
  413. X       quantum(CDL) -- identify module.
  414. X
  415. X   SYNOPSIS
  416. X*/
  417. X       static int quantum(ldptr, source, module)
  418. X       LDFILE *  ldptr;
  419. X       buffer_t  source;
  420. X       char *    module;
  421. X/*
  422. X   DESCRIPTION
  423. X       Here we determine whether what is being processed is an object
  424. X       file or an archive. The buffer_t (see, craft.h) 'source' fields
  425. X       in either case are set to the module name and its modification
  426. X       date/time.
  427. X
  428. X   BUGS
  429. X       Although, there may be other reasons, ldahread(3X) failure is
  430. X       taken as proof that we're dealing with and object file.
  431. X*/
  432. X{
  433. X  ARCHDR  archdr;
  434. X  char    buffer[BLOCK];
  435. X
  436. X  if (ldahread(ldptr, &archdr) == SUCCESS)
  437. X    {
  438. X      (void) sprintf(buffer, "%s[%s]", module, archdr.ar_name);
  439. X
  440. X      source->base = strdup(buffer);
  441. X      source->mark = archdr.ar_date;
  442. X    }
  443. X  else
  444. X    {
  445. X      struct stat  info;
  446. X
  447. X      if (stat(module, &info) == -1)
  448. X        return ERROR(sys_errlist, errno);
  449. X
  450. X      source->base = strdup(module);
  451. X      source->mark = info.st_mtime;
  452. X    }
  453. X
  454. X  return SUCCESS;
  455. X} /* quantum */
  456. X
  457. X
  458. X
  459. X/*
  460. X   NAME
  461. X       realize(CDL) -- realize a newly loaded file.
  462. X
  463. X   SYNOPSIS
  464. X*/
  465. X       static int realize(symtab, card)
  466. X       caddr_t   symtab;
  467. X       caddr_t * card;
  468. X/*
  469. X   DESCRIPTION
  470. X*/
  471. X{
  472. X  int       status = SUCCESS;
  473. X  loader_t  dynamic;
  474. X
  475. X  AVLwalk(symtab, shepherd, (caddr_t) &status);
  476. X
  477. X  if (status == SUCCESS)
  478. X    {
  479. X      AVLwalk(symtab, sloven, (caddr_t) &status);
  480. X
  481. X      while (status == SUCCESS && (dynamic = (loader_t) Stack(card, NIL)))
  482. X        {
  483. X          status = resolve(dynamic);
  484. X
  485. X          if (status == SUCCESS)
  486. X            {
  487. X              struct _assoc   vehicle;
  488. X              struct _assoc * shuttle = &vehicle;
  489. X
  490. X              shuttle->key  = (caddr_t) dynamic->segment;
  491. X              shuttle->item = (caddr_t) &status;
  492. X
  493. X              AVLwalk(symtab, solder, (caddr_t) shuttle);
  494. X            }
  495. X
  496. X          if (status != SUCCESS)
  497. X            deallocate((caddr_t) dynamic->segment);
  498. X
  499. X          deallocate((caddr_t) dynamic->reloc.base);
  500. X          deallocate((caddr_t) dynamic->table);
  501. X          deallocate((caddr_t) dynamic);
  502. X        }
  503. X    }
  504. X
  505. X/* always: completely discard 'card' stack and contents
  506. X*/
  507. X  while (dynamic = (loader_t) Stack(card, NIL))
  508. X    {
  509. X      deallocate((caddr_t) dynamic->reloc.base);
  510. X      deallocate((caddr_t) dynamic->segment);
  511. X      deallocate((caddr_t) dynamic->table);
  512. X      deallocate((caddr_t) dynamic);
  513. X    }
  514. X
  515. X  return status;
  516. X} /* realize */
  517. X
  518. X
  519. X
  520. X/*
  521. X   NAME
  522. X       resolve(CDL) -- resolve relocation entries.
  523. X
  524. X   SYNOPSIS
  525. X*/
  526. X       static int resolve(dynamic)
  527. X       loader_t  dynamic;
  528. X/*
  529. X   DESCRIPTION
  530. X*/
  531. X{
  532. X  SYMENT * symbol;
  533. X  RELOC *  reloc;
  534. X  char *   address;
  535. X  long     datum;
  536. X  ushort   nreloc;
  537. X  ushort   count;
  538. X
  539. X  for (count = 0, nreloc = dynamic->reloc.mark; count < nreloc; count++)
  540. X    {
  541. X      reloc = (RELOC *) (dynamic->reloc.base + count * RELSZ);
  542. X
  543. X      if (reloc->r_type == R_ABS)   /* absolute: no relocation necessary */
  544. X        continue;
  545. X
  546. X      address = (char *) (reloc->r_vaddr + (long) dynamic->segment);
  547. X      symbol  = (SYMENT *) (dynamic->table + reloc->r_symndx * SYMESZ);
  548. X
  549. X      if (symbol->n_scnum == N_UNDEF || symbol->n_scnum == N_TEXT)
  550. X        datum = symbol->n_value;
  551. X      else
  552. X        datum = (long) 0;
  553. X
  554. X      if (symbol->n_sclass)         /* see, assort(CDL) for details */
  555. X        switch (reloc->r_type)
  556. X          {
  557. X            case R_DIR16:
  558. X              (void) puts(DANGER("relocation type R_DIR16 untested"));
  559. X              datum += *(short *) address + (long) dynamic->segment;
  560. X            break;
  561. X
  562. X            case R_REL16:
  563. X              (void) puts(DANGER("relocation type R_REL16 untested"));
  564. X              if (datum)
  565. X                datum -= (long) address + sizeof(short);
  566. X            break;
  567. X
  568. X            case R_DIR32:
  569. X              datum += *(long *) address + (long) dynamic->segment;
  570. X            break;
  571. X
  572. X            case R_PCRLONG:
  573. X              if (datum)
  574. X                datum -= (long) address + sizeof(long);
  575. X            break;
  576. X
  577. X            default:
  578. X              return ELDRESOLVE;
  579. X          }
  580. X
  581. X      switch (reloc->r_type)
  582. X        {
  583. X          case R_DIR16:             /* direct, 16-bit reference          */
  584. X          case R_REL16:             /* PC relative, 16-bit reference     */
  585. X            if (datum < -32768 || datum > 32767)
  586. X              return ELDRESOLVE;
  587. X
  588. X            *(short *) address = datum;
  589. X          break;
  590. X
  591. X          case R_DIR32:             /* direct, 32-bit reference          */
  592. X          case R_PCRLONG:           /* PC relative, 32-bit reference     */
  593. X            if (datum)
  594. X              *(long *) address = datum;
  595. X          break;
  596. X
  597. X          default:
  598. X            return ELDRESOLVE;
  599. X        }
  600. X    }
  601. X
  602. X  return SUCCESS;
  603. X} /* resolve */
  604. X
  605. X
  606. X
  607. X/*
  608. X   NAME
  609. X       selector(CDL) -- select a global symbol.
  610. X
  611. X   SYNOPSIS
  612. X*/
  613. X       static int selector(key, item, ark)
  614. X       caddr_t  key;
  615. X       caddr_t  item;
  616. X       caddr_t  ark;
  617. X/*
  618. X   DESCRIPTION
  619. X       Selector inserts a global symbol in a 'list' when
  620. X       the symbol belongs to the 'module' given.
  621. X
  622. X          ark -> +--------+
  623. X                 | module |
  624. X                 |--------|
  625. X                 | list   |
  626. X                 +--------+
  627. X*/
  628. X{
  629. X  assoc_t shuttle = (assoc_t) ark;
  630. X  collect_t parcel = (collect_t) item;
  631. X  int status = SUCCESS;
  632. X
  633. X  if (parcel->sector != N_FILE)
  634. X    if (strcmp(parcel->segment, (char *) shuttle->key) == 0)
  635. X      status = LLinsert(&(shuttle->item), key, item);
  636. X
  637. X  return status;
  638. X} /* selector */
  639. X
  640. X
  641. X
  642. X/*
  643. X   NAME
  644. X       shepherd(CDL) -- govern a local symbol tree.
  645. X
  646. X   SYNOPSIS
  647. X*/
  648. X       static int shepherd(key, item, ark)
  649. X       caddr_t  key;
  650. X       caddr_t  item;
  651. X       caddr_t  ark;
  652. X/*
  653. X   DESCRIPTION
  654. X       Shepherd flags multiply defined symbols and corrects the
  655. X       address for those which exist.
  656. X*/
  657. X{
  658. X  caddr_t store = (caddr_t) 0;
  659. X
  660. X  if (AVLsearch(Global, key, &store, strcmp) == SUCCESS)
  661. X    {
  662. X      collect_t packet = (collect_t) item;
  663. X      collect_t parcel = (collect_t) store;
  664. X      int * state      = (int *) ark;
  665. X
  666. X      if (*state == SUCCESS)
  667. X        {
  668. X          *state = FAILURE;
  669. X          error(ELDMULDEF);
  670. X        }
  671. X
  672. X      error(ERRMSG, "%s : '%s' already defined in '%s'",
  673. X                packet->segment, key, parcel->segment);
  674. X    }
  675. X
  676. X  return SUCCESS;
  677. X} /* shepherd */
  678. X
  679. X
  680. X
  681. X/*
  682. X   NAME
  683. X       sloven(CDL) -- flag undefined symbols.
  684. X
  685. X   SYNOPSIS
  686. X*/
  687. X       static int sloven(key, item, ark)
  688. X       caddr_t  key;
  689. X       caddr_t  item;
  690. X       caddr_t  ark;
  691. X/*
  692. X   DESCRIPTION
  693. X*/
  694. X{
  695. X  collect_t parcel = (collect_t) item;
  696. X
  697. X  if (parcel->sector == N_UNDEF && parcel->site == (long) 0)
  698. X    {
  699. X      int * state = (int *) ark;
  700. X
  701. X      if (*state == SUCCESS)
  702. X        {
  703. X          *state = FAILURE;
  704. X          error(ELDUNDEF);
  705. X        }
  706. X
  707. X      error(ERRMSG, "'%s' referenced in '%s'", key, parcel->segment);
  708. X    }
  709. X
  710. X  return SUCCESS;
  711. X} /* sloven */
  712. X
  713. X
  714. X
  715. X/*
  716. X   NAME
  717. X       solder(CDL) -- add new symbols to global structure.
  718. X
  719. X   SYNOPSIS
  720. X*/
  721. X       static int solder(key, item, ark)
  722. X       caddr_t  key;
  723. X       caddr_t  item;
  724. X       caddr_t  ark;
  725. X/*
  726. X   DESCRIPTION
  727. X       Solder is an action routine which serves to copy a symbol
  728. X       from a working structure to the global symbols structure.
  729. X
  730. X          ark -> +--------------------------------+
  731. X                 | loader_t record                |
  732. X                 |--------------------------------|
  733. X                 | start of combined section data |
  734. X                 +--------------------------------+
  735. X*/
  736. X{
  737. X  assoc_t   shuttle = (assoc_t) ark;
  738. X  collect_t parcel  = (collect_t) item;
  739. X  int *     state   = (int *) shuttle->item;
  740. X
  741. X  if (*state == SUCCESS)
  742. X    {
  743. X      collect_t store;
  744. X
  745. X      if (store = (collect_t) allocate(NIL, sizeof(struct _collect)))
  746. X        {
  747. X          store->sector  = parcel->sector;
  748. X          store->segment = parcel->segment;
  749. X          store->site    = parcel->site;
  750. X
  751. X          if (store->sector != N_FILE)
  752. X            store->site += (long) shuttle->key;
  753. X
  754. X          *state = AVLinsert(&Global, (caddr_t) key, (caddr_t) store, strcmp);
  755. X        }
  756. X      else
  757. X        {
  758. X          *state = ELDNOMEM;
  759. X        }
  760. X    }
  761. X
  762. X  return SUCCESS;
  763. X} /* solder */
  764. X
  765. X
  766. X
  767. X/*
  768. X   NAME
  769. X       solvent(CDL) -- remove a global symbol.
  770. X
  771. X   SYNOPSIS
  772. X*/
  773. X       static int solvent(key, item)
  774. X       caddr_t  key;
  775. X       caddr_t  item;
  776. X/*
  777. X   DESCRIPTION
  778. X*/
  779. X{
  780. X  return AVLremove(&Global, key, strcmp, destruct);
  781. X} /* solvent */
  782. X
  783. X
  784. X
  785. X/*
  786. X   NAME
  787. X       load(3L) -- load a common object file.
  788. X
  789. X   SYNOPSIS
  790. X*/
  791. X       int load(module)
  792. X       char *  module;
  793. X/*
  794. X   DESCRIPTION
  795. X       If the given 'module' has been loaded already its modification
  796. X       date is compared with the dynamic loading date; when the two dates
  797. X       differ an unload(3L) is performed on the one in memory and dynamic
  798. X       loading is then attempted with the 'module' given.
  799. X
  800. X   SEE ALSO
  801. X       error(3L), symbol(3L), unload(3L).
  802. X
  803. X   DIAGNOSTICS
  804. X       Upon successful completion SUCCESS is returned. Otherwise the
  805. X       value of the return status indicates what error was encountered.
  806. X*/
  807. X{
  808. X  LDFILE *          ldptr = (LDFILE *) 0;
  809. X  caddr_t           item;
  810. X  caddr_t           symtab = (caddr_t) 0;
  811. X  caddr_t           vitals = (caddr_t) 0;
  812. X  int               status;
  813. X  long              stamp;
  814. X  struct _buffer    record;
  815. X  struct _buffer *  source = &record;
  816. X
  817. X  if ((status = initialize(getpid())) == SUCCESS)
  818. X    {
  819. X      do
  820. X        {
  821. X          if (ldptr = ldopen(module, ldptr))
  822. X            {
  823. X              if ((status = quantum(ldptr, source, module)) != SUCCESS)
  824. X                break;
  825. X
  826. X              if (stamp = (long) symbol(source->base))
  827. X                {
  828. X                  if (stamp == source->mark)
  829. X                    continue;
  830. X
  831. X                  if ((status = unload(source->base)) != SUCCESS)
  832. X                    break;
  833. X                }
  834. X
  835. X              status = process(ldptr, source, &symtab, &vitals);
  836. X            }
  837. X        } while (ldclose(ldptr) == FAILURE && status == SUCCESS);
  838. X
  839. X      if (symtab)
  840. X        {
  841. X          if (status == SUCCESS)              /* augment global structure  */
  842. X            status = realize(symtab, &vitals);
  843. X
  844. X          AVLdispose(symtab, (agent_t)((status == SUCCESS) ? 0 : destruct));
  845. X        }
  846. X      else
  847. X        {
  848. X          if (errno)
  849. X            status = ERROR(sys_errlist, errno);
  850. X        }
  851. X    }
  852. X
  853. X  return status;
  854. X} /* load */
  855. X
  856. X
  857. X
  858. X/*
  859. X   NAME
  860. X       symbol(3L) -- symbol look up.
  861. X
  862. X   SYNOPSIS
  863. X*/
  864. X       void *  symbol(name)
  865. X       char *  name;
  866. X/*
  867. X   DESCRIPTION
  868. X       The specified 'name' is looked up and if found its value returned.
  869. X       A value of NIL indicates look up failure.
  870. X*/
  871. X{
  872. X  caddr_t item;
  873. X  void *  entry = NIL;
  874. X
  875. X  if (AVLsearch(Global, (caddr_t) name, &item, strcmp) == SUCCESS)
  876. X    {
  877. X      collect_t parcel = (collect_t) item;
  878. X
  879. X      entry = (void *) parcel->site;
  880. X    }
  881. X
  882. X  return entry;
  883. X} /* symbol */
  884. X
  885. X
  886. X
  887. X/*
  888. X   NAME
  889. X       unload(3L) -- unload all symbols associated with a module.
  890. X
  891. X   SYNOPSIS
  892. X*/
  893. X       int unload(module)
  894. X       char *  module;
  895. X/*
  896. X   DESCRIPTION
  897. X       All symbols associated with the given module are indiscriminately
  898. X       removed and any memory allocated is freed.
  899. X*/
  900. X{
  901. X  caddr_t         item;
  902. X  collect_t       parcel;
  903. X  struct _assoc   vehicle;
  904. X  struct _assoc * shuttle = &vehicle;
  905. X
  906. X  if (AVLsearch(Global, (caddr_t) module, &item, strcmp) != SUCCESS)
  907. X    return ELDNOFILE;
  908. X
  909. X  shuttle->key  = (caddr_t) module;
  910. X  shuttle->item = (caddr_t) 0;
  911. X
  912. X/* we cannot directly remove symbols
  913. X*/
  914. X  AVLwalk(Global, selector, (caddr_t) shuttle);
  915. X
  916. X  LLwalk(shuttle->item, solvent, NIL);
  917. X  LLdispose(shuttle->item, destruct);
  918. X
  919. X/* free what we allocated for combined section data
  920. X*/
  921. X  parcel = (collect_t) item;
  922. X
  923. X  if (parcel->segment)
  924. X    deallocate(parcel->segment);
  925. X
  926. X  return DUBIOUS(AVLremove(&Global, (caddr_t) module, strcmp, destruct));
  927. X} /* unload */
  928. X
  929. X
  930. X
  931. X#ifdef DEBUG
  932. X/*
  933. X   NAME
  934. X       display -- display routine for symbols.
  935. X
  936. X   SYNOPSIS
  937. X*/
  938. X       static int display(key, item, nest, ark)
  939. X       caddr_t  key;
  940. X       caddr_t  item;
  941. X       int      nest;
  942. X       caddr_t  ark;
  943. X/*
  944. X   DESCRIPTION
  945. X*/
  946. X{
  947. X  collect_t  parcel = (collect_t) item;
  948. X  int        status;
  949. X
  950. X  if (parcel->sector == N_FILE)
  951. X    status = printf("%19s(%d) : 0x%8.8x\n", (char*) key,
  952. X                     parcel->site, (long) parcel->segment);
  953. X  else
  954. X    status = printf("%19s(%s) : 0x%8.8x\n", (char*) key,
  955. X                     parcel->segment, parcel->site);
  956. X
  957. X  return status;
  958. X} /* display */
  959. X
  960. X
  961. X
  962. X/*
  963. X   NAME
  964. X       dump -- dump symbol table.
  965. X
  966. X   SYNOPSIS
  967. X*/
  968. X       void dump(symtab)
  969. X       caddr_t  symtab;
  970. X/*
  971. X   DESCRIPTION
  972. X*/
  973. X{
  974. X
  975. X  AVLdump(symtab, display, NIL);
  976. X} /* dump */
  977. X#endif /* DEBUG */
  978. SHAR_EOF
  979. $TOUCH -am 0118122491 loader.c &&
  980. chmod 0444 loader.c ||
  981. echo "restore of loader.c failed"
  982. set `wc -c loader.c`;Wc_c=$1
  983. if test "$Wc_c" != "21155"; then
  984.     echo original size 21155, current size $Wc_c
  985. fi
  986. # ============= loader.h ==============
  987. echo "x - extracting loader.h (Text)"
  988. sed 's/^X//' << 'SHAR_EOF' > loader.h &&
  989. X
  990. X/* UNIX System V/386 COFF Dynamic Loader (CDL) header file.
  991. X
  992. X   loader.h 1.5 1/18/91 by DePalma SoftCraft
  993. X*/
  994. X
  995. X#ifndef __LOADER_H__                   /* guard against multiple includes   */
  996. X#define __LOADER_H__
  997. X
  998. X/* mauro@olympus (19910104.1808)
  999. X
  1000. X     The, UNIX System V/386 Programmer's Guide warns that it is a mistake
  1001. X     to assume the characteristics of sections in general of a COFF file.
  1002. X
  1003. X     Here however the assumption is made that the sections named '.text',
  1004. X     '.data', '.bss' appear as the first three sections in a COFF file.
  1005. X*/
  1006. X#define sectarian(x) (x)               /* .. only if assumption hold true   */
  1007. X
  1008. X#define N_TEXT       1                 /* mnemonic for '.text' section      */
  1009. X#define N_DATA       2                 /* mnemonic for '.data' section      */
  1010. X#define N_BSS        3                 /* mnemonic for '.bss'  section      */
  1011. X
  1012. X#define N_FILE       0x1f              /* special: file name symbol         */
  1013. X
  1014. X
  1015. Xtypedef union                          /* either symbol or auxiliary entry  */
  1016. X  {
  1017. X          AUXENT auxent;               /* .. auxiliary entry                */
  1018. X          SYMENT syment;               /* .. symbol entry                   */
  1019. X  } SYMBOL;
  1020. X
  1021. X
  1022. Xtypedef struct _collect                /* Dynamic Loader symbol data        */
  1023. X  {
  1024. X          char    sector;              /* .. section mnemonic or N_FILE     */
  1025. X          char *  segment;             /* .. combined section data or file  */ 
  1026. X          long    site;                /* .. offset in memory or date/time  */
  1027. X  } *collect_t;
  1028. X
  1029. X
  1030. Xtypedef struct _loader                 /* Dynamic Loader data structure     */
  1031. X  {
  1032. X          struct _buffer reloc;        /* .. relocation entries             */
  1033. X          char *         segment;      /* .. start of combined section data */
  1034. X          char *         table;        /* .. symbol table and auxiliary     */
  1035. X  } *loader_t;
  1036. X
  1037. X
  1038. X/* Dynamic Loader Specific Errors (should be read from a message file)
  1039. X*/
  1040. Xstatic char *ldErrorList[] =
  1041. X  {
  1042. X    "",
  1043. X    "The file doesn't have a COFF header",                           /*  1 */
  1044. X    "Dynamic Loader cannot allocate enough memory",                  /*  2 */
  1045. X    "An error was encountered while reading the file header",        /*  3 */
  1046. X    "An error was encountered while reading the optional header",    /*  4 */
  1047. X    "An error was encountered while reading a section header",       /*  5 */
  1048. X    "An error was encountered while reading section data",           /*  6 */
  1049. X    "An error was encountered while reading relocation information", /*  7 */
  1050. X    "An error was encountered while reading the symbol table",       /*  8 */
  1051. X    "The following symbols are multiply defined:",                   /*  9 */
  1052. X    "The following symbols remain undefined:",                       /* 10 */
  1053. X    "Dynamic Loader cannot handle a relocation entry",               /* 11 */
  1054. X    "No such file dynamically loaded",                               /* 12 */
  1055. X    0
  1056. X  };
  1057. X
  1058. X#define ELDBADHDR   ERROR(ldErrorList, 1)  /* invalid a.out header         */
  1059. X#define ELDNOMEM    ERROR(ldErrorList, 2)  /* can't allocate enough memory */
  1060. X#define ELDFILHDR   ERROR(ldErrorList, 3)  /* error reading file header    */
  1061. X#define ELDOPTHDR   ERROR(ldErrorList, 4)  /* error reading optional header*/
  1062. X#define ELDSCNHDR   ERROR(ldErrorList, 5)  /* error reading section header */
  1063. X#define ELDSECTION  ERROR(ldErrorList, 6)  /* error reading section data   */
  1064. X#define ELDRELOC    ERROR(ldErrorList, 7)  /* error reading reloc. entries */
  1065. X#define ELDSYMBOL   ERROR(ldErrorList, 8)  /* error reading symbol table   */
  1066. X#define ELDMULDEF   ERROR(ldErrorList, 9)  /* multiply defined symbol(s)   */
  1067. X#define ELDUNDEF    ERROR(ldErrorList, 10) /* unresolved symbol(s)         */
  1068. X#define ELDRESOLVE  ERROR(ldErrorList, 11) /* (internal) unable to resolve */
  1069. X#define ELDNOFILE   ERROR(ldErrorList, 12) /* file was not loaded          */
  1070. X
  1071. X
  1072. X
  1073. X/* Dynamic Loader Private
  1074. X*/
  1075. Xstatic int assort(buffer_t, caddr_t *, char *, int, loader_t);
  1076. Xstatic int collect(buffer_t, caddr_t *, char *, SYMENT *, loader_t);
  1077. Xstatic int destruct(caddr_t, caddr_t);
  1078. X
  1079. Xstatic int initialize(int);
  1080. Xstatic int process(LDFILE *, buffer_t, caddr_t *, caddr_t *);
  1081. Xstatic int profile(LDFILE *, loader_t);
  1082. Xstatic int prospect(LDFILE *, buffer_t, caddr_t *, loader_t);
  1083. Xstatic int quantum(LDFILE *, buffer_t, char *);
  1084. Xstatic int realize(caddr_t, caddr_t *);
  1085. Xstatic int resolve(loader_t);
  1086. X
  1087. Xstatic int selector(caddr_t, caddr_t, caddr_t);
  1088. Xstatic int shepherd(caddr_t, caddr_t, caddr_t);
  1089. Xstatic int sloven(caddr_t, caddr_t, caddr_t);
  1090. Xstatic int solder(caddr_t, caddr_t, caddr_t);
  1091. Xstatic int solvent(caddr_t, caddr_t);
  1092. X
  1093. Xstatic caddr_t Global = (caddr_t) 0;        /* symbol table for globals   */
  1094. X
  1095. X
  1096. X/* Dynamic Loader Externals
  1097. X*/
  1098. Xextern char *  ldgetname(LDFILE *, SYMENT *);
  1099. X#endif /*  __LOADER_H__ */
  1100. X
  1101. SHAR_EOF
  1102. $TOUCH -am 0118122491 loader.h &&
  1103. chmod 0444 loader.h ||
  1104. echo "restore of loader.h failed"
  1105. set `wc -c loader.h`;Wc_c=$1
  1106. if test "$Wc_c" != "4799"; then
  1107.     echo original size 4799, current size $Wc_c
  1108. fi
  1109. # ============= simple.c ==============
  1110. echo "x - extracting simple.c (Text)"
  1111. sed 's/^X//' << 'SHAR_EOF' > simple.c &&
  1112. X
  1113. X#include <stdio.h>
  1114. X
  1115. Xextern char* sys_errlist[];
  1116. X
  1117. Xchar *module = __FILE__;
  1118. Xshort bogus;
  1119. X
  1120. Xvoyage(char* caller)
  1121. X{
  1122. X  char* routine = "voyage";
  1123. X
  1124. X  (void) printf("<%s line %d> %s: called by, '%s'\n",
  1125. X                  module, __LINE__, routine, caller);
  1126. X  gossip(routine);
  1127. X}
  1128. X
  1129. Xgossip(char* caller)
  1130. X{
  1131. X  char* routine = "gossip";
  1132. X
  1133. X  (void) printf("<%s line %d> %s: called by, '%s'\n",
  1134. X                  module, __LINE__, routine, caller);
  1135. X
  1136. X  (void) printf("<%s line %d> %s: some extern data, '%s'\n",
  1137. X                  module, __LINE__, routine, sys_errlist[1]);
  1138. X
  1139. X  (void) printf("<%s line %d> %s: some local data, '%d'\n",
  1140. X                  module, __LINE__, routine, bogus=1234);
  1141. X}
  1142. SHAR_EOF
  1143. $TOUCH -am 0116200491 simple.c &&
  1144. chmod 0644 simple.c ||
  1145. echo "restore of simple.c failed"
  1146. set `wc -c simple.c`;Wc_c=$1
  1147. if test "$Wc_c" != "676"; then
  1148.     echo original size 676, current size $Wc_c
  1149. fi
  1150. exit 0
  1151.  
  1152. exit 0 # Just in case...
  1153. -- 
  1154. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1155. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1156. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1157. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1158.