relocate.c 6.3 KB

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