Browse Source

Joakim Tjernlund writes:

PPC32, SPARC32/64 and S390 includes the PLT in its RELA size. This caused ldso
to always do unlazy relocation of the JMPRELs. This patch fixes it.
Eric Andersen 21 years ago
parent
commit
758d1c9ff6
3 changed files with 17 additions and 1 deletions
  1. 10 1
      ldso/ldso/dl-elf.c
  2. 4 0
      ldso/ldso/powerpc/dl-sysdep.h
  3. 3 0
      ldso/ldso/sparc/dl-sysdep.h

+ 10 - 1
ldso/ldso/dl-elf.c

@@ -734,6 +734,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int flag)
 {
 	int goof = 0;
 	struct elf_resolve *tpnt;
+	unsigned long reloc_size;
 
 	if (rpnt->next)
 		goof += _dl_fixup(rpnt->next, flag);
@@ -754,13 +755,21 @@ int _dl_fixup(struct dyn_elf *rpnt, int flag)
 		return goof;
 	}
 
+/* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
+   range.  Note that according to the ELF spec, this is completely legal! */
+#ifdef ELF_MACHINE_PLTREL_OVERLAP
+	reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE] - 
+		tpnt->dynamic_info [DT_PLTRELSZ];
+#else
+	reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
+#endif
 	if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]) {
 		if (tpnt->init_flag & RELOCS_DONE)
 			return goof;
 		tpnt->init_flag |= RELOCS_DONE;
 		goof += _dl_parse_relocation_information(rpnt,
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
-				tpnt->dynamic_info[DT_RELOC_TABLE_SIZE], 0);
+				reloc_size, 0);
 	}
 
 	if (tpnt->dynamic_info[DT_JMPREL]) {

+ 4 - 0
ldso/ldso/powerpc/dl-sysdep.h

@@ -87,3 +87,7 @@ void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt);
     || (type) == R_PPC_REL24				\
     || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* The SVR4 ABI specifies that the JMPREL relocs must be inside the
+   DT_RELA table.  */
+#define ELF_MACHINE_PLTREL_OVERLAP 1

+ 3 - 0
ldso/ldso/sparc/dl-sysdep.h

@@ -107,3 +107,6 @@ sparc_mod(unsigned long m, unsigned long p)
 #define elf_machine_type_class(type) \
   ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)			      \
    | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* The SPARC overlaps DT_RELA and DT_PLTREL.  */
+#define ELF_MACHINE_PLTREL_OVERLAP 1