diff options
Diffstat (limited to 'ldso/ldso/frv/dl-sysdep.h')
-rw-r--r-- | ldso/ldso/frv/dl-sysdep.h | 437 |
1 files changed, 24 insertions, 413 deletions
diff --git a/ldso/ldso/frv/dl-sysdep.h b/ldso/ldso/frv/dl-sysdep.h index 46f8461f7..b121a934c 100644 --- a/ldso/ldso/frv/dl-sysdep.h +++ b/ldso/ldso/frv/dl-sysdep.h @@ -29,6 +29,9 @@ USA. */ */ #undef ELF_USES_RELOCA +/* JMPREL relocs are inside the DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP + #define DL_NO_COPY_RELOCS /* @@ -76,127 +79,10 @@ struct funcdesc_ht; segment, such that they are referenced with GOTOFF instead of GPREL, because GPREL needs the GOT to have already been relocated. */ +#undef SEND_EARLY_STDERR #define SEND_EARLY_STDERR(S) \ do { static char __s[] = (S); SEND_STDERR (__s); } while (0) -#include <bits/elf-fdpic.h> -#ifdef __USE_GNU -# include <link.h> -#else -# define __USE_GNU -# include <link.h> -# undef __USE_GNU -#endif -#include <dl-syscall.h> -#include <dl-string.h> - -/* These are declared in ldso.h, after it includes dl-elf.h that - includes ourselves. */ -extern void *_dl_malloc(int size); -extern void _dl_free(void *); -extern void _dl_dprintf(int, const char *, ...); - - -#ifndef _dl_assert -# define _dl_assert(expr) -#endif - -/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete - load map. */ -inline static void -__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, void *got_value, - struct elf32_fdpic_loadmap *map) -{ - if (map->version != 0) - { - SEND_EARLY_STDERR ("Invalid loadmap version number\n"); - _dl_exit(-1); - } - if (map->nsegs == 0) - { - SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); - _dl_exit(-1); - } - loadaddr->got_value = got_value; - loadaddr->map = map; -} - -/* Figure out how many LOAD segments there are in the given headers, - and allocate a block for the load map big enough for them. - got_value will be properly initialized later on, with INIT_GOT. */ -inline static int -__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt, - int pcnt) -{ - int count = 0, i; - size_t size; - - for (i = 0; i < pcnt; i++) - if (ppnt[i].p_type == PT_LOAD) - count++; - - loadaddr->got_value = 0; - - size = sizeof (struct elf32_fdpic_loadmap) - + sizeof (struct elf32_fdpic_loadseg) * count; - loadaddr->map = _dl_malloc (size); - if (! loadaddr->map) - _dl_exit (-1); - - loadaddr->map->version = 0; - loadaddr->map->nsegs = 0; - - return count; -} - -/* Incrementally initialize a load map. */ -inline static void -__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr, - Elf32_Phdr *phdr, int maxsegs) -{ - struct elf32_fdpic_loadseg *segdata; - - if (loadaddr.map->nsegs == maxsegs) - _dl_exit (-1); - - segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; - segdata->addr = (Elf32_Addr) addr; - segdata->p_vaddr = phdr->p_vaddr; - segdata->p_memsz = phdr->p_memsz; - -#if defined (__SUPPORT_LD_DEBUG__) - { - extern char *_dl_debug; - extern int _dl_debug_file; - if (_dl_debug) - _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", - loadaddr.map->nsegs-1, - segdata->p_vaddr, segdata->addr, segdata->p_memsz); - } -#endif -} - -inline static void __dl_loadaddr_unmap -(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht); - -/* Figure out whether the given address is in one of the mapped - segments. */ -inline static int -__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr) -{ - struct elf32_fdpic_loadmap *map = loadaddr.map; - int c; - - for (c = 0; c < map->nsegs; c++) - if ((void*)map->segs[c].addr <= p - && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) - return 1; - - return 0; -} - -inline static void * _dl_funcdesc_for (void *entry_point, void *got_value); - #define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr #define DL_RELOC_ADDR(ADDR, LOADADDR) \ @@ -235,6 +121,11 @@ inline static void * _dl_funcdesc_for (void *entry_point, void *got_value); #define DL_LOADADDR_BASE(LOADADDR) \ ((LOADADDR).got_value) +/* This is called from dladdr(), such that we map a function + descriptor's address to the function's entry point before trying to + find in which library it's defined. */ +#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS)) + #define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) @@ -272,300 +163,20 @@ while (0) (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) #endif -#include <dl-hash.h> +/* We want to return to dlsym() a function descriptor if the symbol + turns out to be a function. */ +#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \ + (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \ + && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \ + ? _dl_funcdesc_for (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr), \ + (TPNT)->loadaddr.got_value) \ + : DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr)) -/* The hashcode handling code below is heavily inspired in libiberty's - hashtab code, but with most adaptation points and support for - deleting elements removed. - - Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - Contributed by Vladimir Makarov (vmakarov@cygnus.com). */ - -inline static unsigned long -higher_prime_number (unsigned long n) -{ - /* These are primes that are near, but slightly smaller than, a - power of two. */ - static const unsigned long primes[] = { - (unsigned long) 7, - (unsigned long) 13, - (unsigned long) 31, - (unsigned long) 61, - (unsigned long) 127, - (unsigned long) 251, - (unsigned long) 509, - (unsigned long) 1021, - (unsigned long) 2039, - (unsigned long) 4093, - (unsigned long) 8191, - (unsigned long) 16381, - (unsigned long) 32749, - (unsigned long) 65521, - (unsigned long) 131071, - (unsigned long) 262139, - (unsigned long) 524287, - (unsigned long) 1048573, - (unsigned long) 2097143, - (unsigned long) 4194301, - (unsigned long) 8388593, - (unsigned long) 16777213, - (unsigned long) 33554393, - (unsigned long) 67108859, - (unsigned long) 134217689, - (unsigned long) 268435399, - (unsigned long) 536870909, - (unsigned long) 1073741789, - (unsigned long) 2147483647, - /* 4294967291L */ - ((unsigned long) 2147483647) + ((unsigned long) 2147483644), - }; - - const unsigned long *low = &primes[0]; - const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])]; - - while (low != high) - { - const unsigned long *mid = low + (high - low) / 2; - if (n > *mid) - low = mid + 1; - else - high = mid; - } - -#if 0 - /* If we've run out of primes, abort. */ - if (n > *low) - { - fprintf (stderr, "Cannot find prime bigger than %lu\n", n); - abort (); - } +/* Make sure dl_iterate_phdr is defined. */ +#ifdef __USE_GNU +# include <link.h> +#else +# define __USE_GNU +# include <link.h> +# undef __USE_GNU #endif - - return *low; -} - -struct funcdesc_ht -{ - /* Table itself. */ - struct funcdesc_value **entries; - - /* Current size (in entries) of the hash table */ - size_t size; - - /* Current number of elements. */ - size_t n_elements; -}; - -inline static int -hash_pointer (const void *p) -{ - return (int) ((long)p >> 3); -} - -inline static struct funcdesc_ht * -htab_create (void) -{ - struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht)); - - if (! ht) - return NULL; - ht->size = 3; - ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size); - if (! ht->entries) - return NULL; - - ht->n_elements = 0; - - _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size); - - return ht; -} - -inline static void -htab_delete (struct funcdesc_ht *htab) -{ - int i; - - for (i = htab->size - 1; i >= 0; i--) - if (htab->entries[i]) - _dl_free (htab->entries[i]); - - _dl_free (htab->entries); - _dl_free (htab); -} - -/* Similar to htab_find_slot, but without several unwanted side effects: - - Does not call htab->eq_f when it finds an existing entry. - - Does not change the count of elements/searches/collisions in the - hash table. - This function also assumes there are no deleted entries in the table. - HASH is the hash value for the element to be inserted. */ - -inline static struct funcdesc_value ** -find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash) -{ - size_t size = htab->size; - unsigned int index = hash % size; - struct funcdesc_value **slot = htab->entries + index; - int hash2; - - if (! *slot) - return slot; - - hash2 = 1 + hash % (size - 2); - for (;;) - { - index += hash2; - if (index >= size) - index -= size; - - slot = htab->entries + index; - if (! *slot) - return slot; - } -} - -/* The following function changes size of memory allocated for the - entries and repeatedly inserts the table elements. The occupancy - of the table after the call will be about 50%. Naturally the hash - table must already exist. Remember also that the place of the - table entries is changed. If memory allocation failures are allowed, - this function will return zero, indicating that the table could not be - expanded. If all goes well, it will return a non-zero value. */ - -inline static int -htab_expand (struct funcdesc_ht *htab) -{ - struct funcdesc_value **oentries; - struct funcdesc_value **olimit; - struct funcdesc_value **p; - struct funcdesc_value **nentries; - size_t nsize; - - oentries = htab->entries; - olimit = oentries + htab->size; - - /* Resize only when table after removal of unused elements is either - too full or too empty. */ - if (htab->n_elements * 2 > htab->size) - nsize = higher_prime_number (htab->n_elements * 2); - else - nsize = htab->size; - - nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize); - _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize); - if (nentries == NULL) - return 0; - htab->entries = nentries; - htab->size = nsize; - - p = oentries; - do - { - if (*p) - *find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point)) - = *p; - - p++; - } - while (p < olimit); - - _dl_free (oentries); - return 1; -} - -/* This function searches for a hash table slot containing an entry - equal to the given element. To delete an entry, call this with - INSERT = 0, then call htab_clear_slot on the slot returned (possibly - after doing some checks). To insert an entry, call this with - INSERT = 1, then write the value you want into the returned slot. - When inserting an entry, NULL may be returned if memory allocation - fails. */ - -inline static struct funcdesc_value ** -htab_find_slot (struct funcdesc_ht *htab, void *ptr) -{ - unsigned int index; - int hash, hash2; - size_t size; - struct funcdesc_value **entry; - - if (htab->size * 3 <= htab->n_elements * 4 - && htab_expand (htab) == 0) - return NULL; - - hash = hash_pointer (ptr); - - size = htab->size; - index = hash % size; - - entry = &htab->entries[index]; - if (!*entry) - goto empty_entry; - else if ((*entry)->entry_point == ptr) - return entry; - - hash2 = 1 + hash % (size - 2); - for (;;) - { - index += hash2; - if (index >= size) - index -= size; - - entry = &htab->entries[index]; - if (!*entry) - goto empty_entry; - else if ((*entry)->entry_point == ptr) - return entry; - } - - empty_entry: - htab->n_elements++; - return entry; -} - -void * -_dl_funcdesc_for (void *entry_point, void *got_value) -{ - struct elf_resolve *tpnt = ((void**)got_value)[2]; - struct funcdesc_ht *ht = tpnt->funcdesc_ht; - struct funcdesc_value **entry; - - _dl_assert (got_value == tpnt->loadaddr.got_value); - - if (! ht) - { - ht = htab_create (); - if (! ht) - return (void*)-1; - tpnt->funcdesc_ht = ht; - } - - entry = htab_find_slot (ht, entry_point); - if (*entry) - { - _dl_assert ((*entry)->entry_point == entry_point); - return _dl_stabilize_funcdesc (*entry); - } - - *entry = _dl_malloc (sizeof (struct funcdesc_value)); - (*entry)->entry_point = entry_point; - (*entry)->got_value = got_value; - - return _dl_stabilize_funcdesc (*entry); -} - -void -__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr, - struct funcdesc_ht *funcdesc_ht) -{ - int i; - - for (i = 0; i < loadaddr.map->nsegs; i++) - _dl_munmap ((void*)loadaddr.map->segs[i].addr, - loadaddr.map->segs[i].p_memsz); - - _dl_free (loadaddr.map); - if (funcdesc_ht) - htab_delete (funcdesc_ht); -} |