Re: [PATCH pahole] btf_encoder: preserve and encode exported functions as BTF_KIND_FUNC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Mon, Oct 28, 2019 at 10:30:15PM -0700, Andrii Nakryiko escreveu:
> Add encoding of DWARF's DW_TAG_subprogram_type into BTF's BTF_KIND_FUNC
> (plus corresponding BTF_KIND_FUNC_PROTO). Only exported functions are
> converted for now. This allows to capture all the exported kernel functions,
> same subset that's exposed through /proc/kallsyms.

Applied, added these committer notes:

commit 3c5f2a224aa1934c87525d81ff894c9cad1451a9
Author: Andrii Nakryiko <andriin@xxxxxx>
Date:   Mon Oct 28 22:30:15 2019 -0700

    btf_encoder: Preserve and encode exported functions as BTF_KIND_FUNC
    
    Add encoding of DWARF's DW_TAG_subprogram_type into BTF's BTF_KIND_FUNC
    (plus corresponding BTF_KIND_FUNC_PROTO). Only exported functions are
    converted for now. This allows to capture all the exported kernel
    functions, same subset that's exposed through /proc/kallsyms.
    
    Committer testing:
    
    Before:
    
      $ readelf -SW vmlinux  | grep BTF
        [78] .BTF              PROGBITS        0000000000000000 26a27da9 1e5543 00      0   0  1
      $
    
    After:
    
      $ pahole -J vmlinux
      $ readelf -SW vmlinux  | grep BTF
        [78] .BTF              PROGBITS        0000000000000000 26a27da9 2d5f47 00      0   0  1
      $
    
      >>> 0x2d5f47 - 0x1e5543
      985604
    
    The kernel has a lot of functions! :-)
    
      $ pahole -VJ vmlinux > /tmp/pahole-btf-encoding-verbose-output.txt
    
      $ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | wc -l
      22871
      [acme@quaco pahole]$ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | tail
      [4511543] FUNC copy_from_user_nmi type_id=4511542
      [4512934] FUNC memcpy_page_flushcache type_id=4512933
      [4512936] FUNC __memcpy_flushcache type_id=4512935
      [4512938] FUNC __copy_user_flushcache type_id=4512937
      [4512940] FUNC arch_wb_cache_pmem type_id=4512939
      [4512942] FUNC mcsafe_handle_tail type_id=4512941
      [4512944] FUNC copy_user_handle_tail type_id=4512943
      [4512946] FUNC clear_user type_id=4512945
      [4512948] FUNC __clear_user type_id=4512947
      [4512950] FUNC memcpy type_id=4512949
      $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt | tail
      [4512902] FUNC_PROTO (anon) return=4511725 args=(4512097 (anon), 4511544 (anon))
      [4512933] FUNC_PROTO (anon) return=0 args=(4511598 to, 4511725 page, 4511610 offset, 4511610 len)
      [4512935] FUNC_PROTO (anon) return=0 args=(4511638 _dst, 4511759 _src, 4511610 size)
      [4512937] FUNC_PROTO (anon) return=4511585 args=(4511638 dst, 4511759 src, 4511552 size)
      [4512939] FUNC_PROTO (anon) return=0 args=(4511638 addr, 4511610 size)
      [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
      [4512943] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
      [4512945] FUNC_PROTO (anon) return=4511544 args=(4511638 to, 4511544 n)
      [4512947] FUNC_PROTO (anon) return=4511544 args=(4511638 addr, 4511544 size)
      [4512949] FUNC_PROTO (anon) return=4511638 args=(4511638 p, 4511759 q, 4511591 size)
      $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt |grep 4511542
      [4511542] FUNC_PROTO (anon) return=4510159 args=(4510254 to, 4510374 from, 4510159 n)
      $
    
    With a little change to pdwtags to see DW_TAG_subroutine_type, which is
    what BTF's KIND_FUNC_PROTO maps to, we see some of those last
    prototypes:
    
    [acme@quaco pahole]$ pdwtags -F btf vmlinux  | grep '()(' | tail
    void ()(struct insn * insn); /* size: 45404744 */
    int ()(struct insn * insn); /* size: 4 */
    void ()(struct insn * insn, const void  * kaddr, int buf_len, int x86_64); /* size: 45405032 */
    long unsigned int ()(const char  * purpose); /* size: 8 */
    void ()(char * to, struct page * page, size_t offset, size_t len); /* size: 45405864 */
    void ()(void * _dst, const void  * _src, size_t size); /* size: 45406200 */
    long int ()(void * dst, const void  * src, unsigned int size); /* size: 8 */
    long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */
    long unsigned int ()(void * to, long unsigned int n); /* size: 8 */
    long unsigned int ()(void * addr, long unsigned int size); /* size: 8 */
    [acme@quaco pahole]$
    
    I.e.:
    
      [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
    
    gets decoded by pdwtags as:
    
      long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */
    
      $ grep '\[\(4511544\|4511598\|4511550\|4511552\)\]' /tmp/pahole-btf-encoding-verbose-output.txt
      [4511544] INT long unsigned int size=8 bit_offset=0 nr_bits=64 encoding=(none)
      [4511550] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
      [4511552] INT unsigned int size=4 bit_offset=0 nr_bits=32 encoding=(none)
      [4511598] PTR (anon) type_id=4511550
      $
    
    Signed-off-by: Andrii Nakryiko <andriin@xxxxxx>
    Tested-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Tested-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
    Acked-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Cc: Alexei Starovoitov <ast@xxxxxx>
    Cc: Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx>
    Cc: Yonghong Song <yhs@xxxxxx>
    Cc: dwarves@xxxxxxxxxxxxxxx
    Cc: kernel-team@xxxxxx
    Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

diff --git a/btf_encoder.c b/btf_encoder.c
index f85b978a3981..df16ba0ae98e 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -173,6 +173,7 @@ int cu__encode_btf(struct cu *cu, int verbose)
 	bool add_index_type = false;
 	uint32_t type_id_off;
 	uint32_t core_id;
+	struct function *fn;
 	struct tag *pos;
 	int err = 0;
 
@@ -225,6 +226,21 @@ int cu__encode_btf(struct cu *cu, int verbose)
 		btf_elf__add_base_type(btfe, &bt);
 	}
 
+	cu__for_each_function(cu, core_id, fn) {
+		int btf_fnproto_id, btf_fn_id;
+
+		if (fn->declaration || !fn->external)
+			continue;
+
+		btf_fnproto_id = btf_elf__add_func_proto(btfe, &fn->proto, type_id_off);
+		btf_fn_id = btf_elf__add_ref_type(btfe, BTF_KIND_FUNC, btf_fnproto_id, fn->name, false);
+		if (btf_fnproto_id < 0 || btf_fn_id < 0) {
+			err = -1;
+			printf("error: failed to encode function '%s'\n", function__name(fn, cu));
+			goto out;
+		}
+	}
+
 out:
 	if (err)
 		btf_elf__delete(btfe);
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 4c6783b9af7e..09edcfb91bf0 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -920,6 +920,7 @@ static struct function *function__new(Dwarf_Die *die, struct cu *cu)
 		func->name	      = strings__add(strings, attr_string(die, DW_AT_name));
 		func->linkage_name    = strings__add(strings, attr_string(die, DW_AT_MIPS_linkage_name));
 		func->inlined	      = attr_numeric(die, DW_AT_inline);
+		func->declaration     = dwarf_hasattr(die, DW_AT_declaration);
 		func->external	      = dwarf_hasattr(die, DW_AT_external);
 		func->abstract_origin = dwarf_hasattr(die, DW_AT_abstract_origin);
 		dwarf_tag__set_spec(func->proto.tag.priv,
diff --git a/dwarves.h b/dwarves.h
index b162e751cc99..b53bdfc2bca9 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -784,6 +784,7 @@ struct function {
 	uint8_t		 external:1;
 	uint8_t		 accessibility:2; /* DW_ACCESS_{public,protected,private} */
 	uint8_t		 virtuality:2; /* DW_VIRTUALITY_{none,virtual,pure_virtual} */
+	uint8_t		 declaration:1;
 	int32_t		 vtable_entry;
 	struct list_head vtable_node;
 	/* fields used by tools */



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux