relocate.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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 <out.h>
  9. #include "const.h"
  10. #include "debug.h"
  11. #include "defs.h"
  12. #include "orig.h"
  13. #define UBYTE(x) ((x) & BYTEMASK)
  14. /*
  15. * The bits in type indicate how many bytes the value occupies and what
  16. * significance should be attributed to each byte.
  17. */
  18. static long
  19. getvalu(addr, type)
  20. char addr[];
  21. char type;
  22. {
  23. unsigned short word0, word1;
  24. switch (type & RELSZ) {
  25. case RELO1:
  26. return UBYTE(addr[0]);
  27. case RELO2:
  28. if (type & RELBR)
  29. return (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
  30. else
  31. return (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
  32. case RELO4:
  33. if (type & RELBR) {
  34. word0 = (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
  35. word1 = (UBYTE(addr[2]) << WIDTH) + UBYTE(addr[3]);
  36. } else {
  37. word0 = (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
  38. word1 = (UBYTE(addr[3]) << WIDTH) + UBYTE(addr[2]);
  39. }
  40. if (type & RELWR)
  41. return ((long)word0 << (2 * WIDTH)) + word1;
  42. else
  43. return ((long)word1 << (2 * WIDTH)) + word0;
  44. default:
  45. fatal("bad relocation size");
  46. }
  47. /* NOTREACHED */
  48. }
  49. /*
  50. * The bits in type indicate how many bytes the value occupies and what
  51. * significance should be attributed to each byte.
  52. * We do not check for overflow.
  53. */
  54. static
  55. putvalu(valu, addr, type)
  56. long valu;
  57. char addr[];
  58. char type;
  59. {
  60. unsigned short word0, word1;
  61. switch (type & RELSZ) {
  62. case RELO1:
  63. addr[0] = valu;
  64. break;
  65. case RELO2:
  66. if (type & RELBR) {
  67. addr[0] = valu >> WIDTH;
  68. addr[1] = valu;
  69. } else {
  70. addr[0] = valu;
  71. addr[1] = valu >> WIDTH;
  72. }
  73. break;
  74. case RELO4:
  75. if (type & RELWR) {
  76. word0 = valu >> (2 * WIDTH);
  77. word1 = valu;
  78. } else {
  79. word0 = valu;
  80. word1 = valu >> (2 * WIDTH);
  81. }
  82. if (type & RELBR) {
  83. addr[0] = word0 >> WIDTH;
  84. addr[1] = word0;
  85. addr[2] = word1 >> WIDTH;
  86. addr[3] = word1;
  87. } else {
  88. addr[0] = word0;
  89. addr[1] = word0 >> WIDTH;
  90. addr[2] = word1;
  91. addr[3] = word1 >> WIDTH;
  92. }
  93. break;
  94. default:
  95. fatal("bad relocation size");
  96. }
  97. }
  98. extern unsigned short NLocals, NGlobals;
  99. extern struct outsect outsect[];
  100. extern struct orig relorig[];
  101. /*
  102. * There are two cases: `local' is an undefined external or common name,
  103. * or `local' is a section name.
  104. * First case: if the name has been defined in another module,
  105. * its value is known and can be added. Or_nami will be the
  106. * index of the name of the section in which this name was
  107. * defined. Otherwise we must change or_nami to the index of
  108. * this name in the name table of the output file and leave
  109. * its value unchanged.
  110. * Second case: we must update the value by the change
  111. * in position of the section of local.
  112. */
  113. static unsigned
  114. addrelo(relo, names, valu_out)
  115. struct outrelo *relo;
  116. struct outname *names;
  117. long *valu_out; /* Out variable. */
  118. {
  119. register struct outname *local = &names[relo->or_nami];
  120. register unsigned short index = NLocals;
  121. register long valu = *valu_out;
  122. if ((local->on_type & S_SCT)) {
  123. register int sectindex = (local->on_type & S_TYP) - S_MIN;
  124. valu += relorig[sectindex].org_size;
  125. valu += outsect[sectindex].os_base;
  126. index += NGlobals + sectindex;
  127. } else {
  128. register struct outname *name;
  129. extern int hash();
  130. extern struct outname *searchname();
  131. extern unsigned indexof();
  132. extern struct outhead outhead;
  133. name = searchname(local->on_mptr, hash(local->on_mptr));
  134. if (name == (struct outname *)0)
  135. fatal("name %s not found in pass 2", local->on_mptr);
  136. if (ISCOMMON(name) || ISUNDEFINED(name)) {
  137. debug("can't relocate from %s\n",local->on_mptr,0,0,0);
  138. index += indexof(name);
  139. } else {
  140. valu += name->on_valu;
  141. if ((name->on_type & S_TYP) == S_ABS) {
  142. index += NGlobals + outhead.oh_nsect;
  143. }
  144. else index += NGlobals +
  145. (name->on_type & S_TYP) - S_MIN;
  146. }
  147. }
  148. *valu_out = valu;
  149. return index;
  150. }
  151. /*
  152. * This routine relocates a value in a section pointed to by `emit', of
  153. * which the header is pointed to by `head'. Relocation is relative to the
  154. * names in `names'; `relo' tells how to relocate.
  155. */
  156. relocate(head, emit, names, relo, off)
  157. struct outhead *head;
  158. char *emit;
  159. struct outname names[];
  160. struct outrelo *relo;
  161. long off;
  162. {
  163. long valu;
  164. int sectindex = relo->or_sect - S_MIN;
  165. extern struct outhead outhead;
  166. /*
  167. * Pick up previous value at location to be relocated.
  168. */
  169. valu = getvalu(emit + (relo->or_addr - off), relo->or_type);
  170. /*
  171. * Or_nami is an index in the name table of the considered module.
  172. * The name of which it is an index can be:
  173. * - an undefined external or a common name
  174. * - a section name
  175. * - the first name outside! the name table (argh)
  176. */
  177. if (relo->or_nami < head->oh_nname) {
  178. /* First two cases. */
  179. relo->or_nami = addrelo(relo, names, &valu);
  180. } else {
  181. /*
  182. * Third case: it is absolute. The relocation of absolute
  183. * names is always 0. We only need to change the index.
  184. */
  185. relo->or_nami = NLocals + NGlobals + outhead.oh_nsect;
  186. }
  187. /*
  188. * If relocation is pc-relative, we had to update the value by
  189. * the change in distance between the referencING and referencED
  190. * section. We already added the origin of the referencED section;
  191. * now we subtract the origin of the referencING section.
  192. */
  193. if (relo->or_type & RELPC)
  194. valu -= relorig[sectindex].org_size+outsect[sectindex].os_base;
  195. /*
  196. * Now put the value back.
  197. */
  198. putvalu(valu, emit + (relo->or_addr - off), relo->or_type);
  199. /*
  200. * We must change the offset within the section of the value to be
  201. * relocated to its offset in the new section. `Or_addr' must again be
  202. * in the normal part, of course.
  203. */
  204. relo->or_addr += relorig[sectindex].org_size;
  205. }