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