2 # Based on this commit:
4 # commit 62058ce612ed3459501b4c4332e268edfe977f59
5 # Author: Carlos O'Donell <carlos@redhat.com>
6 # Date: Mon Sep 29 13:14:21 2014 -0400
8 # Correctly size profiling reloc table (bug 17411)
10 # During auditing or profiling modes the dynamic loader
11 # builds a cache of the relocated PLT entries in order
12 # to reuse them when called again through the same PLT
13 # entry. This way the PLT entry is never completed and
14 # the call into the resolver always results in profiling
15 # or auditing code running.
17 # The problem is that the PLT relocation cache size
18 # is not computed correctly. The size of the cache
19 # should be "Size of a relocation result structure"
20 # x "Number of PLT-related relocations". Instead the
21 # code erroneously computes "Size of a relocation
22 # result" x "Number of bytes worth of PLT-related
23 # relocations". I can only assume this was a mistake
24 # in the understanding of the value of DT_PLTRELSZ
25 # which is the number of bytes of PLT-related relocs.
26 # We do have a DT_RELACOUNT entry, which is a count
27 # for dynamic relative relocs, but we have no
28 # DT_PLTRELCOUNT and thus we need to compute it.
30 # This patch corrects the computation of the size of the
31 # relocation table used by the glibc profiling code.
33 # For more details see:
34 # https://sourceware.org/ml/libc-alpha/2014-09/msg00513.html
37 # * elf/dl-reloc.c (_dl_relocate_object): Allocate correct amount for
40 diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
41 index d2c6dac..97a7119 100644
44 @@ -279,8 +279,12 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
48 - l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
49 - l->l_info[DT_PLTRELSZ]->d_un.d_val);
50 + size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA
51 + ? sizeof (ElfW(Rela))
52 + : sizeof (ElfW(Rel));
53 + size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel;
54 + l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount);
56 if (l->l_reloc_result == NULL)