Consolidate GOT creation in build_got_entries
Currently GOT/PLT creation happens in two locations depending on whether the GOT/PLT [entry] is required by the symbol or the relocation: - bind_exe_dynsym for relocations to undefined symbol - build_got_entries/put_got_entry for relocations that require a GOT/PLT entry This commit consolidate GOT/PLT creation in build_got_entries by reducing bind_exe_dynsym's job to create a dynamic symbol for undefined symbols. build_got_entries then invoke put_got_entry if the symbol being relocated is undefined or the relocation asks for a PLT or GOT [entry]. put_got_entry is also modified to only export a symbol in the dynamic symbol table when we are in the case of PLT/GOT [entry] required by the relocation (since undefined symbol are already exported by bind_exe_dynsym).
This commit is contained in:
		
							parent
							
								
									1c811a4d1d
								
							
						
					
					
						commit
						a11b0a67e3
					
				
					 2 changed files with 25 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -13,7 +13,7 @@ ST_DATA struct reloc_info relocs_info[] = {
 | 
			
		|||
    INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_THM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_PREL31, 1, AUTO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_ABS32, 0, NO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_ABS32, 0, AUTO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_GOTPLT_ENTRY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0)
 | 
			
		||||
    INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										40
									
								
								tccelf.c
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								tccelf.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -819,19 +819,19 @@ static void build_got(TCCState *s1)
 | 
			
		|||
   in s1->symtab. When creating the dynamic symbol table entry for the GOT
 | 
			
		||||
   relocation, use 'size' and 'info' for the corresponding symbol metadata.
 | 
			
		||||
   Returns the offset of the GOT or (if any) PLT entry. */
 | 
			
		||||
static unsigned long put_got_entry(TCCState *s1,
 | 
			
		||||
				   int reloc_type, unsigned long size, int info,
 | 
			
		||||
				   int sym_index)
 | 
			
		||||
static unsigned long put_got_entry(TCCState *s1, int dyn_reloc_type,
 | 
			
		||||
                                   int reloc_type, unsigned long size,
 | 
			
		||||
                                   int info, int sym_index)
 | 
			
		||||
{
 | 
			
		||||
    int index, need_plt_entry = 0;
 | 
			
		||||
    const char *name;
 | 
			
		||||
    ElfW(Sym) *sym;
 | 
			
		||||
    ElfW(Sym) *sym, *esym;
 | 
			
		||||
    unsigned long offset;
 | 
			
		||||
    int *ptr;
 | 
			
		||||
    size_t got_offset;
 | 
			
		||||
    struct sym_attr *symattr;
 | 
			
		||||
 | 
			
		||||
    need_plt_entry = (reloc_type == R_JMP_SLOT);
 | 
			
		||||
    need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
 | 
			
		||||
 | 
			
		||||
    if (!s1->got)
 | 
			
		||||
        build_got(s1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1001,13 +1001,19 @@ static unsigned long put_got_entry(TCCState *s1,
 | 
			
		|||
        /* create the dynamic symbol table entry that the relocation refers to
 | 
			
		||||
           in its r_info field to identify the symbol */
 | 
			
		||||
	/* XXX This might generate multiple syms for name.  */
 | 
			
		||||
        index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx,
 | 
			
		||||
                            name);
 | 
			
		||||
        put_elf_reloc(s1->dynsym, s1->got, got_offset, reloc_type, index);
 | 
			
		||||
    } else {
 | 
			
		||||
	put_elf_reloc(symtab_section, s1->got, got_offset, reloc_type,
 | 
			
		||||
        index = find_elf_sym (s1->dynsym, name);
 | 
			
		||||
        if (index) {
 | 
			
		||||
            esym = (ElfW(Sym) *) s1->dynsym->data + index;
 | 
			
		||||
            esym->st_value = offset;
 | 
			
		||||
 | 
			
		||||
        } else if (s1->output_type == TCC_OUTPUT_MEMORY ||
 | 
			
		||||
                   relocs_info[reloc_type].gotplt_entry == ALWAYS_GOTPLT_ENTRY)
 | 
			
		||||
            index = put_elf_sym(s1->dynsym, offset, size, info, 0,
 | 
			
		||||
                                sym->st_shndx, name);
 | 
			
		||||
        put_elf_reloc(s1->dynsym, s1->got, got_offset, dyn_reloc_type, index);
 | 
			
		||||
    } else
 | 
			
		||||
	put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type,
 | 
			
		||||
                      sym_index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (need_plt_entry)
 | 
			
		||||
      return symattr->plt_offset;
 | 
			
		||||
| 
						 | 
				
			
			@ -1067,8 +1073,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
 | 
			
		|||
                reloc_type = R_JMP_SLOT;
 | 
			
		||||
            else
 | 
			
		||||
                reloc_type = R_GLOB_DAT;
 | 
			
		||||
            ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
 | 
			
		||||
                                sym_index);
 | 
			
		||||
            ofs = put_got_entry(s1, reloc_type, type, sym->st_size,
 | 
			
		||||
                                sym->st_info, sym_index);
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_RELOC
 | 
			
		||||
            printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -1420,15 +1426,17 @@ 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_got_entry(s1, R_JMP_SLOT, esym->st_size,
 | 
			
		||||
                                  ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
 | 
			
		||||
                                  sym - (ElfW(Sym) *)symtab_section->data);
 | 
			
		||||
                    put_elf_sym(s1->dynsym, 0, esym->st_size,
 | 
			
		||||
                                ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0,
 | 
			
		||||
                                name);
 | 
			
		||||
                } else if (type == STT_OBJECT) {
 | 
			
		||||
                    unsigned long offset;
 | 
			
		||||
                    ElfW(Sym) *dynsym;
 | 
			
		||||
                    offset = bss_section->data_offset;
 | 
			
		||||
                    /* XXX: which alignment ? */
 | 
			
		||||
                    offset = (offset + 16 - 1) & -16;
 | 
			
		||||
                    set_elf_sym (s1->symtab, offset, esym->st_size,
 | 
			
		||||
                                 esym->st_info, 0, bss_section->sh_num, name);
 | 
			
		||||
                    index = put_elf_sym(s1->dynsym, offset, esym->st_size,
 | 
			
		||||
                                        esym->st_info, 0, bss_section->sh_num,
 | 
			
		||||
                                        name);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue