Commit 5c725138437837291db5c25f4a076ee852e806e3

Authored by Trevor Keith
Committed by Linus Torvalds
1 parent e898893399

Fix all -Wmissing-prototypes warnings in x86 defconfig

Signed-off-by: Trevor Keith <tsrk@tsrk.net>
Cc: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 4 changed files with 8 additions and 8 deletions Inline Diff

scripts/conmakehash.c
1 /* 1 /*
2 * conmakehash.c 2 * conmakehash.c
3 * 3 *
4 * Create arrays for initializing the kernel folded tables (using a hash 4 * Create arrays for initializing the kernel folded tables (using a hash
5 * table turned out to be to limiting...) Unfortunately we can't simply 5 * table turned out to be to limiting...) Unfortunately we can't simply
6 * preinitialize the tables at compile time since kfree() cannot accept 6 * preinitialize the tables at compile time since kfree() cannot accept
7 * memory not allocated by kmalloc(), and doing our own memory management 7 * memory not allocated by kmalloc(), and doing our own memory management
8 * just for this seems like massive overkill. 8 * just for this seems like massive overkill.
9 * 9 *
10 * Copyright (C) 1995-1997 H. Peter Anvin 10 * Copyright (C) 1995-1997 H. Peter Anvin
11 * 11 *
12 * This program is a part of the Linux kernel, and may be freely 12 * This program is a part of the Linux kernel, and may be freely
13 * copied under the terms of the GNU General Public License (GPL), 13 * copied under the terms of the GNU General Public License (GPL),
14 * version 2, or at your option any later version. 14 * version 2, or at your option any later version.
15 */ 15 */
16 16
17 #include <stdio.h> 17 #include <stdio.h>
18 #include <stdlib.h> 18 #include <stdlib.h>
19 #include <sysexits.h> 19 #include <sysexits.h>
20 #include <string.h> 20 #include <string.h>
21 #include <ctype.h> 21 #include <ctype.h>
22 22
23 #define MAX_FONTLEN 256 23 #define MAX_FONTLEN 256
24 24
25 typedef unsigned short unicode; 25 typedef unsigned short unicode;
26 26
27 void usage(char *argv0) 27 static void usage(char *argv0)
28 { 28 {
29 fprintf(stderr, "Usage: \n" 29 fprintf(stderr, "Usage: \n"
30 " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0); 30 " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
31 exit(EX_USAGE); 31 exit(EX_USAGE);
32 } 32 }
33 33
34 int getunicode(char **p0) 34 static int getunicode(char **p0)
35 { 35 {
36 char *p = *p0; 36 char *p = *p0;
37 37
38 while (*p == ' ' || *p == '\t') 38 while (*p == ' ' || *p == '\t')
39 p++; 39 p++;
40 if (*p != 'U' || p[1] != '+' || 40 if (*p != 'U' || p[1] != '+' ||
41 !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) || 41 !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
42 !isxdigit(p[5]) || isxdigit(p[6])) 42 !isxdigit(p[5]) || isxdigit(p[6]))
43 return -1; 43 return -1;
44 *p0 = p+6; 44 *p0 = p+6;
45 return strtol(p+2,0,16); 45 return strtol(p+2,0,16);
46 } 46 }
47 47
48 unicode unitable[MAX_FONTLEN][255]; 48 unicode unitable[MAX_FONTLEN][255];
49 /* Massive overkill, but who cares? */ 49 /* Massive overkill, but who cares? */
50 int unicount[MAX_FONTLEN]; 50 int unicount[MAX_FONTLEN];
51 51
52 void addpair(int fp, int un) 52 static void addpair(int fp, int un)
53 { 53 {
54 int i; 54 int i;
55 55
56 if ( un <= 0xfffe ) 56 if ( un <= 0xfffe )
57 { 57 {
58 /* Check it isn't a duplicate */ 58 /* Check it isn't a duplicate */
59 59
60 for ( i = 0 ; i < unicount[fp] ; i++ ) 60 for ( i = 0 ; i < unicount[fp] ; i++ )
61 if ( unitable[fp][i] == un ) 61 if ( unitable[fp][i] == un )
62 return; 62 return;
63 63
64 /* Add to list */ 64 /* Add to list */
65 65
66 if ( unicount[fp] > 254 ) 66 if ( unicount[fp] > 254 )
67 { 67 {
68 fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n"); 68 fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
69 exit(EX_DATAERR); 69 exit(EX_DATAERR);
70 } 70 }
71 71
72 unitable[fp][unicount[fp]] = un; 72 unitable[fp][unicount[fp]] = un;
73 unicount[fp]++; 73 unicount[fp]++;
74 } 74 }
75 75
76 /* otherwise: ignore */ 76 /* otherwise: ignore */
77 } 77 }
78 78
79 int main(int argc, char *argv[]) 79 int main(int argc, char *argv[])
80 { 80 {
81 FILE *ctbl; 81 FILE *ctbl;
82 char *tblname; 82 char *tblname;
83 char buffer[65536]; 83 char buffer[65536];
84 int fontlen; 84 int fontlen;
85 int i, nuni, nent; 85 int i, nuni, nent;
86 int fp0, fp1, un0, un1; 86 int fp0, fp1, un0, un1;
87 char *p, *p1; 87 char *p, *p1;
88 88
89 if ( argc < 2 || argc > 5 ) 89 if ( argc < 2 || argc > 5 )
90 usage(argv[0]); 90 usage(argv[0]);
91 91
92 if ( !strcmp(argv[1],"-") ) 92 if ( !strcmp(argv[1],"-") )
93 { 93 {
94 ctbl = stdin; 94 ctbl = stdin;
95 tblname = "stdin"; 95 tblname = "stdin";
96 } 96 }
97 else 97 else
98 { 98 {
99 ctbl = fopen(tblname = argv[1], "r"); 99 ctbl = fopen(tblname = argv[1], "r");
100 if ( !ctbl ) 100 if ( !ctbl )
101 { 101 {
102 perror(tblname); 102 perror(tblname);
103 exit(EX_NOINPUT); 103 exit(EX_NOINPUT);
104 } 104 }
105 } 105 }
106 106
107 /* For now we assume the default font is always 256 characters. */ 107 /* For now we assume the default font is always 256 characters. */
108 fontlen = 256; 108 fontlen = 256;
109 109
110 /* Initialize table */ 110 /* Initialize table */
111 111
112 for ( i = 0 ; i < fontlen ; i++ ) 112 for ( i = 0 ; i < fontlen ; i++ )
113 unicount[i] = 0; 113 unicount[i] = 0;
114 114
115 /* Now we come to the tricky part. Parse the input table. */ 115 /* Now we come to the tricky part. Parse the input table. */
116 116
117 while ( fgets(buffer, sizeof(buffer), ctbl) != NULL ) 117 while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
118 { 118 {
119 if ( (p = strchr(buffer, '\n')) != NULL ) 119 if ( (p = strchr(buffer, '\n')) != NULL )
120 *p = '\0'; 120 *p = '\0';
121 else 121 else
122 fprintf(stderr, "%s: Warning: line too long\n", tblname); 122 fprintf(stderr, "%s: Warning: line too long\n", tblname);
123 123
124 p = buffer; 124 p = buffer;
125 125
126 /* 126 /*
127 * Syntax accepted: 127 * Syntax accepted:
128 * <fontpos> <unicode> <unicode> ... 128 * <fontpos> <unicode> <unicode> ...
129 * <range> idem 129 * <range> idem
130 * <range> <unicode range> 130 * <range> <unicode range>
131 * 131 *
132 * where <range> ::= <fontpos>-<fontpos> 132 * where <range> ::= <fontpos>-<fontpos>
133 * and <unicode> ::= U+<h><h><h><h> 133 * and <unicode> ::= U+<h><h><h><h>
134 * and <h> ::= <hexadecimal digit> 134 * and <h> ::= <hexadecimal digit>
135 */ 135 */
136 136
137 while (*p == ' ' || *p == '\t') 137 while (*p == ' ' || *p == '\t')
138 p++; 138 p++;
139 if (!*p || *p == '#') 139 if (!*p || *p == '#')
140 continue; /* skip comment or blank line */ 140 continue; /* skip comment or blank line */
141 141
142 fp0 = strtol(p, &p1, 0); 142 fp0 = strtol(p, &p1, 0);
143 if (p1 == p) 143 if (p1 == p)
144 { 144 {
145 fprintf(stderr, "Bad input line: %s\n", buffer); 145 fprintf(stderr, "Bad input line: %s\n", buffer);
146 exit(EX_DATAERR); 146 exit(EX_DATAERR);
147 } 147 }
148 p = p1; 148 p = p1;
149 149
150 while (*p == ' ' || *p == '\t') 150 while (*p == ' ' || *p == '\t')
151 p++; 151 p++;
152 if (*p == '-') 152 if (*p == '-')
153 { 153 {
154 p++; 154 p++;
155 fp1 = strtol(p, &p1, 0); 155 fp1 = strtol(p, &p1, 0);
156 if (p1 == p) 156 if (p1 == p)
157 { 157 {
158 fprintf(stderr, "Bad input line: %s\n", buffer); 158 fprintf(stderr, "Bad input line: %s\n", buffer);
159 exit(EX_DATAERR); 159 exit(EX_DATAERR);
160 } 160 }
161 p = p1; 161 p = p1;
162 } 162 }
163 else 163 else
164 fp1 = 0; 164 fp1 = 0;
165 165
166 if ( fp0 < 0 || fp0 >= fontlen ) 166 if ( fp0 < 0 || fp0 >= fontlen )
167 { 167 {
168 fprintf(stderr, 168 fprintf(stderr,
169 "%s: Glyph number (0x%x) larger than font length\n", 169 "%s: Glyph number (0x%x) larger than font length\n",
170 tblname, fp0); 170 tblname, fp0);
171 exit(EX_DATAERR); 171 exit(EX_DATAERR);
172 } 172 }
173 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) 173 if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
174 { 174 {
175 fprintf(stderr, 175 fprintf(stderr,
176 "%s: Bad end of range (0x%x)\n", 176 "%s: Bad end of range (0x%x)\n",
177 tblname, fp1); 177 tblname, fp1);
178 exit(EX_DATAERR); 178 exit(EX_DATAERR);
179 } 179 }
180 180
181 if (fp1) 181 if (fp1)
182 { 182 {
183 /* we have a range; expect the word "idem" or a Unicode range of the 183 /* we have a range; expect the word "idem" or a Unicode range of the
184 same length */ 184 same length */
185 while (*p == ' ' || *p == '\t') 185 while (*p == ' ' || *p == '\t')
186 p++; 186 p++;
187 if (!strncmp(p, "idem", 4)) 187 if (!strncmp(p, "idem", 4))
188 { 188 {
189 for (i=fp0; i<=fp1; i++) 189 for (i=fp0; i<=fp1; i++)
190 addpair(i,i); 190 addpair(i,i);
191 p += 4; 191 p += 4;
192 } 192 }
193 else 193 else
194 { 194 {
195 un0 = getunicode(&p); 195 un0 = getunicode(&p);
196 while (*p == ' ' || *p == '\t') 196 while (*p == ' ' || *p == '\t')
197 p++; 197 p++;
198 if (*p != '-') 198 if (*p != '-')
199 { 199 {
200 fprintf(stderr, 200 fprintf(stderr,
201 "%s: Corresponding to a range of font positions, there should be a Unicode range\n", 201 "%s: Corresponding to a range of font positions, there should be a Unicode range\n",
202 tblname); 202 tblname);
203 exit(EX_DATAERR); 203 exit(EX_DATAERR);
204 } 204 }
205 p++; 205 p++;
206 un1 = getunicode(&p); 206 un1 = getunicode(&p);
207 if (un0 < 0 || un1 < 0) 207 if (un0 < 0 || un1 < 0)
208 { 208 {
209 fprintf(stderr, 209 fprintf(stderr,
210 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n", 210 "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
211 tblname, fp0, fp1); 211 tblname, fp0, fp1);
212 exit(EX_DATAERR); 212 exit(EX_DATAERR);
213 } 213 }
214 if (un1 - un0 != fp1 - fp0) 214 if (un1 - un0 != fp1 - fp0)
215 { 215 {
216 fprintf(stderr, 216 fprintf(stderr,
217 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n", 217 "%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
218 tblname, un0, un1, fp0, fp1); 218 tblname, un0, un1, fp0, fp1);
219 exit(EX_DATAERR); 219 exit(EX_DATAERR);
220 } 220 }
221 for(i=fp0; i<=fp1; i++) 221 for(i=fp0; i<=fp1; i++)
222 addpair(i,un0-fp0+i); 222 addpair(i,un0-fp0+i);
223 } 223 }
224 } 224 }
225 else 225 else
226 { 226 {
227 /* no range; expect a list of unicode values for a single font position */ 227 /* no range; expect a list of unicode values for a single font position */
228 228
229 while ( (un0 = getunicode(&p)) >= 0 ) 229 while ( (un0 = getunicode(&p)) >= 0 )
230 addpair(fp0, un0); 230 addpair(fp0, un0);
231 } 231 }
232 while (*p == ' ' || *p == '\t') 232 while (*p == ' ' || *p == '\t')
233 p++; 233 p++;
234 if (*p && *p != '#') 234 if (*p && *p != '#')
235 fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p); 235 fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
236 } 236 }
237 237
238 /* Okay, we hit EOF, now output hash table */ 238 /* Okay, we hit EOF, now output hash table */
239 239
240 fclose(ctbl); 240 fclose(ctbl);
241 241
242 242
243 /* Compute total size of Unicode list */ 243 /* Compute total size of Unicode list */
244 nuni = 0; 244 nuni = 0;
245 for ( i = 0 ; i < fontlen ; i++ ) 245 for ( i = 0 ; i < fontlen ; i++ )
246 nuni += unicount[i]; 246 nuni += unicount[i];
247 247
248 printf("\ 248 printf("\
249 /*\n\ 249 /*\n\
250 * Do not edit this file; it was automatically generated by\n\ 250 * Do not edit this file; it was automatically generated by\n\
251 *\n\ 251 *\n\
252 * conmakehash %s > [this file]\n\ 252 * conmakehash %s > [this file]\n\
253 *\n\ 253 *\n\
254 */\n\ 254 */\n\
255 \n\ 255 \n\
256 #include <linux/types.h>\n\ 256 #include <linux/types.h>\n\
257 \n\ 257 \n\
258 u8 dfont_unicount[%d] = \n\ 258 u8 dfont_unicount[%d] = \n\
259 {\n\t", argv[1], fontlen); 259 {\n\t", argv[1], fontlen);
260 260
261 for ( i = 0 ; i < fontlen ; i++ ) 261 for ( i = 0 ; i < fontlen ; i++ )
262 { 262 {
263 printf("%3d", unicount[i]); 263 printf("%3d", unicount[i]);
264 if ( i == fontlen-1 ) 264 if ( i == fontlen-1 )
265 printf("\n};\n"); 265 printf("\n};\n");
266 else if ( i % 8 == 7 ) 266 else if ( i % 8 == 7 )
267 printf(",\n\t"); 267 printf(",\n\t");
268 else 268 else
269 printf(", "); 269 printf(", ");
270 } 270 }
271 271
272 printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni); 272 printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
273 273
274 fp0 = 0; 274 fp0 = 0;
275 nent = 0; 275 nent = 0;
276 for ( i = 0 ; i < nuni ; i++ ) 276 for ( i = 0 ; i < nuni ; i++ )
277 { 277 {
278 while ( nent >= unicount[fp0] ) 278 while ( nent >= unicount[fp0] )
279 { 279 {
280 fp0++; 280 fp0++;
281 nent = 0; 281 nent = 0;
282 } 282 }
283 printf("0x%04x", unitable[fp0][nent++]); 283 printf("0x%04x", unitable[fp0][nent++]);
284 if ( i == nuni-1 ) 284 if ( i == nuni-1 )
285 printf("\n};\n"); 285 printf("\n};\n");
286 else if ( i % 8 == 7 ) 286 else if ( i % 8 == 7 )
287 printf(",\n\t"); 287 printf(",\n\t");
288 else 288 else
289 printf(", "); 289 printf(", ");
290 } 290 }
291 291
292 exit(EX_OK); 292 exit(EX_OK);
293 } 293 }
294 294
scripts/mod/modpost.c
1 /* Postprocess module symbol versions 1 /* Postprocess module symbol versions
2 * 2 *
3 * Copyright 2003 Kai Germaschewski 3 * Copyright 2003 Kai Germaschewski
4 * Copyright 2002-2004 Rusty Russell, IBM Corporation 4 * Copyright 2002-2004 Rusty Russell, IBM Corporation
5 * Copyright 2006-2008 Sam Ravnborg 5 * Copyright 2006-2008 Sam Ravnborg
6 * Based in part on module-init-tools/depmod.c,file2alias 6 * Based in part on module-init-tools/depmod.c,file2alias
7 * 7 *
8 * This software may be used and distributed according to the terms 8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference. 9 * of the GNU General Public License, incorporated herein by reference.
10 * 10 *
11 * Usage: modpost vmlinux module1.o module2.o ... 11 * Usage: modpost vmlinux module1.o module2.o ...
12 */ 12 */
13 13
14 #define _GNU_SOURCE 14 #define _GNU_SOURCE
15 #include <stdio.h> 15 #include <stdio.h>
16 #include <ctype.h> 16 #include <ctype.h>
17 #include "modpost.h" 17 #include "modpost.h"
18 #include "../../include/linux/license.h" 18 #include "../../include/linux/license.h"
19 19
20 /* Are we using CONFIG_MODVERSIONS? */ 20 /* Are we using CONFIG_MODVERSIONS? */
21 int modversions = 0; 21 int modversions = 0;
22 /* Warn about undefined symbols? (do so if we have vmlinux) */ 22 /* Warn about undefined symbols? (do so if we have vmlinux) */
23 int have_vmlinux = 0; 23 int have_vmlinux = 0;
24 /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 24 /* Is CONFIG_MODULE_SRCVERSION_ALL set? */
25 static int all_versions = 0; 25 static int all_versions = 0;
26 /* If we are modposting external module set to 1 */ 26 /* If we are modposting external module set to 1 */
27 static int external_module = 0; 27 static int external_module = 0;
28 /* Warn about section mismatch in vmlinux if set to 1 */ 28 /* Warn about section mismatch in vmlinux if set to 1 */
29 static int vmlinux_section_warnings = 1; 29 static int vmlinux_section_warnings = 1;
30 /* Only warn about unresolved symbols */ 30 /* Only warn about unresolved symbols */
31 static int warn_unresolved = 0; 31 static int warn_unresolved = 0;
32 /* How a symbol is exported */ 32 /* How a symbol is exported */
33 static int sec_mismatch_count = 0; 33 static int sec_mismatch_count = 0;
34 static int sec_mismatch_verbose = 1; 34 static int sec_mismatch_verbose = 1;
35 35
36 enum export { 36 enum export {
37 export_plain, export_unused, export_gpl, 37 export_plain, export_unused, export_gpl,
38 export_unused_gpl, export_gpl_future, export_unknown 38 export_unused_gpl, export_gpl_future, export_unknown
39 }; 39 };
40 40
41 #define PRINTF __attribute__ ((format (printf, 1, 2))) 41 #define PRINTF __attribute__ ((format (printf, 1, 2)))
42 42
43 PRINTF void fatal(const char *fmt, ...) 43 PRINTF void fatal(const char *fmt, ...)
44 { 44 {
45 va_list arglist; 45 va_list arglist;
46 46
47 fprintf(stderr, "FATAL: "); 47 fprintf(stderr, "FATAL: ");
48 48
49 va_start(arglist, fmt); 49 va_start(arglist, fmt);
50 vfprintf(stderr, fmt, arglist); 50 vfprintf(stderr, fmt, arglist);
51 va_end(arglist); 51 va_end(arglist);
52 52
53 exit(1); 53 exit(1);
54 } 54 }
55 55
56 PRINTF void warn(const char *fmt, ...) 56 PRINTF void warn(const char *fmt, ...)
57 { 57 {
58 va_list arglist; 58 va_list arglist;
59 59
60 fprintf(stderr, "WARNING: "); 60 fprintf(stderr, "WARNING: ");
61 61
62 va_start(arglist, fmt); 62 va_start(arglist, fmt);
63 vfprintf(stderr, fmt, arglist); 63 vfprintf(stderr, fmt, arglist);
64 va_end(arglist); 64 va_end(arglist);
65 } 65 }
66 66
67 PRINTF void merror(const char *fmt, ...) 67 PRINTF void merror(const char *fmt, ...)
68 { 68 {
69 va_list arglist; 69 va_list arglist;
70 70
71 fprintf(stderr, "ERROR: "); 71 fprintf(stderr, "ERROR: ");
72 72
73 va_start(arglist, fmt); 73 va_start(arglist, fmt);
74 vfprintf(stderr, fmt, arglist); 74 vfprintf(stderr, fmt, arglist);
75 va_end(arglist); 75 va_end(arglist);
76 } 76 }
77 77
78 static int is_vmlinux(const char *modname) 78 static int is_vmlinux(const char *modname)
79 { 79 {
80 const char *myname; 80 const char *myname;
81 81
82 myname = strrchr(modname, '/'); 82 myname = strrchr(modname, '/');
83 if (myname) 83 if (myname)
84 myname++; 84 myname++;
85 else 85 else
86 myname = modname; 86 myname = modname;
87 87
88 return (strcmp(myname, "vmlinux") == 0) || 88 return (strcmp(myname, "vmlinux") == 0) ||
89 (strcmp(myname, "vmlinux.o") == 0); 89 (strcmp(myname, "vmlinux.o") == 0);
90 } 90 }
91 91
92 void *do_nofail(void *ptr, const char *expr) 92 void *do_nofail(void *ptr, const char *expr)
93 { 93 {
94 if (!ptr) 94 if (!ptr)
95 fatal("modpost: Memory allocation failure: %s.\n", expr); 95 fatal("modpost: Memory allocation failure: %s.\n", expr);
96 96
97 return ptr; 97 return ptr;
98 } 98 }
99 99
100 /* A list of all modules we processed */ 100 /* A list of all modules we processed */
101 static struct module *modules; 101 static struct module *modules;
102 102
103 static struct module *find_module(char *modname) 103 static struct module *find_module(char *modname)
104 { 104 {
105 struct module *mod; 105 struct module *mod;
106 106
107 for (mod = modules; mod; mod = mod->next) 107 for (mod = modules; mod; mod = mod->next)
108 if (strcmp(mod->name, modname) == 0) 108 if (strcmp(mod->name, modname) == 0)
109 break; 109 break;
110 return mod; 110 return mod;
111 } 111 }
112 112
113 static struct module *new_module(char *modname) 113 static struct module *new_module(char *modname)
114 { 114 {
115 struct module *mod; 115 struct module *mod;
116 char *p, *s; 116 char *p, *s;
117 117
118 mod = NOFAIL(malloc(sizeof(*mod))); 118 mod = NOFAIL(malloc(sizeof(*mod)));
119 memset(mod, 0, sizeof(*mod)); 119 memset(mod, 0, sizeof(*mod));
120 p = NOFAIL(strdup(modname)); 120 p = NOFAIL(strdup(modname));
121 121
122 /* strip trailing .o */ 122 /* strip trailing .o */
123 s = strrchr(p, '.'); 123 s = strrchr(p, '.');
124 if (s != NULL) 124 if (s != NULL)
125 if (strcmp(s, ".o") == 0) 125 if (strcmp(s, ".o") == 0)
126 *s = '\0'; 126 *s = '\0';
127 127
128 /* add to list */ 128 /* add to list */
129 mod->name = p; 129 mod->name = p;
130 mod->gpl_compatible = -1; 130 mod->gpl_compatible = -1;
131 mod->next = modules; 131 mod->next = modules;
132 modules = mod; 132 modules = mod;
133 133
134 return mod; 134 return mod;
135 } 135 }
136 136
137 /* A hash of all exported symbols, 137 /* A hash of all exported symbols,
138 * struct symbol is also used for lists of unresolved symbols */ 138 * struct symbol is also used for lists of unresolved symbols */
139 139
140 #define SYMBOL_HASH_SIZE 1024 140 #define SYMBOL_HASH_SIZE 1024
141 141
142 struct symbol { 142 struct symbol {
143 struct symbol *next; 143 struct symbol *next;
144 struct module *module; 144 struct module *module;
145 unsigned int crc; 145 unsigned int crc;
146 int crc_valid; 146 int crc_valid;
147 unsigned int weak:1; 147 unsigned int weak:1;
148 unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ 148 unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
149 unsigned int kernel:1; /* 1 if symbol is from kernel 149 unsigned int kernel:1; /* 1 if symbol is from kernel
150 * (only for external modules) **/ 150 * (only for external modules) **/
151 unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ 151 unsigned int preloaded:1; /* 1 if symbol from Module.symvers */
152 enum export export; /* Type of export */ 152 enum export export; /* Type of export */
153 char name[0]; 153 char name[0];
154 }; 154 };
155 155
156 static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; 156 static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
157 157
158 /* This is based on the hash agorithm from gdbm, via tdb */ 158 /* This is based on the hash agorithm from gdbm, via tdb */
159 static inline unsigned int tdb_hash(const char *name) 159 static inline unsigned int tdb_hash(const char *name)
160 { 160 {
161 unsigned value; /* Used to compute the hash value. */ 161 unsigned value; /* Used to compute the hash value. */
162 unsigned i; /* Used to cycle through random values. */ 162 unsigned i; /* Used to cycle through random values. */
163 163
164 /* Set the initial value from the key size. */ 164 /* Set the initial value from the key size. */
165 for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) 165 for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++)
166 value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); 166 value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
167 167
168 return (1103515243 * value + 12345); 168 return (1103515243 * value + 12345);
169 } 169 }
170 170
171 /** 171 /**
172 * Allocate a new symbols for use in the hash of exported symbols or 172 * Allocate a new symbols for use in the hash of exported symbols or
173 * the list of unresolved symbols per module 173 * the list of unresolved symbols per module
174 **/ 174 **/
175 static struct symbol *alloc_symbol(const char *name, unsigned int weak, 175 static struct symbol *alloc_symbol(const char *name, unsigned int weak,
176 struct symbol *next) 176 struct symbol *next)
177 { 177 {
178 struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); 178 struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
179 179
180 memset(s, 0, sizeof(*s)); 180 memset(s, 0, sizeof(*s));
181 strcpy(s->name, name); 181 strcpy(s->name, name);
182 s->weak = weak; 182 s->weak = weak;
183 s->next = next; 183 s->next = next;
184 return s; 184 return s;
185 } 185 }
186 186
187 /* For the hash of exported symbols */ 187 /* For the hash of exported symbols */
188 static struct symbol *new_symbol(const char *name, struct module *module, 188 static struct symbol *new_symbol(const char *name, struct module *module,
189 enum export export) 189 enum export export)
190 { 190 {
191 unsigned int hash; 191 unsigned int hash;
192 struct symbol *new; 192 struct symbol *new;
193 193
194 hash = tdb_hash(name) % SYMBOL_HASH_SIZE; 194 hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
195 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); 195 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
196 new->module = module; 196 new->module = module;
197 new->export = export; 197 new->export = export;
198 return new; 198 return new;
199 } 199 }
200 200
201 static struct symbol *find_symbol(const char *name) 201 static struct symbol *find_symbol(const char *name)
202 { 202 {
203 struct symbol *s; 203 struct symbol *s;
204 204
205 /* For our purposes, .foo matches foo. PPC64 needs this. */ 205 /* For our purposes, .foo matches foo. PPC64 needs this. */
206 if (name[0] == '.') 206 if (name[0] == '.')
207 name++; 207 name++;
208 208
209 for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { 209 for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) {
210 if (strcmp(s->name, name) == 0) 210 if (strcmp(s->name, name) == 0)
211 return s; 211 return s;
212 } 212 }
213 return NULL; 213 return NULL;
214 } 214 }
215 215
216 static struct { 216 static struct {
217 const char *str; 217 const char *str;
218 enum export export; 218 enum export export;
219 } export_list[] = { 219 } export_list[] = {
220 { .str = "EXPORT_SYMBOL", .export = export_plain }, 220 { .str = "EXPORT_SYMBOL", .export = export_plain },
221 { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, 221 { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
222 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, 222 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
223 { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, 223 { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
224 { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, 224 { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
225 { .str = "(unknown)", .export = export_unknown }, 225 { .str = "(unknown)", .export = export_unknown },
226 }; 226 };
227 227
228 228
229 static const char *export_str(enum export ex) 229 static const char *export_str(enum export ex)
230 { 230 {
231 return export_list[ex].str; 231 return export_list[ex].str;
232 } 232 }
233 233
234 static enum export export_no(const char *s) 234 static enum export export_no(const char *s)
235 { 235 {
236 int i; 236 int i;
237 237
238 if (!s) 238 if (!s)
239 return export_unknown; 239 return export_unknown;
240 for (i = 0; export_list[i].export != export_unknown; i++) { 240 for (i = 0; export_list[i].export != export_unknown; i++) {
241 if (strcmp(export_list[i].str, s) == 0) 241 if (strcmp(export_list[i].str, s) == 0)
242 return export_list[i].export; 242 return export_list[i].export;
243 } 243 }
244 return export_unknown; 244 return export_unknown;
245 } 245 }
246 246
247 static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) 247 static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
248 { 248 {
249 if (sec == elf->export_sec) 249 if (sec == elf->export_sec)
250 return export_plain; 250 return export_plain;
251 else if (sec == elf->export_unused_sec) 251 else if (sec == elf->export_unused_sec)
252 return export_unused; 252 return export_unused;
253 else if (sec == elf->export_gpl_sec) 253 else if (sec == elf->export_gpl_sec)
254 return export_gpl; 254 return export_gpl;
255 else if (sec == elf->export_unused_gpl_sec) 255 else if (sec == elf->export_unused_gpl_sec)
256 return export_unused_gpl; 256 return export_unused_gpl;
257 else if (sec == elf->export_gpl_future_sec) 257 else if (sec == elf->export_gpl_future_sec)
258 return export_gpl_future; 258 return export_gpl_future;
259 else 259 else
260 return export_unknown; 260 return export_unknown;
261 } 261 }
262 262
263 /** 263 /**
264 * Add an exported symbol - it may have already been added without a 264 * Add an exported symbol - it may have already been added without a
265 * CRC, in this case just update the CRC 265 * CRC, in this case just update the CRC
266 **/ 266 **/
267 static struct symbol *sym_add_exported(const char *name, struct module *mod, 267 static struct symbol *sym_add_exported(const char *name, struct module *mod,
268 enum export export) 268 enum export export)
269 { 269 {
270 struct symbol *s = find_symbol(name); 270 struct symbol *s = find_symbol(name);
271 271
272 if (!s) { 272 if (!s) {
273 s = new_symbol(name, mod, export); 273 s = new_symbol(name, mod, export);
274 } else { 274 } else {
275 if (!s->preloaded) { 275 if (!s->preloaded) {
276 warn("%s: '%s' exported twice. Previous export " 276 warn("%s: '%s' exported twice. Previous export "
277 "was in %s%s\n", mod->name, name, 277 "was in %s%s\n", mod->name, name,
278 s->module->name, 278 s->module->name,
279 is_vmlinux(s->module->name) ?"":".ko"); 279 is_vmlinux(s->module->name) ?"":".ko");
280 } else { 280 } else {
281 /* In case Modules.symvers was out of date */ 281 /* In case Modules.symvers was out of date */
282 s->module = mod; 282 s->module = mod;
283 } 283 }
284 } 284 }
285 s->preloaded = 0; 285 s->preloaded = 0;
286 s->vmlinux = is_vmlinux(mod->name); 286 s->vmlinux = is_vmlinux(mod->name);
287 s->kernel = 0; 287 s->kernel = 0;
288 s->export = export; 288 s->export = export;
289 return s; 289 return s;
290 } 290 }
291 291
292 static void sym_update_crc(const char *name, struct module *mod, 292 static void sym_update_crc(const char *name, struct module *mod,
293 unsigned int crc, enum export export) 293 unsigned int crc, enum export export)
294 { 294 {
295 struct symbol *s = find_symbol(name); 295 struct symbol *s = find_symbol(name);
296 296
297 if (!s) 297 if (!s)
298 s = new_symbol(name, mod, export); 298 s = new_symbol(name, mod, export);
299 s->crc = crc; 299 s->crc = crc;
300 s->crc_valid = 1; 300 s->crc_valid = 1;
301 } 301 }
302 302
303 void *grab_file(const char *filename, unsigned long *size) 303 void *grab_file(const char *filename, unsigned long *size)
304 { 304 {
305 struct stat st; 305 struct stat st;
306 void *map; 306 void *map;
307 int fd; 307 int fd;
308 308
309 fd = open(filename, O_RDONLY); 309 fd = open(filename, O_RDONLY);
310 if (fd < 0 || fstat(fd, &st) != 0) 310 if (fd < 0 || fstat(fd, &st) != 0)
311 return NULL; 311 return NULL;
312 312
313 *size = st.st_size; 313 *size = st.st_size;
314 map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 314 map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
315 close(fd); 315 close(fd);
316 316
317 if (map == MAP_FAILED) 317 if (map == MAP_FAILED)
318 return NULL; 318 return NULL;
319 return map; 319 return map;
320 } 320 }
321 321
322 /** 322 /**
323 * Return a copy of the next line in a mmap'ed file. 323 * Return a copy of the next line in a mmap'ed file.
324 * spaces in the beginning of the line is trimmed away. 324 * spaces in the beginning of the line is trimmed away.
325 * Return a pointer to a static buffer. 325 * Return a pointer to a static buffer.
326 **/ 326 **/
327 char *get_next_line(unsigned long *pos, void *file, unsigned long size) 327 char *get_next_line(unsigned long *pos, void *file, unsigned long size)
328 { 328 {
329 static char line[4096]; 329 static char line[4096];
330 int skip = 1; 330 int skip = 1;
331 size_t len = 0; 331 size_t len = 0;
332 signed char *p = (signed char *)file + *pos; 332 signed char *p = (signed char *)file + *pos;
333 char *s = line; 333 char *s = line;
334 334
335 for (; *pos < size ; (*pos)++) { 335 for (; *pos < size ; (*pos)++) {
336 if (skip && isspace(*p)) { 336 if (skip && isspace(*p)) {
337 p++; 337 p++;
338 continue; 338 continue;
339 } 339 }
340 skip = 0; 340 skip = 0;
341 if (*p != '\n' && (*pos < size)) { 341 if (*p != '\n' && (*pos < size)) {
342 len++; 342 len++;
343 *s++ = *p++; 343 *s++ = *p++;
344 if (len > 4095) 344 if (len > 4095)
345 break; /* Too long, stop */ 345 break; /* Too long, stop */
346 } else { 346 } else {
347 /* End of string */ 347 /* End of string */
348 *s = '\0'; 348 *s = '\0';
349 return line; 349 return line;
350 } 350 }
351 } 351 }
352 /* End of buffer */ 352 /* End of buffer */
353 return NULL; 353 return NULL;
354 } 354 }
355 355
356 void release_file(void *file, unsigned long size) 356 void release_file(void *file, unsigned long size)
357 { 357 {
358 munmap(file, size); 358 munmap(file, size);
359 } 359 }
360 360
361 static int parse_elf(struct elf_info *info, const char *filename) 361 static int parse_elf(struct elf_info *info, const char *filename)
362 { 362 {
363 unsigned int i; 363 unsigned int i;
364 Elf_Ehdr *hdr; 364 Elf_Ehdr *hdr;
365 Elf_Shdr *sechdrs; 365 Elf_Shdr *sechdrs;
366 Elf_Sym *sym; 366 Elf_Sym *sym;
367 367
368 hdr = grab_file(filename, &info->size); 368 hdr = grab_file(filename, &info->size);
369 if (!hdr) { 369 if (!hdr) {
370 perror(filename); 370 perror(filename);
371 exit(1); 371 exit(1);
372 } 372 }
373 info->hdr = hdr; 373 info->hdr = hdr;
374 if (info->size < sizeof(*hdr)) { 374 if (info->size < sizeof(*hdr)) {
375 /* file too small, assume this is an empty .o file */ 375 /* file too small, assume this is an empty .o file */
376 return 0; 376 return 0;
377 } 377 }
378 /* Is this a valid ELF file? */ 378 /* Is this a valid ELF file? */
379 if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || 379 if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
380 (hdr->e_ident[EI_MAG1] != ELFMAG1) || 380 (hdr->e_ident[EI_MAG1] != ELFMAG1) ||
381 (hdr->e_ident[EI_MAG2] != ELFMAG2) || 381 (hdr->e_ident[EI_MAG2] != ELFMAG2) ||
382 (hdr->e_ident[EI_MAG3] != ELFMAG3)) { 382 (hdr->e_ident[EI_MAG3] != ELFMAG3)) {
383 /* Not an ELF file - silently ignore it */ 383 /* Not an ELF file - silently ignore it */
384 return 0; 384 return 0;
385 } 385 }
386 /* Fix endianness in ELF header */ 386 /* Fix endianness in ELF header */
387 hdr->e_type = TO_NATIVE(hdr->e_type); 387 hdr->e_type = TO_NATIVE(hdr->e_type);
388 hdr->e_machine = TO_NATIVE(hdr->e_machine); 388 hdr->e_machine = TO_NATIVE(hdr->e_machine);
389 hdr->e_version = TO_NATIVE(hdr->e_version); 389 hdr->e_version = TO_NATIVE(hdr->e_version);
390 hdr->e_entry = TO_NATIVE(hdr->e_entry); 390 hdr->e_entry = TO_NATIVE(hdr->e_entry);
391 hdr->e_phoff = TO_NATIVE(hdr->e_phoff); 391 hdr->e_phoff = TO_NATIVE(hdr->e_phoff);
392 hdr->e_shoff = TO_NATIVE(hdr->e_shoff); 392 hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
393 hdr->e_flags = TO_NATIVE(hdr->e_flags); 393 hdr->e_flags = TO_NATIVE(hdr->e_flags);
394 hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); 394 hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize);
395 hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); 395 hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);
396 hdr->e_phnum = TO_NATIVE(hdr->e_phnum); 396 hdr->e_phnum = TO_NATIVE(hdr->e_phnum);
397 hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); 397 hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);
398 hdr->e_shnum = TO_NATIVE(hdr->e_shnum); 398 hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
399 hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); 399 hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
400 sechdrs = (void *)hdr + hdr->e_shoff; 400 sechdrs = (void *)hdr + hdr->e_shoff;
401 info->sechdrs = sechdrs; 401 info->sechdrs = sechdrs;
402 402
403 /* Check if file offset is correct */ 403 /* Check if file offset is correct */
404 if (hdr->e_shoff > info->size) { 404 if (hdr->e_shoff > info->size) {
405 fatal("section header offset=%lu in file '%s' is bigger than " 405 fatal("section header offset=%lu in file '%s' is bigger than "
406 "filesize=%lu\n", (unsigned long)hdr->e_shoff, 406 "filesize=%lu\n", (unsigned long)hdr->e_shoff,
407 filename, info->size); 407 filename, info->size);
408 return 0; 408 return 0;
409 } 409 }
410 410
411 /* Fix endianness in section headers */ 411 /* Fix endianness in section headers */
412 for (i = 0; i < hdr->e_shnum; i++) { 412 for (i = 0; i < hdr->e_shnum; i++) {
413 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); 413 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
414 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); 414 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
415 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); 415 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
416 sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); 416 sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
417 sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); 417 sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
418 sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); 418 sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
419 sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); 419 sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
420 sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); 420 sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
421 sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); 421 sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);
422 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); 422 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
423 } 423 }
424 /* Find symbol table. */ 424 /* Find symbol table. */
425 for (i = 1; i < hdr->e_shnum; i++) { 425 for (i = 1; i < hdr->e_shnum; i++) {
426 const char *secstrings 426 const char *secstrings
427 = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 427 = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
428 const char *secname; 428 const char *secname;
429 int nobits = sechdrs[i].sh_type == SHT_NOBITS; 429 int nobits = sechdrs[i].sh_type == SHT_NOBITS;
430 430
431 if (!nobits && sechdrs[i].sh_offset > info->size) { 431 if (!nobits && sechdrs[i].sh_offset > info->size) {
432 fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " 432 fatal("%s is truncated. sechdrs[i].sh_offset=%lu > "
433 "sizeof(*hrd)=%zu\n", filename, 433 "sizeof(*hrd)=%zu\n", filename,
434 (unsigned long)sechdrs[i].sh_offset, 434 (unsigned long)sechdrs[i].sh_offset,
435 sizeof(*hdr)); 435 sizeof(*hdr));
436 return 0; 436 return 0;
437 } 437 }
438 secname = secstrings + sechdrs[i].sh_name; 438 secname = secstrings + sechdrs[i].sh_name;
439 if (strcmp(secname, ".modinfo") == 0) { 439 if (strcmp(secname, ".modinfo") == 0) {
440 if (nobits) 440 if (nobits)
441 fatal("%s has NOBITS .modinfo\n", filename); 441 fatal("%s has NOBITS .modinfo\n", filename);
442 info->modinfo = (void *)hdr + sechdrs[i].sh_offset; 442 info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
443 info->modinfo_len = sechdrs[i].sh_size; 443 info->modinfo_len = sechdrs[i].sh_size;
444 } else if (strcmp(secname, "__ksymtab") == 0) 444 } else if (strcmp(secname, "__ksymtab") == 0)
445 info->export_sec = i; 445 info->export_sec = i;
446 else if (strcmp(secname, "__ksymtab_unused") == 0) 446 else if (strcmp(secname, "__ksymtab_unused") == 0)
447 info->export_unused_sec = i; 447 info->export_unused_sec = i;
448 else if (strcmp(secname, "__ksymtab_gpl") == 0) 448 else if (strcmp(secname, "__ksymtab_gpl") == 0)
449 info->export_gpl_sec = i; 449 info->export_gpl_sec = i;
450 else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) 450 else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
451 info->export_unused_gpl_sec = i; 451 info->export_unused_gpl_sec = i;
452 else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 452 else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
453 info->export_gpl_future_sec = i; 453 info->export_gpl_future_sec = i;
454 else if (strcmp(secname, "__markers_strings") == 0) 454 else if (strcmp(secname, "__markers_strings") == 0)
455 info->markers_strings_sec = i; 455 info->markers_strings_sec = i;
456 456
457 if (sechdrs[i].sh_type != SHT_SYMTAB) 457 if (sechdrs[i].sh_type != SHT_SYMTAB)
458 continue; 458 continue;
459 459
460 info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; 460 info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
461 info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset 461 info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
462 + sechdrs[i].sh_size; 462 + sechdrs[i].sh_size;
463 info->strtab = (void *)hdr + 463 info->strtab = (void *)hdr +
464 sechdrs[sechdrs[i].sh_link].sh_offset; 464 sechdrs[sechdrs[i].sh_link].sh_offset;
465 } 465 }
466 if (!info->symtab_start) 466 if (!info->symtab_start)
467 fatal("%s has no symtab?\n", filename); 467 fatal("%s has no symtab?\n", filename);
468 468
469 /* Fix endianness in symbols */ 469 /* Fix endianness in symbols */
470 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { 470 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
471 sym->st_shndx = TO_NATIVE(sym->st_shndx); 471 sym->st_shndx = TO_NATIVE(sym->st_shndx);
472 sym->st_name = TO_NATIVE(sym->st_name); 472 sym->st_name = TO_NATIVE(sym->st_name);
473 sym->st_value = TO_NATIVE(sym->st_value); 473 sym->st_value = TO_NATIVE(sym->st_value);
474 sym->st_size = TO_NATIVE(sym->st_size); 474 sym->st_size = TO_NATIVE(sym->st_size);
475 } 475 }
476 return 1; 476 return 1;
477 } 477 }
478 478
479 static void parse_elf_finish(struct elf_info *info) 479 static void parse_elf_finish(struct elf_info *info)
480 { 480 {
481 release_file(info->hdr, info->size); 481 release_file(info->hdr, info->size);
482 } 482 }
483 483
484 static int ignore_undef_symbol(struct elf_info *info, const char *symname) 484 static int ignore_undef_symbol(struct elf_info *info, const char *symname)
485 { 485 {
486 /* ignore __this_module, it will be resolved shortly */ 486 /* ignore __this_module, it will be resolved shortly */
487 if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) 487 if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0)
488 return 1; 488 return 1;
489 /* ignore global offset table */ 489 /* ignore global offset table */
490 if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) 490 if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
491 return 1; 491 return 1;
492 if (info->hdr->e_machine == EM_PPC) 492 if (info->hdr->e_machine == EM_PPC)
493 /* Special register function linked on all modules during final link of .ko */ 493 /* Special register function linked on all modules during final link of .ko */
494 if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 || 494 if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||
495 strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 || 495 strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||
496 strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 || 496 strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
497 strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0) 497 strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0)
498 return 1; 498 return 1;
499 /* Do not ignore this symbol */ 499 /* Do not ignore this symbol */
500 return 0; 500 return 0;
501 } 501 }
502 502
503 #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_" 503 #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
504 #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" 504 #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
505 505
506 static void handle_modversions(struct module *mod, struct elf_info *info, 506 static void handle_modversions(struct module *mod, struct elf_info *info,
507 Elf_Sym *sym, const char *symname) 507 Elf_Sym *sym, const char *symname)
508 { 508 {
509 unsigned int crc; 509 unsigned int crc;
510 enum export export = export_from_sec(info, sym->st_shndx); 510 enum export export = export_from_sec(info, sym->st_shndx);
511 511
512 switch (sym->st_shndx) { 512 switch (sym->st_shndx) {
513 case SHN_COMMON: 513 case SHN_COMMON:
514 warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); 514 warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
515 break; 515 break;
516 case SHN_ABS: 516 case SHN_ABS:
517 /* CRC'd symbol */ 517 /* CRC'd symbol */
518 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { 518 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
519 crc = (unsigned int) sym->st_value; 519 crc = (unsigned int) sym->st_value;
520 sym_update_crc(symname + strlen(CRC_PFX), mod, crc, 520 sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
521 export); 521 export);
522 } 522 }
523 break; 523 break;
524 case SHN_UNDEF: 524 case SHN_UNDEF:
525 /* undefined symbol */ 525 /* undefined symbol */
526 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && 526 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
527 ELF_ST_BIND(sym->st_info) != STB_WEAK) 527 ELF_ST_BIND(sym->st_info) != STB_WEAK)
528 break; 528 break;
529 if (ignore_undef_symbol(info, symname)) 529 if (ignore_undef_symbol(info, symname))
530 break; 530 break;
531 /* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */ 531 /* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */
532 #if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER) 532 #if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER)
533 /* add compatibility with older glibc */ 533 /* add compatibility with older glibc */
534 #ifndef STT_SPARC_REGISTER 534 #ifndef STT_SPARC_REGISTER
535 #define STT_SPARC_REGISTER STT_REGISTER 535 #define STT_SPARC_REGISTER STT_REGISTER
536 #endif 536 #endif
537 if (info->hdr->e_machine == EM_SPARC || 537 if (info->hdr->e_machine == EM_SPARC ||
538 info->hdr->e_machine == EM_SPARCV9) { 538 info->hdr->e_machine == EM_SPARCV9) {
539 /* Ignore register directives. */ 539 /* Ignore register directives. */
540 if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) 540 if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
541 break; 541 break;
542 if (symname[0] == '.') { 542 if (symname[0] == '.') {
543 char *munged = strdup(symname); 543 char *munged = strdup(symname);
544 munged[0] = '_'; 544 munged[0] = '_';
545 munged[1] = toupper(munged[1]); 545 munged[1] = toupper(munged[1]);
546 symname = munged; 546 symname = munged;
547 } 547 }
548 } 548 }
549 #endif 549 #endif
550 550
551 if (memcmp(symname, MODULE_SYMBOL_PREFIX, 551 if (memcmp(symname, MODULE_SYMBOL_PREFIX,
552 strlen(MODULE_SYMBOL_PREFIX)) == 0) { 552 strlen(MODULE_SYMBOL_PREFIX)) == 0) {
553 mod->unres = 553 mod->unres =
554 alloc_symbol(symname + 554 alloc_symbol(symname +
555 strlen(MODULE_SYMBOL_PREFIX), 555 strlen(MODULE_SYMBOL_PREFIX),
556 ELF_ST_BIND(sym->st_info) == STB_WEAK, 556 ELF_ST_BIND(sym->st_info) == STB_WEAK,
557 mod->unres); 557 mod->unres);
558 } 558 }
559 break; 559 break;
560 default: 560 default:
561 /* All exported symbols */ 561 /* All exported symbols */
562 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { 562 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
563 sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, 563 sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
564 export); 564 export);
565 } 565 }
566 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) 566 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
567 mod->has_init = 1; 567 mod->has_init = 1;
568 if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0) 568 if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
569 mod->has_cleanup = 1; 569 mod->has_cleanup = 1;
570 break; 570 break;
571 } 571 }
572 } 572 }
573 573
574 /** 574 /**
575 * Parse tag=value strings from .modinfo section 575 * Parse tag=value strings from .modinfo section
576 **/ 576 **/
577 static char *next_string(char *string, unsigned long *secsize) 577 static char *next_string(char *string, unsigned long *secsize)
578 { 578 {
579 /* Skip non-zero chars */ 579 /* Skip non-zero chars */
580 while (string[0]) { 580 while (string[0]) {
581 string++; 581 string++;
582 if ((*secsize)-- <= 1) 582 if ((*secsize)-- <= 1)
583 return NULL; 583 return NULL;
584 } 584 }
585 585
586 /* Skip any zero padding. */ 586 /* Skip any zero padding. */
587 while (!string[0]) { 587 while (!string[0]) {
588 string++; 588 string++;
589 if ((*secsize)-- <= 1) 589 if ((*secsize)-- <= 1)
590 return NULL; 590 return NULL;
591 } 591 }
592 return string; 592 return string;
593 } 593 }
594 594
595 static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, 595 static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len,
596 const char *tag, char *info) 596 const char *tag, char *info)
597 { 597 {
598 char *p; 598 char *p;
599 unsigned int taglen = strlen(tag); 599 unsigned int taglen = strlen(tag);
600 unsigned long size = modinfo_len; 600 unsigned long size = modinfo_len;
601 601
602 if (info) { 602 if (info) {
603 size -= info - (char *)modinfo; 603 size -= info - (char *)modinfo;
604 modinfo = next_string(info, &size); 604 modinfo = next_string(info, &size);
605 } 605 }
606 606
607 for (p = modinfo; p; p = next_string(p, &size)) { 607 for (p = modinfo; p; p = next_string(p, &size)) {
608 if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') 608 if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
609 return p + taglen + 1; 609 return p + taglen + 1;
610 } 610 }
611 return NULL; 611 return NULL;
612 } 612 }
613 613
614 static char *get_modinfo(void *modinfo, unsigned long modinfo_len, 614 static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
615 const char *tag) 615 const char *tag)
616 616
617 { 617 {
618 return get_next_modinfo(modinfo, modinfo_len, tag, NULL); 618 return get_next_modinfo(modinfo, modinfo_len, tag, NULL);
619 } 619 }
620 620
621 /** 621 /**
622 * Test if string s ends in string sub 622 * Test if string s ends in string sub
623 * return 0 if match 623 * return 0 if match
624 **/ 624 **/
625 static int strrcmp(const char *s, const char *sub) 625 static int strrcmp(const char *s, const char *sub)
626 { 626 {
627 int slen, sublen; 627 int slen, sublen;
628 628
629 if (!s || !sub) 629 if (!s || !sub)
630 return 1; 630 return 1;
631 631
632 slen = strlen(s); 632 slen = strlen(s);
633 sublen = strlen(sub); 633 sublen = strlen(sub);
634 634
635 if ((slen == 0) || (sublen == 0)) 635 if ((slen == 0) || (sublen == 0))
636 return 1; 636 return 1;
637 637
638 if (sublen > slen) 638 if (sublen > slen)
639 return 1; 639 return 1;
640 640
641 return memcmp(s + slen - sublen, sub, sublen); 641 return memcmp(s + slen - sublen, sub, sublen);
642 } 642 }
643 643
644 static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) 644 static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
645 { 645 {
646 if (sym) 646 if (sym)
647 return elf->strtab + sym->st_name; 647 return elf->strtab + sym->st_name;
648 else 648 else
649 return "(unknown)"; 649 return "(unknown)";
650 } 650 }
651 651
652 static const char *sec_name(struct elf_info *elf, int shndx) 652 static const char *sec_name(struct elf_info *elf, int shndx)
653 { 653 {
654 Elf_Shdr *sechdrs = elf->sechdrs; 654 Elf_Shdr *sechdrs = elf->sechdrs;
655 return (void *)elf->hdr + 655 return (void *)elf->hdr +
656 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + 656 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
657 sechdrs[shndx].sh_name; 657 sechdrs[shndx].sh_name;
658 } 658 }
659 659
660 static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) 660 static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
661 { 661 {
662 return (void *)elf->hdr + 662 return (void *)elf->hdr +
663 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + 663 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
664 sechdr->sh_name; 664 sechdr->sh_name;
665 } 665 }
666 666
667 /* if sym is empty or point to a string 667 /* if sym is empty or point to a string
668 * like ".[0-9]+" then return 1. 668 * like ".[0-9]+" then return 1.
669 * This is the optional prefix added by ld to some sections 669 * This is the optional prefix added by ld to some sections
670 */ 670 */
671 static int number_prefix(const char *sym) 671 static int number_prefix(const char *sym)
672 { 672 {
673 if (*sym++ == '\0') 673 if (*sym++ == '\0')
674 return 1; 674 return 1;
675 if (*sym != '.') 675 if (*sym != '.')
676 return 0; 676 return 0;
677 do { 677 do {
678 char c = *sym++; 678 char c = *sym++;
679 if (c < '0' || c > '9') 679 if (c < '0' || c > '9')
680 return 0; 680 return 0;
681 } while (*sym); 681 } while (*sym);
682 return 1; 682 return 1;
683 } 683 }
684 684
685 /* The pattern is an array of simple patterns. 685 /* The pattern is an array of simple patterns.
686 * "foo" will match an exact string equal to "foo" 686 * "foo" will match an exact string equal to "foo"
687 * "*foo" will match a string that ends with "foo" 687 * "*foo" will match a string that ends with "foo"
688 * "foo*" will match a string that begins with "foo" 688 * "foo*" will match a string that begins with "foo"
689 * "foo$" will match a string equal to "foo" or "foo.1" 689 * "foo$" will match a string equal to "foo" or "foo.1"
690 * where the '1' can be any number including several digits. 690 * where the '1' can be any number including several digits.
691 * The $ syntax is for sections where ld append a dot number 691 * The $ syntax is for sections where ld append a dot number
692 * to make section name unique. 692 * to make section name unique.
693 */ 693 */
694 int match(const char *sym, const char * const pat[]) 694 static int match(const char *sym, const char * const pat[])
695 { 695 {
696 const char *p; 696 const char *p;
697 while (*pat) { 697 while (*pat) {
698 p = *pat++; 698 p = *pat++;
699 const char *endp = p + strlen(p) - 1; 699 const char *endp = p + strlen(p) - 1;
700 700
701 /* "*foo" */ 701 /* "*foo" */
702 if (*p == '*') { 702 if (*p == '*') {
703 if (strrcmp(sym, p + 1) == 0) 703 if (strrcmp(sym, p + 1) == 0)
704 return 1; 704 return 1;
705 } 705 }
706 /* "foo*" */ 706 /* "foo*" */
707 else if (*endp == '*') { 707 else if (*endp == '*') {
708 if (strncmp(sym, p, strlen(p) - 1) == 0) 708 if (strncmp(sym, p, strlen(p) - 1) == 0)
709 return 1; 709 return 1;
710 } 710 }
711 /* "foo$" */ 711 /* "foo$" */
712 else if (*endp == '$') { 712 else if (*endp == '$') {
713 if (strncmp(sym, p, strlen(p) - 1) == 0) { 713 if (strncmp(sym, p, strlen(p) - 1) == 0) {
714 if (number_prefix(sym + strlen(p) - 1)) 714 if (number_prefix(sym + strlen(p) - 1))
715 return 1; 715 return 1;
716 } 716 }
717 } 717 }
718 /* no wildcards */ 718 /* no wildcards */
719 else { 719 else {
720 if (strcmp(p, sym) == 0) 720 if (strcmp(p, sym) == 0)
721 return 1; 721 return 1;
722 } 722 }
723 } 723 }
724 /* no match */ 724 /* no match */
725 return 0; 725 return 0;
726 } 726 }
727 727
728 /* sections that we do not want to do full section mismatch check on */ 728 /* sections that we do not want to do full section mismatch check on */
729 static const char *section_white_list[] = 729 static const char *section_white_list[] =
730 { 730 {
731 ".comment*", 731 ".comment*",
732 ".debug*", 732 ".debug*",
733 ".mdebug*", /* alpha, score, mips etc. */ 733 ".mdebug*", /* alpha, score, mips etc. */
734 ".pdr", /* alpha, score, mips etc. */ 734 ".pdr", /* alpha, score, mips etc. */
735 ".stab*", 735 ".stab*",
736 ".note*", 736 ".note*",
737 ".got*", 737 ".got*",
738 ".toc*", 738 ".toc*",
739 NULL 739 NULL
740 }; 740 };
741 741
742 /* 742 /*
743 * This is used to find sections missing the SHF_ALLOC flag. 743 * This is used to find sections missing the SHF_ALLOC flag.
744 * The cause of this is often a section specified in assembler 744 * The cause of this is often a section specified in assembler
745 * without "ax" / "aw". 745 * without "ax" / "aw".
746 */ 746 */
747 static void check_section(const char *modname, struct elf_info *elf, 747 static void check_section(const char *modname, struct elf_info *elf,
748 Elf_Shdr *sechdr) 748 Elf_Shdr *sechdr)
749 { 749 {
750 const char *sec = sech_name(elf, sechdr); 750 const char *sec = sech_name(elf, sechdr);
751 751
752 if (sechdr->sh_type == SHT_PROGBITS && 752 if (sechdr->sh_type == SHT_PROGBITS &&
753 !(sechdr->sh_flags & SHF_ALLOC) && 753 !(sechdr->sh_flags & SHF_ALLOC) &&
754 !match(sec, section_white_list)) { 754 !match(sec, section_white_list)) {
755 warn("%s (%s): unexpected non-allocatable section.\n" 755 warn("%s (%s): unexpected non-allocatable section.\n"
756 "Did you forget to use \"ax\"/\"aw\" in a .S file?\n" 756 "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
757 "Note that for example <linux/init.h> contains\n" 757 "Note that for example <linux/init.h> contains\n"
758 "section definitions for use in .S files.\n\n", 758 "section definitions for use in .S files.\n\n",
759 modname, sec); 759 modname, sec);
760 } 760 }
761 } 761 }
762 762
763 763
764 764
765 #define ALL_INIT_DATA_SECTIONS \ 765 #define ALL_INIT_DATA_SECTIONS \
766 ".init.setup$", ".init.rodata$", \ 766 ".init.setup$", ".init.rodata$", \
767 ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \ 767 ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \
768 ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$" 768 ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
769 #define ALL_EXIT_DATA_SECTIONS \ 769 #define ALL_EXIT_DATA_SECTIONS \
770 ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$" 770 ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
771 771
772 #define ALL_INIT_TEXT_SECTIONS \ 772 #define ALL_INIT_TEXT_SECTIONS \
773 ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$" 773 ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$"
774 #define ALL_EXIT_TEXT_SECTIONS \ 774 #define ALL_EXIT_TEXT_SECTIONS \
775 ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$" 775 ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"
776 776
777 #define ALL_INIT_SECTIONS INIT_SECTIONS, DEV_INIT_SECTIONS, \ 777 #define ALL_INIT_SECTIONS INIT_SECTIONS, DEV_INIT_SECTIONS, \
778 CPU_INIT_SECTIONS, MEM_INIT_SECTIONS 778 CPU_INIT_SECTIONS, MEM_INIT_SECTIONS
779 #define ALL_EXIT_SECTIONS EXIT_SECTIONS, DEV_EXIT_SECTIONS, \ 779 #define ALL_EXIT_SECTIONS EXIT_SECTIONS, DEV_EXIT_SECTIONS, \
780 CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS 780 CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS
781 781
782 #define DATA_SECTIONS ".data$", ".data.rel$" 782 #define DATA_SECTIONS ".data$", ".data.rel$"
783 #define TEXT_SECTIONS ".text$" 783 #define TEXT_SECTIONS ".text$"
784 784
785 #define INIT_SECTIONS ".init.*" 785 #define INIT_SECTIONS ".init.*"
786 #define DEV_INIT_SECTIONS ".devinit.*" 786 #define DEV_INIT_SECTIONS ".devinit.*"
787 #define CPU_INIT_SECTIONS ".cpuinit.*" 787 #define CPU_INIT_SECTIONS ".cpuinit.*"
788 #define MEM_INIT_SECTIONS ".meminit.*" 788 #define MEM_INIT_SECTIONS ".meminit.*"
789 789
790 #define EXIT_SECTIONS ".exit.*" 790 #define EXIT_SECTIONS ".exit.*"
791 #define DEV_EXIT_SECTIONS ".devexit.*" 791 #define DEV_EXIT_SECTIONS ".devexit.*"
792 #define CPU_EXIT_SECTIONS ".cpuexit.*" 792 #define CPU_EXIT_SECTIONS ".cpuexit.*"
793 #define MEM_EXIT_SECTIONS ".memexit.*" 793 #define MEM_EXIT_SECTIONS ".memexit.*"
794 794
795 /* init data sections */ 795 /* init data sections */
796 static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL }; 796 static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL };
797 797
798 /* all init sections */ 798 /* all init sections */
799 static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL }; 799 static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL };
800 800
801 /* All init and exit sections (code + data) */ 801 /* All init and exit sections (code + data) */
802 static const char *init_exit_sections[] = 802 static const char *init_exit_sections[] =
803 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; 803 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
804 804
805 /* data section */ 805 /* data section */
806 static const char *data_sections[] = { DATA_SECTIONS, NULL }; 806 static const char *data_sections[] = { DATA_SECTIONS, NULL };
807 807
808 808
809 /* symbols in .data that may refer to init/exit sections */ 809 /* symbols in .data that may refer to init/exit sections */
810 static const char *symbol_white_list[] = 810 static const char *symbol_white_list[] =
811 { 811 {
812 "*driver", 812 "*driver",
813 "*_template", /* scsi uses *_template a lot */ 813 "*_template", /* scsi uses *_template a lot */
814 "*_timer", /* arm uses ops structures named _timer a lot */ 814 "*_timer", /* arm uses ops structures named _timer a lot */
815 "*_sht", /* scsi also used *_sht to some extent */ 815 "*_sht", /* scsi also used *_sht to some extent */
816 "*_ops", 816 "*_ops",
817 "*_probe", 817 "*_probe",
818 "*_probe_one", 818 "*_probe_one",
819 "*_console", 819 "*_console",
820 NULL 820 NULL
821 }; 821 };
822 822
823 static const char *head_sections[] = { ".head.text*", NULL }; 823 static const char *head_sections[] = { ".head.text*", NULL };
824 static const char *linker_symbols[] = 824 static const char *linker_symbols[] =
825 { "__init_begin", "_sinittext", "_einittext", NULL }; 825 { "__init_begin", "_sinittext", "_einittext", NULL };
826 826
827 enum mismatch { 827 enum mismatch {
828 NO_MISMATCH, 828 NO_MISMATCH,
829 TEXT_TO_INIT, 829 TEXT_TO_INIT,
830 DATA_TO_INIT, 830 DATA_TO_INIT,
831 TEXT_TO_EXIT, 831 TEXT_TO_EXIT,
832 DATA_TO_EXIT, 832 DATA_TO_EXIT,
833 XXXINIT_TO_INIT, 833 XXXINIT_TO_INIT,
834 XXXEXIT_TO_EXIT, 834 XXXEXIT_TO_EXIT,
835 INIT_TO_EXIT, 835 INIT_TO_EXIT,
836 EXIT_TO_INIT, 836 EXIT_TO_INIT,
837 EXPORT_TO_INIT_EXIT, 837 EXPORT_TO_INIT_EXIT,
838 }; 838 };
839 839
840 struct sectioncheck { 840 struct sectioncheck {
841 const char *fromsec[20]; 841 const char *fromsec[20];
842 const char *tosec[20]; 842 const char *tosec[20];
843 enum mismatch mismatch; 843 enum mismatch mismatch;
844 }; 844 };
845 845
846 const struct sectioncheck sectioncheck[] = { 846 const struct sectioncheck sectioncheck[] = {
847 /* Do not reference init/exit code/data from 847 /* Do not reference init/exit code/data from
848 * normal code and data 848 * normal code and data
849 */ 849 */
850 { 850 {
851 .fromsec = { TEXT_SECTIONS, NULL }, 851 .fromsec = { TEXT_SECTIONS, NULL },
852 .tosec = { ALL_INIT_SECTIONS, NULL }, 852 .tosec = { ALL_INIT_SECTIONS, NULL },
853 .mismatch = TEXT_TO_INIT, 853 .mismatch = TEXT_TO_INIT,
854 }, 854 },
855 { 855 {
856 .fromsec = { DATA_SECTIONS, NULL }, 856 .fromsec = { DATA_SECTIONS, NULL },
857 .tosec = { ALL_INIT_SECTIONS, NULL }, 857 .tosec = { ALL_INIT_SECTIONS, NULL },
858 .mismatch = DATA_TO_INIT, 858 .mismatch = DATA_TO_INIT,
859 }, 859 },
860 { 860 {
861 .fromsec = { TEXT_SECTIONS, NULL }, 861 .fromsec = { TEXT_SECTIONS, NULL },
862 .tosec = { ALL_EXIT_SECTIONS, NULL }, 862 .tosec = { ALL_EXIT_SECTIONS, NULL },
863 .mismatch = TEXT_TO_EXIT, 863 .mismatch = TEXT_TO_EXIT,
864 }, 864 },
865 { 865 {
866 .fromsec = { DATA_SECTIONS, NULL }, 866 .fromsec = { DATA_SECTIONS, NULL },
867 .tosec = { ALL_EXIT_SECTIONS, NULL }, 867 .tosec = { ALL_EXIT_SECTIONS, NULL },
868 .mismatch = DATA_TO_EXIT, 868 .mismatch = DATA_TO_EXIT,
869 }, 869 },
870 /* Do not reference init code/data from devinit/cpuinit/meminit code/data */ 870 /* Do not reference init code/data from devinit/cpuinit/meminit code/data */
871 { 871 {
872 .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL }, 872 .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },
873 .tosec = { INIT_SECTIONS, NULL }, 873 .tosec = { INIT_SECTIONS, NULL },
874 .mismatch = XXXINIT_TO_INIT, 874 .mismatch = XXXINIT_TO_INIT,
875 }, 875 },
876 /* Do not reference cpuinit code/data from meminit code/data */ 876 /* Do not reference cpuinit code/data from meminit code/data */
877 { 877 {
878 .fromsec = { MEM_INIT_SECTIONS, NULL }, 878 .fromsec = { MEM_INIT_SECTIONS, NULL },
879 .tosec = { CPU_INIT_SECTIONS, NULL }, 879 .tosec = { CPU_INIT_SECTIONS, NULL },
880 .mismatch = XXXINIT_TO_INIT, 880 .mismatch = XXXINIT_TO_INIT,
881 }, 881 },
882 /* Do not reference meminit code/data from cpuinit code/data */ 882 /* Do not reference meminit code/data from cpuinit code/data */
883 { 883 {
884 .fromsec = { CPU_INIT_SECTIONS, NULL }, 884 .fromsec = { CPU_INIT_SECTIONS, NULL },
885 .tosec = { MEM_INIT_SECTIONS, NULL }, 885 .tosec = { MEM_INIT_SECTIONS, NULL },
886 .mismatch = XXXINIT_TO_INIT, 886 .mismatch = XXXINIT_TO_INIT,
887 }, 887 },
888 /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ 888 /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
889 { 889 {
890 .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL }, 890 .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },
891 .tosec = { EXIT_SECTIONS, NULL }, 891 .tosec = { EXIT_SECTIONS, NULL },
892 .mismatch = XXXEXIT_TO_EXIT, 892 .mismatch = XXXEXIT_TO_EXIT,
893 }, 893 },
894 /* Do not reference cpuexit code/data from memexit code/data */ 894 /* Do not reference cpuexit code/data from memexit code/data */
895 { 895 {
896 .fromsec = { MEM_EXIT_SECTIONS, NULL }, 896 .fromsec = { MEM_EXIT_SECTIONS, NULL },
897 .tosec = { CPU_EXIT_SECTIONS, NULL }, 897 .tosec = { CPU_EXIT_SECTIONS, NULL },
898 .mismatch = XXXEXIT_TO_EXIT, 898 .mismatch = XXXEXIT_TO_EXIT,
899 }, 899 },
900 /* Do not reference memexit code/data from cpuexit code/data */ 900 /* Do not reference memexit code/data from cpuexit code/data */
901 { 901 {
902 .fromsec = { CPU_EXIT_SECTIONS, NULL }, 902 .fromsec = { CPU_EXIT_SECTIONS, NULL },
903 .tosec = { MEM_EXIT_SECTIONS, NULL }, 903 .tosec = { MEM_EXIT_SECTIONS, NULL },
904 .mismatch = XXXEXIT_TO_EXIT, 904 .mismatch = XXXEXIT_TO_EXIT,
905 }, 905 },
906 /* Do not use exit code/data from init code */ 906 /* Do not use exit code/data from init code */
907 { 907 {
908 .fromsec = { ALL_INIT_SECTIONS, NULL }, 908 .fromsec = { ALL_INIT_SECTIONS, NULL },
909 .tosec = { ALL_EXIT_SECTIONS, NULL }, 909 .tosec = { ALL_EXIT_SECTIONS, NULL },
910 .mismatch = INIT_TO_EXIT, 910 .mismatch = INIT_TO_EXIT,
911 }, 911 },
912 /* Do not use init code/data from exit code */ 912 /* Do not use init code/data from exit code */
913 { 913 {
914 .fromsec = { ALL_EXIT_SECTIONS, NULL }, 914 .fromsec = { ALL_EXIT_SECTIONS, NULL },
915 .tosec = { ALL_INIT_SECTIONS, NULL }, 915 .tosec = { ALL_INIT_SECTIONS, NULL },
916 .mismatch = EXIT_TO_INIT, 916 .mismatch = EXIT_TO_INIT,
917 }, 917 },
918 /* Do not export init/exit functions or data */ 918 /* Do not export init/exit functions or data */
919 { 919 {
920 .fromsec = { "__ksymtab*", NULL }, 920 .fromsec = { "__ksymtab*", NULL },
921 .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, 921 .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
922 .mismatch = EXPORT_TO_INIT_EXIT 922 .mismatch = EXPORT_TO_INIT_EXIT
923 } 923 }
924 }; 924 };
925 925
926 static int section_mismatch(const char *fromsec, const char *tosec) 926 static int section_mismatch(const char *fromsec, const char *tosec)
927 { 927 {
928 int i; 928 int i;
929 int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); 929 int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
930 const struct sectioncheck *check = &sectioncheck[0]; 930 const struct sectioncheck *check = &sectioncheck[0];
931 931
932 for (i = 0; i < elems; i++) { 932 for (i = 0; i < elems; i++) {
933 if (match(fromsec, check->fromsec) && 933 if (match(fromsec, check->fromsec) &&
934 match(tosec, check->tosec)) 934 match(tosec, check->tosec))
935 return check->mismatch; 935 return check->mismatch;
936 check++; 936 check++;
937 } 937 }
938 return NO_MISMATCH; 938 return NO_MISMATCH;
939 } 939 }
940 940
941 /** 941 /**
942 * Whitelist to allow certain references to pass with no warning. 942 * Whitelist to allow certain references to pass with no warning.
943 * 943 *
944 * Pattern 1: 944 * Pattern 1:
945 * If a module parameter is declared __initdata and permissions=0 945 * If a module parameter is declared __initdata and permissions=0
946 * then this is legal despite the warning generated. 946 * then this is legal despite the warning generated.
947 * We cannot see value of permissions here, so just ignore 947 * We cannot see value of permissions here, so just ignore
948 * this pattern. 948 * this pattern.
949 * The pattern is identified by: 949 * The pattern is identified by:
950 * tosec = .init.data 950 * tosec = .init.data
951 * fromsec = .data* 951 * fromsec = .data*
952 * atsym =__param* 952 * atsym =__param*
953 * 953 *
954 * Pattern 2: 954 * Pattern 2:
955 * Many drivers utilise a *driver container with references to 955 * Many drivers utilise a *driver container with references to
956 * add, remove, probe functions etc. 956 * add, remove, probe functions etc.
957 * These functions may often be marked __init and we do not want to 957 * These functions may often be marked __init and we do not want to
958 * warn here. 958 * warn here.
959 * the pattern is identified by: 959 * the pattern is identified by:
960 * tosec = init or exit section 960 * tosec = init or exit section
961 * fromsec = data section 961 * fromsec = data section
962 * atsym = *driver, *_template, *_sht, *_ops, *_probe, 962 * atsym = *driver, *_template, *_sht, *_ops, *_probe,
963 * *probe_one, *_console, *_timer 963 * *probe_one, *_console, *_timer
964 * 964 *
965 * Pattern 3: 965 * Pattern 3:
966 * Whitelist all references from .head.text to any init section 966 * Whitelist all references from .head.text to any init section
967 * 967 *
968 * Pattern 4: 968 * Pattern 4:
969 * Some symbols belong to init section but still it is ok to reference 969 * Some symbols belong to init section but still it is ok to reference
970 * these from non-init sections as these symbols don't have any memory 970 * these from non-init sections as these symbols don't have any memory
971 * allocated for them and symbol address and value are same. So even 971 * allocated for them and symbol address and value are same. So even
972 * if init section is freed, its ok to reference those symbols. 972 * if init section is freed, its ok to reference those symbols.
973 * For ex. symbols marking the init section boundaries. 973 * For ex. symbols marking the init section boundaries.
974 * This pattern is identified by 974 * This pattern is identified by
975 * refsymname = __init_begin, _sinittext, _einittext 975 * refsymname = __init_begin, _sinittext, _einittext
976 * 976 *
977 **/ 977 **/
978 static int secref_whitelist(const char *fromsec, const char *fromsym, 978 static int secref_whitelist(const char *fromsec, const char *fromsym,
979 const char *tosec, const char *tosym) 979 const char *tosec, const char *tosym)
980 { 980 {
981 /* Check for pattern 1 */ 981 /* Check for pattern 1 */
982 if (match(tosec, init_data_sections) && 982 if (match(tosec, init_data_sections) &&
983 match(fromsec, data_sections) && 983 match(fromsec, data_sections) &&
984 (strncmp(fromsym, "__param", strlen("__param")) == 0)) 984 (strncmp(fromsym, "__param", strlen("__param")) == 0))
985 return 0; 985 return 0;
986 986
987 /* Check for pattern 2 */ 987 /* Check for pattern 2 */
988 if (match(tosec, init_exit_sections) && 988 if (match(tosec, init_exit_sections) &&
989 match(fromsec, data_sections) && 989 match(fromsec, data_sections) &&
990 match(fromsym, symbol_white_list)) 990 match(fromsym, symbol_white_list))
991 return 0; 991 return 0;
992 992
993 /* Check for pattern 3 */ 993 /* Check for pattern 3 */
994 if (match(fromsec, head_sections) && 994 if (match(fromsec, head_sections) &&
995 match(tosec, init_sections)) 995 match(tosec, init_sections))
996 return 0; 996 return 0;
997 997
998 /* Check for pattern 4 */ 998 /* Check for pattern 4 */
999 if (match(tosym, linker_symbols)) 999 if (match(tosym, linker_symbols))
1000 return 0; 1000 return 0;
1001 1001
1002 return 1; 1002 return 1;
1003 } 1003 }
1004 1004
1005 /** 1005 /**
1006 * Find symbol based on relocation record info. 1006 * Find symbol based on relocation record info.
1007 * In some cases the symbol supplied is a valid symbol so 1007 * In some cases the symbol supplied is a valid symbol so
1008 * return refsym. If st_name != 0 we assume this is a valid symbol. 1008 * return refsym. If st_name != 0 we assume this is a valid symbol.
1009 * In other cases the symbol needs to be looked up in the symbol table 1009 * In other cases the symbol needs to be looked up in the symbol table
1010 * based on section and address. 1010 * based on section and address.
1011 * **/ 1011 * **/
1012 static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, 1012 static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
1013 Elf_Sym *relsym) 1013 Elf_Sym *relsym)
1014 { 1014 {
1015 Elf_Sym *sym; 1015 Elf_Sym *sym;
1016 Elf_Sym *near = NULL; 1016 Elf_Sym *near = NULL;
1017 Elf64_Sword distance = 20; 1017 Elf64_Sword distance = 20;
1018 Elf64_Sword d; 1018 Elf64_Sword d;
1019 1019
1020 if (relsym->st_name != 0) 1020 if (relsym->st_name != 0)
1021 return relsym; 1021 return relsym;
1022 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 1022 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1023 if (sym->st_shndx != relsym->st_shndx) 1023 if (sym->st_shndx != relsym->st_shndx)
1024 continue; 1024 continue;
1025 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 1025 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
1026 continue; 1026 continue;
1027 if (sym->st_value == addr) 1027 if (sym->st_value == addr)
1028 return sym; 1028 return sym;
1029 /* Find a symbol nearby - addr are maybe negative */ 1029 /* Find a symbol nearby - addr are maybe negative */
1030 d = sym->st_value - addr; 1030 d = sym->st_value - addr;
1031 if (d < 0) 1031 if (d < 0)
1032 d = addr - sym->st_value; 1032 d = addr - sym->st_value;
1033 if (d < distance) { 1033 if (d < distance) {
1034 distance = d; 1034 distance = d;
1035 near = sym; 1035 near = sym;
1036 } 1036 }
1037 } 1037 }
1038 /* We need a close match */ 1038 /* We need a close match */
1039 if (distance < 20) 1039 if (distance < 20)
1040 return near; 1040 return near;
1041 else 1041 else
1042 return NULL; 1042 return NULL;
1043 } 1043 }
1044 1044
1045 static inline int is_arm_mapping_symbol(const char *str) 1045 static inline int is_arm_mapping_symbol(const char *str)
1046 { 1046 {
1047 return str[0] == '$' && strchr("atd", str[1]) 1047 return str[0] == '$' && strchr("atd", str[1])
1048 && (str[2] == '\0' || str[2] == '.'); 1048 && (str[2] == '\0' || str[2] == '.');
1049 } 1049 }
1050 1050
1051 /* 1051 /*
1052 * If there's no name there, ignore it; likewise, ignore it if it's 1052 * If there's no name there, ignore it; likewise, ignore it if it's
1053 * one of the magic symbols emitted used by current ARM tools. 1053 * one of the magic symbols emitted used by current ARM tools.
1054 * 1054 *
1055 * Otherwise if find_symbols_between() returns those symbols, they'll 1055 * Otherwise if find_symbols_between() returns those symbols, they'll
1056 * fail the whitelist tests and cause lots of false alarms ... fixable 1056 * fail the whitelist tests and cause lots of false alarms ... fixable
1057 * only by merging __exit and __init sections into __text, bloating 1057 * only by merging __exit and __init sections into __text, bloating
1058 * the kernel (which is especially evil on embedded platforms). 1058 * the kernel (which is especially evil on embedded platforms).
1059 */ 1059 */
1060 static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) 1060 static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
1061 { 1061 {
1062 const char *name = elf->strtab + sym->st_name; 1062 const char *name = elf->strtab + sym->st_name;
1063 1063
1064 if (!name || !strlen(name)) 1064 if (!name || !strlen(name))
1065 return 0; 1065 return 0;
1066 return !is_arm_mapping_symbol(name); 1066 return !is_arm_mapping_symbol(name);
1067 } 1067 }
1068 1068
1069 /* 1069 /*
1070 * Find symbols before or equal addr and after addr - in the section sec. 1070 * Find symbols before or equal addr and after addr - in the section sec.
1071 * If we find two symbols with equal offset prefer one with a valid name. 1071 * If we find two symbols with equal offset prefer one with a valid name.
1072 * The ELF format may have a better way to detect what type of symbol 1072 * The ELF format may have a better way to detect what type of symbol
1073 * it is, but this works for now. 1073 * it is, but this works for now.
1074 **/ 1074 **/
1075 static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, 1075 static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
1076 const char *sec) 1076 const char *sec)
1077 { 1077 {
1078 Elf_Sym *sym; 1078 Elf_Sym *sym;
1079 Elf_Sym *near = NULL; 1079 Elf_Sym *near = NULL;
1080 Elf_Addr distance = ~0; 1080 Elf_Addr distance = ~0;
1081 1081
1082 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 1082 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1083 const char *symsec; 1083 const char *symsec;
1084 1084
1085 if (sym->st_shndx >= SHN_LORESERVE) 1085 if (sym->st_shndx >= SHN_LORESERVE)
1086 continue; 1086 continue;
1087 symsec = sec_name(elf, sym->st_shndx); 1087 symsec = sec_name(elf, sym->st_shndx);
1088 if (strcmp(symsec, sec) != 0) 1088 if (strcmp(symsec, sec) != 0)
1089 continue; 1089 continue;
1090 if (!is_valid_name(elf, sym)) 1090 if (!is_valid_name(elf, sym))
1091 continue; 1091 continue;
1092 if (sym->st_value <= addr) { 1092 if (sym->st_value <= addr) {
1093 if ((addr - sym->st_value) < distance) { 1093 if ((addr - sym->st_value) < distance) {
1094 distance = addr - sym->st_value; 1094 distance = addr - sym->st_value;
1095 near = sym; 1095 near = sym;
1096 } else if ((addr - sym->st_value) == distance) { 1096 } else if ((addr - sym->st_value) == distance) {
1097 near = sym; 1097 near = sym;
1098 } 1098 }
1099 } 1099 }
1100 } 1100 }
1101 return near; 1101 return near;
1102 } 1102 }
1103 1103
1104 /* 1104 /*
1105 * Convert a section name to the function/data attribute 1105 * Convert a section name to the function/data attribute
1106 * .init.text => __init 1106 * .init.text => __init
1107 * .cpuinit.data => __cpudata 1107 * .cpuinit.data => __cpudata
1108 * .memexitconst => __memconst 1108 * .memexitconst => __memconst
1109 * etc. 1109 * etc.
1110 */ 1110 */
1111 static char *sec2annotation(const char *s) 1111 static char *sec2annotation(const char *s)
1112 { 1112 {
1113 if (match(s, init_exit_sections)) { 1113 if (match(s, init_exit_sections)) {
1114 char *p = malloc(20); 1114 char *p = malloc(20);
1115 char *r = p; 1115 char *r = p;
1116 1116
1117 *p++ = '_'; 1117 *p++ = '_';
1118 *p++ = '_'; 1118 *p++ = '_';
1119 if (*s == '.') 1119 if (*s == '.')
1120 s++; 1120 s++;
1121 while (*s && *s != '.') 1121 while (*s && *s != '.')
1122 *p++ = *s++; 1122 *p++ = *s++;
1123 *p = '\0'; 1123 *p = '\0';
1124 if (*s == '.') 1124 if (*s == '.')
1125 s++; 1125 s++;
1126 if (strstr(s, "rodata") != NULL) 1126 if (strstr(s, "rodata") != NULL)
1127 strcat(p, "const "); 1127 strcat(p, "const ");
1128 else if (strstr(s, "data") != NULL) 1128 else if (strstr(s, "data") != NULL)
1129 strcat(p, "data "); 1129 strcat(p, "data ");
1130 else 1130 else
1131 strcat(p, " "); 1131 strcat(p, " ");
1132 return r; /* we leak her but we do not care */ 1132 return r; /* we leak her but we do not care */
1133 } else { 1133 } else {
1134 return ""; 1134 return "";
1135 } 1135 }
1136 } 1136 }
1137 1137
1138 static int is_function(Elf_Sym *sym) 1138 static int is_function(Elf_Sym *sym)
1139 { 1139 {
1140 if (sym) 1140 if (sym)
1141 return ELF_ST_TYPE(sym->st_info) == STT_FUNC; 1141 return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
1142 else 1142 else
1143 return -1; 1143 return -1;
1144 } 1144 }
1145 1145
1146 /* 1146 /*
1147 * Print a warning about a section mismatch. 1147 * Print a warning about a section mismatch.
1148 * Try to find symbols near it so user can find it. 1148 * Try to find symbols near it so user can find it.
1149 * Check whitelist before warning - it may be a false positive. 1149 * Check whitelist before warning - it may be a false positive.
1150 */ 1150 */
1151 static void report_sec_mismatch(const char *modname, enum mismatch mismatch, 1151 static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
1152 const char *fromsec, 1152 const char *fromsec,
1153 unsigned long long fromaddr, 1153 unsigned long long fromaddr,
1154 const char *fromsym, 1154 const char *fromsym,
1155 int from_is_func, 1155 int from_is_func,
1156 const char *tosec, const char *tosym, 1156 const char *tosec, const char *tosym,
1157 int to_is_func) 1157 int to_is_func)
1158 { 1158 {
1159 const char *from, *from_p; 1159 const char *from, *from_p;
1160 const char *to, *to_p; 1160 const char *to, *to_p;
1161 1161
1162 switch (from_is_func) { 1162 switch (from_is_func) {
1163 case 0: from = "variable"; from_p = ""; break; 1163 case 0: from = "variable"; from_p = ""; break;
1164 case 1: from = "function"; from_p = "()"; break; 1164 case 1: from = "function"; from_p = "()"; break;
1165 default: from = "(unknown reference)"; from_p = ""; break; 1165 default: from = "(unknown reference)"; from_p = ""; break;
1166 } 1166 }
1167 switch (to_is_func) { 1167 switch (to_is_func) {
1168 case 0: to = "variable"; to_p = ""; break; 1168 case 0: to = "variable"; to_p = ""; break;
1169 case 1: to = "function"; to_p = "()"; break; 1169 case 1: to = "function"; to_p = "()"; break;
1170 default: to = "(unknown reference)"; to_p = ""; break; 1170 default: to = "(unknown reference)"; to_p = ""; break;
1171 } 1171 }
1172 1172
1173 sec_mismatch_count++; 1173 sec_mismatch_count++;
1174 if (!sec_mismatch_verbose) 1174 if (!sec_mismatch_verbose)
1175 return; 1175 return;
1176 1176
1177 warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " 1177 warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
1178 "to the %s %s:%s%s\n", 1178 "to the %s %s:%s%s\n",
1179 modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, 1179 modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
1180 tosym, to_p); 1180 tosym, to_p);
1181 1181
1182 switch (mismatch) { 1182 switch (mismatch) {
1183 case TEXT_TO_INIT: 1183 case TEXT_TO_INIT:
1184 fprintf(stderr, 1184 fprintf(stderr,
1185 "The function %s%s() references\n" 1185 "The function %s%s() references\n"
1186 "the %s %s%s%s.\n" 1186 "the %s %s%s%s.\n"
1187 "This is often because %s lacks a %s\n" 1187 "This is often because %s lacks a %s\n"
1188 "annotation or the annotation of %s is wrong.\n", 1188 "annotation or the annotation of %s is wrong.\n",
1189 sec2annotation(fromsec), fromsym, 1189 sec2annotation(fromsec), fromsym,
1190 to, sec2annotation(tosec), tosym, to_p, 1190 to, sec2annotation(tosec), tosym, to_p,
1191 fromsym, sec2annotation(tosec), tosym); 1191 fromsym, sec2annotation(tosec), tosym);
1192 break; 1192 break;
1193 case DATA_TO_INIT: { 1193 case DATA_TO_INIT: {
1194 const char **s = symbol_white_list; 1194 const char **s = symbol_white_list;
1195 fprintf(stderr, 1195 fprintf(stderr,
1196 "The variable %s references\n" 1196 "The variable %s references\n"
1197 "the %s %s%s%s\n" 1197 "the %s %s%s%s\n"
1198 "If the reference is valid then annotate the\n" 1198 "If the reference is valid then annotate the\n"
1199 "variable with __init* or __refdata (see linux/init.h) " 1199 "variable with __init* or __refdata (see linux/init.h) "
1200 "or name the variable:\n", 1200 "or name the variable:\n",
1201 fromsym, to, sec2annotation(tosec), tosym, to_p); 1201 fromsym, to, sec2annotation(tosec), tosym, to_p);
1202 while (*s) 1202 while (*s)
1203 fprintf(stderr, "%s, ", *s++); 1203 fprintf(stderr, "%s, ", *s++);
1204 fprintf(stderr, "\n"); 1204 fprintf(stderr, "\n");
1205 break; 1205 break;
1206 } 1206 }
1207 case TEXT_TO_EXIT: 1207 case TEXT_TO_EXIT:
1208 fprintf(stderr, 1208 fprintf(stderr,
1209 "The function %s() references a %s in an exit section.\n" 1209 "The function %s() references a %s in an exit section.\n"
1210 "Often the %s %s%s has valid usage outside the exit section\n" 1210 "Often the %s %s%s has valid usage outside the exit section\n"
1211 "and the fix is to remove the %sannotation of %s.\n", 1211 "and the fix is to remove the %sannotation of %s.\n",
1212 fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym); 1212 fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
1213 break; 1213 break;
1214 case DATA_TO_EXIT: { 1214 case DATA_TO_EXIT: {
1215 const char **s = symbol_white_list; 1215 const char **s = symbol_white_list;
1216 fprintf(stderr, 1216 fprintf(stderr,
1217 "The variable %s references\n" 1217 "The variable %s references\n"
1218 "the %s %s%s%s\n" 1218 "the %s %s%s%s\n"
1219 "If the reference is valid then annotate the\n" 1219 "If the reference is valid then annotate the\n"
1220 "variable with __exit* (see linux/init.h) or " 1220 "variable with __exit* (see linux/init.h) or "
1221 "name the variable:\n", 1221 "name the variable:\n",
1222 fromsym, to, sec2annotation(tosec), tosym, to_p); 1222 fromsym, to, sec2annotation(tosec), tosym, to_p);
1223 while (*s) 1223 while (*s)
1224 fprintf(stderr, "%s, ", *s++); 1224 fprintf(stderr, "%s, ", *s++);
1225 fprintf(stderr, "\n"); 1225 fprintf(stderr, "\n");
1226 break; 1226 break;
1227 } 1227 }
1228 case XXXINIT_TO_INIT: 1228 case XXXINIT_TO_INIT:
1229 case XXXEXIT_TO_EXIT: 1229 case XXXEXIT_TO_EXIT:
1230 fprintf(stderr, 1230 fprintf(stderr,
1231 "The %s %s%s%s references\n" 1231 "The %s %s%s%s references\n"
1232 "a %s %s%s%s.\n" 1232 "a %s %s%s%s.\n"
1233 "If %s is only used by %s then\n" 1233 "If %s is only used by %s then\n"
1234 "annotate %s with a matching annotation.\n", 1234 "annotate %s with a matching annotation.\n",
1235 from, sec2annotation(fromsec), fromsym, from_p, 1235 from, sec2annotation(fromsec), fromsym, from_p,
1236 to, sec2annotation(tosec), tosym, to_p, 1236 to, sec2annotation(tosec), tosym, to_p,
1237 tosym, fromsym, tosym); 1237 tosym, fromsym, tosym);
1238 break; 1238 break;
1239 case INIT_TO_EXIT: 1239 case INIT_TO_EXIT:
1240 fprintf(stderr, 1240 fprintf(stderr,
1241 "The %s %s%s%s references\n" 1241 "The %s %s%s%s references\n"
1242 "a %s %s%s%s.\n" 1242 "a %s %s%s%s.\n"
1243 "This is often seen when error handling " 1243 "This is often seen when error handling "
1244 "in the init function\n" 1244 "in the init function\n"
1245 "uses functionality in the exit path.\n" 1245 "uses functionality in the exit path.\n"
1246 "The fix is often to remove the %sannotation of\n" 1246 "The fix is often to remove the %sannotation of\n"
1247 "%s%s so it may be used outside an exit section.\n", 1247 "%s%s so it may be used outside an exit section.\n",
1248 from, sec2annotation(fromsec), fromsym, from_p, 1248 from, sec2annotation(fromsec), fromsym, from_p,
1249 to, sec2annotation(tosec), tosym, to_p, 1249 to, sec2annotation(tosec), tosym, to_p,
1250 sec2annotation(tosec), tosym, to_p); 1250 sec2annotation(tosec), tosym, to_p);
1251 break; 1251 break;
1252 case EXIT_TO_INIT: 1252 case EXIT_TO_INIT:
1253 fprintf(stderr, 1253 fprintf(stderr,
1254 "The %s %s%s%s references\n" 1254 "The %s %s%s%s references\n"
1255 "a %s %s%s%s.\n" 1255 "a %s %s%s%s.\n"
1256 "This is often seen when error handling " 1256 "This is often seen when error handling "
1257 "in the exit function\n" 1257 "in the exit function\n"
1258 "uses functionality in the init path.\n" 1258 "uses functionality in the init path.\n"
1259 "The fix is often to remove the %sannotation of\n" 1259 "The fix is often to remove the %sannotation of\n"
1260 "%s%s so it may be used outside an init section.\n", 1260 "%s%s so it may be used outside an init section.\n",
1261 from, sec2annotation(fromsec), fromsym, from_p, 1261 from, sec2annotation(fromsec), fromsym, from_p,
1262 to, sec2annotation(tosec), tosym, to_p, 1262 to, sec2annotation(tosec), tosym, to_p,
1263 sec2annotation(tosec), tosym, to_p); 1263 sec2annotation(tosec), tosym, to_p);
1264 break; 1264 break;
1265 case EXPORT_TO_INIT_EXIT: 1265 case EXPORT_TO_INIT_EXIT:
1266 fprintf(stderr, 1266 fprintf(stderr,
1267 "The symbol %s is exported and annotated %s\n" 1267 "The symbol %s is exported and annotated %s\n"
1268 "Fix this by removing the %sannotation of %s " 1268 "Fix this by removing the %sannotation of %s "
1269 "or drop the export.\n", 1269 "or drop the export.\n",
1270 tosym, sec2annotation(tosec), sec2annotation(tosec), tosym); 1270 tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
1271 case NO_MISMATCH: 1271 case NO_MISMATCH:
1272 /* To get warnings on missing members */ 1272 /* To get warnings on missing members */
1273 break; 1273 break;
1274 } 1274 }
1275 fprintf(stderr, "\n"); 1275 fprintf(stderr, "\n");
1276 } 1276 }
1277 1277
1278 static void check_section_mismatch(const char *modname, struct elf_info *elf, 1278 static void check_section_mismatch(const char *modname, struct elf_info *elf,
1279 Elf_Rela *r, Elf_Sym *sym, const char *fromsec) 1279 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
1280 { 1280 {
1281 const char *tosec; 1281 const char *tosec;
1282 enum mismatch mismatch; 1282 enum mismatch mismatch;
1283 1283
1284 tosec = sec_name(elf, sym->st_shndx); 1284 tosec = sec_name(elf, sym->st_shndx);
1285 mismatch = section_mismatch(fromsec, tosec); 1285 mismatch = section_mismatch(fromsec, tosec);
1286 if (mismatch != NO_MISMATCH) { 1286 if (mismatch != NO_MISMATCH) {
1287 Elf_Sym *to; 1287 Elf_Sym *to;
1288 Elf_Sym *from; 1288 Elf_Sym *from;
1289 const char *tosym; 1289 const char *tosym;
1290 const char *fromsym; 1290 const char *fromsym;
1291 1291
1292 from = find_elf_symbol2(elf, r->r_offset, fromsec); 1292 from = find_elf_symbol2(elf, r->r_offset, fromsec);
1293 fromsym = sym_name(elf, from); 1293 fromsym = sym_name(elf, from);
1294 to = find_elf_symbol(elf, r->r_addend, sym); 1294 to = find_elf_symbol(elf, r->r_addend, sym);
1295 tosym = sym_name(elf, to); 1295 tosym = sym_name(elf, to);
1296 1296
1297 /* check whitelist - we may ignore it */ 1297 /* check whitelist - we may ignore it */
1298 if (secref_whitelist(fromsec, fromsym, tosec, tosym)) { 1298 if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
1299 report_sec_mismatch(modname, mismatch, 1299 report_sec_mismatch(modname, mismatch,
1300 fromsec, r->r_offset, fromsym, 1300 fromsec, r->r_offset, fromsym,
1301 is_function(from), tosec, tosym, 1301 is_function(from), tosec, tosym,
1302 is_function(to)); 1302 is_function(to));
1303 } 1303 }
1304 } 1304 }
1305 } 1305 }
1306 1306
1307 static unsigned int *reloc_location(struct elf_info *elf, 1307 static unsigned int *reloc_location(struct elf_info *elf,
1308 Elf_Shdr *sechdr, Elf_Rela *r) 1308 Elf_Shdr *sechdr, Elf_Rela *r)
1309 { 1309 {
1310 Elf_Shdr *sechdrs = elf->sechdrs; 1310 Elf_Shdr *sechdrs = elf->sechdrs;
1311 int section = sechdr->sh_info; 1311 int section = sechdr->sh_info;
1312 1312
1313 return (void *)elf->hdr + sechdrs[section].sh_offset + 1313 return (void *)elf->hdr + sechdrs[section].sh_offset +
1314 (r->r_offset - sechdrs[section].sh_addr); 1314 (r->r_offset - sechdrs[section].sh_addr);
1315 } 1315 }
1316 1316
1317 static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1317 static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1318 { 1318 {
1319 unsigned int r_typ = ELF_R_TYPE(r->r_info); 1319 unsigned int r_typ = ELF_R_TYPE(r->r_info);
1320 unsigned int *location = reloc_location(elf, sechdr, r); 1320 unsigned int *location = reloc_location(elf, sechdr, r);
1321 1321
1322 switch (r_typ) { 1322 switch (r_typ) {
1323 case R_386_32: 1323 case R_386_32:
1324 r->r_addend = TO_NATIVE(*location); 1324 r->r_addend = TO_NATIVE(*location);
1325 break; 1325 break;
1326 case R_386_PC32: 1326 case R_386_PC32:
1327 r->r_addend = TO_NATIVE(*location) + 4; 1327 r->r_addend = TO_NATIVE(*location) + 4;
1328 /* For CONFIG_RELOCATABLE=y */ 1328 /* For CONFIG_RELOCATABLE=y */
1329 if (elf->hdr->e_type == ET_EXEC) 1329 if (elf->hdr->e_type == ET_EXEC)
1330 r->r_addend += r->r_offset; 1330 r->r_addend += r->r_offset;
1331 break; 1331 break;
1332 } 1332 }
1333 return 0; 1333 return 0;
1334 } 1334 }
1335 1335
1336 static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1336 static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1337 { 1337 {
1338 unsigned int r_typ = ELF_R_TYPE(r->r_info); 1338 unsigned int r_typ = ELF_R_TYPE(r->r_info);
1339 1339
1340 switch (r_typ) { 1340 switch (r_typ) {
1341 case R_ARM_ABS32: 1341 case R_ARM_ABS32:
1342 /* From ARM ABI: (S + A) | T */ 1342 /* From ARM ABI: (S + A) | T */
1343 r->r_addend = (int)(long) 1343 r->r_addend = (int)(long)
1344 (elf->symtab_start + ELF_R_SYM(r->r_info)); 1344 (elf->symtab_start + ELF_R_SYM(r->r_info));
1345 break; 1345 break;
1346 case R_ARM_PC24: 1346 case R_ARM_PC24:
1347 /* From ARM ABI: ((S + A) | T) - P */ 1347 /* From ARM ABI: ((S + A) | T) - P */
1348 r->r_addend = (int)(long)(elf->hdr + 1348 r->r_addend = (int)(long)(elf->hdr +
1349 sechdr->sh_offset + 1349 sechdr->sh_offset +
1350 (r->r_offset - sechdr->sh_addr)); 1350 (r->r_offset - sechdr->sh_addr));
1351 break; 1351 break;
1352 default: 1352 default:
1353 return 1; 1353 return 1;
1354 } 1354 }
1355 return 0; 1355 return 0;
1356 } 1356 }
1357 1357
1358 static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1358 static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
1359 { 1359 {
1360 unsigned int r_typ = ELF_R_TYPE(r->r_info); 1360 unsigned int r_typ = ELF_R_TYPE(r->r_info);
1361 unsigned int *location = reloc_location(elf, sechdr, r); 1361 unsigned int *location = reloc_location(elf, sechdr, r);
1362 unsigned int inst; 1362 unsigned int inst;
1363 1363
1364 if (r_typ == R_MIPS_HI16) 1364 if (r_typ == R_MIPS_HI16)
1365 return 1; /* skip this */ 1365 return 1; /* skip this */
1366 inst = TO_NATIVE(*location); 1366 inst = TO_NATIVE(*location);
1367 switch (r_typ) { 1367 switch (r_typ) {
1368 case R_MIPS_LO16: 1368 case R_MIPS_LO16:
1369 r->r_addend = inst & 0xffff; 1369 r->r_addend = inst & 0xffff;
1370 break; 1370 break;
1371 case R_MIPS_26: 1371 case R_MIPS_26:
1372 r->r_addend = (inst & 0x03ffffff) << 2; 1372 r->r_addend = (inst & 0x03ffffff) << 2;
1373 break; 1373 break;
1374 case R_MIPS_32: 1374 case R_MIPS_32:
1375 r->r_addend = inst; 1375 r->r_addend = inst;
1376 break; 1376 break;
1377 } 1377 }
1378 return 0; 1378 return 0;
1379 } 1379 }
1380 1380
1381 static void section_rela(const char *modname, struct elf_info *elf, 1381 static void section_rela(const char *modname, struct elf_info *elf,
1382 Elf_Shdr *sechdr) 1382 Elf_Shdr *sechdr)
1383 { 1383 {
1384 Elf_Sym *sym; 1384 Elf_Sym *sym;
1385 Elf_Rela *rela; 1385 Elf_Rela *rela;
1386 Elf_Rela r; 1386 Elf_Rela r;
1387 unsigned int r_sym; 1387 unsigned int r_sym;
1388 const char *fromsec; 1388 const char *fromsec;
1389 1389
1390 Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; 1390 Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
1391 Elf_Rela *stop = (void *)start + sechdr->sh_size; 1391 Elf_Rela *stop = (void *)start + sechdr->sh_size;
1392 1392
1393 fromsec = sech_name(elf, sechdr); 1393 fromsec = sech_name(elf, sechdr);
1394 fromsec += strlen(".rela"); 1394 fromsec += strlen(".rela");
1395 /* if from section (name) is know good then skip it */ 1395 /* if from section (name) is know good then skip it */
1396 if (match(fromsec, section_white_list)) 1396 if (match(fromsec, section_white_list))
1397 return; 1397 return;
1398 1398
1399 for (rela = start; rela < stop; rela++) { 1399 for (rela = start; rela < stop; rela++) {
1400 r.r_offset = TO_NATIVE(rela->r_offset); 1400 r.r_offset = TO_NATIVE(rela->r_offset);
1401 #if KERNEL_ELFCLASS == ELFCLASS64 1401 #if KERNEL_ELFCLASS == ELFCLASS64
1402 if (elf->hdr->e_machine == EM_MIPS) { 1402 if (elf->hdr->e_machine == EM_MIPS) {
1403 unsigned int r_typ; 1403 unsigned int r_typ;
1404 r_sym = ELF64_MIPS_R_SYM(rela->r_info); 1404 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
1405 r_sym = TO_NATIVE(r_sym); 1405 r_sym = TO_NATIVE(r_sym);
1406 r_typ = ELF64_MIPS_R_TYPE(rela->r_info); 1406 r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
1407 r.r_info = ELF64_R_INFO(r_sym, r_typ); 1407 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1408 } else { 1408 } else {
1409 r.r_info = TO_NATIVE(rela->r_info); 1409 r.r_info = TO_NATIVE(rela->r_info);
1410 r_sym = ELF_R_SYM(r.r_info); 1410 r_sym = ELF_R_SYM(r.r_info);
1411 } 1411 }
1412 #else 1412 #else
1413 r.r_info = TO_NATIVE(rela->r_info); 1413 r.r_info = TO_NATIVE(rela->r_info);
1414 r_sym = ELF_R_SYM(r.r_info); 1414 r_sym = ELF_R_SYM(r.r_info);
1415 #endif 1415 #endif
1416 r.r_addend = TO_NATIVE(rela->r_addend); 1416 r.r_addend = TO_NATIVE(rela->r_addend);
1417 sym = elf->symtab_start + r_sym; 1417 sym = elf->symtab_start + r_sym;
1418 /* Skip special sections */ 1418 /* Skip special sections */
1419 if (sym->st_shndx >= SHN_LORESERVE) 1419 if (sym->st_shndx >= SHN_LORESERVE)
1420 continue; 1420 continue;
1421 check_section_mismatch(modname, elf, &r, sym, fromsec); 1421 check_section_mismatch(modname, elf, &r, sym, fromsec);
1422 } 1422 }
1423 } 1423 }
1424 1424
1425 static void section_rel(const char *modname, struct elf_info *elf, 1425 static void section_rel(const char *modname, struct elf_info *elf,
1426 Elf_Shdr *sechdr) 1426 Elf_Shdr *sechdr)
1427 { 1427 {
1428 Elf_Sym *sym; 1428 Elf_Sym *sym;
1429 Elf_Rel *rel; 1429 Elf_Rel *rel;
1430 Elf_Rela r; 1430 Elf_Rela r;
1431 unsigned int r_sym; 1431 unsigned int r_sym;
1432 const char *fromsec; 1432 const char *fromsec;
1433 1433
1434 Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; 1434 Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
1435 Elf_Rel *stop = (void *)start + sechdr->sh_size; 1435 Elf_Rel *stop = (void *)start + sechdr->sh_size;
1436 1436
1437 fromsec = sech_name(elf, sechdr); 1437 fromsec = sech_name(elf, sechdr);
1438 fromsec += strlen(".rel"); 1438 fromsec += strlen(".rel");
1439 /* if from section (name) is know good then skip it */ 1439 /* if from section (name) is know good then skip it */
1440 if (match(fromsec, section_white_list)) 1440 if (match(fromsec, section_white_list))
1441 return; 1441 return;
1442 1442
1443 for (rel = start; rel < stop; rel++) { 1443 for (rel = start; rel < stop; rel++) {
1444 r.r_offset = TO_NATIVE(rel->r_offset); 1444 r.r_offset = TO_NATIVE(rel->r_offset);
1445 #if KERNEL_ELFCLASS == ELFCLASS64 1445 #if KERNEL_ELFCLASS == ELFCLASS64
1446 if (elf->hdr->e_machine == EM_MIPS) { 1446 if (elf->hdr->e_machine == EM_MIPS) {
1447 unsigned int r_typ; 1447 unsigned int r_typ;
1448 r_sym = ELF64_MIPS_R_SYM(rel->r_info); 1448 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
1449 r_sym = TO_NATIVE(r_sym); 1449 r_sym = TO_NATIVE(r_sym);
1450 r_typ = ELF64_MIPS_R_TYPE(rel->r_info); 1450 r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
1451 r.r_info = ELF64_R_INFO(r_sym, r_typ); 1451 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1452 } else { 1452 } else {
1453 r.r_info = TO_NATIVE(rel->r_info); 1453 r.r_info = TO_NATIVE(rel->r_info);
1454 r_sym = ELF_R_SYM(r.r_info); 1454 r_sym = ELF_R_SYM(r.r_info);
1455 } 1455 }
1456 #else 1456 #else
1457 r.r_info = TO_NATIVE(rel->r_info); 1457 r.r_info = TO_NATIVE(rel->r_info);
1458 r_sym = ELF_R_SYM(r.r_info); 1458 r_sym = ELF_R_SYM(r.r_info);
1459 #endif 1459 #endif
1460 r.r_addend = 0; 1460 r.r_addend = 0;
1461 switch (elf->hdr->e_machine) { 1461 switch (elf->hdr->e_machine) {
1462 case EM_386: 1462 case EM_386:
1463 if (addend_386_rel(elf, sechdr, &r)) 1463 if (addend_386_rel(elf, sechdr, &r))
1464 continue; 1464 continue;
1465 break; 1465 break;
1466 case EM_ARM: 1466 case EM_ARM:
1467 if (addend_arm_rel(elf, sechdr, &r)) 1467 if (addend_arm_rel(elf, sechdr, &r))
1468 continue; 1468 continue;
1469 break; 1469 break;
1470 case EM_MIPS: 1470 case EM_MIPS:
1471 if (addend_mips_rel(elf, sechdr, &r)) 1471 if (addend_mips_rel(elf, sechdr, &r))
1472 continue; 1472 continue;
1473 break; 1473 break;
1474 } 1474 }
1475 sym = elf->symtab_start + r_sym; 1475 sym = elf->symtab_start + r_sym;
1476 /* Skip special sections */ 1476 /* Skip special sections */
1477 if (sym->st_shndx >= SHN_LORESERVE) 1477 if (sym->st_shndx >= SHN_LORESERVE)
1478 continue; 1478 continue;
1479 check_section_mismatch(modname, elf, &r, sym, fromsec); 1479 check_section_mismatch(modname, elf, &r, sym, fromsec);
1480 } 1480 }
1481 } 1481 }
1482 1482
1483 /** 1483 /**
1484 * A module includes a number of sections that are discarded 1484 * A module includes a number of sections that are discarded
1485 * either when loaded or when used as built-in. 1485 * either when loaded or when used as built-in.
1486 * For loaded modules all functions marked __init and all data 1486 * For loaded modules all functions marked __init and all data
1487 * marked __initdata will be discarded when the module has been intialized. 1487 * marked __initdata will be discarded when the module has been intialized.
1488 * Likewise for modules used built-in the sections marked __exit 1488 * Likewise for modules used built-in the sections marked __exit
1489 * are discarded because __exit marked function are supposed to be called 1489 * are discarded because __exit marked function are supposed to be called
1490 * only when a module is unloaded which never happens for built-in modules. 1490 * only when a module is unloaded which never happens for built-in modules.
1491 * The check_sec_ref() function traverses all relocation records 1491 * The check_sec_ref() function traverses all relocation records
1492 * to find all references to a section that reference a section that will 1492 * to find all references to a section that reference a section that will
1493 * be discarded and warns about it. 1493 * be discarded and warns about it.
1494 **/ 1494 **/
1495 static void check_sec_ref(struct module *mod, const char *modname, 1495 static void check_sec_ref(struct module *mod, const char *modname,
1496 struct elf_info *elf) 1496 struct elf_info *elf)
1497 { 1497 {
1498 int i; 1498 int i;
1499 Elf_Shdr *sechdrs = elf->sechdrs; 1499 Elf_Shdr *sechdrs = elf->sechdrs;
1500 1500
1501 /* Walk through all sections */ 1501 /* Walk through all sections */
1502 for (i = 0; i < elf->hdr->e_shnum; i++) { 1502 for (i = 0; i < elf->hdr->e_shnum; i++) {
1503 check_section(modname, elf, &elf->sechdrs[i]); 1503 check_section(modname, elf, &elf->sechdrs[i]);
1504 /* We want to process only relocation sections and not .init */ 1504 /* We want to process only relocation sections and not .init */
1505 if (sechdrs[i].sh_type == SHT_RELA) 1505 if (sechdrs[i].sh_type == SHT_RELA)
1506 section_rela(modname, elf, &elf->sechdrs[i]); 1506 section_rela(modname, elf, &elf->sechdrs[i]);
1507 else if (sechdrs[i].sh_type == SHT_REL) 1507 else if (sechdrs[i].sh_type == SHT_REL)
1508 section_rel(modname, elf, &elf->sechdrs[i]); 1508 section_rel(modname, elf, &elf->sechdrs[i]);
1509 } 1509 }
1510 } 1510 }
1511 1511
1512 static void get_markers(struct elf_info *info, struct module *mod) 1512 static void get_markers(struct elf_info *info, struct module *mod)
1513 { 1513 {
1514 const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec]; 1514 const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
1515 const char *strings = (const char *) info->hdr + sh->sh_offset; 1515 const char *strings = (const char *) info->hdr + sh->sh_offset;
1516 const Elf_Sym *sym, *first_sym, *last_sym; 1516 const Elf_Sym *sym, *first_sym, *last_sym;
1517 size_t n; 1517 size_t n;
1518 1518
1519 if (!info->markers_strings_sec) 1519 if (!info->markers_strings_sec)
1520 return; 1520 return;
1521 1521
1522 /* 1522 /*
1523 * First count the strings. We look for all the symbols defined 1523 * First count the strings. We look for all the symbols defined
1524 * in the __markers_strings section named __mstrtab_*. For 1524 * in the __markers_strings section named __mstrtab_*. For
1525 * these local names, the compiler puts a random .NNN suffix on, 1525 * these local names, the compiler puts a random .NNN suffix on,
1526 * so the names don't correspond exactly. 1526 * so the names don't correspond exactly.
1527 */ 1527 */
1528 first_sym = last_sym = NULL; 1528 first_sym = last_sym = NULL;
1529 n = 0; 1529 n = 0;
1530 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) 1530 for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
1531 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT && 1531 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
1532 sym->st_shndx == info->markers_strings_sec && 1532 sym->st_shndx == info->markers_strings_sec &&
1533 !strncmp(info->strtab + sym->st_name, 1533 !strncmp(info->strtab + sym->st_name,
1534 "__mstrtab_", sizeof "__mstrtab_" - 1)) { 1534 "__mstrtab_", sizeof "__mstrtab_" - 1)) {
1535 if (first_sym == NULL) 1535 if (first_sym == NULL)
1536 first_sym = sym; 1536 first_sym = sym;
1537 last_sym = sym; 1537 last_sym = sym;
1538 ++n; 1538 ++n;
1539 } 1539 }
1540 1540
1541 if (n == 0) 1541 if (n == 0)
1542 return; 1542 return;
1543 1543
1544 /* 1544 /*
1545 * Now collect each name and format into a line for the output. 1545 * Now collect each name and format into a line for the output.
1546 * Lines look like: 1546 * Lines look like:
1547 * marker_name vmlinux marker %s format %d 1547 * marker_name vmlinux marker %s format %d
1548 * The format string after the second \t can use whitespace. 1548 * The format string after the second \t can use whitespace.
1549 */ 1549 */
1550 mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n)); 1550 mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
1551 mod->nmarkers = n; 1551 mod->nmarkers = n;
1552 1552
1553 n = 0; 1553 n = 0;
1554 for (sym = first_sym; sym <= last_sym; sym++) 1554 for (sym = first_sym; sym <= last_sym; sym++)
1555 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT && 1555 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
1556 sym->st_shndx == info->markers_strings_sec && 1556 sym->st_shndx == info->markers_strings_sec &&
1557 !strncmp(info->strtab + sym->st_name, 1557 !strncmp(info->strtab + sym->st_name,
1558 "__mstrtab_", sizeof "__mstrtab_" - 1)) { 1558 "__mstrtab_", sizeof "__mstrtab_" - 1)) {
1559 const char *name = strings + sym->st_value; 1559 const char *name = strings + sym->st_value;
1560 const char *fmt = strchr(name, '\0') + 1; 1560 const char *fmt = strchr(name, '\0') + 1;
1561 char *line = NULL; 1561 char *line = NULL;
1562 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt); 1562 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
1563 NOFAIL(line); 1563 NOFAIL(line);
1564 mod->markers[n++] = line; 1564 mod->markers[n++] = line;
1565 } 1565 }
1566 } 1566 }
1567 1567
1568 static void read_symbols(char *modname) 1568 static void read_symbols(char *modname)
1569 { 1569 {
1570 const char *symname; 1570 const char *symname;
1571 char *version; 1571 char *version;
1572 char *license; 1572 char *license;
1573 struct module *mod; 1573 struct module *mod;
1574 struct elf_info info = { }; 1574 struct elf_info info = { };
1575 Elf_Sym *sym; 1575 Elf_Sym *sym;
1576 1576
1577 if (!parse_elf(&info, modname)) 1577 if (!parse_elf(&info, modname))
1578 return; 1578 return;
1579 1579
1580 mod = new_module(modname); 1580 mod = new_module(modname);
1581 1581
1582 /* When there's no vmlinux, don't print warnings about 1582 /* When there's no vmlinux, don't print warnings about
1583 * unresolved symbols (since there'll be too many ;) */ 1583 * unresolved symbols (since there'll be too many ;) */
1584 if (is_vmlinux(modname)) { 1584 if (is_vmlinux(modname)) {
1585 have_vmlinux = 1; 1585 have_vmlinux = 1;
1586 mod->skip = 1; 1586 mod->skip = 1;
1587 } 1587 }
1588 1588
1589 license = get_modinfo(info.modinfo, info.modinfo_len, "license"); 1589 license = get_modinfo(info.modinfo, info.modinfo_len, "license");
1590 if (info.modinfo && !license && !is_vmlinux(modname)) 1590 if (info.modinfo && !license && !is_vmlinux(modname))
1591 warn("modpost: missing MODULE_LICENSE() in %s\n" 1591 warn("modpost: missing MODULE_LICENSE() in %s\n"
1592 "see include/linux/module.h for " 1592 "see include/linux/module.h for "
1593 "more information\n", modname); 1593 "more information\n", modname);
1594 while (license) { 1594 while (license) {
1595 if (license_is_gpl_compatible(license)) 1595 if (license_is_gpl_compatible(license))
1596 mod->gpl_compatible = 1; 1596 mod->gpl_compatible = 1;
1597 else { 1597 else {
1598 mod->gpl_compatible = 0; 1598 mod->gpl_compatible = 0;
1599 break; 1599 break;
1600 } 1600 }
1601 license = get_next_modinfo(info.modinfo, info.modinfo_len, 1601 license = get_next_modinfo(info.modinfo, info.modinfo_len,
1602 "license", license); 1602 "license", license);
1603 } 1603 }
1604 1604
1605 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { 1605 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
1606 symname = info.strtab + sym->st_name; 1606 symname = info.strtab + sym->st_name;
1607 1607
1608 handle_modversions(mod, &info, sym, symname); 1608 handle_modversions(mod, &info, sym, symname);
1609 handle_moddevtable(mod, &info, sym, symname); 1609 handle_moddevtable(mod, &info, sym, symname);
1610 } 1610 }
1611 if (!is_vmlinux(modname) || 1611 if (!is_vmlinux(modname) ||
1612 (is_vmlinux(modname) && vmlinux_section_warnings)) 1612 (is_vmlinux(modname) && vmlinux_section_warnings))
1613 check_sec_ref(mod, modname, &info); 1613 check_sec_ref(mod, modname, &info);
1614 1614
1615 version = get_modinfo(info.modinfo, info.modinfo_len, "version"); 1615 version = get_modinfo(info.modinfo, info.modinfo_len, "version");
1616 if (version) 1616 if (version)
1617 maybe_frob_rcs_version(modname, version, info.modinfo, 1617 maybe_frob_rcs_version(modname, version, info.modinfo,
1618 version - (char *)info.hdr); 1618 version - (char *)info.hdr);
1619 if (version || (all_versions && !is_vmlinux(modname))) 1619 if (version || (all_versions && !is_vmlinux(modname)))
1620 get_src_version(modname, mod->srcversion, 1620 get_src_version(modname, mod->srcversion,
1621 sizeof(mod->srcversion)-1); 1621 sizeof(mod->srcversion)-1);
1622 1622
1623 get_markers(&info, mod); 1623 get_markers(&info, mod);
1624 1624
1625 parse_elf_finish(&info); 1625 parse_elf_finish(&info);
1626 1626
1627 /* Our trick to get versioning for module struct etc. - it's 1627 /* Our trick to get versioning for module struct etc. - it's
1628 * never passed as an argument to an exported function, so 1628 * never passed as an argument to an exported function, so
1629 * the automatic versioning doesn't pick it up, but it's really 1629 * the automatic versioning doesn't pick it up, but it's really
1630 * important anyhow */ 1630 * important anyhow */
1631 if (modversions) 1631 if (modversions)
1632 mod->unres = alloc_symbol("module_layout", 0, mod->unres); 1632 mod->unres = alloc_symbol("module_layout", 0, mod->unres);
1633 } 1633 }
1634 1634
1635 #define SZ 500 1635 #define SZ 500
1636 1636
1637 /* We first write the generated file into memory using the 1637 /* We first write the generated file into memory using the
1638 * following helper, then compare to the file on disk and 1638 * following helper, then compare to the file on disk and
1639 * only update the later if anything changed */ 1639 * only update the later if anything changed */
1640 1640
1641 void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, 1641 void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
1642 const char *fmt, ...) 1642 const char *fmt, ...)
1643 { 1643 {
1644 char tmp[SZ]; 1644 char tmp[SZ];
1645 int len; 1645 int len;
1646 va_list ap; 1646 va_list ap;
1647 1647
1648 va_start(ap, fmt); 1648 va_start(ap, fmt);
1649 len = vsnprintf(tmp, SZ, fmt, ap); 1649 len = vsnprintf(tmp, SZ, fmt, ap);
1650 buf_write(buf, tmp, len); 1650 buf_write(buf, tmp, len);
1651 va_end(ap); 1651 va_end(ap);
1652 } 1652 }
1653 1653
1654 void buf_write(struct buffer *buf, const char *s, int len) 1654 void buf_write(struct buffer *buf, const char *s, int len)
1655 { 1655 {
1656 if (buf->size - buf->pos < len) { 1656 if (buf->size - buf->pos < len) {
1657 buf->size += len + SZ; 1657 buf->size += len + SZ;
1658 buf->p = realloc(buf->p, buf->size); 1658 buf->p = realloc(buf->p, buf->size);
1659 } 1659 }
1660 strncpy(buf->p + buf->pos, s, len); 1660 strncpy(buf->p + buf->pos, s, len);
1661 buf->pos += len; 1661 buf->pos += len;
1662 } 1662 }
1663 1663
1664 static void check_for_gpl_usage(enum export exp, const char *m, const char *s) 1664 static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
1665 { 1665 {
1666 const char *e = is_vmlinux(m) ?"":".ko"; 1666 const char *e = is_vmlinux(m) ?"":".ko";
1667 1667
1668 switch (exp) { 1668 switch (exp) {
1669 case export_gpl: 1669 case export_gpl:
1670 fatal("modpost: GPL-incompatible module %s%s " 1670 fatal("modpost: GPL-incompatible module %s%s "
1671 "uses GPL-only symbol '%s'\n", m, e, s); 1671 "uses GPL-only symbol '%s'\n", m, e, s);
1672 break; 1672 break;
1673 case export_unused_gpl: 1673 case export_unused_gpl:
1674 fatal("modpost: GPL-incompatible module %s%s " 1674 fatal("modpost: GPL-incompatible module %s%s "
1675 "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); 1675 "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s);
1676 break; 1676 break;
1677 case export_gpl_future: 1677 case export_gpl_future:
1678 warn("modpost: GPL-incompatible module %s%s " 1678 warn("modpost: GPL-incompatible module %s%s "
1679 "uses future GPL-only symbol '%s'\n", m, e, s); 1679 "uses future GPL-only symbol '%s'\n", m, e, s);
1680 break; 1680 break;
1681 case export_plain: 1681 case export_plain:
1682 case export_unused: 1682 case export_unused:
1683 case export_unknown: 1683 case export_unknown:
1684 /* ignore */ 1684 /* ignore */
1685 break; 1685 break;
1686 } 1686 }
1687 } 1687 }
1688 1688
1689 static void check_for_unused(enum export exp, const char *m, const char *s) 1689 static void check_for_unused(enum export exp, const char *m, const char *s)
1690 { 1690 {
1691 const char *e = is_vmlinux(m) ?"":".ko"; 1691 const char *e = is_vmlinux(m) ?"":".ko";
1692 1692
1693 switch (exp) { 1693 switch (exp) {
1694 case export_unused: 1694 case export_unused:
1695 case export_unused_gpl: 1695 case export_unused_gpl:
1696 warn("modpost: module %s%s " 1696 warn("modpost: module %s%s "
1697 "uses symbol '%s' marked UNUSED\n", m, e, s); 1697 "uses symbol '%s' marked UNUSED\n", m, e, s);
1698 break; 1698 break;
1699 default: 1699 default:
1700 /* ignore */ 1700 /* ignore */
1701 break; 1701 break;
1702 } 1702 }
1703 } 1703 }
1704 1704
1705 static void check_exports(struct module *mod) 1705 static void check_exports(struct module *mod)
1706 { 1706 {
1707 struct symbol *s, *exp; 1707 struct symbol *s, *exp;
1708 1708
1709 for (s = mod->unres; s; s = s->next) { 1709 for (s = mod->unres; s; s = s->next) {
1710 const char *basename; 1710 const char *basename;
1711 exp = find_symbol(s->name); 1711 exp = find_symbol(s->name);
1712 if (!exp || exp->module == mod) 1712 if (!exp || exp->module == mod)
1713 continue; 1713 continue;
1714 basename = strrchr(mod->name, '/'); 1714 basename = strrchr(mod->name, '/');
1715 if (basename) 1715 if (basename)
1716 basename++; 1716 basename++;
1717 else 1717 else
1718 basename = mod->name; 1718 basename = mod->name;
1719 if (!mod->gpl_compatible) 1719 if (!mod->gpl_compatible)
1720 check_for_gpl_usage(exp->export, basename, exp->name); 1720 check_for_gpl_usage(exp->export, basename, exp->name);
1721 check_for_unused(exp->export, basename, exp->name); 1721 check_for_unused(exp->export, basename, exp->name);
1722 } 1722 }
1723 } 1723 }
1724 1724
1725 /** 1725 /**
1726 * Header for the generated file 1726 * Header for the generated file
1727 **/ 1727 **/
1728 static void add_header(struct buffer *b, struct module *mod) 1728 static void add_header(struct buffer *b, struct module *mod)
1729 { 1729 {
1730 buf_printf(b, "#include <linux/module.h>\n"); 1730 buf_printf(b, "#include <linux/module.h>\n");
1731 buf_printf(b, "#include <linux/vermagic.h>\n"); 1731 buf_printf(b, "#include <linux/vermagic.h>\n");
1732 buf_printf(b, "#include <linux/compiler.h>\n"); 1732 buf_printf(b, "#include <linux/compiler.h>\n");
1733 buf_printf(b, "\n"); 1733 buf_printf(b, "\n");
1734 buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); 1734 buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
1735 buf_printf(b, "\n"); 1735 buf_printf(b, "\n");
1736 buf_printf(b, "struct module __this_module\n"); 1736 buf_printf(b, "struct module __this_module\n");
1737 buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); 1737 buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
1738 buf_printf(b, " .name = KBUILD_MODNAME,\n"); 1738 buf_printf(b, " .name = KBUILD_MODNAME,\n");
1739 if (mod->has_init) 1739 if (mod->has_init)
1740 buf_printf(b, " .init = init_module,\n"); 1740 buf_printf(b, " .init = init_module,\n");
1741 if (mod->has_cleanup) 1741 if (mod->has_cleanup)
1742 buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" 1742 buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
1743 " .exit = cleanup_module,\n" 1743 " .exit = cleanup_module,\n"
1744 "#endif\n"); 1744 "#endif\n");
1745 buf_printf(b, " .arch = MODULE_ARCH_INIT,\n"); 1745 buf_printf(b, " .arch = MODULE_ARCH_INIT,\n");
1746 buf_printf(b, "};\n"); 1746 buf_printf(b, "};\n");
1747 } 1747 }
1748 1748
1749 void add_staging_flag(struct buffer *b, const char *name) 1749 static void add_staging_flag(struct buffer *b, const char *name)
1750 { 1750 {
1751 static const char *staging_dir = "drivers/staging"; 1751 static const char *staging_dir = "drivers/staging";
1752 1752
1753 if (strncmp(staging_dir, name, strlen(staging_dir)) == 0) 1753 if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
1754 buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); 1754 buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
1755 } 1755 }
1756 1756
1757 /** 1757 /**
1758 * Record CRCs for unresolved symbols 1758 * Record CRCs for unresolved symbols
1759 **/ 1759 **/
1760 static int add_versions(struct buffer *b, struct module *mod) 1760 static int add_versions(struct buffer *b, struct module *mod)
1761 { 1761 {
1762 struct symbol *s, *exp; 1762 struct symbol *s, *exp;
1763 int err = 0; 1763 int err = 0;
1764 1764
1765 for (s = mod->unres; s; s = s->next) { 1765 for (s = mod->unres; s; s = s->next) {
1766 exp = find_symbol(s->name); 1766 exp = find_symbol(s->name);
1767 if (!exp || exp->module == mod) { 1767 if (!exp || exp->module == mod) {
1768 if (have_vmlinux && !s->weak) { 1768 if (have_vmlinux && !s->weak) {
1769 if (warn_unresolved) { 1769 if (warn_unresolved) {
1770 warn("\"%s\" [%s.ko] undefined!\n", 1770 warn("\"%s\" [%s.ko] undefined!\n",
1771 s->name, mod->name); 1771 s->name, mod->name);
1772 } else { 1772 } else {
1773 merror("\"%s\" [%s.ko] undefined!\n", 1773 merror("\"%s\" [%s.ko] undefined!\n",
1774 s->name, mod->name); 1774 s->name, mod->name);
1775 err = 1; 1775 err = 1;
1776 } 1776 }
1777 } 1777 }
1778 continue; 1778 continue;
1779 } 1779 }
1780 s->module = exp->module; 1780 s->module = exp->module;
1781 s->crc_valid = exp->crc_valid; 1781 s->crc_valid = exp->crc_valid;
1782 s->crc = exp->crc; 1782 s->crc = exp->crc;
1783 } 1783 }
1784 1784
1785 if (!modversions) 1785 if (!modversions)
1786 return err; 1786 return err;
1787 1787
1788 buf_printf(b, "\n"); 1788 buf_printf(b, "\n");
1789 buf_printf(b, "static const struct modversion_info ____versions[]\n"); 1789 buf_printf(b, "static const struct modversion_info ____versions[]\n");
1790 buf_printf(b, "__used\n"); 1790 buf_printf(b, "__used\n");
1791 buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n"); 1791 buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n");
1792 1792
1793 for (s = mod->unres; s; s = s->next) { 1793 for (s = mod->unres; s; s = s->next) {
1794 if (!s->module) 1794 if (!s->module)
1795 continue; 1795 continue;
1796 if (!s->crc_valid) { 1796 if (!s->crc_valid) {
1797 warn("\"%s\" [%s.ko] has no CRC!\n", 1797 warn("\"%s\" [%s.ko] has no CRC!\n",
1798 s->name, mod->name); 1798 s->name, mod->name);
1799 continue; 1799 continue;
1800 } 1800 }
1801 buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name); 1801 buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name);
1802 } 1802 }
1803 1803
1804 buf_printf(b, "};\n"); 1804 buf_printf(b, "};\n");
1805 1805
1806 return err; 1806 return err;
1807 } 1807 }
1808 1808
1809 static void add_depends(struct buffer *b, struct module *mod, 1809 static void add_depends(struct buffer *b, struct module *mod,
1810 struct module *modules) 1810 struct module *modules)
1811 { 1811 {
1812 struct symbol *s; 1812 struct symbol *s;
1813 struct module *m; 1813 struct module *m;
1814 int first = 1; 1814 int first = 1;
1815 1815
1816 for (m = modules; m; m = m->next) 1816 for (m = modules; m; m = m->next)
1817 m->seen = is_vmlinux(m->name); 1817 m->seen = is_vmlinux(m->name);
1818 1818
1819 buf_printf(b, "\n"); 1819 buf_printf(b, "\n");
1820 buf_printf(b, "static const char __module_depends[]\n"); 1820 buf_printf(b, "static const char __module_depends[]\n");
1821 buf_printf(b, "__used\n"); 1821 buf_printf(b, "__used\n");
1822 buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); 1822 buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
1823 buf_printf(b, "\"depends="); 1823 buf_printf(b, "\"depends=");
1824 for (s = mod->unres; s; s = s->next) { 1824 for (s = mod->unres; s; s = s->next) {
1825 const char *p; 1825 const char *p;
1826 if (!s->module) 1826 if (!s->module)
1827 continue; 1827 continue;
1828 1828
1829 if (s->module->seen) 1829 if (s->module->seen)
1830 continue; 1830 continue;
1831 1831
1832 s->module->seen = 1; 1832 s->module->seen = 1;
1833 p = strrchr(s->module->name, '/'); 1833 p = strrchr(s->module->name, '/');
1834 if (p) 1834 if (p)
1835 p++; 1835 p++;
1836 else 1836 else
1837 p = s->module->name; 1837 p = s->module->name;
1838 buf_printf(b, "%s%s", first ? "" : ",", p); 1838 buf_printf(b, "%s%s", first ? "" : ",", p);
1839 first = 0; 1839 first = 0;
1840 } 1840 }
1841 buf_printf(b, "\";\n"); 1841 buf_printf(b, "\";\n");
1842 } 1842 }
1843 1843
1844 static void add_srcversion(struct buffer *b, struct module *mod) 1844 static void add_srcversion(struct buffer *b, struct module *mod)
1845 { 1845 {
1846 if (mod->srcversion[0]) { 1846 if (mod->srcversion[0]) {
1847 buf_printf(b, "\n"); 1847 buf_printf(b, "\n");
1848 buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", 1848 buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
1849 mod->srcversion); 1849 mod->srcversion);
1850 } 1850 }
1851 } 1851 }
1852 1852
1853 static void write_if_changed(struct buffer *b, const char *fname) 1853 static void write_if_changed(struct buffer *b, const char *fname)
1854 { 1854 {
1855 char *tmp; 1855 char *tmp;
1856 FILE *file; 1856 FILE *file;
1857 struct stat st; 1857 struct stat st;
1858 1858
1859 file = fopen(fname, "r"); 1859 file = fopen(fname, "r");
1860 if (!file) 1860 if (!file)
1861 goto write; 1861 goto write;
1862 1862
1863 if (fstat(fileno(file), &st) < 0) 1863 if (fstat(fileno(file), &st) < 0)
1864 goto close_write; 1864 goto close_write;
1865 1865
1866 if (st.st_size != b->pos) 1866 if (st.st_size != b->pos)
1867 goto close_write; 1867 goto close_write;
1868 1868
1869 tmp = NOFAIL(malloc(b->pos)); 1869 tmp = NOFAIL(malloc(b->pos));
1870 if (fread(tmp, 1, b->pos, file) != b->pos) 1870 if (fread(tmp, 1, b->pos, file) != b->pos)
1871 goto free_write; 1871 goto free_write;
1872 1872
1873 if (memcmp(tmp, b->p, b->pos) != 0) 1873 if (memcmp(tmp, b->p, b->pos) != 0)
1874 goto free_write; 1874 goto free_write;
1875 1875
1876 free(tmp); 1876 free(tmp);
1877 fclose(file); 1877 fclose(file);
1878 return; 1878 return;
1879 1879
1880 free_write: 1880 free_write:
1881 free(tmp); 1881 free(tmp);
1882 close_write: 1882 close_write:
1883 fclose(file); 1883 fclose(file);
1884 write: 1884 write:
1885 file = fopen(fname, "w"); 1885 file = fopen(fname, "w");
1886 if (!file) { 1886 if (!file) {
1887 perror(fname); 1887 perror(fname);
1888 exit(1); 1888 exit(1);
1889 } 1889 }
1890 if (fwrite(b->p, 1, b->pos, file) != b->pos) { 1890 if (fwrite(b->p, 1, b->pos, file) != b->pos) {
1891 perror(fname); 1891 perror(fname);
1892 exit(1); 1892 exit(1);
1893 } 1893 }
1894 fclose(file); 1894 fclose(file);
1895 } 1895 }
1896 1896
1897 /* parse Module.symvers file. line format: 1897 /* parse Module.symvers file. line format:
1898 * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something] 1898 * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
1899 **/ 1899 **/
1900 static void read_dump(const char *fname, unsigned int kernel) 1900 static void read_dump(const char *fname, unsigned int kernel)
1901 { 1901 {
1902 unsigned long size, pos = 0; 1902 unsigned long size, pos = 0;
1903 void *file = grab_file(fname, &size); 1903 void *file = grab_file(fname, &size);
1904 char *line; 1904 char *line;
1905 1905
1906 if (!file) 1906 if (!file)
1907 /* No symbol versions, silently ignore */ 1907 /* No symbol versions, silently ignore */
1908 return; 1908 return;
1909 1909
1910 while ((line = get_next_line(&pos, file, size))) { 1910 while ((line = get_next_line(&pos, file, size))) {
1911 char *symname, *modname, *d, *export, *end; 1911 char *symname, *modname, *d, *export, *end;
1912 unsigned int crc; 1912 unsigned int crc;
1913 struct module *mod; 1913 struct module *mod;
1914 struct symbol *s; 1914 struct symbol *s;
1915 1915
1916 if (!(symname = strchr(line, '\t'))) 1916 if (!(symname = strchr(line, '\t')))
1917 goto fail; 1917 goto fail;
1918 *symname++ = '\0'; 1918 *symname++ = '\0';
1919 if (!(modname = strchr(symname, '\t'))) 1919 if (!(modname = strchr(symname, '\t')))
1920 goto fail; 1920 goto fail;
1921 *modname++ = '\0'; 1921 *modname++ = '\0';
1922 if ((export = strchr(modname, '\t')) != NULL) 1922 if ((export = strchr(modname, '\t')) != NULL)
1923 *export++ = '\0'; 1923 *export++ = '\0';
1924 if (export && ((end = strchr(export, '\t')) != NULL)) 1924 if (export && ((end = strchr(export, '\t')) != NULL))
1925 *end = '\0'; 1925 *end = '\0';
1926 crc = strtoul(line, &d, 16); 1926 crc = strtoul(line, &d, 16);
1927 if (*symname == '\0' || *modname == '\0' || *d != '\0') 1927 if (*symname == '\0' || *modname == '\0' || *d != '\0')
1928 goto fail; 1928 goto fail;
1929 mod = find_module(modname); 1929 mod = find_module(modname);
1930 if (!mod) { 1930 if (!mod) {
1931 if (is_vmlinux(modname)) 1931 if (is_vmlinux(modname))
1932 have_vmlinux = 1; 1932 have_vmlinux = 1;
1933 mod = new_module(modname); 1933 mod = new_module(modname);
1934 mod->skip = 1; 1934 mod->skip = 1;
1935 } 1935 }
1936 s = sym_add_exported(symname, mod, export_no(export)); 1936 s = sym_add_exported(symname, mod, export_no(export));
1937 s->kernel = kernel; 1937 s->kernel = kernel;
1938 s->preloaded = 1; 1938 s->preloaded = 1;
1939 sym_update_crc(symname, mod, crc, export_no(export)); 1939 sym_update_crc(symname, mod, crc, export_no(export));
1940 } 1940 }
1941 return; 1941 return;
1942 fail: 1942 fail:
1943 fatal("parse error in symbol dump file\n"); 1943 fatal("parse error in symbol dump file\n");
1944 } 1944 }
1945 1945
1946 /* For normal builds always dump all symbols. 1946 /* For normal builds always dump all symbols.
1947 * For external modules only dump symbols 1947 * For external modules only dump symbols
1948 * that are not read from kernel Module.symvers. 1948 * that are not read from kernel Module.symvers.
1949 **/ 1949 **/
1950 static int dump_sym(struct symbol *sym) 1950 static int dump_sym(struct symbol *sym)
1951 { 1951 {
1952 if (!external_module) 1952 if (!external_module)
1953 return 1; 1953 return 1;
1954 if (sym->vmlinux || sym->kernel) 1954 if (sym->vmlinux || sym->kernel)
1955 return 0; 1955 return 0;
1956 return 1; 1956 return 1;
1957 } 1957 }
1958 1958
1959 static void write_dump(const char *fname) 1959 static void write_dump(const char *fname)
1960 { 1960 {
1961 struct buffer buf = { }; 1961 struct buffer buf = { };
1962 struct symbol *symbol; 1962 struct symbol *symbol;
1963 int n; 1963 int n;
1964 1964
1965 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { 1965 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
1966 symbol = symbolhash[n]; 1966 symbol = symbolhash[n];
1967 while (symbol) { 1967 while (symbol) {
1968 if (dump_sym(symbol)) 1968 if (dump_sym(symbol))
1969 buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", 1969 buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
1970 symbol->crc, symbol->name, 1970 symbol->crc, symbol->name,
1971 symbol->module->name, 1971 symbol->module->name,
1972 export_str(symbol->export)); 1972 export_str(symbol->export));
1973 symbol = symbol->next; 1973 symbol = symbol->next;
1974 } 1974 }
1975 } 1975 }
1976 write_if_changed(&buf, fname); 1976 write_if_changed(&buf, fname);
1977 } 1977 }
1978 1978
1979 static void add_marker(struct module *mod, const char *name, const char *fmt) 1979 static void add_marker(struct module *mod, const char *name, const char *fmt)
1980 { 1980 {
1981 char *line = NULL; 1981 char *line = NULL;
1982 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt); 1982 asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
1983 NOFAIL(line); 1983 NOFAIL(line);
1984 1984
1985 mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) * 1985 mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
1986 sizeof mod->markers[0]))); 1986 sizeof mod->markers[0])));
1987 mod->markers[mod->nmarkers++] = line; 1987 mod->markers[mod->nmarkers++] = line;
1988 } 1988 }
1989 1989
1990 static void read_markers(const char *fname) 1990 static void read_markers(const char *fname)
1991 { 1991 {
1992 unsigned long size, pos = 0; 1992 unsigned long size, pos = 0;
1993 void *file = grab_file(fname, &size); 1993 void *file = grab_file(fname, &size);
1994 char *line; 1994 char *line;
1995 1995
1996 if (!file) /* No old markers, silently ignore */ 1996 if (!file) /* No old markers, silently ignore */
1997 return; 1997 return;
1998 1998
1999 while ((line = get_next_line(&pos, file, size))) { 1999 while ((line = get_next_line(&pos, file, size))) {
2000 char *marker, *modname, *fmt; 2000 char *marker, *modname, *fmt;
2001 struct module *mod; 2001 struct module *mod;
2002 2002
2003 marker = line; 2003 marker = line;
2004 modname = strchr(marker, '\t'); 2004 modname = strchr(marker, '\t');
2005 if (!modname) 2005 if (!modname)
2006 goto fail; 2006 goto fail;
2007 *modname++ = '\0'; 2007 *modname++ = '\0';
2008 fmt = strchr(modname, '\t'); 2008 fmt = strchr(modname, '\t');
2009 if (!fmt) 2009 if (!fmt)
2010 goto fail; 2010 goto fail;
2011 *fmt++ = '\0'; 2011 *fmt++ = '\0';
2012 if (*marker == '\0' || *modname == '\0') 2012 if (*marker == '\0' || *modname == '\0')
2013 goto fail; 2013 goto fail;
2014 2014
2015 mod = find_module(modname); 2015 mod = find_module(modname);
2016 if (!mod) { 2016 if (!mod) {
2017 mod = new_module(modname); 2017 mod = new_module(modname);
2018 mod->skip = 1; 2018 mod->skip = 1;
2019 } 2019 }
2020 if (is_vmlinux(modname)) { 2020 if (is_vmlinux(modname)) {
2021 have_vmlinux = 1; 2021 have_vmlinux = 1;
2022 mod->skip = 0; 2022 mod->skip = 0;
2023 } 2023 }
2024 2024
2025 if (!mod->skip) 2025 if (!mod->skip)
2026 add_marker(mod, marker, fmt); 2026 add_marker(mod, marker, fmt);
2027 } 2027 }
2028 release_file(file, size); 2028 release_file(file, size);
2029 return; 2029 return;
2030 fail: 2030 fail:
2031 fatal("parse error in markers list file\n"); 2031 fatal("parse error in markers list file\n");
2032 } 2032 }
2033 2033
2034 static int compare_strings(const void *a, const void *b) 2034 static int compare_strings(const void *a, const void *b)
2035 { 2035 {
2036 return strcmp(*(const char **) a, *(const char **) b); 2036 return strcmp(*(const char **) a, *(const char **) b);
2037 } 2037 }
2038 2038
2039 static void write_markers(const char *fname) 2039 static void write_markers(const char *fname)
2040 { 2040 {
2041 struct buffer buf = { }; 2041 struct buffer buf = { };
2042 struct module *mod; 2042 struct module *mod;
2043 size_t i; 2043 size_t i;
2044 2044
2045 for (mod = modules; mod; mod = mod->next) 2045 for (mod = modules; mod; mod = mod->next)
2046 if ((!external_module || !mod->skip) && mod->markers != NULL) { 2046 if ((!external_module || !mod->skip) && mod->markers != NULL) {
2047 /* 2047 /*
2048 * Sort the strings so we can skip duplicates when 2048 * Sort the strings so we can skip duplicates when
2049 * we write them out. 2049 * we write them out.
2050 */ 2050 */
2051 qsort(mod->markers, mod->nmarkers, 2051 qsort(mod->markers, mod->nmarkers,
2052 sizeof mod->markers[0], &compare_strings); 2052 sizeof mod->markers[0], &compare_strings);
2053 for (i = 0; i < mod->nmarkers; ++i) { 2053 for (i = 0; i < mod->nmarkers; ++i) {
2054 char *line = mod->markers[i]; 2054 char *line = mod->markers[i];
2055 buf_write(&buf, line, strlen(line)); 2055 buf_write(&buf, line, strlen(line));
2056 while (i + 1 < mod->nmarkers && 2056 while (i + 1 < mod->nmarkers &&
2057 !strcmp(mod->markers[i], 2057 !strcmp(mod->markers[i],
2058 mod->markers[i + 1])) 2058 mod->markers[i + 1]))
2059 free(mod->markers[i++]); 2059 free(mod->markers[i++]);
2060 free(mod->markers[i]); 2060 free(mod->markers[i]);
2061 } 2061 }
2062 free(mod->markers); 2062 free(mod->markers);
2063 mod->markers = NULL; 2063 mod->markers = NULL;
2064 } 2064 }
2065 2065
2066 write_if_changed(&buf, fname); 2066 write_if_changed(&buf, fname);
2067 } 2067 }
2068 2068
2069 struct ext_sym_list { 2069 struct ext_sym_list {
2070 struct ext_sym_list *next; 2070 struct ext_sym_list *next;
2071 const char *file; 2071 const char *file;
2072 }; 2072 };
2073 2073
2074 int main(int argc, char **argv) 2074 int main(int argc, char **argv)
2075 { 2075 {
2076 struct module *mod; 2076 struct module *mod;
2077 struct buffer buf = { }; 2077 struct buffer buf = { };
2078 char *kernel_read = NULL, *module_read = NULL; 2078 char *kernel_read = NULL, *module_read = NULL;
2079 char *dump_write = NULL; 2079 char *dump_write = NULL;
2080 char *markers_read = NULL; 2080 char *markers_read = NULL;
2081 char *markers_write = NULL; 2081 char *markers_write = NULL;
2082 int opt; 2082 int opt;
2083 int err; 2083 int err;
2084 struct ext_sym_list *extsym_iter; 2084 struct ext_sym_list *extsym_iter;
2085 struct ext_sym_list *extsym_start = NULL; 2085 struct ext_sym_list *extsym_start = NULL;
2086 2086
2087 while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) { 2087 while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
2088 switch (opt) { 2088 switch (opt) {
2089 case 'i': 2089 case 'i':
2090 kernel_read = optarg; 2090 kernel_read = optarg;
2091 break; 2091 break;
2092 case 'I': 2092 case 'I':
2093 module_read = optarg; 2093 module_read = optarg;
2094 external_module = 1; 2094 external_module = 1;
2095 break; 2095 break;
2096 case 'c': 2096 case 'c':
2097 cross_build = 1; 2097 cross_build = 1;
2098 break; 2098 break;
2099 case 'e': 2099 case 'e':
2100 external_module = 1; 2100 external_module = 1;
2101 extsym_iter = 2101 extsym_iter =
2102 NOFAIL(malloc(sizeof(*extsym_iter))); 2102 NOFAIL(malloc(sizeof(*extsym_iter)));
2103 extsym_iter->next = extsym_start; 2103 extsym_iter->next = extsym_start;
2104 extsym_iter->file = optarg; 2104 extsym_iter->file = optarg;
2105 extsym_start = extsym_iter; 2105 extsym_start = extsym_iter;
2106 break; 2106 break;
2107 case 'm': 2107 case 'm':
2108 modversions = 1; 2108 modversions = 1;
2109 break; 2109 break;
2110 case 'o': 2110 case 'o':
2111 dump_write = optarg; 2111 dump_write = optarg;
2112 break; 2112 break;
2113 case 'a': 2113 case 'a':
2114 all_versions = 1; 2114 all_versions = 1;
2115 break; 2115 break;
2116 case 's': 2116 case 's':
2117 vmlinux_section_warnings = 0; 2117 vmlinux_section_warnings = 0;
2118 break; 2118 break;
2119 case 'S': 2119 case 'S':
2120 sec_mismatch_verbose = 0; 2120 sec_mismatch_verbose = 0;
2121 break; 2121 break;
2122 case 'w': 2122 case 'w':
2123 warn_unresolved = 1; 2123 warn_unresolved = 1;
2124 break; 2124 break;
2125 case 'M': 2125 case 'M':
2126 markers_write = optarg; 2126 markers_write = optarg;
2127 break; 2127 break;
2128 case 'K': 2128 case 'K':
2129 markers_read = optarg; 2129 markers_read = optarg;
2130 break; 2130 break;
2131 default: 2131 default:
2132 exit(1); 2132 exit(1);
2133 } 2133 }
2134 } 2134 }
2135 2135
2136 if (kernel_read) 2136 if (kernel_read)
2137 read_dump(kernel_read, 1); 2137 read_dump(kernel_read, 1);
2138 if (module_read) 2138 if (module_read)
2139 read_dump(module_read, 0); 2139 read_dump(module_read, 0);
2140 while (extsym_start) { 2140 while (extsym_start) {
2141 read_dump(extsym_start->file, 0); 2141 read_dump(extsym_start->file, 0);
2142 extsym_iter = extsym_start->next; 2142 extsym_iter = extsym_start->next;
2143 free(extsym_start); 2143 free(extsym_start);
2144 extsym_start = extsym_iter; 2144 extsym_start = extsym_iter;
2145 } 2145 }
2146 2146
2147 while (optind < argc) 2147 while (optind < argc)
2148 read_symbols(argv[optind++]); 2148 read_symbols(argv[optind++]);
2149 2149
2150 for (mod = modules; mod; mod = mod->next) { 2150 for (mod = modules; mod; mod = mod->next) {
2151 if (mod->skip) 2151 if (mod->skip)
2152 continue; 2152 continue;
2153 check_exports(mod); 2153 check_exports(mod);
2154 } 2154 }
2155 2155
2156 err = 0; 2156 err = 0;
2157 2157
2158 for (mod = modules; mod; mod = mod->next) { 2158 for (mod = modules; mod; mod = mod->next) {
2159 char fname[strlen(mod->name) + 10]; 2159 char fname[strlen(mod->name) + 10];
2160 2160
2161 if (mod->skip) 2161 if (mod->skip)
2162 continue; 2162 continue;
2163 2163
2164 buf.pos = 0; 2164 buf.pos = 0;
2165 2165
2166 add_header(&buf, mod); 2166 add_header(&buf, mod);
2167 add_staging_flag(&buf, mod->name); 2167 add_staging_flag(&buf, mod->name);
2168 err |= add_versions(&buf, mod); 2168 err |= add_versions(&buf, mod);
2169 add_depends(&buf, mod, modules); 2169 add_depends(&buf, mod, modules);
2170 add_moddevtable(&buf, mod); 2170 add_moddevtable(&buf, mod);
2171 add_srcversion(&buf, mod); 2171 add_srcversion(&buf, mod);
2172 2172
2173 sprintf(fname, "%s.mod.c", mod->name); 2173 sprintf(fname, "%s.mod.c", mod->name);
2174 write_if_changed(&buf, fname); 2174 write_if_changed(&buf, fname);
2175 } 2175 }
2176 2176
2177 if (dump_write) 2177 if (dump_write)
2178 write_dump(dump_write); 2178 write_dump(dump_write);
2179 if (sec_mismatch_count && !sec_mismatch_verbose) 2179 if (sec_mismatch_count && !sec_mismatch_verbose)
2180 warn("modpost: Found %d section mismatch(es).\n" 2180 warn("modpost: Found %d section mismatch(es).\n"
2181 "To see full details build your kernel with:\n" 2181 "To see full details build your kernel with:\n"
2182 "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n", 2182 "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
2183 sec_mismatch_count); 2183 sec_mismatch_count);
2184 2184
2185 if (markers_read) 2185 if (markers_read)
2186 read_markers(markers_read); 2186 read_markers(markers_read);
2187 2187
2188 if (markers_write) 2188 if (markers_write)
2189 write_markers(markers_write); 2189 write_markers(markers_write);
2190 2190
2191 return err; 2191 return err;
2192 } 2192 }
2193 2193
scripts/selinux/mdp/mdp.c
1 /* 1 /*
2 * 2 *
3 * mdp - make dummy policy 3 * mdp - make dummy policy
4 * 4 *
5 * When pointed at a kernel tree, builds a dummy policy for that kernel 5 * When pointed at a kernel tree, builds a dummy policy for that kernel
6 * with exactly one type with full rights to itself. 6 * with exactly one type with full rights to itself.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 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 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 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 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 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 21 *
22 * Copyright (C) IBM Corporation, 2006 22 * Copyright (C) IBM Corporation, 2006
23 * 23 *
24 * Authors: Serge E. Hallyn <serue@us.ibm.com> 24 * Authors: Serge E. Hallyn <serue@us.ibm.com>
25 */ 25 */
26 26
27 #include <stdio.h> 27 #include <stdio.h>
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <unistd.h> 29 #include <unistd.h>
30 #include <string.h> 30 #include <string.h>
31 31
32 #include "flask.h" 32 #include "flask.h"
33 33
34 void usage(char *name) 34 static void usage(char *name)
35 { 35 {
36 printf("usage: %s [-m] policy_file context_file\n", name); 36 printf("usage: %s [-m] policy_file context_file\n", name);
37 exit(1); 37 exit(1);
38 } 38 }
39 39
40 void find_common_name(char *cname, char *dest, int len) 40 static void find_common_name(char *cname, char *dest, int len)
41 { 41 {
42 char *start, *end; 42 char *start, *end;
43 43
44 start = strchr(cname, '_')+1; 44 start = strchr(cname, '_')+1;
45 end = strchr(start, '_'); 45 end = strchr(start, '_');
46 if (!start || !end || start-cname > len || end-start > len) { 46 if (!start || !end || start-cname > len || end-start > len) {
47 printf("Error with commons defines\n"); 47 printf("Error with commons defines\n");
48 exit(1); 48 exit(1);
49 } 49 }
50 strncpy(dest, start, end-start); 50 strncpy(dest, start, end-start);
51 dest[end-start] = '\0'; 51 dest[end-start] = '\0';
52 } 52 }
53 53
54 #define S_(x) x, 54 #define S_(x) x,
55 static char *classlist[] = { 55 static char *classlist[] = {
56 #include "class_to_string.h" 56 #include "class_to_string.h"
57 NULL 57 NULL
58 }; 58 };
59 #undef S_ 59 #undef S_
60 60
61 #include "initial_sid_to_string.h" 61 #include "initial_sid_to_string.h"
62 62
63 #define TB_(x) char *x[] = { 63 #define TB_(x) char *x[] = {
64 #define TE_(x) NULL }; 64 #define TE_(x) NULL };
65 #define S_(x) x, 65 #define S_(x) x,
66 #include "common_perm_to_string.h" 66 #include "common_perm_to_string.h"
67 #undef TB_ 67 #undef TB_
68 #undef TE_ 68 #undef TE_
69 #undef S_ 69 #undef S_
70 70
71 struct common { 71 struct common {
72 char *cname; 72 char *cname;
73 char **perms; 73 char **perms;
74 }; 74 };
75 struct common common[] = { 75 struct common common[] = {
76 #define TB_(x) { #x, x }, 76 #define TB_(x) { #x, x },
77 #define S_(x) 77 #define S_(x)
78 #define TE_(x) 78 #define TE_(x)
79 #include "common_perm_to_string.h" 79 #include "common_perm_to_string.h"
80 #undef TB_ 80 #undef TB_
81 #undef TE_ 81 #undef TE_
82 #undef S_ 82 #undef S_
83 }; 83 };
84 84
85 #define S_(x, y, z) {x, #y}, 85 #define S_(x, y, z) {x, #y},
86 struct av_inherit { 86 struct av_inherit {
87 int class; 87 int class;
88 char *common; 88 char *common;
89 }; 89 };
90 struct av_inherit av_inherit[] = { 90 struct av_inherit av_inherit[] = {
91 #include "av_inherit.h" 91 #include "av_inherit.h"
92 }; 92 };
93 #undef S_ 93 #undef S_
94 94
95 #include "av_permissions.h" 95 #include "av_permissions.h"
96 #define S_(x, y, z) {x, y, z}, 96 #define S_(x, y, z) {x, y, z},
97 struct av_perms { 97 struct av_perms {
98 int class; 98 int class;
99 int perm_i; 99 int perm_i;
100 char *perm_s; 100 char *perm_s;
101 }; 101 };
102 struct av_perms av_perms[] = { 102 struct av_perms av_perms[] = {
103 #include "av_perm_to_string.h" 103 #include "av_perm_to_string.h"
104 }; 104 };
105 #undef S_ 105 #undef S_
106 106
107 int main(int argc, char *argv[]) 107 int main(int argc, char *argv[])
108 { 108 {
109 int i, j, mls = 0; 109 int i, j, mls = 0;
110 char **arg, *polout, *ctxout; 110 char **arg, *polout, *ctxout;
111 int classlist_len, initial_sid_to_string_len; 111 int classlist_len, initial_sid_to_string_len;
112 FILE *fout; 112 FILE *fout;
113 113
114 if (argc < 3) 114 if (argc < 3)
115 usage(argv[0]); 115 usage(argv[0]);
116 arg = argv+1; 116 arg = argv+1;
117 if (argc==4 && strcmp(argv[1], "-m") == 0) { 117 if (argc==4 && strcmp(argv[1], "-m") == 0) {
118 mls = 1; 118 mls = 1;
119 arg++; 119 arg++;
120 } 120 }
121 polout = *arg++; 121 polout = *arg++;
122 ctxout = *arg; 122 ctxout = *arg;
123 123
124 fout = fopen(polout, "w"); 124 fout = fopen(polout, "w");
125 if (!fout) { 125 if (!fout) {
126 printf("Could not open %s for writing\n", polout); 126 printf("Could not open %s for writing\n", polout);
127 usage(argv[0]); 127 usage(argv[0]);
128 } 128 }
129 129
130 classlist_len = sizeof(classlist) / sizeof(char *); 130 classlist_len = sizeof(classlist) / sizeof(char *);
131 /* print out the classes */ 131 /* print out the classes */
132 for (i=1; i < classlist_len; i++) { 132 for (i=1; i < classlist_len; i++) {
133 if(classlist[i]) 133 if(classlist[i])
134 fprintf(fout, "class %s\n", classlist[i]); 134 fprintf(fout, "class %s\n", classlist[i]);
135 else 135 else
136 fprintf(fout, "class user%d\n", i); 136 fprintf(fout, "class user%d\n", i);
137 } 137 }
138 fprintf(fout, "\n"); 138 fprintf(fout, "\n");
139 139
140 initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *); 140 initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
141 /* print out the sids */ 141 /* print out the sids */
142 for (i=1; i < initial_sid_to_string_len; i++) 142 for (i=1; i < initial_sid_to_string_len; i++)
143 fprintf(fout, "sid %s\n", initial_sid_to_string[i]); 143 fprintf(fout, "sid %s\n", initial_sid_to_string[i]);
144 fprintf(fout, "\n"); 144 fprintf(fout, "\n");
145 145
146 /* print out the commons */ 146 /* print out the commons */
147 for (i=0; i< sizeof(common)/sizeof(struct common); i++) { 147 for (i=0; i< sizeof(common)/sizeof(struct common); i++) {
148 char cname[101]; 148 char cname[101];
149 find_common_name(common[i].cname, cname, 100); 149 find_common_name(common[i].cname, cname, 100);
150 cname[100] = '\0'; 150 cname[100] = '\0';
151 fprintf(fout, "common %s\n{\n", cname); 151 fprintf(fout, "common %s\n{\n", cname);
152 for (j=0; common[i].perms[j]; j++) 152 for (j=0; common[i].perms[j]; j++)
153 fprintf(fout, "\t%s\n", common[i].perms[j]); 153 fprintf(fout, "\t%s\n", common[i].perms[j]);
154 fprintf(fout, "}\n\n"); 154 fprintf(fout, "}\n\n");
155 } 155 }
156 fprintf(fout, "\n"); 156 fprintf(fout, "\n");
157 157
158 /* print out the class permissions */ 158 /* print out the class permissions */
159 for (i=1; i < classlist_len; i++) { 159 for (i=1; i < classlist_len; i++) {
160 if (classlist[i]) { 160 if (classlist[i]) {
161 int firstperm = -1, numperms = 0; 161 int firstperm = -1, numperms = 0;
162 162
163 fprintf(fout, "class %s\n", classlist[i]); 163 fprintf(fout, "class %s\n", classlist[i]);
164 /* does it inherit from a common? */ 164 /* does it inherit from a common? */
165 for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++) 165 for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++)
166 if (av_inherit[j].class == i) 166 if (av_inherit[j].class == i)
167 fprintf(fout, "inherits %s\n", av_inherit[j].common); 167 fprintf(fout, "inherits %s\n", av_inherit[j].common);
168 168
169 for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) { 169 for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) {
170 if (av_perms[j].class == i) { 170 if (av_perms[j].class == i) {
171 if (firstperm == -1) 171 if (firstperm == -1)
172 firstperm = j; 172 firstperm = j;
173 numperms++; 173 numperms++;
174 } 174 }
175 } 175 }
176 if (!numperms) { 176 if (!numperms) {
177 fprintf(fout, "\n"); 177 fprintf(fout, "\n");
178 continue; 178 continue;
179 } 179 }
180 180
181 fprintf(fout, "{\n"); 181 fprintf(fout, "{\n");
182 /* print out the av_perms */ 182 /* print out the av_perms */
183 for (j=0; j < numperms; j++) { 183 for (j=0; j < numperms; j++) {
184 fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s); 184 fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s);
185 } 185 }
186 fprintf(fout, "}\n\n"); 186 fprintf(fout, "}\n\n");
187 } 187 }
188 } 188 }
189 fprintf(fout, "\n"); 189 fprintf(fout, "\n");
190 190
191 /* NOW PRINT OUT MLS STUFF */ 191 /* NOW PRINT OUT MLS STUFF */
192 if (mls) { 192 if (mls) {
193 printf("MLS not yet implemented\n"); 193 printf("MLS not yet implemented\n");
194 exit(1); 194 exit(1);
195 } 195 }
196 196
197 /* types, roles, and allows */ 197 /* types, roles, and allows */
198 fprintf(fout, "type base_t;\n"); 198 fprintf(fout, "type base_t;\n");
199 fprintf(fout, "role base_r types { base_t };\n"); 199 fprintf(fout, "role base_r types { base_t };\n");
200 for (i=1; i < classlist_len; i++) { 200 for (i=1; i < classlist_len; i++) {
201 if (classlist[i]) 201 if (classlist[i])
202 fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]); 202 fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]);
203 else 203 else
204 fprintf(fout, "allow base_t base_t:user%d *;\n", i); 204 fprintf(fout, "allow base_t base_t:user%d *;\n", i);
205 } 205 }
206 fprintf(fout, "user user_u roles { base_r };\n"); 206 fprintf(fout, "user user_u roles { base_r };\n");
207 fprintf(fout, "\n"); 207 fprintf(fout, "\n");
208 208
209 /* default sids */ 209 /* default sids */
210 for (i=1; i < initial_sid_to_string_len; i++) 210 for (i=1; i < initial_sid_to_string_len; i++)
211 fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]); 211 fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
212 fprintf(fout, "\n"); 212 fprintf(fout, "\n");
213 213
214 214
215 fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n"); 215 fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");
216 fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); 216 fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n");
217 fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n"); 217 fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");
218 fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n"); 218 fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");
219 fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); 219 fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n");
220 220
221 fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n"); 221 fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");
222 fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); 222 fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n");
223 223
224 fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); 224 fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n");
225 fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n"); 225 fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");
226 fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); 226 fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n");
227 227
228 fprintf(fout, "genfscon proc / user_u:base_r:base_t\n"); 228 fprintf(fout, "genfscon proc / user_u:base_r:base_t\n");
229 229
230 fclose(fout); 230 fclose(fout);
231 231
232 fout = fopen(ctxout, "w"); 232 fout = fopen(ctxout, "w");
233 if (!fout) { 233 if (!fout) {
234 printf("Wrote policy, but cannot open %s for writing\n", ctxout); 234 printf("Wrote policy, but cannot open %s for writing\n", ctxout);
235 usage(argv[0]); 235 usage(argv[0]);
236 } 236 }
237 fprintf(fout, "/ user_u:base_r:base_t\n"); 237 fprintf(fout, "/ user_u:base_r:base_t\n");
238 fprintf(fout, "/.* user_u:base_r:base_t\n"); 238 fprintf(fout, "/.* user_u:base_r:base_t\n");
239 fclose(fout); 239 fclose(fout);
240 240
241 return 0; 241 return 0;
242 } 242 }
243 243
1 #include <stdio.h> 1 #include <stdio.h>
2 #include <stdlib.h> 2 #include <stdlib.h>
3 #include <sys/types.h> 3 #include <sys/types.h>
4 #include <sys/stat.h> 4 #include <sys/stat.h>
5 #include <string.h> 5 #include <string.h>
6 #include <unistd.h> 6 #include <unistd.h>
7 #include <time.h> 7 #include <time.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <ctype.h> 10 #include <ctype.h>
11 #include <limits.h> 11 #include <limits.h>
12 12
13 /* 13 /*
14 * Original work by Jeff Garzik 14 * Original work by Jeff Garzik
15 * 15 *
16 * External file lists, symlink, pipe and fifo support by Thayne Harbaugh 16 * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
17 * Hard link support by Luciano Rocha 17 * Hard link support by Luciano Rocha
18 */ 18 */
19 19
20 #define xstr(s) #s 20 #define xstr(s) #s
21 #define str(s) xstr(s) 21 #define str(s) xstr(s)
22 22
23 static unsigned int offset; 23 static unsigned int offset;
24 static unsigned int ino = 721; 24 static unsigned int ino = 721;
25 25
26 struct file_handler { 26 struct file_handler {
27 const char *type; 27 const char *type;
28 int (*handler)(const char *line); 28 int (*handler)(const char *line);
29 }; 29 };
30 30
31 static void push_string(const char *name) 31 static void push_string(const char *name)
32 { 32 {
33 unsigned int name_len = strlen(name) + 1; 33 unsigned int name_len = strlen(name) + 1;
34 34
35 fputs(name, stdout); 35 fputs(name, stdout);
36 putchar(0); 36 putchar(0);
37 offset += name_len; 37 offset += name_len;
38 } 38 }
39 39
40 static void push_pad (void) 40 static void push_pad (void)
41 { 41 {
42 while (offset & 3) { 42 while (offset & 3) {
43 putchar(0); 43 putchar(0);
44 offset++; 44 offset++;
45 } 45 }
46 } 46 }
47 47
48 static void push_rest(const char *name) 48 static void push_rest(const char *name)
49 { 49 {
50 unsigned int name_len = strlen(name) + 1; 50 unsigned int name_len = strlen(name) + 1;
51 unsigned int tmp_ofs; 51 unsigned int tmp_ofs;
52 52
53 fputs(name, stdout); 53 fputs(name, stdout);
54 putchar(0); 54 putchar(0);
55 offset += name_len; 55 offset += name_len;
56 56
57 tmp_ofs = name_len + 110; 57 tmp_ofs = name_len + 110;
58 while (tmp_ofs & 3) { 58 while (tmp_ofs & 3) {
59 putchar(0); 59 putchar(0);
60 offset++; 60 offset++;
61 tmp_ofs++; 61 tmp_ofs++;
62 } 62 }
63 } 63 }
64 64
65 static void push_hdr(const char *s) 65 static void push_hdr(const char *s)
66 { 66 {
67 fputs(s, stdout); 67 fputs(s, stdout);
68 offset += 110; 68 offset += 110;
69 } 69 }
70 70
71 static void cpio_trailer(void) 71 static void cpio_trailer(void)
72 { 72 {
73 char s[256]; 73 char s[256];
74 const char name[] = "TRAILER!!!"; 74 const char name[] = "TRAILER!!!";
75 75
76 sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX" 76 sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
77 "%08X%08X%08X%08X%08X%08X%08X", 77 "%08X%08X%08X%08X%08X%08X%08X",
78 "070701", /* magic */ 78 "070701", /* magic */
79 0, /* ino */ 79 0, /* ino */
80 0, /* mode */ 80 0, /* mode */
81 (long) 0, /* uid */ 81 (long) 0, /* uid */
82 (long) 0, /* gid */ 82 (long) 0, /* gid */
83 1, /* nlink */ 83 1, /* nlink */
84 (long) 0, /* mtime */ 84 (long) 0, /* mtime */
85 0, /* filesize */ 85 0, /* filesize */
86 0, /* major */ 86 0, /* major */
87 0, /* minor */ 87 0, /* minor */
88 0, /* rmajor */ 88 0, /* rmajor */
89 0, /* rminor */ 89 0, /* rminor */
90 (unsigned)strlen(name)+1, /* namesize */ 90 (unsigned)strlen(name)+1, /* namesize */
91 0); /* chksum */ 91 0); /* chksum */
92 push_hdr(s); 92 push_hdr(s);
93 push_rest(name); 93 push_rest(name);
94 94
95 while (offset % 512) { 95 while (offset % 512) {
96 putchar(0); 96 putchar(0);
97 offset++; 97 offset++;
98 } 98 }
99 } 99 }
100 100
101 static int cpio_mkslink(const char *name, const char *target, 101 static int cpio_mkslink(const char *name, const char *target,
102 unsigned int mode, uid_t uid, gid_t gid) 102 unsigned int mode, uid_t uid, gid_t gid)
103 { 103 {
104 char s[256]; 104 char s[256];
105 time_t mtime = time(NULL); 105 time_t mtime = time(NULL);
106 106
107 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" 107 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
108 "%08X%08X%08X%08X%08X%08X%08X", 108 "%08X%08X%08X%08X%08X%08X%08X",
109 "070701", /* magic */ 109 "070701", /* magic */
110 ino++, /* ino */ 110 ino++, /* ino */
111 S_IFLNK | mode, /* mode */ 111 S_IFLNK | mode, /* mode */
112 (long) uid, /* uid */ 112 (long) uid, /* uid */
113 (long) gid, /* gid */ 113 (long) gid, /* gid */
114 1, /* nlink */ 114 1, /* nlink */
115 (long) mtime, /* mtime */ 115 (long) mtime, /* mtime */
116 (unsigned)strlen(target)+1, /* filesize */ 116 (unsigned)strlen(target)+1, /* filesize */
117 3, /* major */ 117 3, /* major */
118 1, /* minor */ 118 1, /* minor */
119 0, /* rmajor */ 119 0, /* rmajor */
120 0, /* rminor */ 120 0, /* rminor */
121 (unsigned)strlen(name) + 1,/* namesize */ 121 (unsigned)strlen(name) + 1,/* namesize */
122 0); /* chksum */ 122 0); /* chksum */
123 push_hdr(s); 123 push_hdr(s);
124 push_string(name); 124 push_string(name);
125 push_pad(); 125 push_pad();
126 push_string(target); 126 push_string(target);
127 push_pad(); 127 push_pad();
128 return 0; 128 return 0;
129 } 129 }
130 130
131 static int cpio_mkslink_line(const char *line) 131 static int cpio_mkslink_line(const char *line)
132 { 132 {
133 char name[PATH_MAX + 1]; 133 char name[PATH_MAX + 1];
134 char target[PATH_MAX + 1]; 134 char target[PATH_MAX + 1];
135 unsigned int mode; 135 unsigned int mode;
136 int uid; 136 int uid;
137 int gid; 137 int gid;
138 int rc = -1; 138 int rc = -1;
139 139
140 if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) { 140 if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
141 fprintf(stderr, "Unrecognized dir format '%s'", line); 141 fprintf(stderr, "Unrecognized dir format '%s'", line);
142 goto fail; 142 goto fail;
143 } 143 }
144 rc = cpio_mkslink(name, target, mode, uid, gid); 144 rc = cpio_mkslink(name, target, mode, uid, gid);
145 fail: 145 fail:
146 return rc; 146 return rc;
147 } 147 }
148 148
149 static int cpio_mkgeneric(const char *name, unsigned int mode, 149 static int cpio_mkgeneric(const char *name, unsigned int mode,
150 uid_t uid, gid_t gid) 150 uid_t uid, gid_t gid)
151 { 151 {
152 char s[256]; 152 char s[256];
153 time_t mtime = time(NULL); 153 time_t mtime = time(NULL);
154 154
155 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" 155 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
156 "%08X%08X%08X%08X%08X%08X%08X", 156 "%08X%08X%08X%08X%08X%08X%08X",
157 "070701", /* magic */ 157 "070701", /* magic */
158 ino++, /* ino */ 158 ino++, /* ino */
159 mode, /* mode */ 159 mode, /* mode */
160 (long) uid, /* uid */ 160 (long) uid, /* uid */
161 (long) gid, /* gid */ 161 (long) gid, /* gid */
162 2, /* nlink */ 162 2, /* nlink */
163 (long) mtime, /* mtime */ 163 (long) mtime, /* mtime */
164 0, /* filesize */ 164 0, /* filesize */
165 3, /* major */ 165 3, /* major */
166 1, /* minor */ 166 1, /* minor */
167 0, /* rmajor */ 167 0, /* rmajor */
168 0, /* rminor */ 168 0, /* rminor */
169 (unsigned)strlen(name) + 1,/* namesize */ 169 (unsigned)strlen(name) + 1,/* namesize */
170 0); /* chksum */ 170 0); /* chksum */
171 push_hdr(s); 171 push_hdr(s);
172 push_rest(name); 172 push_rest(name);
173 return 0; 173 return 0;
174 } 174 }
175 175
176 enum generic_types { 176 enum generic_types {
177 GT_DIR, 177 GT_DIR,
178 GT_PIPE, 178 GT_PIPE,
179 GT_SOCK 179 GT_SOCK
180 }; 180 };
181 181
182 struct generic_type { 182 struct generic_type {
183 const char *type; 183 const char *type;
184 mode_t mode; 184 mode_t mode;
185 }; 185 };
186 186
187 static struct generic_type generic_type_table[] = { 187 static struct generic_type generic_type_table[] = {
188 [GT_DIR] = { 188 [GT_DIR] = {
189 .type = "dir", 189 .type = "dir",
190 .mode = S_IFDIR 190 .mode = S_IFDIR
191 }, 191 },
192 [GT_PIPE] = { 192 [GT_PIPE] = {
193 .type = "pipe", 193 .type = "pipe",
194 .mode = S_IFIFO 194 .mode = S_IFIFO
195 }, 195 },
196 [GT_SOCK] = { 196 [GT_SOCK] = {
197 .type = "sock", 197 .type = "sock",
198 .mode = S_IFSOCK 198 .mode = S_IFSOCK
199 } 199 }
200 }; 200 };
201 201
202 static int cpio_mkgeneric_line(const char *line, enum generic_types gt) 202 static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
203 { 203 {
204 char name[PATH_MAX + 1]; 204 char name[PATH_MAX + 1];
205 unsigned int mode; 205 unsigned int mode;
206 int uid; 206 int uid;
207 int gid; 207 int gid;
208 int rc = -1; 208 int rc = -1;
209 209
210 if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) { 210 if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
211 fprintf(stderr, "Unrecognized %s format '%s'", 211 fprintf(stderr, "Unrecognized %s format '%s'",
212 line, generic_type_table[gt].type); 212 line, generic_type_table[gt].type);
213 goto fail; 213 goto fail;
214 } 214 }
215 mode |= generic_type_table[gt].mode; 215 mode |= generic_type_table[gt].mode;
216 rc = cpio_mkgeneric(name, mode, uid, gid); 216 rc = cpio_mkgeneric(name, mode, uid, gid);
217 fail: 217 fail:
218 return rc; 218 return rc;
219 } 219 }
220 220
221 static int cpio_mkdir_line(const char *line) 221 static int cpio_mkdir_line(const char *line)
222 { 222 {
223 return cpio_mkgeneric_line(line, GT_DIR); 223 return cpio_mkgeneric_line(line, GT_DIR);
224 } 224 }
225 225
226 static int cpio_mkpipe_line(const char *line) 226 static int cpio_mkpipe_line(const char *line)
227 { 227 {
228 return cpio_mkgeneric_line(line, GT_PIPE); 228 return cpio_mkgeneric_line(line, GT_PIPE);
229 } 229 }
230 230
231 static int cpio_mksock_line(const char *line) 231 static int cpio_mksock_line(const char *line)
232 { 232 {
233 return cpio_mkgeneric_line(line, GT_SOCK); 233 return cpio_mkgeneric_line(line, GT_SOCK);
234 } 234 }
235 235
236 static int cpio_mknod(const char *name, unsigned int mode, 236 static int cpio_mknod(const char *name, unsigned int mode,
237 uid_t uid, gid_t gid, char dev_type, 237 uid_t uid, gid_t gid, char dev_type,
238 unsigned int maj, unsigned int min) 238 unsigned int maj, unsigned int min)
239 { 239 {
240 char s[256]; 240 char s[256];
241 time_t mtime = time(NULL); 241 time_t mtime = time(NULL);
242 242
243 if (dev_type == 'b') 243 if (dev_type == 'b')
244 mode |= S_IFBLK; 244 mode |= S_IFBLK;
245 else 245 else
246 mode |= S_IFCHR; 246 mode |= S_IFCHR;
247 247
248 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" 248 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
249 "%08X%08X%08X%08X%08X%08X%08X", 249 "%08X%08X%08X%08X%08X%08X%08X",
250 "070701", /* magic */ 250 "070701", /* magic */
251 ino++, /* ino */ 251 ino++, /* ino */
252 mode, /* mode */ 252 mode, /* mode */
253 (long) uid, /* uid */ 253 (long) uid, /* uid */
254 (long) gid, /* gid */ 254 (long) gid, /* gid */
255 1, /* nlink */ 255 1, /* nlink */
256 (long) mtime, /* mtime */ 256 (long) mtime, /* mtime */
257 0, /* filesize */ 257 0, /* filesize */
258 3, /* major */ 258 3, /* major */
259 1, /* minor */ 259 1, /* minor */
260 maj, /* rmajor */ 260 maj, /* rmajor */
261 min, /* rminor */ 261 min, /* rminor */
262 (unsigned)strlen(name) + 1,/* namesize */ 262 (unsigned)strlen(name) + 1,/* namesize */
263 0); /* chksum */ 263 0); /* chksum */
264 push_hdr(s); 264 push_hdr(s);
265 push_rest(name); 265 push_rest(name);
266 return 0; 266 return 0;
267 } 267 }
268 268
269 static int cpio_mknod_line(const char *line) 269 static int cpio_mknod_line(const char *line)
270 { 270 {
271 char name[PATH_MAX + 1]; 271 char name[PATH_MAX + 1];
272 unsigned int mode; 272 unsigned int mode;
273 int uid; 273 int uid;
274 int gid; 274 int gid;
275 char dev_type; 275 char dev_type;
276 unsigned int maj; 276 unsigned int maj;
277 unsigned int min; 277 unsigned int min;
278 int rc = -1; 278 int rc = -1;
279 279
280 if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u", 280 if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
281 name, &mode, &uid, &gid, &dev_type, &maj, &min)) { 281 name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
282 fprintf(stderr, "Unrecognized nod format '%s'", line); 282 fprintf(stderr, "Unrecognized nod format '%s'", line);
283 goto fail; 283 goto fail;
284 } 284 }
285 rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min); 285 rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);
286 fail: 286 fail:
287 return rc; 287 return rc;
288 } 288 }
289 289
290 static int cpio_mkfile(const char *name, const char *location, 290 static int cpio_mkfile(const char *name, const char *location,
291 unsigned int mode, uid_t uid, gid_t gid, 291 unsigned int mode, uid_t uid, gid_t gid,
292 unsigned int nlinks) 292 unsigned int nlinks)
293 { 293 {
294 char s[256]; 294 char s[256];
295 char *filebuf = NULL; 295 char *filebuf = NULL;
296 struct stat buf; 296 struct stat buf;
297 long size; 297 long size;
298 int file = -1; 298 int file = -1;
299 int retval; 299 int retval;
300 int rc = -1; 300 int rc = -1;
301 int namesize; 301 int namesize;
302 int i; 302 int i;
303 303
304 mode |= S_IFREG; 304 mode |= S_IFREG;
305 305
306 retval = stat (location, &buf); 306 retval = stat (location, &buf);
307 if (retval) { 307 if (retval) {
308 fprintf (stderr, "File %s could not be located\n", location); 308 fprintf (stderr, "File %s could not be located\n", location);
309 goto error; 309 goto error;
310 } 310 }
311 311
312 file = open (location, O_RDONLY); 312 file = open (location, O_RDONLY);
313 if (file < 0) { 313 if (file < 0) {
314 fprintf (stderr, "File %s could not be opened for reading\n", location); 314 fprintf (stderr, "File %s could not be opened for reading\n", location);
315 goto error; 315 goto error;
316 } 316 }
317 317
318 filebuf = malloc(buf.st_size); 318 filebuf = malloc(buf.st_size);
319 if (!filebuf) { 319 if (!filebuf) {
320 fprintf (stderr, "out of memory\n"); 320 fprintf (stderr, "out of memory\n");
321 goto error; 321 goto error;
322 } 322 }
323 323
324 retval = read (file, filebuf, buf.st_size); 324 retval = read (file, filebuf, buf.st_size);
325 if (retval < 0) { 325 if (retval < 0) {
326 fprintf (stderr, "Can not read %s file\n", location); 326 fprintf (stderr, "Can not read %s file\n", location);
327 goto error; 327 goto error;
328 } 328 }
329 329
330 size = 0; 330 size = 0;
331 for (i = 1; i <= nlinks; i++) { 331 for (i = 1; i <= nlinks; i++) {
332 /* data goes on last link */ 332 /* data goes on last link */
333 if (i == nlinks) size = buf.st_size; 333 if (i == nlinks) size = buf.st_size;
334 334
335 namesize = strlen(name) + 1; 335 namesize = strlen(name) + 1;
336 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" 336 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
337 "%08lX%08X%08X%08X%08X%08X%08X", 337 "%08lX%08X%08X%08X%08X%08X%08X",
338 "070701", /* magic */ 338 "070701", /* magic */
339 ino, /* ino */ 339 ino, /* ino */
340 mode, /* mode */ 340 mode, /* mode */
341 (long) uid, /* uid */ 341 (long) uid, /* uid */
342 (long) gid, /* gid */ 342 (long) gid, /* gid */
343 nlinks, /* nlink */ 343 nlinks, /* nlink */
344 (long) buf.st_mtime, /* mtime */ 344 (long) buf.st_mtime, /* mtime */
345 size, /* filesize */ 345 size, /* filesize */
346 3, /* major */ 346 3, /* major */
347 1, /* minor */ 347 1, /* minor */
348 0, /* rmajor */ 348 0, /* rmajor */
349 0, /* rminor */ 349 0, /* rminor */
350 namesize, /* namesize */ 350 namesize, /* namesize */
351 0); /* chksum */ 351 0); /* chksum */
352 push_hdr(s); 352 push_hdr(s);
353 push_string(name); 353 push_string(name);
354 push_pad(); 354 push_pad();
355 355
356 if (size) { 356 if (size) {
357 fwrite(filebuf, size, 1, stdout); 357 fwrite(filebuf, size, 1, stdout);
358 offset += size; 358 offset += size;
359 push_pad(); 359 push_pad();
360 } 360 }
361 361
362 name += namesize; 362 name += namesize;
363 } 363 }
364 ino++; 364 ino++;
365 rc = 0; 365 rc = 0;
366 366
367 error: 367 error:
368 if (filebuf) free(filebuf); 368 if (filebuf) free(filebuf);
369 if (file >= 0) close(file); 369 if (file >= 0) close(file);
370 return rc; 370 return rc;
371 } 371 }
372 372
373 static char *cpio_replace_env(char *new_location) 373 static char *cpio_replace_env(char *new_location)
374 { 374 {
375 char expanded[PATH_MAX + 1]; 375 char expanded[PATH_MAX + 1];
376 char env_var[PATH_MAX + 1]; 376 char env_var[PATH_MAX + 1];
377 char *start; 377 char *start;
378 char *end; 378 char *end;
379 379
380 for (start = NULL; (start = strstr(new_location, "${")); ) { 380 for (start = NULL; (start = strstr(new_location, "${")); ) {
381 end = strchr(start, '}'); 381 end = strchr(start, '}');
382 if (start < end) { 382 if (start < end) {
383 *env_var = *expanded = '\0'; 383 *env_var = *expanded = '\0';
384 strncat(env_var, start + 2, end - start - 2); 384 strncat(env_var, start + 2, end - start - 2);
385 strncat(expanded, new_location, start - new_location); 385 strncat(expanded, new_location, start - new_location);
386 strncat(expanded, getenv(env_var), PATH_MAX); 386 strncat(expanded, getenv(env_var), PATH_MAX);
387 strncat(expanded, end + 1, PATH_MAX); 387 strncat(expanded, end + 1, PATH_MAX);
388 strncpy(new_location, expanded, PATH_MAX); 388 strncpy(new_location, expanded, PATH_MAX);
389 } else 389 } else
390 break; 390 break;
391 } 391 }
392 392
393 return new_location; 393 return new_location;
394 } 394 }
395 395
396 396
397 static int cpio_mkfile_line(const char *line) 397 static int cpio_mkfile_line(const char *line)
398 { 398 {
399 char name[PATH_MAX + 1]; 399 char name[PATH_MAX + 1];
400 char *dname = NULL; /* malloc'ed buffer for hard links */ 400 char *dname = NULL; /* malloc'ed buffer for hard links */
401 char location[PATH_MAX + 1]; 401 char location[PATH_MAX + 1];
402 unsigned int mode; 402 unsigned int mode;
403 int uid; 403 int uid;
404 int gid; 404 int gid;
405 int nlinks = 1; 405 int nlinks = 1;
406 int end = 0, dname_len = 0; 406 int end = 0, dname_len = 0;
407 int rc = -1; 407 int rc = -1;
408 408
409 if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) 409 if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
410 "s %o %d %d %n", 410 "s %o %d %d %n",
411 name, location, &mode, &uid, &gid, &end)) { 411 name, location, &mode, &uid, &gid, &end)) {
412 fprintf(stderr, "Unrecognized file format '%s'", line); 412 fprintf(stderr, "Unrecognized file format '%s'", line);
413 goto fail; 413 goto fail;
414 } 414 }
415 if (end && isgraph(line[end])) { 415 if (end && isgraph(line[end])) {
416 int len; 416 int len;
417 int nend; 417 int nend;
418 418
419 dname = malloc(strlen(line)); 419 dname = malloc(strlen(line));
420 if (!dname) { 420 if (!dname) {
421 fprintf (stderr, "out of memory (%d)\n", dname_len); 421 fprintf (stderr, "out of memory (%d)\n", dname_len);
422 goto fail; 422 goto fail;
423 } 423 }
424 424
425 dname_len = strlen(name) + 1; 425 dname_len = strlen(name) + 1;
426 memcpy(dname, name, dname_len); 426 memcpy(dname, name, dname_len);
427 427
428 do { 428 do {
429 nend = 0; 429 nend = 0;
430 if (sscanf(line + end, "%" str(PATH_MAX) "s %n", 430 if (sscanf(line + end, "%" str(PATH_MAX) "s %n",
431 name, &nend) < 1) 431 name, &nend) < 1)
432 break; 432 break;
433 len = strlen(name) + 1; 433 len = strlen(name) + 1;
434 memcpy(dname + dname_len, name, len); 434 memcpy(dname + dname_len, name, len);
435 dname_len += len; 435 dname_len += len;
436 nlinks++; 436 nlinks++;
437 end += nend; 437 end += nend;
438 } while (isgraph(line[end])); 438 } while (isgraph(line[end]));
439 } else { 439 } else {
440 dname = name; 440 dname = name;
441 } 441 }
442 rc = cpio_mkfile(dname, cpio_replace_env(location), 442 rc = cpio_mkfile(dname, cpio_replace_env(location),
443 mode, uid, gid, nlinks); 443 mode, uid, gid, nlinks);
444 fail: 444 fail:
445 if (dname_len) free(dname); 445 if (dname_len) free(dname);
446 return rc; 446 return rc;
447 } 447 }
448 448
449 void usage(const char *prog) 449 static void usage(const char *prog)
450 { 450 {
451 fprintf(stderr, "Usage:\n" 451 fprintf(stderr, "Usage:\n"
452 "\t%s <cpio_list>\n" 452 "\t%s <cpio_list>\n"
453 "\n" 453 "\n"
454 "<cpio_list> is a file containing newline separated entries that\n" 454 "<cpio_list> is a file containing newline separated entries that\n"
455 "describe the files to be included in the initramfs archive:\n" 455 "describe the files to be included in the initramfs archive:\n"
456 "\n" 456 "\n"
457 "# a comment\n" 457 "# a comment\n"
458 "file <name> <location> <mode> <uid> <gid> [<hard links>]\n" 458 "file <name> <location> <mode> <uid> <gid> [<hard links>]\n"
459 "dir <name> <mode> <uid> <gid>\n" 459 "dir <name> <mode> <uid> <gid>\n"
460 "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n" 460 "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
461 "slink <name> <target> <mode> <uid> <gid>\n" 461 "slink <name> <target> <mode> <uid> <gid>\n"
462 "pipe <name> <mode> <uid> <gid>\n" 462 "pipe <name> <mode> <uid> <gid>\n"
463 "sock <name> <mode> <uid> <gid>\n" 463 "sock <name> <mode> <uid> <gid>\n"
464 "\n" 464 "\n"
465 "<name> name of the file/dir/nod/etc in the archive\n" 465 "<name> name of the file/dir/nod/etc in the archive\n"
466 "<location> location of the file in the current filesystem\n" 466 "<location> location of the file in the current filesystem\n"
467 " expands shell variables quoted with ${}\n" 467 " expands shell variables quoted with ${}\n"
468 "<target> link target\n" 468 "<target> link target\n"
469 "<mode> mode/permissions of the file\n" 469 "<mode> mode/permissions of the file\n"
470 "<uid> user id (0=root)\n" 470 "<uid> user id (0=root)\n"
471 "<gid> group id (0=root)\n" 471 "<gid> group id (0=root)\n"
472 "<dev_type> device type (b=block, c=character)\n" 472 "<dev_type> device type (b=block, c=character)\n"
473 "<maj> major number of nod\n" 473 "<maj> major number of nod\n"
474 "<min> minor number of nod\n" 474 "<min> minor number of nod\n"
475 "<hard links> space separated list of other links to file\n" 475 "<hard links> space separated list of other links to file\n"
476 "\n" 476 "\n"
477 "example:\n" 477 "example:\n"
478 "# A simple initramfs\n" 478 "# A simple initramfs\n"
479 "dir /dev 0755 0 0\n" 479 "dir /dev 0755 0 0\n"
480 "nod /dev/console 0600 0 0 c 5 1\n" 480 "nod /dev/console 0600 0 0 c 5 1\n"
481 "dir /root 0700 0 0\n" 481 "dir /root 0700 0 0\n"
482 "dir /sbin 0755 0 0\n" 482 "dir /sbin 0755 0 0\n"
483 "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n", 483 "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n",
484 prog); 484 prog);
485 } 485 }
486 486
487 struct file_handler file_handler_table[] = { 487 struct file_handler file_handler_table[] = {
488 { 488 {
489 .type = "file", 489 .type = "file",
490 .handler = cpio_mkfile_line, 490 .handler = cpio_mkfile_line,
491 }, { 491 }, {
492 .type = "nod", 492 .type = "nod",
493 .handler = cpio_mknod_line, 493 .handler = cpio_mknod_line,
494 }, { 494 }, {
495 .type = "dir", 495 .type = "dir",
496 .handler = cpio_mkdir_line, 496 .handler = cpio_mkdir_line,
497 }, { 497 }, {
498 .type = "slink", 498 .type = "slink",
499 .handler = cpio_mkslink_line, 499 .handler = cpio_mkslink_line,
500 }, { 500 }, {
501 .type = "pipe", 501 .type = "pipe",
502 .handler = cpio_mkpipe_line, 502 .handler = cpio_mkpipe_line,
503 }, { 503 }, {
504 .type = "sock", 504 .type = "sock",
505 .handler = cpio_mksock_line, 505 .handler = cpio_mksock_line,
506 }, { 506 }, {
507 .type = NULL, 507 .type = NULL,
508 .handler = NULL, 508 .handler = NULL,
509 } 509 }
510 }; 510 };
511 511
512 #define LINE_SIZE (2 * PATH_MAX + 50) 512 #define LINE_SIZE (2 * PATH_MAX + 50)
513 513
514 int main (int argc, char *argv[]) 514 int main (int argc, char *argv[])
515 { 515 {
516 FILE *cpio_list; 516 FILE *cpio_list;
517 char line[LINE_SIZE]; 517 char line[LINE_SIZE];
518 char *args, *type; 518 char *args, *type;
519 int ec = 0; 519 int ec = 0;
520 int line_nr = 0; 520 int line_nr = 0;
521 521
522 if (2 != argc) { 522 if (2 != argc) {
523 usage(argv[0]); 523 usage(argv[0]);
524 exit(1); 524 exit(1);
525 } 525 }
526 526
527 if (!strcmp(argv[1], "-")) 527 if (!strcmp(argv[1], "-"))
528 cpio_list = stdin; 528 cpio_list = stdin;
529 else if (! (cpio_list = fopen(argv[1], "r"))) { 529 else if (! (cpio_list = fopen(argv[1], "r"))) {
530 fprintf(stderr, "ERROR: unable to open '%s': %s\n\n", 530 fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",
531 argv[1], strerror(errno)); 531 argv[1], strerror(errno));
532 usage(argv[0]); 532 usage(argv[0]);
533 exit(1); 533 exit(1);
534 } 534 }
535 535
536 while (fgets(line, LINE_SIZE, cpio_list)) { 536 while (fgets(line, LINE_SIZE, cpio_list)) {
537 int type_idx; 537 int type_idx;
538 size_t slen = strlen(line); 538 size_t slen = strlen(line);
539 539
540 line_nr++; 540 line_nr++;
541 541
542 if ('#' == *line) { 542 if ('#' == *line) {
543 /* comment - skip to next line */ 543 /* comment - skip to next line */
544 continue; 544 continue;
545 } 545 }
546 546
547 if (! (type = strtok(line, " \t"))) { 547 if (! (type = strtok(line, " \t"))) {
548 fprintf(stderr, 548 fprintf(stderr,
549 "ERROR: incorrect format, could not locate file type line %d: '%s'\n", 549 "ERROR: incorrect format, could not locate file type line %d: '%s'\n",
550 line_nr, line); 550 line_nr, line);
551 ec = -1; 551 ec = -1;
552 break; 552 break;
553 } 553 }
554 554
555 if ('\n' == *type) { 555 if ('\n' == *type) {
556 /* a blank line */ 556 /* a blank line */
557 continue; 557 continue;
558 } 558 }
559 559
560 if (slen == strlen(type)) { 560 if (slen == strlen(type)) {
561 /* must be an empty line */ 561 /* must be an empty line */
562 continue; 562 continue;
563 } 563 }
564 564
565 if (! (args = strtok(NULL, "\n"))) { 565 if (! (args = strtok(NULL, "\n"))) {
566 fprintf(stderr, 566 fprintf(stderr,
567 "ERROR: incorrect format, newline required line %d: '%s'\n", 567 "ERROR: incorrect format, newline required line %d: '%s'\n",
568 line_nr, line); 568 line_nr, line);
569 ec = -1; 569 ec = -1;
570 } 570 }
571 571
572 for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) { 572 for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
573 int rc; 573 int rc;
574 if (! strcmp(line, file_handler_table[type_idx].type)) { 574 if (! strcmp(line, file_handler_table[type_idx].type)) {
575 if ((rc = file_handler_table[type_idx].handler(args))) { 575 if ((rc = file_handler_table[type_idx].handler(args))) {
576 ec = rc; 576 ec = rc;
577 fprintf(stderr, " line %d\n", line_nr); 577 fprintf(stderr, " line %d\n", line_nr);
578 } 578 }
579 break; 579 break;
580 } 580 }
581 } 581 }
582 582
583 if (NULL == file_handler_table[type_idx].type) { 583 if (NULL == file_handler_table[type_idx].type) {
584 fprintf(stderr, "unknown file type line %d: '%s'\n", 584 fprintf(stderr, "unknown file type line %d: '%s'\n",
585 line_nr, line); 585 line_nr, line);
586 } 586 }
587 } 587 }
588 if (ec == 0) 588 if (ec == 0)
589 cpio_trailer(); 589 cpio_trailer();
590 590
591 exit(ec); 591 exit(ec);
592 } 592 }
593 593