2000-05-05  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-load.c (_dl_map_object_from_fd): Little of computation of
	parameter to mprotect and for variable assignments.

2000-05-03  Jes Sorensen  <jes@linuxcare.com>

	* sysdeps/generic/ldsodefs.h (LOOKUP_VALUE_ADDRESS): Check the
	validity of map before dereferencing it.

	* elf/dl-reloc.c (RESOLVE_MAP): Define.

2000-05-02  Jes Sorensen  <jes@linuxcare.com>

	* elf/dl-runtime.c (fixup): Add the value returned in the symbol
	lookup to the arguments to elf_machine_fixup_plt().

	* sysdeps/ia64/dl-machine.h (elf_machine_fixup_plt): Add Link_map
	of the symbol being resolved to input argument list and make the
	function return the pointer to the reloc.

	* sysdeps/alpha/dl-machine.h (elf_machine_fixup_plt): Change
	return valuie to lookup_t and return the value.
	* sysdeps/arm/dl-machine.h (elf_machine_fixup_plt): Likewise.
	* sysdeps/generic/dl-machine.h (elf_machine_fixup_plt): Likewise.
	* sysdeps/i386/dl-machine.h (elf_machine_fixup_plt): Likewise.
	* sysdeps/m68k/dl-machine.h (elf_machine_fixup_plt): Likewise.
	* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_fixup_plt): Likewise.
	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_fixup_plt): Likewise.

	* sysdeps/powerpc/dl-machine.h (elf_machine_fixup_plt): Likewise.
	Make it an inline function returning value after calling
	__elf_machine_fixup_plt().

	* elf/dl-sym.c (_dl_vsym): Use DL_SYMBOL_ADDRESS() to obtain the
	symbol address.

	* elf/dl-symbol.c (_dl_symbol_value): Use LOOKUP_VALUE_ADDRESS to
	obtain the symbol address.

	* sysdeps/generic/ldsodefs.h: Add generic DL_SYMBOL_ADDRESS() macro
	depending on the definition of ELF_FUNCTION_PTR_IS_SPECIAL.

	* sysdeps/ia64/dl-machine.h: Add DL_SYMBOL_ADDRESS() macro calling
	_dl_symbol_address() - this way DL_SYMBOL_ADDRESS() turns into an
	inline on non ia64.

2000-04-28  Jes Sorensen  <jes@linuxcare.com>

	* elf/dl-runtime.c (fixup): Use the portable macros to get the
	symbol address of an object.

	* elf/dl-runtime.c (fixup-profile): Use the portable macros to get
	the symbol address of an object.

	* elf/dl-libc.c (struct do_dlsym_args): Change loadbase to a lookup_t.
	* elf/dl-lookup.c (_dl_lookup_symbol): Likewise.
	(_dl_lookup_symbol_skip): Likewise.
	(_dl_lookup_versioned_symbol): Likewise.
	(_dl_lookup_versioned_symbol_skip): Likewise.

2000-04-27  Jes Sorensen  <jes@linuxcare.com>

	* elf/rtld.c (_dl_start): Get the function pointer return address
	via _dl_start_address for architectures that need a function
	pointer descriptor rather than just a pointer (ia64).

	* sysdeps/generic/dl-lookupcfg.h: New file.
	* sysdeps/ia64/dl-lookupcfg.h: New file.
	* sysdeps/ia64/dl-machine.h: New file.
	* sysdeps/ia64/dl-symaddr.c: New file.
	* sysdeps/ia64/dl-fptr.c: New file.

	* elf/elf.h: Add IA-64 specific definitions.
This commit is contained in:
Ulrich Drepper 2000-05-05 07:15:29 +00:00
parent 61d357cae3
commit c0282c0642
24 changed files with 1212 additions and 125 deletions

View file

@ -1,3 +1,78 @@
2000-05-05 Ulrich Drepper <drepper@redhat.com>
* elf/dl-load.c (_dl_map_object_from_fd): Little of computation of
parameter to mprotect and for variable assignments.
2000-05-03 Jes Sorensen <jes@linuxcare.com>
* sysdeps/generic/ldsodefs.h (LOOKUP_VALUE_ADDRESS): Check the
validity of map before dereferencing it.
* elf/dl-reloc.c (RESOLVE_MAP): Define.
2000-05-02 Jes Sorensen <jes@linuxcare.com>
* elf/dl-runtime.c (fixup): Add the value returned in the symbol
lookup to the arguments to elf_machine_fixup_plt().
* sysdeps/ia64/dl-machine.h (elf_machine_fixup_plt): Add Link_map
of the symbol being resolved to input argument list and make the
function return the pointer to the reloc.
* sysdeps/alpha/dl-machine.h (elf_machine_fixup_plt): Change
return valuie to lookup_t and return the value.
* sysdeps/arm/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/generic/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/i386/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/m68k/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_fixup_plt): Likewise.
* sysdeps/powerpc/dl-machine.h (elf_machine_fixup_plt): Likewise.
Make it an inline function returning value after calling
__elf_machine_fixup_plt().
* elf/dl-sym.c (_dl_vsym): Use DL_SYMBOL_ADDRESS() to obtain the
symbol address.
* elf/dl-symbol.c (_dl_symbol_value): Use LOOKUP_VALUE_ADDRESS to
obtain the symbol address.
* sysdeps/generic/ldsodefs.h: Add generic DL_SYMBOL_ADDRESS() macro
depending on the definition of ELF_FUNCTION_PTR_IS_SPECIAL.
* sysdeps/ia64/dl-machine.h: Add DL_SYMBOL_ADDRESS() macro calling
_dl_symbol_address() - this way DL_SYMBOL_ADDRESS() turns into an
inline on non ia64.
2000-04-28 Jes Sorensen <jes@linuxcare.com>
* elf/dl-runtime.c (fixup): Use the portable macros to get the
symbol address of an object.
* elf/dl-runtime.c (fixup-profile): Use the portable macros to get
the symbol address of an object.
* elf/dl-libc.c (struct do_dlsym_args): Change loadbase to a lookup_t.
* elf/dl-lookup.c (_dl_lookup_symbol): Likewise.
(_dl_lookup_symbol_skip): Likewise.
(_dl_lookup_versioned_symbol): Likewise.
(_dl_lookup_versioned_symbol_skip): Likewise.
2000-04-27 Jes Sorensen <jes@linuxcare.com>
* elf/rtld.c (_dl_start): Get the function pointer return address
via _dl_start_address for architectures that need a function
pointer descriptor rather than just a pointer (ia64).
* sysdeps/generic/dl-lookupcfg.h: New file.
* sysdeps/ia64/dl-lookupcfg.h: New file.
* sysdeps/ia64/dl-machine.h: New file.
* sysdeps/ia64/dl-symaddr.c: New file.
* sysdeps/ia64/dl-fptr.c: New file.
* elf/elf.h: Add IA-64 specific definitions.
2000-05-04 Jakub Jelinek <jakub@redhat.com>
* sysdeps/generic/bits/confname.h (_SC* enum): Avoid comma at the

