ソースを参照

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 年 前
コミット
758d1c9ff6
3 ファイル変更17 行追加1 行削除
  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;
 	int goof = 0;
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
+	unsigned long reloc_size;
 
 
 	if (rpnt->next)
 	if (rpnt->next)
 		goof += _dl_fixup(rpnt->next, flag);
 		goof += _dl_fixup(rpnt->next, flag);
@@ -754,13 +755,21 @@ int _dl_fixup(struct dyn_elf *rpnt, int flag)
 		return goof;
 		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->dynamic_info[DT_RELOC_TABLE_ADDR]) {
 		if (tpnt->init_flag & RELOCS_DONE)
 		if (tpnt->init_flag & RELOCS_DONE)
 			return goof;
 			return goof;
 		tpnt->init_flag |= RELOCS_DONE;
 		tpnt->init_flag |= RELOCS_DONE;
 		goof += _dl_parse_relocation_information(rpnt,
 		goof += _dl_parse_relocation_information(rpnt,
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
-				tpnt->dynamic_info[DT_RELOC_TABLE_SIZE], 0);
+				reloc_size, 0);
 	}
 	}
 
 
 	if (tpnt->dynamic_info[DT_JMPREL]) {
 	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_REL24				\
     || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
     || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
    | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
    | (((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) \
 #define elf_machine_type_class(type) \
   ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)			      \
   ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)			      \
    | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
    | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
+
+/* The SPARC overlaps DT_RELA and DT_PLTREL.  */
+#define ELF_MACHINE_PLTREL_OVERLAP 1