# tracing\_system

### 简介

![Linux\_Tracing\_System](/files/w711p6NEmFlOZ7jGfHrd)

静态探针，`Tracepoint`：预先在目标函数调用钩子函数

动态探针，`Kprobe`：在运行时，将目标函数的某一个函数对应的指令替换成钩子函数

`Ftrace`：在编译时，在目标函数入口处加入两个 `NOP` 指令， 在启动初始化过程中，将 第一个 `NOP` 指令 替换成 `MOV X9, LR` 指令， 最后使能trace功能时，将第二个 `NOP` 指令替换成钩子函数

### Tracepoint原理

```
Documentation/trace/tracepoints.rst
Documentation/trace/tracepoint-analysis.rst
Documentation/trace/events.rst
```

### Kprobe原理

`kprobe` 可以用来跟踪内核函数中某一条指令在运行前和运行后的情况。

我们只需在 `kprobe` 模块中定义好指令执行前的回调函数 `pre_handler()` 和执行后的回调函数 `post_handler()`， 那么内核将会在被跟踪的指令执行前调用 `pre_handler()` 函数，并且在指令执行后调用 `post_handler()` 函数

具体流程如下：

![kprobe](/files/3FXoqO6Y34FghHHiffvp)

当使用 `kprobe` 来跟踪内核函数的某条指令时，`kprobe` 首先会把要追踪的指令保存起来， 然后把要追踪的指令替换成 `INT3` 指令，当内核执行到这条指令时，将会触发 `do_int3()` 异常处理例程

`do_int3()` 异常处理流程为：首先调用 `kprobe` 模块的 `pre_handler()` 回调函数， 然后将 CPU 设置为单步调试模式，接着从异常处理例程中返回，并且执行原来的指令。

由于设置了单步调试模式，当执行完原来的指令后，将会触发 `debug` 异常（这是 `Intel x86 CPU` 的一个特性）

内核将会执行 `debug` 异常处理例程 `do_debug()`，而 `do_debug()` 异常处理例程将会 调用 `kprobe` 模块的 `post_handler()` 回调函数

### Ftrace

> Base aarch64
>
> Documentation/trace/ftrace-design.rst
>
> Documentation/trace/ftrace.rst

![ftrace](/files/MBz9epmjpXbxzTuqRDXi)

`GCC` 编译时加上 `-fpatchable-function-entry=2` 参数，编译后，自动在目标函数入口处加入两个 `NOP` 指令， 同时将第一条 `NOP` 指令所在的地址 存储在 `__patchable_function_entries` 段中，链接时，将所有 `.o` 的 `__patchable_function_entries` 段 整合存储到 `[__start_mcount_loc, __stop_mcount_loc]` 区域中， 即 `[__start_mcount_loc, __stop_mcount_loc]` 区域 存储 所有函数入口处的第一条 `NOP` 指令所在的地址

在启动初始化过程中，`start_kernel() -> ftrace_init()`，从区域 `[__start_mcount_loc, __stop_mcount_loc]` 中 获得所有函数入口处的第二条 `NOP` 指令所在的地址 保存在 `struct dyn_ftrace->ip` 中， 其中 `struct dyn_ftrace` 所占内存是通过页分配器动态分配出来的， 同时调用 `ftrace_init_nop()` 将 第一个 `NOP` 指令 替换成 `MOV X9, LR` 指令

最后使能trace功能中，通过对 `/sys/kernel/traing/current_tracer` 配置使用哪一种 `tracer` 时， 将调用 `ftrace_make_call()` 将第二个 `NOP` 指令替换成 `BL ftrace_caller` 指令来调用钩子函数 , `ftrace_caller()` 会根据 `/sys/kernel/traing/xxx` 的配置，调用用户注册的 `trace` 函数


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://vernon2gb.gitbook.io/notes/linuxkernel/tracing_system.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