View file

@ -65,7 +65,7 @@ struct do_dlsym_args
const char *name;
/* Return values of do_dlsym. */
ElfW(Addr) loadbase;
lookup_t loadbase;
const ElfW(Sym) *ref;
};

View file

@ -917,11 +917,14 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
As a refinement, sometimes we have an address that we would
prefer to map such objects at; but this is only a preference,
the OS can do whatever it likes. */
caddr_t mapat;
ElfW(Addr) mappref;
mappref = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart)
- MAP_BASE_ADDR (l));
mapat = map_segment (mappref, maplength, c->prot, 0, c->mapoff);
/* Remember which part of the address space this object uses. */
l->l_map_start = map_segment (mappref, maplength, c->prot, 0,
c->mapoff);
l->l_map_end = l->l_map_start + maplength;
l->l_addr = (ElfW(Addr)) mapat - c->mapstart;
/* Change protection on the excess portion to disallow all access;
@ -929,14 +932,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
unallocated. Then jump into the normal segment-mapping loop to
handle the portion of the segment past the end of the file
mapping. */
__mprotect ((caddr_t) (l->l_addr + c->mapend),
__mprotect ((caddr_t) l->l_map_start,
loadcmds[nloadcmds - 1].allocend - c->mapend,
0);
/* Remember which part of the address space this object uses. */
l->l_map_start = c->mapstart + l->l_addr;
l->l_map_end = l->l_map_start + maplength;
goto postmap;
}
else

View file

@ -86,7 +86,7 @@ static int
add_dependency (struct link_map *undef_map, struct link_map *map)
{
struct link_map **list;
unsigned act;
unsigned int act;
unsigned int i;
int result = 0;
@ -183,7 +183,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
/* Search loaded objects' symbol tables for a definition of the symbol
UNDEF_NAME. */
ElfW(Addr)
lookup_t
internal_function
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
@ -241,7 +241,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
": symbol `", undef_name, "'\n", NULL);
*ref = current_value.s;
return current_value.m->l_addr;
return LOOKUP_VALUE (current_value.m);
}
@ -250,7 +250,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
it only considers objects which were loaded after the described
object. If there are more search lists the object described by
SKIP_MAP is only skipped. */
ElfW(Addr)
lookup_t
internal_function
_dl_lookup_symbol_skip (const char *undef_name,
struct link_map *undef_map, const ElfW(Sym) **ref,
@ -328,7 +328,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
": symbol `", undef_name, "' (skip)\n", NULL);
*ref = current_value.s;
return current_value.m->l_addr;
return LOOKUP_VALUE (current_value.m);
}
@ -337,7 +337,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
symbol.
XXX We'll see whether we need this separate function. */
ElfW(Addr)
lookup_t
internal_function
_dl_lookup_versioned_symbol (const char *undef_name,
struct link_map *undef_map, const ElfW(Sym) **ref,
@ -422,13 +422,13 @@ _dl_lookup_versioned_symbol (const char *undef_name,
"]\n", NULL);
*ref = current_value.s;
return current_value.m->l_addr;
return LOOKUP_VALUE (current_value.m);
}
/* Similar to _dl_lookup_symbol_skip but takes an additional argument
with the version we are looking for. */
ElfW(Addr)
lookup_t
internal_function
_dl_lookup_versioned_symbol_skip (const char *undef_name,
struct link_map *undef_map,
@ -523,7 +523,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
"] (skip)\n", NULL);
*ref = current_value.s;
return current_value.m->l_addr;
return LOOKUP_VALUE (current_value.m);
}

View file

