Fix gawk miscompile
See testcase. Function pointer use was hosed when the destination function wasn't also called normally by the program.
This commit is contained in:
		
							parent
							
								
									cd9514abc4
								
							
						
					
					
						commit
						77d7ea04ac
					
				
					 5 changed files with 56 additions and 27 deletions
				
			
		|  | @ -56,12 +56,17 @@ int gotplt_entry_type (int reloc_type) | |||
|     switch (reloc_type) { | ||||
| 	case R_386_RELATIVE: | ||||
| 	case R_386_16: | ||||
|         case R_386_32: | ||||
| 	case R_386_GLOB_DAT: | ||||
| 	case R_386_JMP_SLOT: | ||||
| 	case R_386_COPY: | ||||
|             return NO_GOTPLT_ENTRY; | ||||
| 
 | ||||
|         case R_386_32: | ||||
| 	    /* This relocations shouldn't normally need GOT or PLT
 | ||||
| 	       slots if it weren't for simplicity in the code generator. | ||||
| 	       See our caller for comments.  */ | ||||
|             return AUTO_GOTPLT_ENTRY; | ||||
| 
 | ||||
| 	case R_386_PC16: | ||||
| 	case R_386_PC32: | ||||
|             return AUTO_GOTPLT_ENTRY; | ||||
|  |  | |||
							
								
								
									
										56
									
								
								tccelf.c
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								tccelf.c
									
										
									
									
									
								
							|  | @ -956,32 +956,39 @@ ST_FUNC void build_got_entries(TCCState *s1) | |||
|             sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | ||||
| 
 | ||||
|             if (gotplt_entry == NO_GOTPLT_ENTRY) { | ||||
| #ifdef TCC_TARGET_I386 | ||||
|                 if (type == R_386_32 && sym->st_shndx == SHN_UNDEF) { | ||||
|                     /* the i386 generator uses the plt address for function
 | ||||
|                        pointers into .so.  This may break pointer equality | ||||
|                        but helps to keep it simple */ | ||||
|                     char *name = (char *)symtab_section->link->data + sym->st_name; | ||||
|                     int index = find_elf_sym(s1->dynsymtab_section, name); | ||||
|                     ElfW(Sym) *esym = (ElfW(Sym) *)s1->dynsymtab_section->data + index; | ||||
|                     if (index | ||||
|                         && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC | ||||
|                             || (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE | ||||
|                                 && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) | ||||
|                         goto jmp_slot; | ||||
|                 } | ||||
| #endif | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             /* Automatically create PLT/GOT [entry] it is an undefined reference
 | ||||
|                (resolved at runtime), or the symbol is absolute, probably created | ||||
|                by tcc_add_symbol, and thus on 64-bit targets might be too far | ||||
|                from application code */ | ||||
|             /* Automatically create PLT/GOT [entry] if it is an undefined
 | ||||
| 	       reference (resolved at runtime), or the symbol is absolute, | ||||
| 	       probably created by tcc_add_symbol, and thus on 64-bit | ||||
| 	       targets might be too far from application code.  */ | ||||
|             if (gotplt_entry == AUTO_GOTPLT_ENTRY) { | ||||
|                 if (sym->st_shndx == SHN_UNDEF) { | ||||
|                     ElfW(Sym) *esym; | ||||
| 		    int dynindex; | ||||
|                     if (s1->output_type == TCC_OUTPUT_DLL && ! PCRELATIVE_DLLPLT) | ||||
|                         continue; | ||||
| 		    /* Relocations for UNDEF symbols would normally need
 | ||||
| 		       to be transferred into the executable or shared object. | ||||
| 		       If that were done AUTO_GOTPLT_ENTRY wouldn't exist. | ||||
| 		       But TCC doesn't do that (at least for exes), so we | ||||
| 		       need to resolve all such relocs locally.  And that | ||||
| 		       means PLT slots for functions in DLLs and COPY relocs for | ||||
| 		       data symbols.  COPY relocs were generated in | ||||
| 		       bind_exe_dynsyms (and the symbol adjusted to be defined), | ||||
| 		       and for functions we were generated a dynamic symbol | ||||
| 		       of function type.  */ | ||||
| 		    if (s1->dynsym) { | ||||
| 			/* dynsym isn't set for -run :-/  */ | ||||
| 			dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index; | ||||
| 			esym = (ElfW(Sym) *)s1->dynsym->data + dynindex; | ||||
| 			if (dynindex | ||||
| 			    && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC | ||||
| 				|| (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE | ||||
| 				    && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC))) | ||||
| 			    goto jmp_slot; | ||||
| 		    } | ||||
|                 } else if (!(sym->st_shndx == SHN_ABS && PTR_SIZE == 8)) | ||||
|                     continue; | ||||
|             } | ||||
|  | @ -994,9 +1001,7 @@ ST_FUNC void build_got_entries(TCCState *s1) | |||
|             } | ||||
| #endif | ||||
|             if (code_reloc(type)) { | ||||
| #ifdef TCC_TARGET_I386 | ||||
|             jmp_slot: | ||||
| #endif | ||||
|                 reloc_type = R_JMP_SLOT; | ||||
|             } else | ||||
|                 reloc_type = R_GLOB_DAT; | ||||
|  | @ -1278,9 +1283,12 @@ static void bind_exe_dynsyms(TCCState *s1) | |||
|                      * of the function wanted by the caller of dlsym instead of | ||||
|                      * the address of the function that would return that | ||||
|                      * address */ | ||||
|                     put_elf_sym(s1->dynsym, 0, esym->st_size, | ||||
|                                 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, | ||||
|                                 name); | ||||
|                     int dynindex | ||||
| 		      = put_elf_sym(s1->dynsym, 0, esym->st_size, | ||||
| 				    ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, | ||||
| 				    name); | ||||
| 		    int index = sym - (ElfW(Sym) *) symtab_section->data; | ||||
| 		    get_sym_attr(s1, index, 1)->dyn_index = dynindex; | ||||
|                 } else if (type == STT_OBJECT) { | ||||
|                     unsigned long offset; | ||||
|                     ElfW(Sym) *dynsym; | ||||
|  |  | |||
|  | @ -8,9 +8,13 @@ int fred(int p) | |||
| 
 | ||||
| int (*f)(int) = &fred; | ||||
| 
 | ||||
| /* To test what this is supposed to test the destination function
 | ||||
|    (fprint here) must not be called directly anywhere in the test.  */ | ||||
| int (*fprintfptr)(FILE *, const char *, ...) = &fprintf; | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
|    printf("%d\n", (*f)(24)); | ||||
|    fprintfptr(stdout, "%d\n", (*f)(24)); | ||||
| 
 | ||||
|    return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -34,6 +34,10 @@ ARGS = | |||
| 31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5 | ||||
| 46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c | ||||
| 
 | ||||
| # And some tests don't test the right thing with -run
 | ||||
| NORUN = | ||||
| 42_function_pointer.test : NORUN = true | ||||
| 
 | ||||
| # Some tests might need different flags
 | ||||
| 76_dollars_in_identifiers.test : TCCFLAGS += -fdollars-in-identifiers | ||||
| 
 | ||||
|  | @ -49,7 +53,12 @@ all test: $(filter-out $(SKIP),$(TESTS)) | |||
| %.test: %.c %.expect | ||||
| 	@echo Test: $*... | ||||
| # test -run
 | ||||
| 	@$(TCC) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true | ||||
| 	@if test -z "$(NORUN)"; then \
 | ||||
| 	    $(TCC) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true; \
 | ||||
| 	  else \
 | ||||
| 	    $(TCC) $< -o ./$*.exe $(FILTER) 2>&1 && \
 | ||||
| 	    ./$*.exe $(ARGS) >$*.output 2>&1 || true; \
 | ||||
| 	  fi | ||||
| 	@diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output | ||||
| 
 | ||||
| # automatically generate .expect files with gcc:
 | ||||
|  |  | |||
|  | @ -61,6 +61,9 @@ int gotplt_entry_type (int reloc_type) | |||
| 	case R_X86_64_RELATIVE: | ||||
|             return NO_GOTPLT_ENTRY; | ||||
| 
 | ||||
| 	/* The following relocs wouldn't normally need GOT or PLT
 | ||||
| 	   slots, but we need them for simplicity in the link | ||||
| 	   editor part.  See our caller for comments.  */ | ||||
|         case R_X86_64_32: | ||||
|         case R_X86_64_32S: | ||||
|         case R_X86_64_64: | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue