@@ -55,17 +55,35 @@ do { \
55
55
* Check that sizeof(device_id type) are consistent with size of section
56
56
* in .o file. If in-consistent then userspace and kernel does not agree
57
57
* on actual size which is a bug.
58
+ * Also verify that the final entry in the table is all zeros.
58
59
**/
59
- static void device_id_size_check (const char * modname , const char * device_id ,
60
- unsigned long size , unsigned long id_size )
60
+ static void device_id_check (const char * modname , const char * device_id ,
61
+ unsigned long size , unsigned long id_size ,
62
+ void * symval )
61
63
{
64
+ int i ;
65
+
62
66
if (size % id_size || size < id_size ) {
63
67
fatal ("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
64
68
"of the size of section __mod_%s_device_table=%lu.\n"
65
69
"Fix definition of struct %s_device_id "
66
70
"in mod_devicetable.h\n" ,
67
71
modname , device_id , id_size , device_id , size , device_id );
68
72
}
73
+ /* Verify last one is a terminator */
74
+ for (i = 0 ; i < id_size ; i ++ ) {
75
+ if (* (uint8_t * )(symval + size - id_size + i )) {
76
+ fprintf (stderr ,"%s: struct %s_device_id is %lu bytes. "
77
+ "The last of %lu is:\n" ,
78
+ modname , device_id , id_size , size / id_size );
79
+ for (i = 0 ; i < id_size ; i ++ )
80
+ fprintf (stderr ,"0x%02x " ,
81
+ * (uint8_t * )(symval + size - id_size + i ) );
82
+ fprintf (stderr ,"\n" );
83
+ fatal ("%s: struct %s_device_id is not terminated "
84
+ "with a NULL entry!\n" , modname , device_id );
85
+ }
86
+ }
69
87
}
70
88
71
89
/* USB is special because the bcdDevice can be matched against a numeric range */
@@ -168,7 +186,7 @@ static void do_usb_table(void *symval, unsigned long size,
168
186
unsigned int i ;
169
187
const unsigned long id_size = sizeof (struct usb_device_id );
170
188
171
- device_id_size_check (mod -> name , "usb" , size , id_size );
189
+ device_id_check (mod -> name , "usb" , size , id_size , symval );
172
190
173
191
/* Leave last one: it's the terminator. */
174
192
size -= id_size ;
@@ -535,7 +553,7 @@ static void do_table(void *symval, unsigned long size,
535
553
char alias [500 ];
536
554
int (* do_entry )(const char * , void * entry , char * alias ) = function ;
537
555
538
- device_id_size_check (mod -> name , device_id , size , id_size );
556
+ device_id_check (mod -> name , device_id , size , id_size , symval );
539
557
/* Leave last one: it's the terminator. */
540
558
size -= id_size ;
541
559
@@ -557,14 +575,21 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
557
575
Elf_Sym * sym , const char * symname )
558
576
{
559
577
void * symval ;
578
+ char * zeros = NULL ;
560
579
561
580
/* We're looking for a section relative symbol */
562
581
if (!sym -> st_shndx || sym -> st_shndx >= info -> hdr -> e_shnum )
563
582
return ;
564
583
565
- symval = (void * )info -> hdr
566
- + info -> sechdrs [sym -> st_shndx ].sh_offset
567
- + sym -> st_value ;
584
+ /* Handle all-NULL symbols allocated into .bss */
585
+ if (info -> sechdrs [sym -> st_shndx ].sh_type & SHT_NOBITS ) {
586
+ zeros = calloc (1 , sym -> st_size );
587
+ symval = zeros ;
588
+ } else {
589
+ symval = (void * )info -> hdr
590
+ + info -> sechdrs [sym -> st_shndx ].sh_offset
591
+ + sym -> st_value ;
592
+ }
568
593
569
594
if (sym_is (symname , "__mod_pci_device_table" ))
570
595
do_table (symval , sym -> st_size ,
@@ -637,6 +662,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
637
662
do_table (symval , sym -> st_size ,
638
663
sizeof (struct ssb_device_id ), "ssb" ,
639
664
do_ssb_entry , mod );
665
+ free (zeros );
640
666
}
641
667
642
668
/* Now add out buffered information to the generated C source */
0 commit comments