@ -70,6 +70,14 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
#define RESOLVE_MAP(ref, version, flags) \
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, (version), (flags)) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \
(flags))) \
: l)
#define RESOLVE(ref, version, flags) \
(__builtin_expect (ELFW(ST_VISIBILITY) ((*ref)->st_other), 0) == 0 \
? ((version) != NULL && (version)->hash != 0 \

View file

@ -57,6 +57,7 @@ fixup (
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
lookup_t result;
ElfW(Addr) value;
/* The use of `alloca' here looks ridiculous but it helps. The goal is
@ -83,33 +84,38 @@ fixup (
if (version->hash != 0)
{
value = _dl_lookup_versioned_symbol(strtab + sym->st_name, l,
&sym, l->l_scope, version,
ELF_MACHINE_JMP_SLOT);
result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
l, &sym, l->l_scope,
version,
ELF_MACHINE_JMP_SLOT);
break;
}
}
case 0:
value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_MACHINE_JMP_SLOT);
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_MACHINE_JMP_SLOT);
}
/* Currently value contains the base load address of the object
that defines sym. Now add in the symbol offset. */
value = (sym ? value + sym->st_value : 0);
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
value = l->l_addr + sym->st_value;
value = l->l_addr + sym->st_value;
#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
/* Finally, fix up the plt itself. */
elf_machine_fixup_plt (l, reloc, rel_addr, value);
return value;
return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
}
#endif
@ -124,6 +130,7 @@ profile_fixup (
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
ElfW(Addr) *resultp;
lookup_t result;
ElfW(Addr) value;
/* The use of `alloca' here looks ridiculous but it helps. The goal is
@ -166,27 +173,32 @@ profile_fixup (
if (version->hash != 0)
{
value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
l, &sym, l->l_scope,
version,
ELF_MACHINE_JMP_SLOT);
result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
l, &sym, l->l_scope,
version,
ELF_MACHINE_JMP_SLOT);
break;
}
}
case 0:
value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_MACHINE_JMP_SLOT);
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
l->l_scope, ELF_MACHINE_JMP_SLOT);
}
/* Currently value contains the base load address of the object
that defines sym. Now add in the symbol offset. */
value = (sym ? value + sym->st_value : 0);
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
value = l->l_addr + sym->st_value;
#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);

View file

@ -1,5 +1,5 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
Copyright (C) 1999 Free Software Foundation, Inc.
Copyright (C) 1999, 2000 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
@ -29,12 +29,12 @@ void *
internal_function
_dl_sym (void *handle, const char *name, void *who)
{
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
lookup_t result;
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
loadbase = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
result = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
else
{
struct link_map *l, *match;
@ -56,8 +56,8 @@ _dl_sym (void *handle, const char *name, void *who)
main program (we hope). */
match = _dl_loaded;
loadbase = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
0);
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
0);
}
else
{
@ -69,13 +69,13 @@ RTLD_NEXT used in code not dynamically loaded"));
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
match);
result = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
match);
}
}
if (loadbase)
return (void *) (loadbase + ref->st_value);
if (result)
return DL_SYMBOL_ADDRESS (result, ref);
return NULL;
}
@ -84,9 +84,9 @@ void *
internal_function
_dl_vsym (void *handle, const char *name, const char *version, void *who)
{
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
struct r_found_version vers;
lookup_t result;
/* Compute hash value to the version string. */
vers.name = version;
@ -97,8 +97,8 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
loadbase = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
&vers, 0);
result = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
&vers, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
@ -118,20 +118,19 @@ RTLD_NEXT used in code not dynamically loaded"));
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_versioned_symbol_skip (name, l, &ref,
l->l_local_scope,
&vers, match);
result = _dl_lookup_versioned_symbol_skip (name, l, &ref,
l->l_local_scope,
&vers, match);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
loadbase = _dl_lookup_versioned_symbol (name, map, &ref,
map->l_local_scope, &vers, 0);
result = _dl_lookup_versioned_symbol (name, map, &ref,
map->l_local_scope, &vers, 0);
}
if (loadbase)
return (void *) (loadbase + ref->st_value);
if (result)
return DL_SYMBOL_ADDRESS (result, ref);
return NULL;
}

View file

@ -1,5 +1,5 @@
/* Look up a symbol's run-time value in the scope of a loaded object.
Copyright (C) 1995,96,98,99,2000 Free Software Foundation, Inc.
Copyright (C) 1995, 96, 98, 99, 2000 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
@ -26,8 +26,8 @@ ElfW(Addr)
internal_function
_dl_symbol_value (struct link_map *map, const char *name)
{
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
loadbase = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
return loadbase + ref->st_value;
lookup_t result;
result = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
return (result ? LOOKUP_VALUE_ADDRESS (result) : 0) + ref->st_value;
}

View file

@ -1757,6 +1757,86 @@ typedef Elf32_Addr Elf32_Conflict;
/* Keep this the last entry. */
#define R_ARM_NUM 256
/* IA-64 specific declarations. */
/* Processor specific flags for the Ehdr e_flags field. */
#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
/* Processor specific values for the Phdr p_type field. */
#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
/* Processor specific flags for the Phdr p_flags field. */
#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
/* Processor specific values for the Shdr sh_type field. */
#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
/* Processor specific flags for the Shdr sh_flags field. */
#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
/* Processor specific values for the Dyn d_tag field. */
#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
#define DT_IA_64_NUM 1
/* IA-64 relocations. */
#define R_IA64_NONE 0x00 /* none */
#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
#define R_IA64_LTV32MSB 0x70 /* symbol + addend, data4 MSB */
#define R_IA64_LTV32LSB 0x71 /* symbol + addend, data4 LSB */
#define R_IA64_LTV64MSB 0x72 /* symbol + addend, data8 MSB */
#define R_IA64_LTV64LSB 0x73 /* symbol + addend, data8 LSB */
#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
__END_DECLS
#endif /* elf.h */

View file

@ -160,6 +160,8 @@ _dl_start (void *arg)
/* This #define produces dynamic linking inline functions for
bootstrap relocation instead of general-purpose relocation. */
#define RTLD_BOOTSTRAP
#define RESOLVE_MAP(sym, version, flags) \
((*(sym))->st_shndx == SHN_UNDEF ? 0 : &bootstrap_map)
#define RESOLVE(sym, version, flags) \
((*(sym))->st_shndx == SHN_UNDEF ? 0 : bootstrap_map.l_addr)
#include "dynamic-link.h"
@ -200,7 +202,15 @@ _dl_start (void *arg)
header table in core. Put the rest of _dl_start into a separate
function, that way the compiler cannot put accesses to the GOT
before ELF_DYNAMIC_RELOCATE. */
return _dl_start_final (arg, &bootstrap_map, start_time);
{
ElfW(Addr) entry = _dl_start_final (arg, &bootstrap_map, start_time);
#ifndef ELF_MACHINE_START_ADDRESS
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
#endif
return ELF_MACHINE_START_ADDRESS (_dl_loaded, entry);
}
}
@ -886,10 +896,16 @@ of this helper program; chances are you did not intend to run this program.\n\
for (i = 1; i < _dl_argc; ++i)
{
const ElfW(Sym) *ref = NULL;
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
&ref, _dl_loaded->l_scope,
ELF_MACHINE_JMP_SLOT);
ElfW(Addr) loadbase;
lookup_t result;
char buf[20], *bp;
result = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
&ref, _dl_loaded->l_scope,
ELF_MACHINE_JMP_SLOT);
loadbase = LOOKUP_VALUE_ADDRESS (result);
buf[sizeof buf - 1] = '\0';
bp = _itoa_word (ref->st_value, &buf[sizeof buf - 1], 16, 0);
while ((size_t) (&buf[sizeof buf - 1] - bp) < sizeof loadbase * 2)

View file

