chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

如何使用gobpf和uprobe來為Go程序構建函數(shù)參數(shù)跟蹤程序

Linux閱碼場 ? 來源:Linux內(nèi)核之旅 ? 作者:Zain Asgar, 陳恒奇 ? 2021-04-03 16:15 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

這是本系列文章的第一篇,講述了我們?nèi)绾卧谏a(chǎn)環(huán)境中使用 eBPF 調(diào)試應用程序而無需重新編譯/重新部署。這篇文章介紹了如何使用 gobpf 和 uprobe 來為 Go 程序構建函數(shù)參數(shù)跟蹤程序。這項技術也可以擴展應用于其他編譯型語言,例如 C++,Rust 等。本系列的后續(xù)文章將討論如何使用 eBPF 來跟蹤 HTTP/gRPC/SSL 等。

簡介

在調(diào)試時,我們通常對了解程序的狀態(tài)感興趣。這使我們能夠檢查程序正在做什么,并確定缺陷在代碼中的位置。觀察狀態(tài)的一種簡單方法是使用調(diào)試器來捕獲函數(shù)的參數(shù)。對于 Go 程序來說,我們經(jīng)常使用 Delve 或者 GDB。

在開發(fā)環(huán)境中,Delve 和 GDB 工作得很好,但是在生產(chǎn)環(huán)境中并不經(jīng)常使用它們。那些使調(diào)試器強大的特性也讓它們不適合在生產(chǎn)環(huán)境中使用。調(diào)試器會導致程序中斷,甚至允許修改狀態(tài),這可能會導致軟件產(chǎn)生意外故障。

為了更好地捕獲函數(shù)參數(shù),我們將探索使用 eBPF(在 Linux 4.x+ 中可用)以及高級的 Go 程序庫 gobpf。

eBPF 是什么?

擴展的 BPF(eBPF) 是 Linux 4.x+ 里的一項內(nèi)核技術。你可以把它想像成一個運行在 Linux 內(nèi)核中的輕量級的沙箱虛擬機,可以提供對內(nèi)核內(nèi)存的經(jīng)過驗證的訪問。

如下概述所示,eBPF 允許內(nèi)核運行 BPF 字節(jié)碼。盡管使用的前端語言可能會有所不同,但它通常是 C 的受限子集。一般情況下,使用 Clang 將 C 代碼編譯為 BPF 字節(jié)碼,然后驗證這些字節(jié)碼,確??梢园踩\行。這些嚴格的驗證確保了機器碼不會有意或無意地破壞 Linux 內(nèi)核,并且 BPF 探針每次被觸發(fā)時,都只會執(zhí)行有限的指令。這些保證使 eBPF 可以用于性能關鍵的工作負載,例如數(shù)據(jù)包過濾,網(wǎng)絡監(jiān)控等。

從功能上講,eBPF 允許你在某些事件(例如定時器,網(wǎng)絡事件或函數(shù)調(diào)用)觸發(fā)時運行受限的 C 代碼。當在函數(shù)調(diào)用上觸發(fā)時,我們稱這些函數(shù)為探針,它們既可以用于內(nèi)核里的函數(shù)調(diào)用(kprobe) 也可以用于用戶態(tài)程序中的函數(shù)調(diào)用(uprobe)。本文重點介紹使用 uprobe 來動態(tài)跟蹤函數(shù)參數(shù)。

Uprobe

uprobe 可以通過插入觸發(fā)軟中斷的調(diào)試陷阱指令(x86 上的 int3)來攔截用戶態(tài)程序。這也是調(diào)試器的工作方式。uprobe 的流程與任何其他 BPF 程序基本相同,如下圖所示。經(jīng)過編譯和驗證的 BPF 程序將作為 uprobe 的一部分執(zhí)行,并且可以將結果寫入緩沖區(qū)。

fe942248-8cdd-11eb-8b86-12bb97331649.jpg

讓我們看看 uprobe 是如何工作的。要部署 uprobe 并捕獲函數(shù)參數(shù),我們將使用這個簡單的示例程序。這個 Go 程序的相關部分如下所示。

main() 是一個簡單的 HTTP 服務器,在路徑 /e 上公開單個 GET 端點,該端點使用迭代逼近來計算歐拉數(shù)(e)。computeE接受單個查詢參數(shù)(iterations),該參數(shù)指定計算近似值要運行的迭代次數(shù)。迭代次數(shù)越多,近似值越準確,但會消耗指令周期。理解函數(shù)背后的數(shù)學并不是必需的。我們只是想跟蹤對 computeE 的任何調(diào)用的參數(shù)。

