]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/sparc/boot/btfixupprep.c
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.
6 Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
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.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
32 static char * symtab
= "SYMBOL TABLE:" ;
33 static char * relrec
= "RELOCATION RECORDS FOR [" ;
40 typedef struct _btfixuprel
{
45 struct _btfixuprel
* next
;
48 typedef struct _btfixup
{
57 btfixup array
[ MAXSYMS
];
60 unsigned long lastfoffset
= - 1 ;
61 unsigned long lastfrelno
;
64 static void fatal ( void ) __attribute__ (( noreturn
));
65 static void fatal ( void )
67 fprintf ( stderr
, "Malformed output from objdump \n %s \n " , buffer
);
71 static btfixup
* find ( int type
, char * name
)
74 for ( i
= 0 ; i
< last
; i
++) {
75 if ( array
[ i
]. type
== type
&& ! strcmp ( array
[ i
]. name
, name
))
78 array
[ last
]. type
= type
;
79 array
[ last
]. name
= strdup ( name
);
80 array
[ last
]. setinitval
= 0 ;
81 if (! array
[ last
]. name
) fatal ();
82 array
[ last
]. rel
= NULL
;
84 if ( last
>= MAXSYMS
) {
85 fprintf ( stderr
, "Ugh. Something strange. More than %d different BTFIXUP symbols \n " , MAXSYMS
);
88 return array
+ last
- 1 ;
91 static void set_mode ( char * buffer
)
93 for ( mode
= 0 ;; mode
++)
94 if ( buffer
[ mode
] < '0' || buffer
[ mode
] > '9' )
96 if ( mode
!= 8 && mode
!= 16 )
101 int main ( int argc
, char ** argv
)
106 unsigned int initval
;
110 unsigned long offset
;
113 symlen
= strlen ( symtab
);
114 while ( fgets ( buffer
, 1024 , stdin
) != NULL
)
115 if (! strncmp ( buffer
, symtab
, symlen
))
119 rellen
= strlen ( relrec
);
120 while ( fgets ( buffer
, 1024 , stdin
) != NULL
)
121 if (! strncmp ( buffer
, relrec
, rellen
))
125 sect
= malloc ( strlen ( buffer
+ rellen
) + 1 );
127 strcpy ( sect
, buffer
+ rellen
);
128 p
= strchr ( sect
, ']' );
131 if ( fgets ( buffer
, 1024 , stdin
) == NULL
)
133 while ( fgets ( buffer
, 1024 , stdin
) != NULL
) {
135 if (! strncmp ( buffer
, relrec
, rellen
))
139 p
= strchr ( buffer
, ' \n ' );
141 if ( strlen ( buffer
) < 22 + mode
)
143 if ( strncmp ( buffer
+ mode
, " R_SPARC_" , 9 ))
145 nbase
= 27 - 8 + mode
;
146 if ( buffer
[ nbase
] != '_' || buffer
[ nbase
+ 1 ] != '_' || buffer
[ nbase
+ 2 ] != '_' )
148 switch ( buffer
[ nbase
+ 3 ]) {
150 case 'b' : /* BLACKBOX */
151 case 's' : /* SIMM13 */
153 case 'h' : /* SETHI */
159 p
= strchr ( buffer
+ nbase
+ 5 , '+' );
162 if ( buffer
[ nbase
+ 4 ] == 's' && buffer
[ nbase
+ 5 ] == '_' ) {
164 if ( strcmp ( sect
, ".init.text" )) {
166 "Wrong use of '%s' BTFIXUPSET in '%s' section. \n "
167 "BTFIXUPSET_CALL can be used only in"
168 " __init sections \n " ,
169 buffer
+ shift
, sect
);
172 } else if ( buffer
[ nbase
+ 4 ] != '_' )
174 if (! strcmp ( sect
, ".text.exit" ))
176 if ( strcmp ( sect
, ".text" ) &&
177 strcmp ( sect
, ".init.text" ) &&
178 strcmp ( sect
, ".fixup" ) &&
179 ( strcmp ( sect
, "__ksymtab" ) || buffer
[ nbase
+ 3 ] != 'f' )) {
180 if ( buffer
[ nbase
+ 3 ] == 'f' )
182 "Wrong use of '%s' in '%s' section. \n "
183 " It can be used only in .text, .init.text,"
184 " .fixup and __ksymtab \n " ,
185 buffer
+ shift
, sect
);
188 "Wrong use of '%s' in '%s' section. \n "
189 " It can be only used in .text, .init.text,"
190 " and .fixup \n " , buffer
+ shift
, sect
);
193 p
= strstr ( buffer
+ shift
, "__btset_" );
194 if ( p
&& buffer
[ nbase
+ 4 ] == 's' ) {
195 fprintf ( stderr
, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting \n %s \n " , buffer
);
201 if ( p
[ 8 ] != '0' || p
[ 9 ] != 'x' ) {
202 fprintf ( stderr
, "Pre-initialized values can be only initialized with hexadecimal constants starting 0x \n %s \n " , buffer
);
205 initval
= strtoul ( p
+ 10 , & q
, 16 );
206 if (* q
|| ! initval
) {
207 fprintf ( stderr
, "Pre-initialized values can be only in the form name__btset_0xXXXXXXXX where X are hex digits. \n They cannot be name__btset_0x00000000 though. Use BTFIXUPDEF_XX instead of BTFIXUPDEF_XX_INIT then. \n %s \n " , buffer
);
213 f
= find ( buffer
[ nbase
+ 3 ], buffer
+ shift
);
214 if ( buffer
[ nbase
+ 4 ] == 's' )
216 switch ( buffer
[ nbase
+ 3 ]) {
219 fprintf ( stderr
, "Cannot use pre-initialized fixups for calls \n %s \n " , buffer
);
222 if (! strcmp ( sect
, "__ksymtab" )) {
223 if ( strncmp ( buffer
+ mode
+ 9 , "32 " , 10 )) {
224 fprintf ( stderr
, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32 \n \%s \n " , buffer
);
227 } else if ( strncmp ( buffer
+ mode
+ 9 , "WDISP30 " , 10 ) &&
228 strncmp ( buffer
+ mode
+ 9 , "HI22 " , 10 ) &&
229 strncmp ( buffer
+ mode
+ 9 , "LO10 " , 10 )) {
230 fprintf ( stderr
, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10 \n %s \n " , buffer
);
236 fprintf ( stderr
, "Cannot use pre-initialized fixups for blackboxes \n %s \n " , buffer
);
239 if ( strncmp ( buffer
+ mode
+ 9 , "HI22 " , 10 )) {
240 fprintf ( stderr
, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22 \n %s \n " , buffer
);
245 if ( initval
+ 0x1000 >= 0x2000 ) {
246 fprintf ( stderr
, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff \n %s \n " , buffer
);
249 if ( strncmp ( buffer
+ mode
+ 9 , "13 " , 10 )) {
250 fprintf ( stderr
, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13 \n %s \n " , buffer
);
255 if ( initval
+ 0x1000 >= 0x2000 && ( initval
& 0x3ff )) {
256 fprintf ( stderr
, "Wrong initializer for HALF. \n %s \n " , buffer
);
259 if ( strncmp ( buffer
+ mode
+ 9 , "13 " , 10 )) {
260 fprintf ( stderr
, "BTFIXUP_HALF results in relocation other than R_SPARC_13 \n %s \n " , buffer
);
265 if ( initval
& 0x3ff ) {
266 fprintf ( stderr
, "Wrong initializer for SETHI. Cannot have set low 10 bits \n %s \n " , buffer
);
269 if ( strncmp ( buffer
+ mode
+ 9 , "HI22 " , 10 )) {
270 fprintf ( stderr
, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22 \n %s \n " , buffer
);
276 fprintf ( stderr
, "Cannot use pre-initialized fixups for INT \n %s \n " , buffer
);
279 if ( strncmp ( buffer
+ mode
+ 9 , "HI22 " , 10 ) && strncmp ( buffer
+ mode
+ 9 , "LO10 " , 10 )) {
280 fprintf ( stderr
, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10 \n %s \n " , buffer
);
285 if (! f
-> setinitval
) {
286 f
-> initval
= initval
;
288 f
-> initvalstr
= strdup ( initvalstr
);
289 if (! f
-> initvalstr
) fatal ();
292 } else if ( f
-> initval
!= initval
) {
293 fprintf ( stderr
, "Btfixup %s previously used with initializer %s which doesn't match with current initializer \n %s \n " ,
294 f
-> name
, f
-> initvalstr
? : "0x00000000" , buffer
);
296 } else if ( initval
&& strcmp ( f
-> initvalstr
, initvalstr
)) {
297 fprintf ( stderr
, "Btfixup %s previously used with initializer %s which doesn't match with current initializer. \n "
298 "Initializers have to match literally as well. \n %s \n " ,
299 f
-> name
, f
-> initvalstr
, buffer
);
302 offset
= strtoul ( buffer
, & q
, 16 );
303 if ( q
!= buffer
+ mode
|| (! offset
&& ( mode
== 8 ? strncmp ( buffer
, "00000000 " , 9 ) : strncmp ( buffer
, "0000000000000000 " , 17 )))) {
304 fprintf ( stderr
, "Malformed relocation address in \n %s \n " , buffer
);
307 for ( k
= 0 , r
= f
-> rel
, rr
= & f
-> rel
; r
; rr
= & r
-> next
, r
= r
-> next
, k
++)
308 if ( r
-> offset
== offset
&& ! strcmp ( r
-> sect
, sect
)) {
309 fprintf ( stderr
, "Ugh. One address has two relocation records \n " );
312 * rr
= malloc ( sizeof ( btfixuprel
));
314 (* rr
)-> offset
= offset
;
316 if ( buffer
[ nbase
+ 3 ] == 'f' ) {
318 lastfoffset
= offset
;
320 } else if ( lastfoffset
+ 4 == offset
) {
322 (* rr
)-> frel
= lastfrelno
;
327 printf ( "! Generated by btfixupprep. Do not edit. \n\n " );
328 printf ( " \t .section \t\" .data.init \" ,#alloc,#write \n\t .align \t 4 \n\n " );
329 printf ( " \t .global \t ___btfixup_start \n ___btfixup_start: \n\n " );
330 for ( i
= 0 ; i
< last
; i
++) {
332 printf ( " \t .global \t ___%cs_%s \n " , f
-> type
, f
-> name
);
334 printf ( "___%cs_%s: \n\t .word 0x%08x,0,0," , f
-> type
, f
-> name
, f
-> type
<< 24 );
336 printf ( "___%cs_%s: \n\t .word 0x%08x,0," , f
-> type
, f
-> name
, f
-> type
<< 24 );
337 for ( j
= 0 , r
= f
-> rel
; r
!= NULL
; j
++, r
= r
-> next
);
339 printf ( "%d \n\t .word \t " , j
* 2 );
342 for ( r
= f
-> rel
, j
--; r
!= NULL
; j
--, r
= r
-> next
) {
343 if (! strcmp ( r
-> sect
, ".text" ))
344 printf ( "_stext+0x%08lx" , r
-> offset
);
345 else if (! strcmp ( r
-> sect
, ".init.text" ))
346 printf ( "__init_begin+0x%08lx" , r
-> offset
);
347 else if (! strcmp ( r
-> sect
, "__ksymtab" ))
348 printf ( "__start___ksymtab+0x%08lx" , r
-> offset
);
349 else if (! strcmp ( r
-> sect
, ".fixup" ))
350 printf ( "__start___fixup+0x%08lx" , r
-> offset
);
353 if ( f
-> type
== 'f' || ! r
-> f
)
356 printf ( ",___fs_%s+0x%08x" , r
-> f
-> name
, ( 4 + r
-> frel
* 2 )* 4 + 4 );
362 printf ( " \n\t .global \t ___btfixup_end \n ___btfixup_end: \n " );
363 printf ( " \n\n ! Define undefined references \n\n " );
364 for ( i
= 0 ; i
< last
; i
++) {
366 if ( f
-> type
== 'f' ) {
367 printf ( " \t .global \t ___f_%s \n " , f
-> name
);
368 printf ( "___f_%s: \n " , f
-> name
);
371 printf ( " \t retl \n\t nop \n\n " );
372 for ( i
= 0 ; i
< last
; i
++) {
374 if ( f
-> type
!= 'f' ) {
376 printf ( " \t .global \t ___%c_%s \n " , f
-> type
, f
-> name
);
377 printf ( "___%c_%s = 0 \n " , f
-> type
, f
-> name
);
379 printf ( " \t .global \t ___%c_%s__btset_0x%s \n " , f
-> type
, f
-> name
, f
-> initvalstr
);
380 printf ( "___%c_%s__btset_0x%s = 0x%08x \n " , f
-> type
, f
-> name
, f
-> initvalstr
, f
-> initval
);