Bug#350501: nscd: [hppa] error while loading shared libraries: unexpected reloc type 0x42
tag 350501 + patch
thanks
Hi,
The problem is that since version all network daemons, including nscd,
are built with -fPIE, thanks to RedHat. GCC treats this flag just as
-fPIC, but binutils generates relocs of type R_PARISC_PLABEL14 and
R_PARISC_PLABEL21. Glibc does not handle those relocs.
Currently we have the choice of building them with -fPIE or not building
them at all.
The workaround would be to build snscd without -fPIE, but that would say
hacking nscd/Makefile, as Gentoo does. There is a proper fix that has
been comitted on cvs.parisc-linux.org last July. It adds support for
those relocs.
Please find attached the patch that could be put in debian/patches. I
have tested it successfully on a 2.3.6 glibc (SVN r1164).
Bye,
Aurelien
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
2005-06-10 Randolph Chung <tausq@debian.org>
* elf/elf.h (R_PARISC_PLABEL21L, R_PARISC_PLABEL14R): Define.
* sysdeps/hppa/dl-machine.h (reassemble_21, reassemble_14): Define.
(elf_machine_rela): Handle R_PARISC_DIR21L/14R and
R_PARISC_PLABEL21L/14R relocations.
===================================================================
RCS file: /var/lib/cvs/glibc/elf/elf.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- glibc/elf/elf.h 2005/06/09 01:14:04 1.3
+++ glibc/elf/elf.h 2005/06/10 23:41:20 1.4
@@ -1703,6 +1703,8 @@
#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
#define R_PARISC_FPTR64 64 /* 64 bits function address. */
#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
+#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fct ptr. */
+#define R_PARISC_PLABEL14R 70 /* Left 21 bits of fct ptr. */
#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
===================================================================
RCS file: /var/lib/cvs/glibc/sysdeps/hppa/dl-machine.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- glibc/sysdeps/hppa/dl-machine.h 2005/06/09 04:27:13 1.3
+++ glibc/sysdeps/hppa/dl-machine.h 2005/06/10 23:41:20 1.4
@@ -223,7 +223,8 @@
}
else
{
- if (_dl_name_match_p (GLRO(dl_profile), l))
+ if (GLRO(dl_profile) != NULL
+ && _dl_name_match_p (GLRO(dl_profile), l))
{
/* This is the object we are looking for. Say that
we really want profiling and the timers are
@@ -514,6 +515,18 @@
/* These are only actually used where RESOLVE_MAP is defined, anyway. */
#ifdef RESOLVE_MAP
+
+#define reassemble_21(as21) \
+ ( (((as21) & 0x100000) >> 20) \
+ | (((as21) & 0x0ffe00) >> 8) \
+ | (((as21) & 0x000180) << 7) \
+ | (((as21) & 0x00007c) << 14) \
+ | (((as21) & 0x000003) << 12))
+
+#define reassemble_14(as14) \
+ ( (((as14) & 0x1fff) << 1) \
+ | (((as14) & 0x2000) >> 13))
+
auto void __attribute__((always_inline))
elf_machine_rela (struct link_map *map,
const Elf32_Rela *reloc,
@@ -573,6 +586,27 @@
}
break;
+ case R_PARISC_DIR21L:
+ {
+ unsigned int insn = *(unsigned int *)reloc_addr;
+ value = sym_map->l_addr + sym->st_value
+ + ((reloc->r_addend + 0x1000) & -0x2000);
+ value = value >> 11;
+ insn = (insn &~ 0x1fffff) | reassemble_21 (value);
+ *(unsigned int *)reloc_addr = insn;
+ }
+ return;
+
+ case R_PARISC_DIR14R:
+ {
+ unsigned int insn = *(unsigned int *)reloc_addr;
+ value = ((sym_map->l_addr + sym->st_value) & 0x7ff)
+ + (((reloc->r_addend & 0x1fff) ^ 0x1000) - 0x1000);
+ insn = (insn &~ 0x3fff) | reassemble_14 (value);
+ *(unsigned int *)reloc_addr = insn;
+ }
+ return;
+
case R_PARISC_PLABEL32:
/* Easy rule: If there is a symbol and it is global, then we
need to make a dynamic function descriptor. Otherwise we
@@ -591,6 +625,31 @@
value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
break;
+ case R_PARISC_PLABEL21L:
+ case R_PARISC_PLABEL14R:
+ {
+ unsigned int insn = *(unsigned int *)reloc_addr;
+
+ if (__builtin_expect (sym == NULL, 0))
+ break;
+
+ value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
+
+ if (r_type == R_PARISC_PLABEL21L)
+ {
+ value >>= 11;
+ insn = (insn &~ 0x1fffff) | reassemble_21 (value);
+ }
+ else
+ {
+ value &= 0x7ff;
+ insn = (insn &~ 0x3fff) | reassemble_14 (value);
+ }
+
+ *(unsigned int *)reloc_addr = insn;
+ }
+ return;
+
case R_PARISC_IPLT:
if (__builtin_expect (sym_map != NULL, 1))
{
Reply to: