188278ca27a43ae503572b52ea2c171fbf45db5a2Adrian Bunk/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Simple utility to prepare vmlinux image for sparc. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Resolves all BTFIXUP uses and settings and creates 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a special .s object to link to the image. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdio.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <ctype.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <unistd.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdlib.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <malloc.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAXSYMS 1024 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *symtab = "SYMBOL TABLE:"; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *relrec = "RELOCATION RECORDS FOR ["; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rellen; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int symlen; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mode; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct _btfixup; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _btfixuprel { 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *sect; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct _btfixup *f; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int frel; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct _btfixuprel *next; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} btfixuprel; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct _btfixup { 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int type; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int setinitval; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int initval; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *initvalstr; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btfixuprel *rel; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} btfixup; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbtfixup array[MAXSYMS]; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint last = 0; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar buffer[1024]; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long lastfoffset = -1; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long lastfrelno; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbtfixup *lastf; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64c843e315469a1519b83835628ca8906daf9a2c0aJosh Triplettstatic void fatal(void) __attribute__((noreturn)); 65c843e315469a1519b83835628ca8906daf9a2c0aJosh Triplettstatic void fatal(void) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Malformed output from objdump\n%s\n", buffer); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71c843e315469a1519b83835628ca8906daf9a2c0aJosh Triplettstatic btfixup *find(int type, char *name) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < last; i++) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (array[i].type == type && !strcmp(array[i].name, name)) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return array + i; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds array[last].type = type; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds array[last].name = strdup(name); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds array[last].setinitval = 0; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!array[last].name) fatal(); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds array[last].rel = NULL; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last++; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (last >= MAXSYMS) { 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Ugh. Something strange. More than %d different BTFIXUP symbols\n", MAXSYMS); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return array + last - 1; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91c843e315469a1519b83835628ca8906daf9a2c0aJosh Triplettstatic void set_mode (char *buffer) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (mode = 0;; mode++) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[mode] < '0' || buffer[mode] > '9') 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode != 8 && mode != 16) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatal(); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint main(int argc,char **argv) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p, *q; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *sect; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, k; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int initval; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int shift; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btfixup *f; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds btfixuprel *r, **rr; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *initvalstr; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds symlen = strlen(symtab); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (fgets (buffer, 1024, stdin) != NULL) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp (buffer, symtab, symlen)) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto main0; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatal(); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmain0: 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rellen = strlen(relrec); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (fgets (buffer, 1024, stdin) != NULL) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp (buffer, relrec, rellen)) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto main1; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatal(); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmain1: 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sect = malloc(strlen (buffer + rellen) + 1); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sect) fatal(); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy (sect, buffer + rellen); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = strchr (sect, ']'); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p) fatal(); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *p = 0; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fgets (buffer, 1024, stdin) == NULL) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatal(); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (fgets (buffer, 1024, stdin) != NULL) { 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nbase; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp (buffer, relrec, rellen)) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto main1; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode == 0) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_mode (buffer); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = strchr (buffer, '\n'); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p) *p = 0; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strlen (buffer) < 22+mode) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode, " R_SPARC_", 9)) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nbase = 27 - 8 + mode; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_') 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buffer[nbase+3]) { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'f': /* CALL */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'b': /* BLACKBOX */ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 's': /* SIMM13 */ 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'a': /* HALF */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'h': /* SETHI */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'i': /* INT */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = strchr (buffer + nbase+5, '+'); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p) *p = 0; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = nbase + 5; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') { 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = nbase + 6; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp (sect, ".init.text")) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Wrong use of '%s' BTFIXUPSET in '%s' section.\n" 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "BTFIXUPSET_CALL can be used only in" 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " __init sections\n", 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer + shift, sect); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (buffer[nbase+4] != '_') 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strcmp (sect, ".text.exit")) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp (sect, ".text") && 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcmp (sect, ".init.text") && 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcmp (sect, ".fixup") && 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) { 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[nbase+3] == 'f') 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Wrong use of '%s' in '%s' section.\n" 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " It can be used only in .text, .init.text," 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " .fixup and __ksymtab\n", 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer + shift, sect); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Wrong use of '%s' in '%s' section.\n" 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " It can be only used in .text, .init.text," 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " and .fixup\n", buffer + shift, sect); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = strstr (buffer + shift, "__btset_"); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p && buffer[nbase+4] == 's') { 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds initval = 0; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds initvalstr = NULL; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p) { 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p[8] != '0' || p[9] != 'x') { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Pre-initialized values can be only initialized with hexadecimal constants starting 0x\n%s\n", buffer); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds initval = strtoul(p + 10, &q, 16); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*q || !initval) { 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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%s\n", buffer); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds initvalstr = p + 10; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *p = 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f = find(buffer[nbase+3], buffer + shift); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[nbase+4] == 's') 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buffer[nbase+3]) { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'f': 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval) { 219421f91d21ad6f799dc7b489bb33cc560ccc56f98Uwe Kleine-König fprintf(stderr, "Cannot use pre-initialized fixups for calls\n%s\n", buffer); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strcmp (sect, "__ksymtab")) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "32 ", 10)) { 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (strncmp (buffer + mode+9, "WDISP30 ", 10) && 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncmp (buffer + mode+9, "HI22 ", 10) && 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strncmp (buffer + mode+9, "LO10 ", 10)) { 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'b': 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "HI22 ", 10)) { 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 's': 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval + 0x1000 >= 0x2000) { 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "13 ", 10)) { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'a': 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval + 0x1000 >= 0x2000 && (initval & 0x3ff)) { 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "13 ", 10)) { 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'h': 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval & 0x3ff) { 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "HI22 ", 10)) { 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 'i': 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initval) { 276421f91d21ad6f799dc7b489bb33cc560ccc56f98Uwe Kleine-König fprintf(stderr, "Cannot use pre-initialized fixups for INT\n%s\n", buffer); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp (buffer + mode+9, "HI22 ", 10) && strncmp (buffer + mode+9, "LO10 ", 10)) { 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!f->setinitval) { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f->initval = initval; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (initvalstr) { 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f->initvalstr = strdup(initvalstr); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!f->initvalstr) fatal(); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f->setinitval = 1; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (f->initval != initval) { 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer\n%s\n", 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f->name, f->initvalstr ? : "0x00000000", buffer); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (initval && strcmp(f->initvalstr, initvalstr)) { 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Btfixup %s previously used with initializer %s which doesn't match with current initializer.\n" 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Initializers have to match literally as well.\n%s\n", 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f->name, f->initvalstr, buffer); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = strtoul(buffer, &q, 16); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) { 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Malformed relocation address in\n%s\n", buffer); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0, r = f->rel, rr = &f->rel; r; rr = &r->next, r = r->next, k++) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r->offset == offset && !strcmp(r->sect, sect)) { 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fprintf(stderr, "Ugh. One address has two relocation records\n"); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(1); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *rr = malloc(sizeof(btfixuprel)); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!*rr) fatal(); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->offset = offset; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->f = NULL; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer[nbase+3] == 'f') { 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lastf = f; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lastfoffset = offset; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lastfrelno = k; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (lastfoffset + 4 == offset) { 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->f = lastf; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->frel = lastfrelno; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->sect = sect; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*rr)->next = NULL; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("! Generated by btfixupprep. Do not edit.\n\n"); 328c273fb3b5d0490d3058f6cce77a92860671ee7b6Denys Vlasenko printf("\t.section\t\".data..init\",#alloc,#write\n\t.align\t4\n\n"); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\t.global\t___btfixup_start\n___btfixup_start:\n\n"); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < last; i++) { 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f = array + i; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\t.global\t___%cs_%s\n", f->type, f->name); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (f->type == 'f') 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("___%cs_%s:\n\t.word 0x%08x,0,0,", f->type, f->name, f->type << 24); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("___%cs_%s:\n\t.word 0x%08x,0,", f->type, f->name, f->type << 24); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 0, r = f->rel; r != NULL; j++, r = r->next); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j) 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("%d\n\t.word\t", j * 2); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("0\n"); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (r = f->rel, j--; r != NULL; j--, r = r->next) { 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strcmp (r->sect, ".text")) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf ("_stext+0x%08lx", r->offset); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!strcmp (r->sect, ".init.text")) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf ("__init_begin+0x%08lx", r->offset); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!strcmp (r->sect, "__ksymtab")) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf ("__start___ksymtab+0x%08lx", r->offset); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!strcmp (r->sect, ".fixup")) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf ("__start___fixup+0x%08lx", r->offset); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatal(); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (f->type == 'f' || !r->f) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf (",0"); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf (",___fs_%s+0x%08x", r->f->name, (4 + r->frel*2)*4 + 4); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j) printf (","); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else printf ("\n"); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\n"); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\n\t.global\t___btfixup_end\n___btfixup_end:\n"); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\n\n! Define undefined references\n\n"); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < last; i++) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f = array + i; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (f->type == 'f') { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\t.global\t___f_%s\n", f->name); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("___f_%s:\n", f->name); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\tretl\n\t nop\n\n"); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < last; i++) { 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f = array + i; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (f->type != 'f') { 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!f->initval) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\t.global\t___%c_%s\n", f->type, f->name); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("___%c_%s = 0\n", f->type, f->name); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\t.global\t___%c_%s__btset_0x%s\n", f->type, f->name, f->initvalstr); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("___%c_%s__btset_0x%s = 0x%08x\n", f->type, f->name, f->initvalstr, f->initval); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printf("\n\n"); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exit(0); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 387