1. 16 Apr, 2024 2 commits
    • Namhyung Kim's avatar
      perf dwarf-aux: Check pointer offset when checking variables · 645af3fb
      Namhyung Kim authored
      In match_var_offset(), it checks the offset range with the target type
      only for non-pointer types.  But it also needs to check the pointer
      types with the target type.
      
      This is because there can be more than one pointer variable located in
      the same register.  Let's look at the following example.  It's looking
      up a variable for reg3 at tcp_get_info+0x62.  It found "sk" variable but
      it wasn't the right one since it accesses beyond the target type (struct
      'sock' in this case) size.
      
        -----------------------------------------------------------
        find data type for 0x7bc(reg3) at tcp_get_info+0x62
        CU for net/ipv4/tcp.c (die:0x7b5f516)
        frame base: cfa=0 fbreg=6
        offset: 1980 is bigger than size: 760
        check variable "sk" failed (die: 0x7b92b2c)
         variable location: reg3
         type='struct sock' size=0x2f8 (die:0x7b63c3ab)
      
      Actually there was another variable "tp" in the function and it's
      located at the same (reg3) because it's just type-casted like below.
      
        void tcp_get_info(struct sock *sk, struct tcp_info *info)
        {
            const struct tcp_sock *tp = tcp_sk(sk);
            ...
      
      The 'struct tcp_sock' contains the 'struct sock' at offset 0 so it can
      just use the same address as a pointer to tcp_sock.  That means it
      should match variables correctly by checking the offset and size.
      Actually it cannot distinguish if the offset was smaller than the size
      of the original struct sock.  But I think it's fine as they are the same
      at that part.
      
      So let's check the target type size and retry if it doesn't match.
      Now it succeeded to find the correct variable.
      
        -----------------------------------------------------------
        find data type for 0x7bc(reg3) at tcp_get_info+0x62
        CU for net/ipv4/tcp.c (die:0x7b5f516)
        frame base: cfa=0 fbreg=6
        found "tp" in scope=1/1 (die: 0x7b92b16) type_offset=0x7bc
         variable location: reg3
         type='struct tcp_sock' size=0xa68 (die:0x7b81380)
      
      Fixes: bc10db8e ("perf annotate-data: Support stack variables")
      Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
      Cc: Adrian Hunter <adrian.hunter@intel.com>
      Cc: Ian Rogers <irogers@google.com>
      Cc: Ingo Molnar <mingo@kernel.org>
      Cc: Jiri Olsa <jolsa@kernel.org>
      Cc: Kan Liang <kan.liang@linux.intel.com>
      Cc: Masami Hiramatsu <mhiramat@kernel.org>
      Cc: Namhyung Kim <namhyung@kernel.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Link: https://lore.kernel.org/r/20240412183310.2518474-3-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      645af3fb
    • Namhyung Kim's avatar
      perf annotate-data: Improve debug message with location info · 2bc3cf57
      Namhyung Kim authored
      To verify it found the correct variable, let's add the location
      expression to the debug message.
      
        $ perf --debug type-profile annotate --data-type
        ...
        -----------------------------------------------------------
        find data type for 0xaf0(reg15) at schedule+0xeb
        CU for kernel/sched/core.c (die:0x1180523)
        frame base: cfa=0 fbreg=6
        found "rq" in scope=3/4 (die: 0x11b6a00) type_offset=0xaf0
         variable location: reg15
         type='struct rq' size=0xfc0 (die:0x11892e2)
        -----------------------------------------------------------
        find data type for 0x7bc(reg3) at tcp_get_info+0x62
        CU for net/ipv4/tcp.c (die:0x7b5f516)
        frame base: cfa=0 fbreg=6
        offset: 1980 is bigger than size: 760
        check variable "sk" failed (die: 0x7b92b2c)
         variable location: reg3
         type='struct sock' size=0x2f8 (die:0x7b63c3ab)
        -----------------------------------------------------------
        ...
      
      The first case is fine.  It looked up a data type in r15 with offset of
      0xaf0 at schedule+0xeb.  It found the CU die and the frame base info and
      the variable "rq" was found in the scope 3/4.  Its location is the r15
      register and the type size is 0xfc0 which includes 0xaf0.
      
      But the second case is not good.  It looked up a data type in rbx (reg3)
      with offset 0x7bc.  It found a CU and the frame base which is good so
      far.  And it also found a variable "sk" but the access offset is bigger
      than the type size (1980 vs. 760 or 0x7bc vs. 0x2f8).  The variable has
      the right location (reg3) but I need to figure out why it accesses
      beyond what it's supposed to.
      Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
      Cc: Adrian Hunter <adrian.hunter@intel.com>
      Cc: Ian Rogers <irogers@google.com>
      Cc: Ingo Molnar <mingo@kernel.org>
      Cc: Jiri Olsa <jolsa@kernel.org>
      Cc: Kan Liang <kan.liang@linux.intel.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Link: https://lore.kernel.org/r/20240412183310.2518474-2-namhyung@kernel.org
      [ Fix the build on 32-bit by casting Dwarf_Word to (long) in pr_debug_location() ]
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      2bc3cf57
  2. 12 Apr, 2024 29 commits
  3. 08 Apr, 2024 9 commits