extract.c 6.4 KB

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