@@ -26,6 +26,7 @@ static unsigned int dispmod_flag = 0;
2626static int irx1_flag = 0 ;
2727static int br_conv = 0 ;
2828static int print_config = 0 ;
29+ static int allow_zero_text = 0 ;
2930// clang-format off
3031static const Opttable opttable [] =
3132{
@@ -42,6 +43,7 @@ static const Opttable opttable[] =
4243 { "--rb" , ARG_HAVEARG_NONE , 'f' , & br_conv },
4344 { "--relative-branch" , ARG_HAVEARG_NONE , 'f' , & br_conv },
4445 { "--print-internal-config" , ARG_HAVEARG_NONE , 'f' , & print_config },
46+ { "--allow-zero-text" , ARG_HAVEARG_NONE , 'f' , & allow_zero_text },
4547 { NULL , 0 , '\0' , NULL },
4648};
4749static const Opttable stripopttable [] =
@@ -56,13 +58,15 @@ static const Opttable stripopttable[] =
5658 { "--rb" , ARG_HAVEARG_NONE , 'f' , & br_conv },
5759 { "--relative-branch" , ARG_HAVEARG_NONE , 'f' , & br_conv },
5860 { "--print-internal-config" , ARG_HAVEARG_NONE , 'f' , & print_config },
61+ { "--allow-zero-text" , ARG_HAVEARG_NONE , 'f' , & allow_zero_text },
5962 { NULL , 0 , '\0' , NULL },
6063};
6164// clang-format on
6265
6366static void display_module_info (elf_file * elf );
6467static void convert_relative_branch_an_section (elf_section * relsect );
6568static void convert_relative_branch (elf_file * elf );
69+ static int check_zero_text_symbols (const char * source , const elf_file * elf );
6670
6771void usage (const char * myname )
6872{
@@ -79,7 +83,8 @@ void usage(const char *myname)
7983 " -o <elf_relocatable_nosymbol_output_file>\n"
8084 " -r <elf_relocatable_output_file>\n"
8185 " -e <entry_point_symbol>\n"
82- " --relative-branch or --rb\n" );
86+ " --relative-branch or --rb\n"
87+ " --allow-zero-text (skip check for .text symbols with value 0)\n" );
8388 if ( verbose )
8489 {
8590 printf (" -t <.text start address>\n"
@@ -223,6 +228,10 @@ int main(int argc, char **argv)
223228 {
224229 exit (1 );
225230 }
231+ if ( !allow_zero_text && check_zero_text_symbols (source , elf ) )
232+ {
233+ exit (1 );
234+ }
226235 if (
227236 ((elf -> ehp -> e_flags & EF_MIPS_MACH ) == EF_MIPS_MACH_5900 )
228237 && ((elf -> ehp -> e_flags & EF_MIPS_ARCH ) == EF_MIPS_ARCH_3 ) )
@@ -487,3 +496,79 @@ static void convert_relative_branch(elf_file *elf)
487496 }
488497 }
489498}
499+
500+ static int check_zero_text_symbols (const char * source , const elf_file * elf )
501+ {
502+ int text_idx ;
503+ int i ;
504+ int found ;
505+
506+ if ( elf -> scp == NULL )
507+ {
508+ return 0 ;
509+ }
510+
511+ /* Find the index of the .text section by name */
512+ text_idx = -1 ;
513+ for ( i = 1 ; i < elf -> ehp -> e_shnum ; i += 1 )
514+ {
515+ if ( elf -> scp [i ]-> name && strcmp (elf -> scp [i ]-> name , ".text" ) == 0 )
516+ {
517+ text_idx = i ;
518+ break ;
519+ }
520+ }
521+ if ( text_idx < 0 )
522+ {
523+ return 0 ; /* No .text section — nothing to check */
524+ }
525+
526+ found = 0 ;
527+ for ( i = 1 ; i < elf -> ehp -> e_shnum ; i += 1 )
528+ {
529+ elf_section * sect ;
530+ unsigned int nsyms ;
531+ unsigned int j ;
532+ elf_syment * * syms ;
533+
534+ sect = elf -> scp [i ];
535+ if ( sect -> shr .sh_type != SHT_SYMTAB || sect -> data == NULL || sect -> shr .sh_entsize == 0 )
536+ {
537+ continue ;
538+ }
539+ nsyms = sect -> shr .sh_size / sect -> shr .sh_entsize ;
540+ syms = (elf_syment * * )sect -> data ;
541+ for ( j = 1 ; j < nsyms ; j += 1 ) /* skip sym[0]: ELF null symbol */
542+ {
543+ elf_syment * sym ;
544+
545+ sym = syms [j ];
546+ /* _start is the IOP module entry point called via the .iopmod
547+ * header, never via a jal from within the module.
548+ * _ftext is a linker label at the start of .text, also never
549+ * the target of an intra-module jal. Both are safe at .text+0. */
550+ if ( sym -> name
551+ && (strcmp (sym -> name , "_start" ) == 0 || strcmp (sym -> name , "_ftext" ) == 0 ) )
552+ {
553+ continue ;
554+ }
555+ if ( (unsigned int )sym -> sym .st_shndx == (unsigned int )text_idx
556+ && (sym -> type == STT_FUNC || sym -> type == STT_NOTYPE )
557+ && sym -> sym .st_value == 0 )
558+ {
559+ fprintf (
560+ stderr ,
561+ "ERROR: %s: symbol '%s' (sym#%u) is in .text with value 0"
562+ " -- if this module has an export table, put exports.o"
563+ " first in IOP_OBJS and move _retonly after"
564+ " DECLARE_EXPORT_TABLE in exports.tab;"
565+ " otherwise use --allow-zero-text.\n" ,
566+ source ,
567+ (sym -> name && sym -> name [0 ]) ? sym -> name : "<unnamed>" ,
568+ j );
569+ found = 1 ;
570+ }
571+ }
572+ }
573+ return found ;
574+ }
0 commit comments