extract.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. #ifndef lint
  6. static char rcsid[] = "$Id$";
  7. #endif
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include "arch.h"
  11. #include "out.h"
  12. #include "const.h"
  13. #include "debug.h"
  14. #include "memory.h"
  15. #include "orig.h"
  16. #include "scan.h"
  17. #include "defs.h"
  18. static void get_names(struct outhead *head);
  19. static void process(struct outhead *head);
  20. static void getexternal(struct outname *name);
  21. static void redefine(struct outname *new, struct outname *old);
  22. static void transfer(struct outname *src, struct outname *dst);
  23. /*
  24. * Get section sizes and symboltable information from present module.
  25. */
  26. void extract()
  27. {
  28. struct outhead head;
  29. get_modul();
  30. /*
  31. * Copy head because we need it so often but it can change place,
  32. * so we can't trust a pointer to it.
  33. */
  34. head = *(struct outhead *)modulptr(IND_HEAD);
  35. get_names(&head);
  36. process(&head);
  37. skip_modul(&head);
  38. }
  39. unsigned short NLocals = 0; /* Number of local names to be saved. */
  40. unsigned short NGlobals = 0; /* Number of global names. */
  41. /*
  42. * Walk through the nametable of this module, counting the locals that must
  43. * appear in the final output file if this module is linked.
  44. * That number will be returned.
  45. */
  46. static void get_names(struct outhead *head)
  47. {
  48. register int nnames;
  49. register ind_t nameindex, charindex;
  50. register ind_t charoff;
  51. extern int flagword;
  52. nnames = head->oh_nname;
  53. nameindex = IND_NAME(*head);
  54. charindex = IND_CHAR(*head);
  55. charoff = OFF_CHAR(*head);
  56. while (nnames--) {
  57. struct outname name; /* A local copy. */
  58. /*
  59. * Because savelocal/getexternal might relocate the modules
  60. * we have to compute the core addresses again.
  61. */
  62. name = *(struct outname *)modulptr(nameindex);
  63. /*
  64. * Change the offset in file into an offset in the memory area.
  65. * There will always be at least a header before the string
  66. * area, so we don't have to be afraid to confuse "no name"
  67. * with "the first name".
  68. */
  69. if (name.on_foff) {
  70. if (name.on_foff < charoff ||
  71. name.on_foff >= charoff+head->oh_nchar) {
  72. fatal("illegal offset in name");
  73. }
  74. name.on_foff += charindex - charoff;
  75. }
  76. namerelocate(&name);
  77. if ((name.on_type & S_TYP) == S_CRS) {
  78. name.on_valu += charindex - charoff;
  79. name.on_valu = savechar(ALLOGCHR, (ind_t)name.on_valu);
  80. }
  81. if (name.on_type & S_EXT) {
  82. getexternal(&name);
  83. } else {
  84. /*
  85. * The only thing we want to know about locals is
  86. * whether they must appear in the output file.
  87. */
  88. if (!(flagword & SFLAG) && mustsavelocal(&name)) {
  89. NLocals++;
  90. savelocal(&name);
  91. }
  92. }
  93. nameindex += sizeof(struct outname);
  94. }
  95. }
  96. extern struct orig relorig[];
  97. static void process(struct outhead *head)
  98. {
  99. struct outsect *sects;
  100. struct outsect *outsp;
  101. int nsect;
  102. struct orig *orig = relorig;
  103. extern struct outhead outhead;
  104. extern struct outsect outsect[];
  105. outhead.oh_nrelo += head->oh_nrelo;
  106. outhead.oh_nemit += head->oh_nemit;
  107. if (head->oh_nsect > outhead.oh_nsect)
  108. outhead.oh_nsect = head->oh_nsect;
  109. sects = (struct outsect *)modulptr(IND_SECT(*head));
  110. nsect = head->oh_nsect;
  111. outsp = outsect;
  112. while (nsect--) {
  113. if (sects->os_flen) {
  114. /* contains non-zero stuff */
  115. outhead.oh_nemit += outsp->os_size - outsp->os_flen;
  116. outsp->os_flen = outsp->os_size + sects->os_flen;
  117. }
  118. else {
  119. outsp->os_flen += sects->os_flen;
  120. }
  121. outsp->os_size += sects->os_size;
  122. /*
  123. * Add all flen's and all (size - flen == zero)'s of
  124. * preceding sections with the same number.
  125. */
  126. orig->org_size = outsp->os_size;
  127. orig++; outsp++; sects++;
  128. }
  129. }
  130. /*
  131. * Add relocation constant for names in user defined sections.
  132. * The value of a common name indicates a size instead of an offset,
  133. * and hence shouldn't be relocated.
  134. * Otherwise we just add the accumulated size of all normal parts in preceding
  135. * sections with the same size.
  136. */
  137. void namerelocate(struct outname *name)
  138. {
  139. int type = name->on_type;
  140. int sct = type & S_TYP;
  141. if (sct == S_UND || sct == S_ABS || sct == S_CRS)
  142. return;
  143. if (type & S_COM) {
  144. if ( ! (type&S_EXT) ) fatal("local commons should be handled by the assembler") ;
  145. return;
  146. }
  147. name->on_valu += relorig[(type & S_TYP) - S_MIN].org_size;
  148. }
  149. /*
  150. * If we see this name for the first time, we must remember it for
  151. * we might need it later on. Otherwise it must confirm to what we already
  152. * know about it, and eventually add to that knowledge.
  153. */
  154. static void getexternal(struct outname *name)
  155. {
  156. register char *string;
  157. register int h;
  158. register struct outname *old;
  159. extern int hash();
  160. extern struct outname *searchname();
  161. string = modulptr((ind_t)name->on_foff);
  162. h = hash(string);
  163. old = searchname(string, h);
  164. if (old == (struct outname *)0) {
  165. NGlobals++;
  166. entername(name, h);
  167. if (ISUNDEFINED(name)) {
  168. verbose("requires %s", string, 0, 0, 0);
  169. }
  170. } else if (!ISUNDEFINED(name)) {
  171. if (ISUNDEFINED(old)) {
  172. name->on_mptr = string; /* Just for convenience. */
  173. transfer(name, old);
  174. } else {
  175. name->on_mptr = string; /* Just for convenience. */
  176. redefine(name, old);
  177. }
  178. }
  179. }
  180. /*
  181. * Handle the redefinition of `new' in the current module.
  182. * A name can be defined in three ways, in increasing priority:
  183. * undefined,
  184. * common,
  185. * defined in a section.
  186. * A name may become "higher" when defined, but not "lower".
  187. * A redefinition as common is allowed. It is ignored, but a warning is given
  188. * when the desired section of `new' doesn't correspond with the section of
  189. * `old'. If a common definition is given again for a name, we take the
  190. * greatest value so that the common declared name always has enough space.
  191. * If a common is defined as a not-common, the old definition is ignored.
  192. */
  193. static void redefine(struct outname *new, struct outname *old)
  194. {
  195. if (!ISCOMMON(old)) {
  196. if (!ISCOMMON(new))
  197. error("%s: multiply defined", new->on_mptr);
  198. /*
  199. else if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
  200. warning("%s: sections differ", new->on_mptr);
  201. */
  202. } else {
  203. /* `Old' is common. */
  204. if (ISCOMMON(new)) {
  205. if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
  206. warning("%s: sections differ", new->on_mptr);
  207. if (new->on_valu > old->on_valu)
  208. old->on_valu = new->on_valu;
  209. } else {
  210. transfer(new, old);
  211. }
  212. }
  213. }
  214. /*
  215. * Transfer things we want to know from `src' to `dst'.
  216. */
  217. static void transfer(struct outname *src, struct outname *dst)
  218. {
  219. debug("%s defined here\n", src->on_mptr);
  220. dst->on_valu = src->on_valu;
  221. dst->on_type = src->on_type;
  222. dst->on_desc = src->on_desc;
  223. }