<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          LWN:快速、低開銷的堆棧跟蹤工具SFrame!

          共 5356字,需瀏覽 11分鐘

           ·

          2023-08-23 00:30

          關(guān)注了就能看到更多這么棒的文章哦~

          SFrame: fast, low-overhead stack traces

          By Jake Edge
          August 8, 2023
          OSSNA
          ChatGPT assisted translation
          https://lwn.net/Articles/940686/

          獲取運(yùn)行中程序的 stack trace 在很多場景下都非常有用:跟蹤(tracing)、性能分析(profiling)、調(diào)試、性能優(yōu)化等。雖然已經(jīng)有了一些機(jī)制可以獲取 stack trace,但它們存在一些缺點(diǎn)。于是"Simple Frame"(SFrame) stack trace 格式應(yīng)運(yùn)而生,希望解決其他技術(shù)的不足之處。今年五月,Steve Rostedt 和 Indu Bhagat 在 LSFMM+BPF 活動中就內(nèi)核中的 SFrame 支持進(jìn)行了演講;幾天后,Bhagat 在溫哥華的北美開源峰會上做了一個(gè)更加全面的關(guān)于 SFrame 的演講(YouTube 上有視頻)。第二個(gè)演講可以幫助了解 SFrame 和整體 stack trace 的其他方面。

          Background

          Bhagat 首先定義了什么是 stack trace:"線程中當(dāng)前正處于 active 狀態(tài)的函數(shù)調(diào)用列表"。有價(jià)值的 stack trace 將顯示相關(guān)的 call-chain list 中每個(gè)函數(shù)內(nèi)的指令指針(IP, instruction pointer)指向位置的信息,以及一些人類可讀的符號名稱,包括函數(shù)名,但也可以提供文件名和行號等信息。然而,她的演講重點(diǎn)不在這些符號化的部分,而是專注于如何獲取 call chain 中的 IP 指針列表。

          d7606efcc7286b2589ad6e2d462d2fee.webp

          不同的工具會用不同的方式生成調(diào)用鏈的 IP,因?yàn)樗鼈兌际顷P(guān)注在自身的使用場景。"調(diào)試器的做法與性能分析工具就不同"。從她的幻燈片中,她列出了五種現(xiàn)有的 stack trace 機(jī)制,但表示她會專門討論其中三種:幀指針(frame pointer)、EH frame ,以及應(yīng)用程序特有的格式。她說,這三種機(jī)制將提供足夠的背景,從而解釋為什么要有 SFrame 格式。

          幀指針技術(shù)可能是最古老的 stack trace 方法之一。它預(yù)留了一個(gè)寄存器來保存幀指針,幀指針是指向當(dāng)前堆棧幀的指針;編譯器會生成額外的代碼,在函數(shù)進(jìn)入和退出時(shí)將棧指針的值保存到該寄存器(或恢復(fù)出來)。因此,每個(gè)函數(shù)調(diào)用都會有一些額外的代碼性能開銷;除此之外,編譯器必須專門為幀指針預(yù)留一個(gè)寄存器,這也會影響性能。但它是一個(gè)易于理解的機(jī)制,效果良好;"它設(shè)計(jì)得很漂亮,運(yùn)作良好,而且非常簡單"。

          EH frame 機(jī)制是一種基于 DWARF 的方法,不僅可以進(jìn)行 stack trace,還可以進(jìn)行堆棧展開(stack unwinding),也就是說它可以把調(diào)用鏈中的每一個(gè)點(diǎn)上的所有寄存器的狀態(tài)都恢復(fù)出來。執(zhí)行此操作所需的信息存儲在二進(jìn)制文件的 .eh_frame 和 .eh_frame_hdr 這兩個(gè) ELF section 中。這個(gè)格式本身緊湊多樣,實(shí)用效果不錯(cuò),Bhagat 表示,對于希望處理該格式的應(yīng)用程序來說也可以直接使用現(xiàn)有的功能良好的庫。

          使用 EH frame 不需要為幀指針保留寄存器,但" stack tracer 工具本身速度較慢且復(fù)雜"。原因是 DWARF 信息是一組用來把感興趣信息的堆棧偏移恢復(fù)出來的指令;其中一些指令簡單,一些復(fù)雜,"但你需要實(shí)現(xiàn)一種可以執(zhí)行操作碼的 stack machine"。關(guān)于該方法的主要抱怨是關(guān)于其速度和復(fù)雜性,這也使得它在內(nèi)核中不太適合。她指出,關(guān)于現(xiàn)在已被接受的 Fedora 37 提案就要在該發(fā)行版的構(gòu)建中默認(rèn)啟用幀指針的討論(LWN 有報(bào)道)也觸及了幀指針和 EH frame 方法的一些問題。

          應(yīng)用程序特定的格式,就是因?yàn)樯鲜霾蛔愣a(chǎn)生的。例如,內(nèi)核的基于 ORC 的 stack trace 就是因?yàn)?EH frame 方法的局限而產(chǎn)生的;還有其他一些應(yīng)用程序特定格式但是不是開源的,但也確實(shí)可以支持快速和簡單的 stack trace 解決方案。應(yīng)用程序特定的解決方案并不使用由工具鏈生成的信息,因此可能需要反向工程來以其他方式使用這些格式;這可能會使得移植和維護(hù)這些格式變得困難。

          Requirements

          她展示了一張幻燈片,總結(jié)了這三種方法的優(yōu)缺點(diǎn),可以用來制定新的 stack trace 方法的需要滿足哪些需求。第一個(gè)要求是,在給出任何一個(gè) PC (program counter)值或 IP (instruction pointer)值的情況下(在演講中她兩個(gè)名詞都用到了),可以生成精確的 stack trace,她稱之為 "asynchronous stack trace"。演講結(jié)束時(shí),一名觀眾問了一下在這個(gè)上下文中這個(gè)術(shù)語的含義。Bhagat 說,基于幀指針的 stack trace 并不總是精確的,因?yàn)榫幾g器會在函數(shù)的前置動作和收尾動作中添加額外的指令。如果 stack trace 是從這些指令之一開始,就丟失一部分 trace 內(nèi)容,因?yàn)樵谶@些點(diǎn)上幀指針處理本身是不完整的。

          其他需求更明顯地源自她的幻燈片上的優(yōu)缺點(diǎn):需要更低開銷,使用低復(fù)雜度的 tracer,并使用由工具鏈生成的信息。SFrame 是在考慮這些需求的基礎(chǔ)上設(shè)計(jì)的,她說。

          SFrame 格式在 Binutils 2.40 中被定義和實(shí)現(xiàn)為 SFrame version 1。自演講以來,已經(jīng)發(fā)布了 Binutils 2.41,對該格式進(jìn)行了一些相當(dāng)小的、但不向后兼容的更改,現(xiàn)在版本為 SFrame version 2。該格式僅包含足夠的信息來進(jìn)行 stack trace:對于指定程序計(jì)數(shù)器(PC)值,可以查詢出規(guī)一化之后的幀地址(CFA, canonical frame address)、幀指針(FP, frame pointer)和返回地址(RA, return address)。"這就是進(jìn)行 stack trace 所需的一切內(nèi)容了,也是在 Simple Frame stack trace 格式的編碼中所包含的一切內(nèi)容。"

          SFrame 定義了兩種 ABI:x86_64 和 64 位 Arm。它支持編碼過程鏈接表項(xiàng)(pltN, procedure linkage table entries)。在 Arm 上,這個(gè)功能可以對指針認(rèn)證信息進(jìn)行編碼,以便后續(xù)對已被認(rèn)證處理過之后的返回地址值進(jìn)行解碼。

          SFrame 信息存儲在 .sframe ELF section 中,也就存儲在其自己的 PT_GNU_SFRAME segment 里。需要將 –gsframe 選項(xiàng)傳遞給 GNU 匯編器來生成這部分信息。如果 GNU 鏈接器(linker)看到多個(gè) .sframe 部分,它會在輸出中將它們合并起來。readelf 和 objdump 工具也支持 SFrame;使用 –sframe 選項(xiàng)將對 SFrame 信息提供出人類可讀的文本描述。

          Format

          SFrame 格式由三個(gè)部分組成:header、一組函數(shù)描述符實(shí)體(FDE, function descriptor entities)和一組幀行條目(FRE, frame row entries)。header 包含一個(gè) magic 數(shù)值、一個(gè)版本號,以及兩個(gè)部分的偏移地址。FDE 是固定大小的,按照 PC 順序排序,因此可以使用二分搜索來找到與指定 PC 值對應(yīng)的函數(shù)。FRE 是可變長度的,以盡可能緊湊。offset 偏移就是用于訪問格式中的各種信息。

          每個(gè) FDE 對應(yīng)了一個(gè)函數(shù)。它存儲了起始 PC 值以及函數(shù) size(以字節(jié)為單位)。還指示出它是一個(gè)常規(guī)代碼塊還是 pltN。在此之后,它有一個(gè)偏移量指向第一個(gè) FRE,以及該函數(shù)擁有的 FRE 數(shù)量和類型。

          FRE 是這個(gè)格式的核心內(nèi)容,她說。它們提供了可用于恢復(fù)出指定函數(shù)內(nèi)特定 PC 處的 CFA、FP 和 RA 的堆棧偏移量。由于函數(shù) size 不同,表示從起始 PC 值開始的偏移量所需的空間也不同;根據(jù)偏移量是否可以在一個(gè)、兩個(gè)或四個(gè)字節(jié)中編碼,F(xiàn)RE 有三種不同的表示方式。每個(gè) FRE 都包含了函數(shù)內(nèi)連續(xù)地址范圍,并對適用于該范圍的 CFA、FP 和 RA 值的堆棧偏移量進(jìn)行了編碼保存。

          可以在 FDE 上進(jìn)行二分搜索,這是 SFrame 的一個(gè)優(yōu)點(diǎn);這樣就可以迅速得到 trace 的起始點(diǎn)。該格式的另一個(gè)優(yōu)點(diǎn)是,F(xiàn)RE 直接編碼了恢復(fù) CFA、FP 和 RA 所需的偏移量;無需執(zhí)行 stack-machine instruction 來實(shí)現(xiàn)這一點(diǎn)。內(nèi)核的 ORC 格式也直接編碼了這些偏移量,但 SFrame 進(jìn)行了一些空間優(yōu)化,使其格式更緊湊。她展示了一張圖表("請對此保持獨(dú)立的思考"),顯示了對比 Binutils 中的十個(gè)不同二進(jìn)制文件的 x86_64 SFrame 和 EH frame 的大小,結(jié)果顯示 SFrame 大約為 EH frame 所需大小的 80%。她確實(shí)提醒說,EH frame 的用例不同,所以這并不是完全公平的比較。

          Library

          libsframe 格式庫隨著 Binutils(從 2.40 版本開始)一起發(fā)布,它包含了讀取和寫入 SFrame 數(shù)據(jù)的 API;之所以創(chuàng)建該庫,主要是考慮到 linker 會有這個(gè)需求,因此包含了一個(gè) stack tracer 可能不需要的寫入 API。還有一些針對 stack tracer 的 API,例如用于找到與 PC 值相對應(yīng)的 FRE 或從 FRE 獲取堆棧偏移量的 API。

          Bhagat 表示,libsframe 庫還很年輕,所以現(xiàn)在還沒法保證其 ABI 穩(wěn)定,畢竟太早了。API 在 sframe-api.h 中有描述。SFrame 格式在磁盤上并不對齊,但是庫函數(shù)在內(nèi)部安排數(shù)據(jù)時(shí)會避免不對齊的訪問。她展示了一些示例代碼,以演示 "進(jìn)行堆棧遍歷是多么容易";它可以根據(jù) PC 值找到一個(gè) FRE(find_fre()),然后獲取 CFA、FP 和 RA 值的偏移量(get_*_offset()),從而獲取到它們。

          在匯編器中仍然需要支持一個(gè)目前被跳過了的 CFI 指令(.cfi_escape);這意味著 SFrame 并不完全是異步的,但編譯器很少會發(fā)出該指令,因此在實(shí)際使用中這不是一個(gè)大問題。此外,還需要為 SFrame unwinding 來增加更多的 regression 測試,從而可以用在 GNU 匯編器的測試。除此之外,她表示,SFrame 開發(fā)人員計(jì)劃與社區(qū)合作,探討 SFrame 的用例,包括用于用戶空間應(yīng)用程序和內(nèi)核的用戶空間 stack trace。自演講以來,也有提議將 SFrame 支持添加到 LLVM 中。

          Bhagat 在演講結(jié)束時(shí)建議,有興趣使用 SFrame 的人可以通過 Binutils 郵件列表與開發(fā)人員取得聯(lián)系。一名觀眾詢問了目前使用 SFrame 的應(yīng)用程序;Bhagat 表示,除了與 perf、Ftrace、BPF 等相關(guān)的內(nèi)核部分之外,沒有其他應(yīng)用程序在使用這種格式。SFrame 開發(fā)人員最初從內(nèi)核場景開始,現(xiàn)在開始研究有哪些用戶空間應(yīng)用程序可能可以從快速、低開銷的 stack trace 中受益。

          一名參與者詢問了其他架構(gòu)的情況,指出他認(rèn)為 RISC-V ABI 有些不同。Bhagat 表示,SFrame 已經(jīng)適配了 x86_64 和 Arm64 之間的差異,但如果另一種架構(gòu)在處理返回地址的方式上有重大差異,那么 SFrame 可能需要進(jìn)行更改來適配。目前,x86_64 總是使用堆棧來存儲其 RA,而 Arm64 同時(shí)使用堆棧和專用寄存器,SFrame 已經(jīng)處理了這兩種情況。

          Bhagat 的同事 Jose Marchesi 問到了 SFrame 與 ORC 之間的關(guān)系;他想知道為什么內(nèi)核需要像 SFrame 這樣的功能,而不是簡單地使用 ORC。Bhagat 表示,因?yàn)?ORC 是應(yīng)用程序特定格式,它可以表示內(nèi)核中所有不同類型代碼的堆棧使用情況,包括手動編寫的匯編代碼。但要做用戶空間 stack trace 的話,ORC 格式還需要進(jìn)行一些改動;SFrame 并不是要替代內(nèi)核內(nèi)部使用的 ORC,雖然兩者都有類似的目標(biāo),但是 SFFrame 主要是希望能對 ORC 進(jìn)行補(bǔ)充,從而可以從內(nèi)核來進(jìn)行用戶空間 tracing。

          全文完
          LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。

          歡迎分享、轉(zhuǎn)載及基于現(xiàn)有協(xié)議再創(chuàng)作~

          長按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~



          瀏覽 58
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码精品电影 | 日韩性爱视频在线观看 | 免费观看靠逼视频网战 | 青青免费在线观看高清无码视频 | 人人艹超碰 |