| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 | /* Support for relocating static PIE.   Copyright (C) 2017-2022 Free Software Foundation, Inc.   This file is part of the GNU C Library.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, see   <https://www.gnu.org/licenses/>.  */#define IS_IN_rtld      // force inline function calls#include <link.h>#include <elf.h>#include <dl-elf.h>#include <ldso.h>#if defined(__m68k__) || defined(__mips__) || defined(__xtensa__)#include <dl-startup.h>#endifextern ElfW(Addr) _dl_load_base;voidreloc_static_pie (ElfW(Addr) load_addr);voidreloc_static_pie(ElfW(Addr) load_addr){    int indx;    ElfW(Addr) got;    ElfW(Dyn) *dpnt;    struct elf_resolve tpnt_tmp;	struct elf_resolve *tpnt = &tpnt_tmp;    DL_BOOT_COMPUTE_GOT(got);    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);    _dl_memset(tpnt, 0, sizeof(struct elf_resolve));    tpnt->loadaddr = load_addr;    tpnt->dynamic_addr = dpnt;    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);#if defined(PERFORM_BOOTSTRAP_GOT)	/* some arches (like MIPS) we have to tweak the GOT before relocations */	PERFORM_BOOTSTRAP_GOT(tpnt);#endif#if !defined(__FDPIC__)    DL_RELOCATE_RELR(tpnt);#endif#if defined(ELF_MACHINE_PLTREL_OVERLAP)# define INDX_MAX 1#else# define INDX_MAX 2#endif    for (indx = 0; indx < INDX_MAX; indx++) {        unsigned long rel_addr, rel_size;        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :                           tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :			               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);        if (!rel_addr)            continue;        if((0 == indx) && relative_count) {			rel_size -= relative_count * sizeof(ELF_RELOC);            elf_machine_relative(load_addr, rel_addr, relative_count);			rel_addr += relative_count * sizeof(ELF_RELOC);        }#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS			{				ELF_RELOC *rpnt;				unsigned int i;				ElfW(Sym) *sym;				unsigned long symbol_addr;				int symtab_index;				unsigned long *reloc_addr;				/* Now parse the relocation information */				rpnt = (ELF_RELOC *) rel_addr;				for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {					reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset);					symtab_index = ELF_R_SYM(rpnt->r_info);					symbol_addr = 0;					sym = NULL;					if (symtab_index) {						ElfW(Sym) *symtab;						symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];						sym = &symtab[symtab_index];						symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);					}					/* Use this machine-specific macro to perform the actual relocation.  */					PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);				}			}#else			(void)rel_size;#endif    }    _dl_load_base = load_addr;}
 |