// computeE computes the approximation of e by running a fixed number of iterations.

func computeE(iterations int64) float64 {

res := 2.0

fact := 1.0

for i := int64(2); i 《 iterations; i++ {

fact *= float64(i)

res += 1 / fact

}

return res

}

func main() {

http.HandleFunc(“/e”, func(w http.ResponseWriter, r *http.Request) {

// Parse iters argument from get request, use default if not available.

// 。.. removed for brevity 。..

w.Write([]byte(fmt.Sprintf(“e = %0.4f

”, computeE(iters))))

})

// Start server.。.

}

要了解 uprobe 的工作原理,讓我們看一下二進制文件中如何跟蹤符號。由于 uprobe 通過插入調(diào)試陷阱指令來工作,因此我們需要獲取函數(shù)所在的地址。Linux 上的 Go 二進制文件使用 ELF 存儲調(diào)試信息。除非刪除了調(diào)試數(shù)據(jù),否則即使在優(yōu)化過的二進制文件中也可以找到這些信息。我們可以使用 objdump 命令檢查二進制文件中的符號:

[0] % objdump --syms app|grep computeE

00000000006609a0 g F .text 000000000000004b main.computeE

從這個輸出中,我們知道函數(shù) computeE 位于地址 0x6609a0。要看到它前后的指令,我們可以使用 objdump 來反匯編二進制文件(通過添加 -d 選項實現(xiàn))。反匯編后的代碼如下:

[0] % objdump -d app | less

00000000006609a0 《main.computeE》:

6609a0: 48 8b 44 24 08 mov 0x8(%rsp),%rax

6609a5: b9 02 00 00 00 mov $0x2,%ecx

6609aa: f2 0f 10 05 16 a6 0f movsd 0xfa616(%rip),%xmm0

6609b1: 00

6609b2: f2 0f 10 0d 36 a6 0f movsd 0xfa636(%rip),%xmm1

由此可見,當 computeE 被調(diào)用時會發(fā)生什么。第一條指令是 mov 0x8(%rsp), %rax。它把 rsp 寄存器偏移 0x8 的內(nèi)容移動到 rax 寄存器。這實際上就是上面的輸入?yún)?shù) iterations。Go 的參數(shù)在棧上傳遞。

有了這些信息,我們現(xiàn)在就可以繼續(xù)深入,編寫代碼來跟蹤 computeE 的參數(shù)了。

構建跟蹤程序

要捕獲事件,我們需要注冊一個 uprobe 函數(shù),還需要一個可以讀取輸出的用戶空間函數(shù)。如下圖所示。我們將編寫一個稱為跟蹤程序的二進制文件,它負責注冊 BPF 代碼并讀取 BPF 代碼的結果。如圖所示,uprobe 簡單地寫入 perf buffer,這是用于 perf 事件的 Linux 內(nèi)核數(shù)據(jù)結構。

fec975f6-8cdd-11eb-8b86-12bb97331649.png

現(xiàn)在,我們已了解了涉及到的各個部分,下面讓我們詳細研究添加 uprobe 時發(fā)生的情況。下圖顯示了 Linux 內(nèi)核如何使用uprobe 修改二進制文件。軟中斷指令(int3)作為第一條指令被插入 main.computeE 中。這將導致軟中斷,從而允許 Linux 內(nèi)核執(zhí)行我們的 BPF 函數(shù)。然后我們將參數(shù)寫入 perf buffer,該緩沖區(qū)由跟蹤程序異步讀取。

ff0bbdbc-8cdd-11eb-8b86-12bb97331649.png

BPF 函數(shù)相對簡單,C代碼如下所示。我們注冊這個函數(shù),每次調(diào)用 main.computeE 時都將調(diào)用它。一旦調(diào)用,我們只需讀取函數(shù)參數(shù)并寫入 perf buffer。設置緩沖區(qū)需要很多樣板代碼,可以在完整的示例中找到。

#include 《uapi/linux/ptrace.h》

BPF_PERF_OUTPUT(trace);

inline int computeECalled(struct pt_regs *ctx) {

// The input argument is stored in ax.

long val = ctx-》ax;

trace.perf_submit(ctx, &val, sizeof(val));

return 0;

}

現(xiàn)在我們有了一個用于 main.computeE 函數(shù)的功能完善的端到端的參數(shù)跟蹤程序!下面的視頻片段展示了這一結果。

ff4b47e8-8cdd-11eb-8b86-12bb97331649.gif

另一個很棒的事情是,我們可以使用 GDB 來查看對二進制文件所做的修改。在運行我們的跟蹤程序之前,我們輸出地址 0x6609a0 的指令。

