8prefix.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Pre-resolve references inside an object file.
  3. * Mark such functions static so that linking with
  4. * other object files can't get at them.
  5. * Also rename "main".
  6. */
  7. #include <u.h>
  8. #include <libc.h>
  9. #include <bio.h>
  10. #include "/sys/src/cmd/8c/8.out.h"
  11. typedef struct Sym Sym;
  12. struct Sym
  13. {
  14. char *name;
  15. char *newname;
  16. short type;
  17. short version;
  18. Sym *link;
  19. };
  20. typedef struct Obj Obj;
  21. struct Obj
  22. {
  23. int fd;
  24. int version;
  25. uchar *bp;
  26. uchar *ep;
  27. char *name;
  28. };
  29. enum
  30. {
  31. NHASH = 10007
  32. };
  33. Sym *hash[NHASH];
  34. int nsymbol;
  35. int renamemain = 1;
  36. Sym *xsym[256];
  37. int version = 1;
  38. Obj **obj;
  39. int nobj;
  40. Biobuf bout;
  41. char *prefix;
  42. int verbose;
  43. void *emalloc(ulong);
  44. Sym *lookup(char*, int);
  45. Obj *openobj(char*);
  46. void walkobj(Obj*, void (*fn)(int, Sym*, uchar*, int));
  47. void walkobjs(void (*fn)(int, Sym*, uchar*, int));
  48. void dump(int, Sym*, uchar*, int);
  49. void nop(int, Sym*, uchar*, int);
  50. void owrite(int, Sym*, uchar*, int);
  51. int zaddr(uchar*, Sym**);
  52. void renamesyms(int, Sym*, uchar*, int);
  53. void
  54. usage(void)
  55. {
  56. fprint(2, "usage: 8prelink [-mv] prefix file.8...\n");
  57. exits("usage");
  58. }
  59. void
  60. main(int argc, char **argv)
  61. {
  62. int i;
  63. Obj *o;
  64. ARGBEGIN{
  65. case 'm':
  66. renamemain = 0;
  67. break;
  68. case 'v':
  69. verbose = 1;
  70. break;
  71. default:
  72. usage();
  73. }ARGEND
  74. if(argc < 2)
  75. usage();
  76. prefix = argv[0];
  77. argv++;
  78. argc--;
  79. nobj = argc;
  80. obj = emalloc(nobj*sizeof obj[0]);
  81. for(i=0; i<argc; i++)
  82. obj[i] = openobj(argv[i]);
  83. walkobjs(nop); /* initialize symbol table */
  84. if(verbose)
  85. walkobjs(dump);
  86. walkobjs(renamesyms);
  87. for(i=0; i<nobj; i++){
  88. o = obj[i];
  89. seek(o->fd, 0, 0);
  90. Binit(&bout, o->fd, OWRITE);
  91. walkobj(o, owrite);
  92. Bflush(&bout);
  93. }
  94. exits(0);
  95. }
  96. void
  97. renamesyms(int op, Sym *sym, uchar*, int)
  98. {
  99. if(sym && sym->version==0 && !sym->newname)
  100. switch(op){
  101. case AGLOBL:
  102. case AINIT:
  103. case ADATA:
  104. case ATEXT:
  105. if(!renamemain && strcmp(sym->name, "main") == 0)
  106. break;
  107. sym->newname = smprint("%s%s", prefix, sym->name);
  108. break;
  109. }
  110. }
  111. void
  112. dump(int op, Sym *sym, uchar*, int)
  113. {
  114. if(sym && sym->version==0)
  115. switch(op){
  116. case AGLOBL:
  117. case AINIT:
  118. case ADATA:
  119. case ATEXT:
  120. print("%s\n", sym->name);
  121. break;
  122. }
  123. }
  124. void
  125. nop(int, Sym*, uchar*, int)
  126. {
  127. }
  128. void
  129. owrite(int op, Sym *sym, uchar *p, int l)
  130. {
  131. switch(op){
  132. case ASIGNAME:
  133. Bwrite(&bout, p, 4);
  134. p += 4;
  135. l -= 4;
  136. case ANAME:
  137. if(sym->newname){
  138. Bwrite(&bout, p, 4);
  139. Bwrite(&bout, sym->newname, strlen(sym->newname)+1);
  140. break;
  141. }
  142. default:
  143. Bwrite(&bout, p, l);
  144. break;
  145. }
  146. }
  147. int
  148. zaddr(uchar *p, Sym **symp)
  149. {
  150. int c, t;
  151. t = p[0];
  152. c = 1;
  153. if(t & T_INDEX)
  154. c += 2;
  155. if(t & T_OFFSET)
  156. c += 4;
  157. if(t & T_SYM){
  158. if(symp)
  159. *symp = xsym[p[c]];
  160. c++;
  161. }
  162. if(t & T_FCONST)
  163. c += 8;
  164. else if(t & T_SCONST)
  165. c += NSNAME;
  166. if(t & T_TYPE)
  167. c++;
  168. return c;
  169. }
  170. void*
  171. emalloc(ulong n)
  172. {
  173. void *v;
  174. v = mallocz(n, 1);
  175. if(v == nil)
  176. sysfatal("out of memory");
  177. return v;
  178. }
  179. Sym*
  180. lookup(char *symb, int v)
  181. {
  182. Sym *s;
  183. char *p;
  184. long h;
  185. int l, c;
  186. h = v;
  187. for(p=symb; c = *p; p++)
  188. h = h+h+h + c;
  189. l = (p - symb) + 1;
  190. if(h < 0)
  191. h = ~h;
  192. h %= NHASH;
  193. for(s = hash[h]; s != nil; s = s->link)
  194. if(s->version == v)
  195. if(memcmp(s->name, symb, l) == 0)
  196. return s;
  197. s = emalloc(sizeof *s);
  198. s->name = emalloc(l + 1);
  199. memmove(s->name, symb, l);
  200. s->link = hash[h];
  201. s->type = 0;
  202. s->version = v;
  203. hash[h] = s;
  204. nsymbol++;
  205. return s;
  206. }
  207. Obj*
  208. openobj(char *name)
  209. {
  210. Dir *d;
  211. Obj *obj;
  212. obj = emalloc(sizeof *obj);
  213. obj->name = name;
  214. obj->version = version++;
  215. if((obj->fd = open(name, ORDWR)) < 0)
  216. sysfatal("open %s: %r", name);
  217. if((d = dirfstat(obj->fd)) == nil)
  218. sysfatal("dirfstat: %r");
  219. obj->bp = emalloc(d->length);
  220. if(readn(obj->fd, obj->bp, d->length) != d->length)
  221. sysfatal("read %s: %r", name);
  222. obj->ep = obj->bp+d->length;
  223. return obj;
  224. }
  225. void
  226. walkobjs(void (*fn)(int, Sym*, uchar*, int))
  227. {
  228. int i;
  229. for(i=0; i<nobj; i++)
  230. walkobj(obj[i], fn);
  231. }
  232. void
  233. walkobj(Obj *obj, void (*fn)(int, Sym*, uchar*, int))
  234. {
  235. int op, type;
  236. Sym *sym;
  237. uchar *p, *p0;
  238. for(p=obj->bp; p+4<=obj->ep; ){
  239. op = p[0] | (p[1]<<8);
  240. if(op <= AXXX || op >= ALAST)
  241. sysfatal("%s: opcode out of range - probably not a .8 file", obj->name);
  242. p0 = p;
  243. switch(op){
  244. case ASIGNAME:
  245. p += 4; /* sign */
  246. case ANAME:
  247. type = p[2];
  248. sym = lookup((char*)p+4, type==D_STATIC ? obj->version : 0);
  249. xsym[p[3]] = sym;
  250. p += 4+strlen(sym->name)+1;
  251. fn(op, sym, p0, p-p0);
  252. break;
  253. default:
  254. p += 6;
  255. p += zaddr(p, &sym);
  256. p += zaddr(p, nil);
  257. fn(op, sym, p0, p-p0);
  258. break;
  259. }
  260. }
  261. }