perf tools: Fix copying of /proc/kcore
authorAdrian Hunter <adrian.hunter@intel.com>
Thu, 24 Sep 2015 10:05:22 +0000 (13:05 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 25 Sep 2015 13:45:50 +0000 (10:45 -0300)
A copy of /proc/kcore containing the kernel text can be made to the
buildid cache. e.g.

perf buildid-cache -v -k /proc/kcore

To workaround objdump limitations, a copy is also made when annotating
against /proc/kcore.

The copying process stops working from libelf about v1.62 onwards (the
problem was found with v1.63).

The cause is that a call to gelf_getphdr() in kcore__add_phdr() fails
because additional validation has been added to gelf_getphdr().

The use of gelf_getphdr() is a misguided attempt to get default
initialization of the Gelf_Phdr structure.  That should not be
necessary because every member of the Gelf_Phdr structure is
subsequently assigned.  So just remove the call to gelf_getphdr().

Similarly, a call to gelf_getehdr() in gelf_kcore__init() can be
removed also.

Committer notes:

Note to stable@kernel.org, from Adrian in the cover letter for this
patchkit:

The "Fix copying of /proc/kcore" problem goes back to v3.13 if you think
it is important enough for stable.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: stable@kernel.org
Link: http://lkml.kernel.org/r/1443089122-19082-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/symbol-elf.c

index f78ea3dc4c084b632ac438782787eda2225e7bde..475d88d0a1c9a772323b3218cfcf5f5900c0e809 100644 (file)
@@ -1271,8 +1271,6 @@ out_close:
 static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
                       bool temp)
 {
-       GElf_Ehdr *ehdr;
-
        kcore->elfclass = elfclass;
 
        if (temp)
@@ -1289,9 +1287,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
        if (!gelf_newehdr(kcore->elf, elfclass))
                goto out_end;
 
-       ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
-       if (!ehdr)
-               goto out_end;
+       memset(&kcore->ehdr, 0, sizeof(GElf_Ehdr));
 
        return 0;
 
@@ -1348,23 +1344,18 @@ static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
 static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
                           u64 addr, u64 len)
 {
-       GElf_Phdr gphdr;
-       GElf_Phdr *phdr;
-
-       phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
-       if (!phdr)
-               return -1;
-
-       phdr->p_type    = PT_LOAD;
-       phdr->p_flags   = PF_R | PF_W | PF_X;
-       phdr->p_offset  = offset;
-       phdr->p_vaddr   = addr;
-       phdr->p_paddr   = 0;
-       phdr->p_filesz  = len;
-       phdr->p_memsz   = len;
-       phdr->p_align   = page_size;
-
-       if (!gelf_update_phdr(kcore->elf, idx, phdr))
+       GElf_Phdr phdr = {
+               .p_type         = PT_LOAD,
+               .p_flags        = PF_R | PF_W | PF_X,
+               .p_offset       = offset,
+               .p_vaddr        = addr,
+               .p_paddr        = 0,
+               .p_filesz       = len,
+               .p_memsz        = len,
+               .p_align        = page_size,
+       };
+
+       if (!gelf_update_phdr(kcore->elf, idx, &phdr))
                return -1;
 
        return 0;