(gdb) display /4i 0x6609a0

10: x/4i 0x6609a0

0x6609a0 《main.computeE》: mov 0x8(%rsp),%rax

0x6609a5 《main.computeE+5》: mov $0x2,%ecx

0x6609aa 《main.computeE+10》: movsd 0xfa616(%rip),%xmm0

0x6609b2 《main.computeE+18》: movsd 0xfa636(%rip),%xmm1

而這是在我們運行跟蹤程序之后。我們可以清楚地看到,第一個指令現(xiàn)在變成 int3 了。

(gdb) display /4i 0x6609a0

7: x/4i 0x6609a0

0x6609a0 《main.computeE》: int3

0x6609a1 《main.computeE+1》: mov 0x8(%rsp),%eax

0x6609a5 《main.computeE+5》: mov $0x2,%ecx

0x6609aa 《main.computeE+10》: movsd 0xfa616(%rip),%xmm0

盡管我們?yōu)樵撎囟ㄊ纠龑Ω櫝绦蜻M行了硬編碼,但是這個過程是可以通用化的。Go 的許多方面(例如嵌套指針,接口,通道等)讓這個過程變得有挑戰(zhàn)性,但是解決這些問題可以使用現(xiàn)有系統(tǒng)中不存在的另一種檢測模式。另外,因為這一過程工作在二進制層面,它也可以用于其他語言(C++,Rust 等)編譯的二進制文件。我們只需考慮它們各自 ABI 的差異。

下一步是什么?

使用 uprobe 進行 BPF 跟蹤有其自身的優(yōu)缺點。當我們需要觀察二進制程序的狀態(tài)時,BPF 很有用,甚至在連接調(diào)試器會產(chǎn)生問題或者壞處的環(huán)境(例如生產(chǎn)環(huán)境二進制程序)。最大的缺點是,即使是最簡單的程序狀態(tài)的觀測性,也需要編寫代碼來實現(xiàn)。編寫和維護 BPF 代碼很復雜。沒有大量高級工具,不太可能把它當作一般的調(diào)試手段。
編輯:lyn

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • LINUX內(nèi)核

    關注

    1

    文章

    317

    瀏覽量

    22853
  • 函數(shù)參數(shù)

    關注

    0

    文章

    6

    瀏覽量

    6127
  • BPF
    BPF
    +關注

    關注

    0

    文章

    26

    瀏覽量

    4533