@ -68,7 +68,7 @@ elf_machine_load_address (void)
are usually many many terabytes away. */
Elf64_Addr dot;
long zero_disp;
long int zero_disp;
asm("br %0, 1f\n\t"
".weak __load_address_undefined\n\t"
@ -119,7 +119,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
/* If the first instruction of the plt entry is not
"br $28, plt0", we cannot do lazy relocation. */
lazy = (*(unsigned *)(plt + 32) == 0xc39ffff7);
lazy = (*(unsigned int *)(plt + 32) == 0xc39ffff7);
}
return lazy;
@ -363,13 +363,14 @@ $fixup_stack:
/* Fix up the instructions of a PLT entry to invoke the function
rather than the dynamic linker. */
static inline void
elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc,
Elf64_Addr *got_addr, Elf64_Addr value)
static inline Elf64_Addr
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
const Elf64_Rela *reloc,
Elf64_Addr *got_addr, Elf64_Addr value)
{
const Elf64_Rela *rela_plt;
Elf64_Word *plte;
long edisp;
long int edisp;
/* Store the value we are going to load. */
*got_addr = value;
@ -381,7 +382,7 @@ elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc,
plte += 3 * (reloc - rela_plt);
/* Find the displacement from the plt entry to the function. */
edisp = (long)(value - (Elf64_Addr)&plte[3]) / 4;
edisp = (long int) (value - (Elf64_Addr)&plte[3]) / 4;
if (edisp >= -0x100000 && edisp < 0x100000)
{
@ -391,7 +392,7 @@ elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc,
int hi, lo;
hi = value - (Elf64_Addr)&plte[0];
lo = (short)hi;
lo = (short int) hi;
hi = (hi - lo) >> 16;
/* Emit "lda $27,lo($27)" */
@ -436,6 +437,8 @@ elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc,
This will be taken care of in _dl_runtime_resolve. If instead we are
doing this as part of non-lazy startup relocation, that bit of code
hasn't made it into Icache yet, so there's nothing to clean up. */
return value;
}
/* Return the final value of a plt relocation. */
@ -459,7 +462,7 @@ elf_machine_rela (struct link_map *map,
const struct r_found_version *version,
Elf64_Addr *const reloc_addr)
{
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
#ifndef RTLD_BOOTSTRAP
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
@ -525,7 +528,7 @@ elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset);
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
if (r_type == R_ALPHA_JMP_SLOT)
{

View file

@ -354,11 +354,12 @@ dl_platform_init (void)
_dl_platform = NULL;
}
static inline void
elf_machine_fixup_plt (struct link_map *map, const Elf32_Rel *reloc,
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf32_Rel *reloc,
Elf32_Addr *reloc_addr, Elf32_Addr value)
{
*reloc_addr = value;
return *reloc_addr = value;
}
/* Return the final value of a plt relocation. */

View file

@ -0,0 +1,22 @@
/* Configuration of lookup functions.
Copyright (C) 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Some platforms need more information from the symbol lookup function
than just the address. But this is not generally the case. */
#undef DL_LOOKUP_RETURNS_MAP

View file

@ -52,11 +52,12 @@ elf_machine_load_address (void)
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
static inline void
elf_machine_fixup_plt (struct link_map *map, const Elf32_Rel *reloc,
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf32_Rel *reloc,
Elf32_Addr *reloc_addr, Elf32_Addr value)
{
*reloc_addr = value;
return *reloc_addr = value;
}
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).

View file

