2

I have a system tap script that probes the kernel function "memcpy". I want to print the stack trace based on the content of the src buffer which is a void pointer.

My code:

%{
        #include <linux/string.h>
%}
probe begin
{
        printf("Begin\n");
}
probe kernel.function("memcpy")
{
        buffer = @cast($src, "char");
        if (isinstr(buffer, "some pattern") != NULL) {
                printf("Found\n");
                print_backtrace();
        }
}

This script gives me an error when I ran the script as follows: "stap -g stacktrace.stp"

unresolved target-symbol expression: identifier '$src'

semantic error: type mismatch (string): identifier 'buffer' at stacktrace.stp:31:14

 source:         if (isinstr(buffer, "shubham") != NULL) {
                                ^

semantic error: type was first inferred here (long): identifier 'buffer' at :30:2

   source:         buffer = @cast($src, "char");
                    ^

Pass 2: analysis failed. [man error::pass2]

I have seen function definition of memcpy in linux kernel code and the parameter is named as src only. I am unable to get the variable name resolved. I tried different names $src, $from, $s, but nothing worked.

The machine's kernel version is: 3.10.0-514.el7.x86_64 (RHEL 7.3 (Maipo))

The following kernel packages are installed on it:

  • kernel-debuginfo-common-x86_64-3.10.0-514.el7.x86_64
  • kernel-3.10.0-514.el7.x86_64
  • kernel-headers-3.10.0-514.el7.x86_64
  • kernel-debuginfo-3.10.0-514.el7.x86_64
  • kernel-devel-3.10.0-514.el7.x86_64
Shubham Pendharkar
  • 310
  • 1
  • 4
  • 17
  • 1
    I think all you need is `buffer = kernel_string($src);`, but if you could explain why you want to cast the void* to char - maybe you just want one byte? - we can help with that. – Mark Plotnick Feb 20 '19 at 23:34
  • First of all I am getting an error saying that the variable src is non resolvable. I don't know why this error is getting generated even though memcpy has src as a parameter. Now, coming to your question @MarkPlotnick, I want to read the content of the buffer passed to memcpy and want to compare it with a predefined pattern, that is the reason I want to cast it to a char*. – Shubham Pendharkar Feb 21 '19 at 06:18
  • In your revised question, you say that systemtap can't resolve `$src`. Can you edit your question to say what distribution you're running and which kernel-devel, kernel-debug, and kernel-debuginfo packages you have installed? – Mark Plotnick Feb 21 '19 at 16:04
  • @MarkPlotnick, added all the configuration details. – Shubham Pendharkar Feb 21 '19 at 16:53
  • 1
    use stap -L 'kernel.function("memcpy")' to see what variables are available at that probe point. – fche Feb 01 '20 at 04:52

2 Answers2

0

Update 2:

buffer = @cast($src, "char");

Should that be a char pointer instead of a char?


Update 1: From the systemtap docs

semantic error: unresolved target-symbol expression

A target variable was referred to in a probe handler that was not resolvable. Or, a target variable is not valid at all in a context such as a script function. This variable may have been elided by an optimizing compiler, or may not have a suitable type, or there might just be an annoying bug somewhere. Try again with a slightly different probe point (use statement() instead of function()) to search for a more cooperative neighbour in the same area.


Original ramblings

The concept of the variable as a friendly thing called src only exists in the human-readable source code. Look around your code. You haven't declared anything variables named src.

I have seen function definition of memcpy in linux kernel code and the parameter is named as src

Yes, but once again that is all for the benefit of the human.


The part you are missing is that when source code is compiled into an application the compiler collates all of our human constructs and turns them into stack offsets.

Warning: I'm totally ignoring function calling conventions for simplicity.

If you look at the compiled binary, for your platform, you can see some better hints for what you need to do. Assuming you are on an x86 system you would see something like this:

memcpy:
  push ebp
  mov ebp, esp
  sub esp, 8

  // The function body starts here and you will see references 
  // to what we recognize as the variable "src" with an instructions like

  mov edi, esp+0
  // That just loaded the EDI register with a reference to the location of src

You can see the assembly for your platform using gdb.

Guy Hoozdis
  • 111
  • 1
  • 6
  • Using the disassembly I still won't be able to find the parameter name of the function memcpy. What do you suggest to get it resolved? Also, "buffer = @cast($src, "char");" here the cast operator returns a "long" as a data type, and not a string or character pointer which I needed. – Shubham Pendharkar Feb 28 '19 at 14:07
0

gcc debuginfo for the kernel may be inconsistent in preserving the formal parameters for inlined copies of memcpy in every place it's used.

stap -vL 'kernel.function("memcpy").*'

should list individual or a summary of all sites. Chances are something like

stap -e '
  probe kernel.function("memcpy") 
   { if (@defined($p) && @defined($q)) println($p, " ", $q) }'

may do the trick. It will only fire the println in those probe locations where both those parameters are defined. On my more recent kernel, one sees variations like ...

kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x68c6a */ $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x178ec */ $size:__kernel_size_t $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x15a31 */ $size:__kernel_size_t $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x13f1f */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0xc717 */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t

... so the stap code must tolerate the gamut.

fche
  • 2,641
  • 20
  • 28