原文標題:在生產(chǎn)環(huán)境中使用 eBPF 調(diào)試 GO 程序

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    FreeRTOS增加新的設備驅動程序

    如果你正在使用FreeRTOS構建嵌入式系統(tǒng),并且考慮添加新的設備驅動程序,那么這篇文章很適合你。高效的設備集成不僅僅是讓設備功能正常運行——更關乎模塊化、可靠性和安全性。
    的頭像 發(fā)表于 08-06 15:44 ?594次閱讀
    <b class='flag-5'>為</b>FreeRTOS增加新的設備驅動<b class='flag-5'>程序</b>

    zephyr設備驅動程序模型

    ? ? 1:Zephyr 內(nèi)核支持多種設備驅動程序。驅動程序是否可用取決于board 和驅動程序。 Zephyr 設備模型配置作為系統(tǒng)一部分的驅動
    的頭像 發(fā)表于 07-29 10:34 ?349次閱讀
    zephyr設備驅動<b class='flag-5'>程序</b>模型

    詳解hal_entry入口函數(shù)

    當使用RTOS時,程序從main函數(shù)開始進行線程調(diào)度;當沒有使用RTOS時,C語言程序的入口函數(shù)main函數(shù)調(diào)用了hal_entry
    的頭像 發(fā)表于 07-25 15:34 ?1457次閱讀

    請問是否可以在通用Windows平臺中構建OpenVINO? GenAI C++ 應用程序

    無法在通用 Windows 平臺中構建OpenVINO? GenAI C++ 應用程序
    發(fā)表于 06-24 07:35

    構建fx2lp程序時出現(xiàn)問題求解決

    我已經(jīng)遇到這個問題好幾天了,我需要大家的幫助。 我有 fx3sdkSetup_1.3.4 和 sdcc-4.1.0-x64 設置 已安裝。 我正在使用 2 種方法構建我的程序但遇到了一個問題: i
    發(fā)表于 05-29 06:35

    使用Percepio View免費跟蹤工具分析Zephyr應用

    Percepio View免費跟蹤工具現(xiàn)在可以針對Zephyr應用程序進行跟蹤和可視化分析了。Percepio View可以幫助開發(fā)人員理解和調(diào)試Zephyr中的固定優(yōu)先級的多線程行為及復雜的線程交互。
    的頭像 發(fā)表于 05-27 15:08 ?433次閱讀
    使用Percepio View免費<b class='flag-5'>跟蹤</b>工具分析Zephyr應用

    如何使用window程序對控制參數(shù)進行調(diào)整?

    目前我已經(jīng)把程序刷寫到控制器中,我想在不給對方控制程序代碼的基礎上,讓對方可以實現(xiàn)對參數(shù)進行調(diào)整。請問如何做到
    發(fā)表于 04-23 07:51

    部署計算機上運行 LabVIEW 應用程序時出現(xiàn)以下錯誤: “缺少外部函數(shù) dll...”解決辦法

    如果你既有 DLL 文件,也有頭 (.h) 文件,那么可以使用共享庫批量生成VI,不用再一個一個使用“調(diào)用庫函數(shù)節(jié)點”調(diào)用DLL,源代碼運行是沒有問題,一旦生成應用程序報錯缺失外部函數(shù)
    發(fā)表于 04-01 19:10

    如何在 Raspberry Pi AI Camera 上構建開發(fā)人員提供實時的智能應用程序!

    在這篇特邀文章中,我們的合作伙伴索尼公司的雷蒙娜-雷納(RamonaRayner)將向您展示如何快速探索不同的模型和人工智能功能,以及如何在RaspberryPi人工智能相機的基礎上輕松構建應用程序
    的頭像 發(fā)表于 03-25 09:37 ?485次閱讀
    如何在 Raspberry Pi AI Camera 上<b class='flag-5'>構建</b><b class='flag-5'>為</b>開發(fā)人員提供實時的智能應用<b class='flag-5'>程序</b>!

    TMETRIC:簡單步驟將工作區(qū)連接到時間跟蹤應用程序

    將計時器按鈕添加到組合門票 完成這三個簡單步驟以在 Assembla 中啟用時間跟蹤。設置時間不超過 3 分鐘。 注冊 TMetric 具有高級計費和報告功能的時間跟蹤應用程序 安裝瀏覽器擴展
    的頭像 發(fā)表于 01-07 09:23 ?560次閱讀
    TMETRIC:簡單步驟將工作區(qū)連接到時間<b class='flag-5'>跟蹤</b>應用<b class='flag-5'>程序</b>

    Todoist一鍵時間跟蹤

    過三個簡單的步驟將您的Todoist工作區(qū)連接到TMetric時間跟蹤應用。通過單擊鼠標跟蹤執(zhí)行任務所花費的時間。項目獲取廣泛而精確的報告。 添加計時器按鈕到Todoist任務中 完成這三個簡單
    的頭像 發(fā)表于 01-03 11:08 ?654次閱讀
    Todoist一鍵時間<b class='flag-5'>跟蹤</b>

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-spi編程示例之spi編寫程序

    傳輸數(shù)據(jù)。它使用`ioctl`系統(tǒng)調(diào)用和`SPI_IOC_MESSAGE`命令執(zhí)行SPI數(shù)據(jù)傳輸。第四部分:`main`函數(shù)程序的入口點。它將`send_num`變量設置38,然
    發(fā)表于 11-07 09:36

    飛凌嵌入式ElfBoard ELF 1板卡-spi編程示例之spi編寫程序

    傳輸數(shù)據(jù)。它使用`ioctl`系統(tǒng)調(diào)用和`SPI_IOC_MESSAGE`命令執(zhí)行SPI數(shù)據(jù)傳輸。第四部分:`main`函數(shù)程序的入口點。它將`send_num`變量設置38,然
    發(fā)表于 11-06 09:15

    硬盤電機怎么驅動程序?它有什么典型特征?

    驅動程序的設計原理 硬盤電機驅動程序的設計原理主要包括以下幾個方面: 電機控制理論:硬盤電機驅動程序需要根據(jù)電機控制理論設計,包括電機的啟動、停止、轉速調(diào)節(jié)等操作。這些操作需要根據(jù)硬
    的頭像 發(fā)表于 10-22 11:10 ?1456次閱讀

    使用CSL補充操作系統(tǒng)調(diào)度程序處理級聯(lián)中斷

    電子發(fā)燒友網(wǎng)站提供《使用CSL補充操作系統(tǒng)調(diào)度程序處理級聯(lián)中斷.pdf》資料免費下載
    發(fā)表于 10-16 10:12 ?0次下載
    使用CSL<b class='flag-5'>來</b>補充操作系統(tǒng)調(diào)度<b class='flag-5'>程序</b>處理級聯(lián)中斷