@ -30,6 +30,7 @@
#include <elf.h>
#include <dlfcn.h>
#include <link.h>
#include <dl-lookupcfg.h>
__BEGIN_DECLS
@ -49,6 +50,27 @@ __BEGIN_DECLS
# define D_PTR(map,i) map->i->d_un.d_ptr
#endif
/* On some platforms more information than just the address of the symbol
is needed from the lookup functions. In this case we return the whole
link map. */
#ifdef DL_LOOKUP_RETURNS_MAP
typedef struct link_map *lookup_t;
# define LOOKUP_VALUE(map) map
# define LOOKUP_VALUE_ADDRESS(map) (map ? map->l_addr : 0)
#else
typedef ElfW(Addr) lookup_t;
# define LOOKUP_VALUE(map) map->l_addr
# define LOOKUP_VALUE_ADDRESS(address) address
#endif
/* on some architectures a pointer to a function is not just a pointer
to the actual code of the function but rather an architecture
specific descriptor. */
#ifndef ELF_FUNCTION_PTR_IS_SPECIAL
#define DL_SYMBOL_ADDRESS(map, ref) \
(void *) (LOOKUP_VALUE_ADDRESS (map) + ref->st_value)
#endif
/* For the version handling we need an array with only names and their
hash values. */
struct r_found_version
@ -271,38 +293,38 @@ extern void _dl_setup_hash (struct link_map *map) internal_function;
RELOC_TYPE is a machine-dependent reloc type, which is passed to
the `elf_machine_lookup_*_p' macros in dl-machine.h to affect which
symbols can be chosen. */
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
int reloc_type)
extern lookup_t _dl_lookup_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
int reloc_type)
internal_function;
/* Lookup versioned symbol. */
extern ElfW(Addr) _dl_lookup_versioned_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
int reloc_type)
extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
int reloc_type)
internal_function;
/* For handling RTLD_NEXT we must be able to skip shared objects. */
extern ElfW(Addr) _dl_lookup_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
struct link_map *skip_this)
extern lookup_t _dl_lookup_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
struct link_map *skip_this)
internal_function;
/* For handling RTLD_NEXT with versioned symbols we must be able to
skip shared objects. */
extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
struct link_map *skip_this)
extern lookup_t _dl_lookup_versioned_symbol_skip (const char *undef,
struct link_map *undef_map,
const ElfW(Sym) **sym,
struct r_scope_elem *symbol_scope[],
const struct r_found_version *version,
struct link_map *skip_this)
internal_function;
/* Look up symbol NAME in MAP's scope and return its run-time address. */

View file

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. i386 version.
Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
Copyright (C) 1995, 96, 97, 98, 99, 2000 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
@ -279,11 +279,12 @@ dl_platform_init (void)
_dl_platform = NULL;
}
static inline void
elf_machine_fixup_plt (struct link_map *map, const Elf32_Rel *reloc,
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf32_Rel *reloc,
Elf32_Addr *reloc_addr, Elf32_Addr value)
{
*reloc_addr = value;
return *reloc_addr = value;
}
/* Return the final value of a plt relocation. */

186
sysdeps/ia64/dl-fptr.c Normal file
View file

@ -0,0 +1,186 @@
/* Unmap a loaded object. IA-64 version.
Copyright (C) 1999, 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <unistd.h>
#include <string.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <link.h>
#include <ldsodefs.h>
#include <elf/dynamic-link.h>
#include <dl-machine.h>
#ifdef _LIBC_REENTRANT
# include <pt-machine.h>
static int __ia64_fptr_lock = 0;
#endif
/* Because ld.so is now versioned, these functions can be in their own
file; no relocations need to be done to call them. Of course, if
ld.so is not versioned... */
#if 0
#ifndef DO_VERSIONING
# error "This will not work with versioning turned off, sorry."
#endif
#endif
#ifdef MAP_ANON
/* The fd is not examined when using MAP_ANON. */
#define ANONFD -1
#else
extern int _dl_zerofd;
#define ANONFD _dl_zerofd
#endif
/* ld.so currently has 14 FPTR relocs, we take 256 and use them for
the relocs for the dynamic app itself. */
struct ia64_fptr __boot_ldso_fptr[IA64_BOOT_FPTR_SIZE];
struct ia64_fptr *__fptr_root = NULL;
struct ia64_fptr *__fptr_next = __boot_ldso_fptr;
static struct ia64_fptr *__fptr_free = NULL;
int __fptr_count = IA64_BOOT_FPTR_SIZE;
Elf64_Addr
__ia64_make_fptr (const struct link_map *sym_map, Elf64_Addr value,
struct ia64_fptr **root, struct ia64_fptr *mem)
{
struct ia64_fptr **loc;
struct ia64_fptr *f;
#ifdef _LIBC_REENTRANT
/* Make sure we are alone. We don't need a lock during bootstrap. */
if (mem == NULL)
while (testandset (&__ia64_fptr_lock));
#endif
/* Search the sorted linked list for an existing entry for this
symbol. */
loc = root;
f = *loc;
while (f != NULL && f->func <= value)
{
if (f->func == value)
goto found;
loc = &f->next;
f = *loc;
}
/* Not found. Create a new one. */
if (mem != NULL)
f = mem;
else if (__fptr_free != NULL)
{
f = __fptr_free;
__fptr_free = f->next;
}
else
{
if (__fptr_count == 0)
{
#ifndef MAP_ANON
# define MAP_ANON 0
if (_dl_zerofd == -1)
{
_dl_zerofd = _dl_sysdep_open_zero_fill ();
if (_dl_zerofd == -1)
{
__close (fd);
_dl_signal_error (errno, NULL,
"cannot open zero fill device");
}
}
#endif
__fptr_next = __mmap (0, _dl_pagesize, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, ANONFD, 0);
if (__fptr_next == MAP_FAILED)
_dl_signal_error(errno, NULL, "cannot map page for fptr");
__fptr_count = _dl_pagesize / sizeof (struct ia64_fptr);
}
f = __fptr_next++;
__fptr_count--;
}
f->func = value;
/* GOT has already been relocated in elf_get_dynamic_info - don't
try to relocate it again. */
f->gp = sym_map->l_info[DT_PLTGOT]->d_un.d_ptr;
f->next = *loc;
*loc = f;
found:
#ifdef _LIBC_REENTRANT
/* Release the lock. */
if (mem == NULL)
__ia64_fptr_lock = 0;
#endif
return (Elf64_Addr) f;
}
void
_dl_unmap (struct link_map *map)
{
struct ia64_fptr **floc;
struct ia64_fptr *f;
struct ia64_fptr **lloc;
struct ia64_fptr *l;
__munmap ((void *) map->l_map_start, map->l_map_end - map->l_map_start);
#ifdef _LIBC_REENTRANT
/* Make sure we are alone. */
while (testandset (&__ia64_fptr_lock));
#endif
/* Search the sorted linked list for the first entry for this object. */
floc = &__fptr_root;
f = *floc;
while (f != NULL && f->func < map->l_map_start)
{
floc = &f->next;
f = *floc;
}
/* We found one. */
if (f != NULL && f->func < map->l_map_end)
{
/* Get the last entry. */
lloc = floc;
l = f;
while (l && l->func < map->l_map_end)
{
lloc = &l->next;
l = *lloc;
}
/* Updated FPTR. */
*floc = l;
/* Prepend them to the free list. */
*lloc = __fptr_free;
__fptr_free = f;
}
#ifdef _LIBC_REENTRANT
/* Release the lock. */
__ia64_fptr_lock = 0;
#endif
}

View file

@ -0,0 +1,23 @@
/* Configuration of lookup functions.
Copyright (C) 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* The ia64 need more information from the symbol lookup function
than just the address. */
#define DL_LOOKUP_RETURNS_MAP
#define ELF_FUNCTION_PTR_IS_SPECIAL

585
sysdeps/ia64/dl-machine.h Normal file
View file

@ -0,0 +1,585 @@
/* Machine-dependent ELF dynamic relocation inline functions. IA-64 version.
Copyright (C) 1995, 1996, 1997, 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef dl_machine_h
#define dl_machine_h 1
#define ELF_MACHINE_NAME "ia64"
#include <assert.h>
#include <string.h>
#include <link.h>
#include <errno.h>
/* Translate a processor specific dynamic tag to the index
in l_info array. */
#define DT_IA_64(x) (DT_IA_64_##x - DT_LOPROC + DT_NUM)
/* An FPTR is a function descriptor. Properly they consist of just
FUNC and GP. But we want to traverse a binary tree too. */
#define IA64_BOOT_FPTR_SIZE 256
struct ia64_fptr
{
Elf64_Addr func;
Elf64_Addr gp;
struct ia64_fptr *next;
};
extern struct ia64_fptr __boot_ldso_fptr[];
extern struct ia64_fptr *__fptr_next;
extern struct ia64_fptr *__fptr_root;
extern int __fptr_count;
extern Elf64_Addr __ia64_make_fptr (const struct link_map *, Elf64_Addr,
struct ia64_fptr **, struct ia64_fptr *);
/* Return nonzero iff E_MACHINE is compatible with the running host. */
static inline int
elf_machine_matches_host (Elf64_Word e_machine)
{
return e_machine == EM_IA_64;
}
void * _dl_symbol_address (const struct link_map *map, const ElfW(Sym) *ref);
#define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref)
/* Return the link-time address of _DYNAMIC. */
static inline Elf64_Addr
elf_machine_dynamic (void)
{
Elf64_Addr *p;
__asm__(
".section .sdata\n"
" .type __dynamic_ltv#, @object\n"
" .size __dynamic_ltv#, 8\n"
"__dynamic_ltv:\n"
" data8 @ltv(_DYNAMIC#)\n"
".previous\n"
" addl %0 = @gprel(__dynamic_ltv#), gp ;;"
: "=r"(p));
return *p;
}
/* Return the run-time load address of the shared object. */
static inline Elf64_Addr
elf_machine_load_address (void)
{
Elf64_Addr ip;
int *p;
__asm__(
"1: mov %0 = ip\n"
".section .sdata\n"
"2: data4 @ltv(1b)\n"
" .align 8\n"
".previous\n"
" addl %1 = @gprel(2b), gp ;;"
: "=r"(ip), "=r"(p));
return ip - (Elf64_Addr)*p;
}
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
extern void _dl_runtime_resolve (void);
extern void _dl_runtime_profile (void);
if (lazy)
{
register Elf64_Addr gp __asm__("gp");
Elf64_Addr *reserve, doit;
/*
* Careful with the typecast here or it will try to add l-l_addr
* pointer elements
*/
reserve = (Elf64_Addr *)
(l->l_info[DT_IA_64(PLT_RESERVE)]->d_un.d_ptr + l->l_addr);
/* Identify this shared object. */
reserve[0] = (Elf64_Addr) l;
/* This function will be called to perform the relocation. */
if (!profile)
doit = (Elf64_Addr) ((struct ia64_fptr *)&_dl_runtime_resolve)->func;
else
{
if (_dl_name_match_p (_dl_profile, l))
{
/* This is the object we are looking for. Say that we really
want profiling and the timers are started. */
_dl_profile_map = l;
}
doit = (Elf64_Addr) ((struct ia64_fptr *)&_dl_runtime_profile)->func;
}
reserve[1] = doit;
reserve[2] = gp;
}
return lazy;
}
/*
This code is used in dl-runtime.c to call the `fixup' function
and then redirect to the address it returns. `fixup()' takes two
arguments, however fixup_profile() takes three.
The ABI specifies that we will never see more than 8 input
registers to a function call, thus it is safe to simply allocate
those, and simpler than playing stack games.
- 12/09/99 Jes
*/
#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
extern void tramp_name (void); \
asm ( "\
.global " #tramp_name "#
.proc " #tramp_name "#
" #tramp_name ":
{ .mmi
alloc loc0 = ar.pfs, 8, 2, 3, 0
adds r2 = -144, r12
adds r3 = -128, r12
}
{ .mii
adds r12 = -160, r12
mov loc1 = b0
mov out2 = b0 /* needed by fixup_profile */
;;
}
{ .mmi
stf.spill [r2] = f8, 32
stf.spill [r3] = f9, 32
mov out0 = r16
;;
}
{ .mmi
stf.spill [r2] = f10, 32
stf.spill [r3] = f11, 32
shl out1 = r15, 4
;;
}
{ .mmi
stf.spill [r2] = f12, 32
stf.spill [r3] = f13, 32
shladd out1 = r15, 3, out1
;;
}
{ .mmb
stf.spill [r2] = f14
stf.spill [r3] = f15
br.call.sptk.many b0 = " #fixup_name "#
}
{ .mii
ld8 r9 = [ret0], 8
adds r2 = 16, r12
adds r3 = 32, r12
;;
}
{ .mmi
ldf.fill f8 = [r2], 32
ldf.fill f9 = [r3], 32
mov b0 = loc1
;;
}
{ .mmi
ldf.fill f10 = [r2], 32
ldf.fill f11 = [r3], 32
mov b6 = r9
;;
}
{ .mmi
ldf.fill f12 = [r2], 32
ldf.fill f13 = [r3], 32
mov ar.pfs = loc0
;;
}
{ .mmi
ldf.fill f14 = [r2], 32
ldf.fill f15 = [r3], 32
adds r12 = 160, r12
;;
}
/* An alloc is needed for the break system call to work.
We don't care about the old value of the pfs register. */
{ .mmb
alloc r2 = ar.pfs, 0, 0, 8, 0
ld8 gp = [ret0]
br.sptk.many b6
;;
}
.endp " #tramp_name "#")
#ifndef PROF
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
#else
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
#endif
/* Initial entry point code for the dynamic linker.
The C function `_dl_start' is the real entry point;
its return value is the user program's entry point. */
#define RTLD_START asm ("\
.text
.global _start#
.proc _start#
_start:
0: { .mii
alloc loc0 = ar.pfs, 0, 3, 4, 0
mov r2 = ip
addl r3 = @gprel(0b), r0
;;
}
{ .mlx
/* Calculate the GP, and save a copy in loc1. */
sub gp = r2, r3
movl r8 = 0x9804c0270033f
;;
}
{ .mii
mov ar.fpsr = r8
sub loc1 = r2, r3
/* _dl_start wants a pointer to the pointer to the arg block
and the arg block starts with an integer, thus the magic 16. */
adds out0 = 16, sp
}
{ .bbb
br.call.sptk.many b0 = _dl_start#
;;
}
.endp _start#
/* FALLTHRU */
.global _dl_start_user#
.proc _dl_start_user#
_dl_start_user:
{ .mii
/* Save the pointer to the user entry point fptr in loc2. */
mov loc2 = ret0
/* Store the highest stack address. */
addl r2 = @ltoff(__libc_stack_end#), gp
addl r3 = @gprel(_dl_skip_args), gp
;;
}
{ .mmi
ld8 r2 = [r2]
ld4 r3 = [r3]
adds r11 = 24, sp /* Load the address of argv. */
;;
}
{ .mii
st8 [r2] = sp
adds r10 = 16, sp /* Load the address of argc. */
mov out2 = r11
;;
/* See if we were run as a command with the executable file
name as an extra leading argument. If so, adjust the argv
pointer to skip _dl_skip_args words.
Note that _dl_skip_args is an integer, not a long - Jes
The stack pointer has to be 16 byte aligned. We cannot simply
addjust the stack pointer. We have to move the whole argv and
envp. H.J. */
}
{ .mmi
ld8 out1 = [r10] /* is argc actually stored as a long
or as an int? */
;;
sub out1 = out1, r3 /* Get the new argc. */
shladd r15 = r3, 3, r11 /* The address of the argv we move */
;;
}
/* ??? Could probably merge these two loops into 3 bundles.
using predication to control which set of copies we're on. */
1: /* Copy argv. */
{ .mfi
ld8 r16 = [r15], 8 /* Load the value in the old argv. */
;;
}
{ .mib
st8 [r11] = r16, 8 /* Store it in the new argv. */
cmp.ne p6, p7 = 0, r16
(p6) br.cond.dptk.few 1b
;;
}
{ .mib
mov out3 = r11
addl out0 = @ltoff(_dl_loaded), gp
}
1: /* Copy env. */
{ .mfi
ld8 r16 = [r15], 8 /* Load the value in the old env. */
;;
}
{ .mib
st8 [r11] = r16, 8 /* Store it in the new env. */
cmp.ne p6, p7 = 0, r16
(p6) br.cond.dptk.few 1b
;;
}
{ .mmb
st8 [r10] = out1 /* Record the new argc. */
ld8 out0 = [out0]
}
{ .mfb
ld8 out0 = [out0] /* get the linkmap */
br.call.sptk.many b0 = _dl_init#
;;
}
/* Pass our finializer function to the user,
and jump to the user's entry point. */
{ .mmi
ld8 r3 = [loc2], 8
mov b0 = r0
}
{ .mmi
addl ret0 = @ltoff(@fptr(_dl_fini#)), gp
;;
mov b6 = r3
}
{ .mmi
ld8 ret0 = [ret0]
ld8 gp = [loc2]
mov ar.pfs = loc0
;;
}
{ .mfb
br.sptk.many b6
;;
}
.endp _dl_start_user#
.previous");
#ifndef RTLD_START_SPECIAL_INIT
#define RTLD_START_SPECIAL_INIT /* nothing */
#endif
/* Nonzero iff TYPE describes relocation of a PLT entry, so
PLT entries should not be allowed to define the value. */
/* ??? Ignore IPLTMSB for now. */
#define elf_machine_lookup_noplt_p(type) ((type) == R_IA64_IPLTLSB)
/* Nonzero iff TYPE should not be allowed to resolve to one of
the main executable's symbols, as for a COPY reloc, which we don't use. */
#define elf_machine_lookup_noexec_p(type) (0)
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
#define ELF_MACHINE_JMP_SLOT R_IA64_IPLTLSB
/* According to the IA-64 specific documentation, Rela is always used. */
#define ELF_MACHINE_NO_REL 1
/* Since ia64's stack has to be 16byte aligned, we cannot arbitrarily
move the stack pointer. */
#define ELF_MACHINE_FIXED_STACK 1
/* Return the address of the entry point. */
extern ElfW(Addr) _dl_start_address (const struct link_map *map,
ElfW(Addr) start);
#define ELF_MACHINE_START_ADDRESS(map, start) \
_dl_start_address ((map), (start))
#define elf_machine_profile_fixup_plt(l, reloc, rel_addr, value) \
elf_machine_fixup_plt ((l), (reloc), (rel_addr), (value))
#define elf_machine_profile_plt(reloc_addr) ((Elf64_Addr) (reloc_addr))
/* Fixup a PLT entry to bounce directly to the function at VALUE. */
static inline Elf64_Addr
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
const Elf64_Rela *reloc,
Elf64_Addr *reloc_addr, Elf64_Addr value)
{
/* l is the link_map for the caller, t is the link_map for the object
* being called */
/* got has already been relocated in elf_get_dynamic_info() */
reloc_addr[1] = t->l_info[DT_PLTGOT]->d_un.d_ptr;
reloc_addr[0] = value;
return (Elf64_Addr) reloc_addr;
}
/* Return the final value of a plt relocation. */
static inline Elf64_Addr
elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
Elf64_Addr value)
{
/* No need to handle rel vs rela since IA64 is rela only */
return value + reloc->r_addend;
}
#endif /* !dl_machine_h */
#ifdef RESOLVE_MAP
#define R_IA64_TYPE(R) ((R) & -8)
#define R_IA64_FORMAT(R) ((R) & 7)
#define R_IA64_FORMAT_32MSB 4
#define R_IA64_FORMAT_32LSB 5
#define R_IA64_FORMAT_64MSB 6
#define R_IA64_FORMAT_64LSB 7
/* Perform the relocation specified by RELOC and SYM (which is fully
resolved). MAP is the object containing the reloc. */
static inline void
elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc,
const Elf64_Sym *sym,
const struct r_found_version *version,
Elf64_Addr *const reloc_addr)
{
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
Elf64_Addr value;
#ifndef RTLD_BOOTSTRAP
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
reference weak so static programs can still link. This declaration
cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP)
because rtld.c contains the common defn for _dl_rtld_map, which is
incompatible with a weak decl in the same file. */
weak_extern (_dl_rtld_map);
#endif
/* We cannot use a switch here because we cannot locate the switch
jump table until we've self-relocated. */
if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_REL64LSB))
{
value = *reloc_addr;
#ifndef RTLD_BOOTSTRAP
/* Already done in dynamic linker. */
if (map != &_dl_rtld_map)
#endif
value += map->l_addr;
}
else if (r_type == R_IA64_NONE)
return;
else
{
struct link_map *sym_map;
/*
* RESOLVE_MAP() will return NULL if it fail to locate the symbol
*/
if ((sym_map = RESOLVE_MAP (&sym, version, r_type)))
{
value = sym ? sym_map->l_addr + sym->st_value : 0;
value += reloc->r_addend;
if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DIR64LSB))
;/* No adjustment. */
else if (r_type == R_IA64_IPLTLSB)
{
elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, value);
return;
}
else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_FPTR64LSB))
#ifndef RTLD_BOOTSTRAP
value = __ia64_make_fptr (sym_map, value, &__fptr_root, NULL);
#else
{
struct ia64_fptr *p_boot_ldso_fptr;
struct ia64_fptr **p_fptr_root;
int *p_fptr_count;
/* Special care must be taken to address these variables
during bootstrap. Further, since we don't know exactly
when __fptr_next will be relocated, we index directly
off __boot_ldso_fptr. */
asm ("addl %0 = @gprel(__boot_ldso_fptr#), gp\n\t"
"addl %1 = @gprel(__fptr_root#), gp\n\t"
"addl %2 = @gprel(__fptr_count#), gp"
: "=r"(p_boot_ldso_fptr),
"=r"(p_fptr_root),
"=r"(p_fptr_count));
/*
* Go from the top - __ia64_make_fptr goes from the bottom,
* this way we will never clash.
*/
value = __ia64_make_fptr (sym_map, value, p_fptr_root,
&p_boot_ldso_fptr[--*p_fptr_count]);
}
#endif
else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_PCREL64LSB))
value -= (Elf64_Addr)reloc_addr & -16;
else
assert (! "unexpected dynamic reloc type");
}
else
value = 0;
}
/* ??? Ignore MSB and Instruction format for now. */
if (R_IA64_FORMAT (r_type) == R_IA64_FORMAT_64LSB)
*reloc_addr = value;
else if (R_IA64_FORMAT (r_type) == R_IA64_FORMAT_32LSB)
*(int *)reloc_addr = value;
else if (r_type == R_IA64_IPLTLSB)
{
reloc_addr[0] = 0;
reloc_addr[1] = 0;
}
else
assert (! "unexpected dynamic reloc format");
}
/* Perform a RELATIVE reloc on the .got entry that transfers to the .plt. */
static inline void
elf_machine_lazy_rel (struct link_map *map,
Elf64_Addr l_addr, const Elf64_Rela *reloc)
{
Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset);
unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
if (r_type == R_IA64_IPLTLSB)
{
reloc_addr[0] += l_addr;
reloc_addr[1] += l_addr;
}
else if (r_type == R_IA64_NONE)
return;
else
assert (! "unexpected PLT reloc type");
}
#endif /* RESOLVE_MAP */

