bpf: Add size arg to build_id_parse function
authorJiri Olsa <jolsa@kernel.org>
Thu, 14 Jan 2021 13:40:43 +0000 (14:40 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 15 Jan 2021 03:29:58 +0000 (19:29 -0800)
It's possible to have other build id types (other than default SHA1).
Currently there's also ld support for MD5 build id.

Adding size argument to build_id_parse function, that returns (if defined)
size of the parsed build id, so we can recognize the build id type.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210114134044.1418404-3-jolsa@kernel.org
include/linux/buildid.h
kernel/bpf/stackmap.c
lib/buildid.c

index 08028a2..40232f9 100644 (file)
@@ -6,6 +6,7 @@
 
 #define BUILD_ID_SIZE_MAX 20
 
-int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id);
+int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
+                  __u32 *size);
 
 #endif
index 55d254a..cabaf7d 100644 (file)
@@ -189,7 +189,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
 
        for (i = 0; i < trace_nr; i++) {
                vma = find_vma(current->mm, ips[i]);
-               if (!vma || build_id_parse(vma, id_offs[i].build_id)) {
+               if (!vma || build_id_parse(vma, id_offs[i].build_id, NULL)) {
                        /* per entry fall back to ips */
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
index 4a4f520..6156997 100644 (file)
@@ -12,6 +12,7 @@
  */
 static inline int parse_build_id(void *page_addr,
                                 unsigned char *build_id,
+                                __u32 *size,
                                 void *note_start,
                                 Elf32_Word note_size)
 {
@@ -38,6 +39,8 @@ static inline int parse_build_id(void *page_addr,
                               nhdr->n_descsz);
                        memset(build_id + nhdr->n_descsz, 0,
                               BUILD_ID_SIZE_MAX - nhdr->n_descsz);
+                       if (size)
+                               *size = nhdr->n_descsz;
                        return 0;
                }
                new_offs = note_offs + sizeof(Elf32_Nhdr) +
@@ -50,7 +53,8 @@ static inline int parse_build_id(void *page_addr,
 }
 
 /* Parse build ID from 32-bit ELF */
-static int get_build_id_32(void *page_addr, unsigned char *build_id)
+static int get_build_id_32(void *page_addr, unsigned char *build_id,
+                          __u32 *size)
 {
        Elf32_Ehdr *ehdr = (Elf32_Ehdr *)page_addr;
        Elf32_Phdr *phdr;
@@ -65,7 +69,7 @@ static int get_build_id_32(void *page_addr, unsigned char *build_id)
 
        for (i = 0; i < ehdr->e_phnum; ++i) {
                if (phdr[i].p_type == PT_NOTE &&
-                   !parse_build_id(page_addr, build_id,
+                   !parse_build_id(page_addr, build_id, size,
                                    page_addr + phdr[i].p_offset,
                                    phdr[i].p_filesz))
                        return 0;
@@ -74,7 +78,8 @@ static int get_build_id_32(void *page_addr, unsigned char *build_id)
 }
 
 /* Parse build ID from 64-bit ELF */
-static int get_build_id_64(void *page_addr, unsigned char *build_id)
+static int get_build_id_64(void *page_addr, unsigned char *build_id,
+                          __u32 *size)
 {
        Elf64_Ehdr *ehdr = (Elf64_Ehdr *)page_addr;
        Elf64_Phdr *phdr;
@@ -89,7 +94,7 @@ static int get_build_id_64(void *page_addr, unsigned char *build_id)
 
        for (i = 0; i < ehdr->e_phnum; ++i) {
                if (phdr[i].p_type == PT_NOTE &&
-                   !parse_build_id(page_addr, build_id,
+                   !parse_build_id(page_addr, build_id, size,
                                    page_addr + phdr[i].p_offset,
                                    phdr[i].p_filesz))
                        return 0;
@@ -97,8 +102,16 @@ static int get_build_id_64(void *page_addr, unsigned char *build_id)
        return -EINVAL;
 }
 
-/* Parse build ID of ELF file mapped to vma */
-int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id)
+/*
+ * Parse build ID of ELF file mapped to vma
+ * @vma:      vma object
+ * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
+ * @size:     returns actual build id size in case of success
+ *
+ * Returns 0 on success, otherwise error (< 0).
+ */
+int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
+                  __u32 *size)
 {
        Elf32_Ehdr *ehdr;
        struct page *page;
@@ -126,9 +139,9 @@ int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id)
                goto out;
 
        if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
-               ret = get_build_id_32(page_addr, build_id);
+               ret = get_build_id_32(page_addr, build_id, size);
        else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
-               ret = get_build_id_64(page_addr, build_id);
+               ret = get_build_id_64(page_addr, build_id, size);
 out:
        kunmap_atomic(page_addr);
        put_page(page);