btfixupprep.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: btfixupprep.c,v 1.6 2001/08/22 15:27:47 davem Exp $
  2.    Simple utility to prepare vmlinux image for sparc.
  3.    Resolves all BTFIXUP uses and settings and creates
  4.    a special .s object to link to the image.
  5.    
  6.    Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  7.    
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.    
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.    
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <errno.h>
  25. #include <unistd.h>
  26. #include <stdlib.h>
  27. #include <malloc.h>
  28. #define MAXSYMS 1024
  29. static char *symtab = "SYMBOL TABLE:";
  30. static char *relrec = "RELOCATION RECORDS FOR [";
  31. static int rellen;
  32. static int symlen;
  33. int mode;
  34. struct _btfixup;
  35. typedef struct _btfixuprel {
  36. char *sect;
  37. unsigned long offset;
  38. struct _btfixup *f;
  39. int frel;
  40. struct _btfixuprel *next;
  41. } btfixuprel;
  42. typedef struct _btfixup {
  43. int type;
  44. int setinitval;
  45. unsigned int initval;
  46. char *initvalstr;
  47. char *name;
  48. btfixuprel *rel;
  49. } btfixup;
  50. btfixup array[MAXSYMS];
  51. int last = 0;
  52. char buffer[1024];
  53. unsigned long lastfoffset = -1;
  54. unsigned long lastfrelno;
  55. btfixup *lastf;
  56. void fatal(void) __attribute__((noreturn));
  57. void fatal(void)
  58. {
  59. fprintf(stderr, "Malformed output from objdumpn%sn", buffer);
  60. exit(1);
  61. }
  62. btfixup *find(int type, char *name)
  63. {
  64. int i;
  65. for (i = 0; i < last; i++) {
  66. if (array[i].type == type && !strcmp(array[i].name, name))
  67. return array + i;
  68. }
  69. array[last].type = type;
  70. array[last].name = strdup(name);
  71. array[last].setinitval = 0;
  72. if (!array[last].name) fatal();
  73. array[last].rel = NULL;
  74. last++;
  75. if (last >= MAXSYMS) {
  76. fprintf(stderr, "Ugh. Something strange. More than %d different BTFIXUP symbolsn", MAXSYMS);
  77. exit(1);
  78. }
  79. return array + last - 1;
  80. }
  81. void set_mode (char *buffer)
  82. {
  83.    for (mode = 0;; mode++)
  84. if (buffer[mode] < '0' || buffer[mode] > '9')
  85. break;
  86. if (mode != 8 && mode != 16)
  87. fatal();
  88. }
  89. int main(int argc,char **argv)
  90. {
  91. char *p, *q;
  92. char *sect;
  93. int i, j, k;
  94. unsigned int initval;
  95. int shift;
  96. btfixup *f;
  97. btfixuprel *r, **rr;
  98. unsigned long offset;
  99. char *initvalstr;
  100. symlen = strlen(symtab);
  101. while (fgets (buffer, 1024, stdin) != NULL)
  102. if (!strncmp (buffer, symtab, symlen))
  103. goto main0;
  104. fatal();
  105. main0:
  106. rellen = strlen(relrec);
  107. while (fgets (buffer, 1024, stdin) != NULL)
  108. if (!strncmp (buffer, relrec, rellen))
  109. goto main1;
  110. fatal();
  111. main1:
  112. sect = malloc(strlen (buffer + rellen) + 1);
  113. if (!sect) fatal();
  114. strcpy (sect, buffer + rellen);
  115. p = strchr (sect, ']');
  116. if (!p) fatal();
  117. *p = 0;
  118. if (fgets (buffer, 1024, stdin) == NULL)
  119. fatal();
  120. while (fgets (buffer, 1024, stdin) != NULL) {
  121. int nbase;
  122. if (!strncmp (buffer, relrec, rellen))
  123. goto main1;
  124. if (mode == 0)
  125. set_mode (buffer);
  126. p = strchr (buffer, 'n');
  127. if (p) *p = 0;
  128. if (strlen (buffer) < 22+mode)
  129. continue;
  130. if (strncmp (buffer + mode, " R_SPARC_", 9))
  131. continue;
  132. nbase = 27 - 8 + mode;
  133. if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_')
  134. continue;
  135. switch (buffer[nbase+3]) {
  136. case 'f': /* CALL */
  137. case 'b': /* BLACKBOX */
  138. case 's': /* SIMM13 */
  139. case 'a': /* HALF */
  140. case 'h': /* SETHI */
  141. case 'i': /* INT */
  142. break;
  143. default:
  144. continue;
  145. }
  146. p = strchr (buffer + nbase+5, '+');
  147. if (p) *p = 0;
  148. shift = nbase + 5;
  149. if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') {
  150. shift = nbase + 6;
  151. if (strcmp (sect, ".text.init")) {
  152. fprintf(stderr, "Wrong use of '%s' BTFIXUPSET.nBTFIXUPSET_CALL can be used only in __init sectionsn", buffer+shift);
  153. exit(1);
  154. }
  155. } else if (buffer[nbase+4] != '_')
  156. continue;
  157. if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && strcmp (sect, ".fixup") && (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
  158. if (buffer[nbase+3] == 'f')
  159. fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init, .fixup and __ksymtabn", buffer + shift, sect);
  160. else
  161. fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .fixup and .text.initn", buffer + shift, sect);
  162. exit(1);
  163. }
  164. p = strstr (buffer + shift, "__btset_");
  165. if (p && buffer[nbase+4] == 's') {
  166. fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for settingn%sn", buffer);
  167. exit(1);
  168. }
  169. initval = 0;
  170. initvalstr = NULL;
  171. if (p) {
  172. if (p[8] != '0' || p[9] != 'x') {
  173. fprintf(stderr, "Pre-initialized values can be only initialized with hexadecimal constants starting 0xn%sn", buffer);
  174. exit(1);
  175. }
  176. initval = strtoul(p + 10, &q, 16);
  177. if (*q || !initval) {
  178. fprintf(stderr, "Pre-initialized values can be only in the form name__btset_0xXXXXXXXX where X are hex digits.nThey cannot be name__btset_0x00000000 though. Use BTFIXUPDEF_XX instead of BTFIXUPDEF_XX_INIT then.n%sn", buffer);
  179. exit(1);
  180. }
  181. initvalstr = p + 10;
  182. *p = 0;
  183. }
  184. f = find(buffer[nbase+3], buffer + shift);
  185. if (buffer[nbase+4] == 's')
  186. continue;
  187. switch (buffer[nbase+3]) {
  188. case 'f':
  189. if (initval) {
  190. fprintf(stderr, "Cannot use pre-initalized fixups for callsn%sn", buffer);
  191. exit(1);
  192. }
  193. if (!strcmp (sect, "__ksymtab")) {
  194. if (strncmp (buffer + mode+9, "32        ", 10)) {
  195. fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32n%sn", buffer);
  196. exit(1);
  197. }
  198. } else if (strncmp (buffer + mode+9, "WDISP30   ", 10) &&
  199.    strncmp (buffer + mode+9, "HI22      ", 10) &&
  200.    strncmp (buffer + mode+9, "LO10      ", 10)) {
  201. fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10n%sn", buffer);
  202. exit(1);
  203. }
  204. break;
  205. case 'b':
  206. if (initval) {
  207. fprintf(stderr, "Cannot use pre-initialized fixups for blackboxesn%sn", buffer);
  208. exit(1);
  209. }
  210. if (strncmp (buffer + mode+9, "HI22      ", 10)) {
  211. fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22n%sn", buffer);
  212. exit(1);
  213. }
  214. break;
  215. case 's':
  216. if (initval + 0x1000 >= 0x2000) {
  217. fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fffn%sn", buffer);
  218. exit(1);
  219. }
  220. if (strncmp (buffer + mode+9, "13        ", 10)) {
  221. fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13n%sn", buffer);
  222. exit(1);
  223. }
  224. break;
  225. case 'a':
  226. if (initval + 0x1000 >= 0x2000 && (initval & 0x3ff)) {
  227. fprintf(stderr, "Wrong initializer for HALF.n%sn", buffer);
  228. exit(1);
  229. }
  230. if (strncmp (buffer + mode+9, "13        ", 10)) {
  231. fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13n%sn", buffer);
  232. exit(1);
  233. }
  234. break;
  235. case 'h':
  236. if (initval & 0x3ff) {
  237. fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bitsn%sn", buffer);
  238. exit(1);
  239. }
  240. if (strncmp (buffer + mode+9, "HI22      ", 10)) {
  241. fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22n%sn", buffer);
  242. exit(1);
  243. }
  244. break;
  245. case 'i':
  246. if (initval) {
  247. fprintf(stderr, "Cannot use pre-initalized fixups for INTn%sn", buffer);
  248. exit(1);
  249. }
  250. if (strncmp (buffer + mode+9, "HI22      ", 10) && strncmp (buffer + mode+9, "LO10      ", 10)) {
  251. fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10n%sn", buffer);
  252. exit(1);
  253. }
  254. break;
  255. }
  256. if (!f->setinitval) {
  257. f->initval = initval;
  258. if (initvalstr) {
  259. f->initvalstr = strdup(initvalstr);
  260. if (!f->initvalstr) fatal();
  261. }
  262. f->setinitval = 1;
  263. } else if (f->initval != initval) {
  264. fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializern%sn",
  265. f->name, f->initvalstr ? : "0x00000000", buffer);
  266. exit(1);
  267. } else if (initval && strcmp(f->initvalstr, initvalstr)) {
  268. fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer.n"
  269. "Initializers have to match literally as well.n%sn",
  270. f->name, f->initvalstr, buffer);
  271. exit(1);
  272. }
  273. offset = strtoul(buffer, &q, 16);
  274. if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) {
  275. fprintf(stderr, "Malformed relocation address inn%sn", buffer);
  276. exit(1);
  277. }
  278. for (k = 0, r = f->rel, rr = &f->rel; r; rr = &r->next, r = r->next, k++)
  279. if (r->offset == offset && !strcmp(r->sect, sect)) {
  280. fprintf(stderr, "Ugh. One address has two relocation recordsn");
  281. exit(1);
  282. }
  283. *rr = malloc(sizeof(btfixuprel));
  284. if (!*rr) fatal();
  285. (*rr)->offset = offset;
  286. (*rr)->f = NULL;
  287. if (buffer[nbase+3] == 'f') {
  288. lastf = f;
  289. lastfoffset = offset;
  290. lastfrelno = k;
  291. } else if (lastfoffset + 4 == offset) {
  292. (*rr)->f = lastf;
  293. (*rr)->frel = lastfrelno;
  294. }
  295. (*rr)->sect = sect;
  296. (*rr)->next = NULL;
  297. }
  298. printf("! Generated by btfixupprep. Do not edit.nn");
  299. printf("t.sectiont".data.init",#alloc,#writent.alignt4nn");
  300. printf("t.globalt___btfixup_startn___btfixup_start:nn");
  301. for (i = 0; i < last; i++) {
  302. f = array + i;
  303. printf("t.globalt___%cs_%sn", f->type, f->name);
  304. if (f->type == 'f')
  305. printf("___%cs_%s:nt.word 0x%08x,0,0,", f->type, f->name, f->type << 24);
  306. else
  307. printf("___%cs_%s:nt.word 0x%08x,0,", f->type, f->name, f->type << 24);
  308. for (j = 0, r = f->rel; r != NULL; j++, r = r->next);
  309. if (j)
  310. printf("%dnt.wordt", j * 2);
  311. else
  312. printf("0n");
  313. for (r = f->rel, j--; r != NULL; j--, r = r->next) {
  314. if (!strcmp (r->sect, ".text"))
  315. printf ("_stext+0x%08lx", r->offset);
  316. else if (!strcmp (r->sect, ".text.init"))
  317. printf ("__init_begin+0x%08lx", r->offset);
  318. else if (!strcmp (r->sect, "__ksymtab"))
  319. printf ("__start___ksymtab+0x%08lx", r->offset);
  320. else if (!strcmp (r->sect, ".fixup"))
  321. printf ("__start___fixup+0x%08lx", r->offset);
  322. else
  323. fatal();
  324. if (f->type == 'f' || !r->f)
  325. printf (",0");
  326. else
  327. printf (",___fs_%s+0x%08x", r->f->name, (4 + r->frel*2)*4 + 4);
  328. if (j) printf (",");
  329. else printf ("n");
  330. }
  331. printf("n");
  332. }
  333. printf("nt.globalt___btfixup_endn___btfixup_end:n");
  334. printf("nn! Define undefined referencesnn");
  335. for (i = 0; i < last; i++) {
  336. f = array + i;
  337. if (f->type == 'f') {
  338. printf("t.globalt___f_%sn", f->name);
  339. printf("___f_%s:n", f->name);
  340. }
  341. }
  342. printf("tretlnt nopnn");
  343. for (i = 0; i < last; i++) {
  344. f = array + i;
  345. if (f->type != 'f') {
  346. if (!f->initval) {
  347. printf("t.globalt___%c_%sn", f->type, f->name);
  348. printf("___%c_%s = 0n", f->type, f->name);
  349. } else {
  350. printf("t.globalt___%c_%s__btset_0x%sn", f->type, f->name, f->initvalstr);
  351. printf("___%c_%s__btset_0x%s = 0x%08xn", f->type, f->name, f->initvalstr, f->initval);
  352. }
  353. }
  354. }
  355. printf("nn");
  356.      exit(0);
  357. }