39
sysdeps/ia64/dl-symaddr.c Normal file
View file

@ -0,0 +1,39 @@
/* Get the symbol address. IA-64 version.
Copyright (C) 1999, 2000 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <ldsodefs.h>
#include <dl-machine.h>
void *
_dl_symbol_address (const struct link_map *map, const ElfW(Sym) *ref)
{
Elf64_Addr value = (map ? map->l_addr : 0) + ref->st_value;
/* On ia64, we have to return the pointer to function descriptor. */
if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC)
return (void *) __ia64_make_fptr (map, value, &__fptr_root, NULL);
else
return (void *) value;
}
ElfW(Addr)
_dl_start_address (const struct link_map *map, ElfW(Addr) start)
{
return __ia64_make_fptr (map, start, &__fptr_root, NULL);
}

View file

@ -209,11 +209,12 @@ _dl_start_user:
/* The m68k never uses Elf32_Rel relocations. */
#define ELF_MACHINE_NO_REL 1
static inline void
elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf32_Rela *reloc,
Elf32_Addr *reloc_addr, Elf32_Addr value)
{
*reloc_addr = value;
return *reloc_addr = value;
}
/* Return the final value of a plt relocation. On the m68k the JMP_SLOT

View file

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. PowerPC version.
Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Copyright (C) 1995, 96, 97, 98, 99, 2000 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
@ -47,8 +47,8 @@ elf_machine_dynamic (void)
static inline Elf32_Addr
elf_machine_load_address (void)
{
unsigned *got;
unsigned *branchaddr;
unsigned int *got;
unsigned int *branchaddr;
/* This is much harder than you'd expect. Possibly I'm missing something.
The 'obvious' way:
@ -246,11 +246,19 @@ elf_machine_lazy_rel (struct link_map *map,
}
/* Change the PLT entry whose reloc is 'reloc' to call the actual routine. */
extern void __elf_machine_fixup_plt(struct link_map *map,
const Elf32_Rela *reloc,
Elf32_Addr *reloc_addr,
Elf32_Addr finaladdr);
#define elf_machine_fixup_plt __elf_machine_fixup_plt
extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
const Elf32_Rela *reloc,
Elf32_Addr *reloc_addr,
Elf32_Addr finaladdr);
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *l, lookup_t t,
const Elf32_Rela *reloc,
Elf32_Addr *reloc_addr, Elf64_Addr value)
{
__elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);
return value;
}
/* Return the final value of a plt relocation. */
static inline Elf32_Addr

