8prefix.c 4.8 KB

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