View file

@ -285,8 +285,9 @@ _dl_start_user:
.size _dl_start_user, . - _dl_start_user
.previous");
static inline void
elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
static inline Elf32_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf32_Rela *reloc,
Elf32_Addr *reloc_addr, Elf32_Addr value)
{
#ifndef RTLD_BOOTSTRAP
@ -315,6 +316,8 @@ elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10);
if (do_flush)
__asm __volatile ("flush %0+4" : : "r"(reloc_addr));
return value;
}
/* Return the final value of a plt relocation. */

View file

@ -66,9 +66,10 @@ elf_machine_load_address (void)
/* We have 4 cases to handle. And we code different code sequences
for each one. I love V9 code models... */
static inline void
elf_machine_fixup_plt(struct link_map *map, const Elf64_Rela *reloc,
Elf64_Addr *reloc_addr, Elf64_Addr value)
static inline Elf64_Addr
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
const Elf64_Rela *reloc,
Elf64_Addr *reloc_addr, Elf64_Addr value)
{
unsigned int *insns = (unsigned int *) reloc_addr;
Elf64_Addr plt_vaddr = (Elf64_Addr) reloc_addr;
@ -156,6 +157,8 @@ elf_machine_fixup_plt(struct link_map *map, const Elf64_Rela *reloc,
insns[1] = 0x03000000 | (high32 >> 10);
__asm __volatile ("flush %0 + 4" : : "r" (insns));
}
return value;
}
/* Return the final value of a plt relocation. */