国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用 Python 拓展 GDB(四)

Seay / 3018人閱讀

摘要:歡迎來到用拓展的最后一篇。對(duì)于通用語言來說,暴露的接口不過是又一個(gè)庫而已。這兩者間的通訊使用協(xié)議。該客戶端可以向外界暴露出調(diào)試時(shí)的信息。用拓展系列到此就結(jié)束了。

歡迎來到《用python拓展gdb》的最后一篇。第一篇結(jié)尾,我提到了通用語言相對(duì)于領(lǐng)域特定語言的一項(xiàng)優(yōu)勢,即在處理數(shù)據(jù)上更加靈活。其實(shí)通用語言還有著另一樣優(yōu)勢,領(lǐng)域特定語言只能局限在宿主程序中使用,而通用語言則無此限制。對(duì)于通用語言來說,gdb暴露的接口不過是又一個(gè)庫而已。

在本篇中,我們會(huì)把python當(dāng)作一門“膠水語言”,A面是gdb的接口,B面是一個(gè)終端界面的程序。姑且把這個(gè)終端界面程序稱之為gti(gdb"s terminal interface)吧。我們會(huì)實(shí)現(xiàn)從gdb到gti的單向數(shù)據(jù)傳輸。每當(dāng)gdb觸發(fā)斷點(diǎn)時(shí),就在gti上自動(dòng)輸出各項(xiàng)相關(guān)信息。這兩者間的通訊使用UDP協(xié)議。換言之,接下來要完成的是一個(gè)位于gdb內(nèi)部UDP客戶端,和監(jiān)聽指定端口的帶終端界面的UDP服務(wù)端。

gdb 端實(shí)現(xiàn)

gdb端功能如下:

每當(dāng)斷點(diǎn)被觸發(fā)時(shí),通過gdb接口獲取info breakpointsinfo args,以及info locals三者的值

把上述三者的值轉(zhuǎn)換成json格式

通過UDP協(xié)議發(fā)送到端口9876

功能要求看上去很多,不過實(shí)現(xiàn)成代碼其實(shí)也就二三十行:

import json
import socket
import gdb


HOST = "localhost"
PORT = 9876
SOCK = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
SOCK.connect((HOST, PORT))

def send_data(event):
    cur = event.breakpoints[0].location
    if cur is None:
        cur = event.breakpoints[0].expr
    local_vars = gdb.execute("info locals", to_string=True)
    args = gdb.execute("info args", to_string=True)
    bps = gdb.execute("info breakpoints", to_string=True)
    data = {
        "current": cur,
        "locals": local_vars,
        "args": args,
        "breakpoints": bps
    }
    data = json.dumps(data)
    SOCK.send(bytes(data, "utf-8"))


gdb.events.stop.connect(send_data)

在此之前,需要設(shè)置一個(gè)監(jiān)聽9876端口的服務(wù)端,不然客戶端這邊就建立不了連接。運(yùn)行nc -l 9876作為服務(wù)端的mock,暫時(shí)只需觀察下發(fā)送過來的數(shù)據(jù)是否正確。

寫一個(gè)自動(dòng)化腳本,讓gdb設(shè)置若干斷點(diǎn)并運(yùn)行,連續(xù)執(zhí)行多次continue。你應(yīng)該可以觀察到接連有數(shù)據(jù)顯示在nc的輸出中:

$ nc -l 9876
{"locals": "pointers = ...
gti 端實(shí)現(xiàn)

gti 端功能如下:

監(jiān)聽端口9876

每當(dāng)收到數(shù)據(jù)包時(shí),提取出json格式的數(shù)據(jù)

根據(jù)收到的數(shù)據(jù),重繪當(dāng)前界面

在繪制終端界面時(shí),我用的是自帶的curses模塊。在監(jiān)聽端口方面,我用的是python3.4之后才有的async模塊。當(dāng)然蘿卜白菜,各有所愛,大可改用你自己喜歡的庫。

#!/usr/bin/env python3
import asyncio
import curses
import json

def main():
    loop = asyncio.get_event_loop()
    # 1. 監(jiān)聽端口9876
    server = loop.create_datagram_endpoint(
        GtiProtocol, local_addr=("127.0.0.1", 9876))
    try:
        loop.run_until_complete(server)
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        curses.endwin()


class GtiProtocol(asyncio.Protocol):
    def __init__(self):
        self.ui = TextPad()

    def datagram_received(self, byte, _):
        "2. 將收到的數(shù)據(jù)從byte轉(zhuǎn)成json"
        data = byte.decode()
        data = json.loads(data)
        self.ui.display(data)


class TextPad:
    def __init__(self):
        self.pad = curses.initscr()
        curses.start_color()

    def _addstr(self, text):
        self.pad.addstr(text, curses.A_BOLD)

    def display(self, data):
        "3. 根據(jù)給定的數(shù)據(jù)重繪界面"
        try:
            self.pad.erase()
            self._addstr("current: %s

" % data["current"])
            for key, value in data.items():
                if key != "current":
                    self._addstr("%s:
" % key)
                    self._addstr(value)
                    self._addstr("
")
            self.pad.refresh()
        except curses.error:
            pass


main()

現(xiàn)在可以用./gti.py來替換掉nc -l 9876,再重新運(yùn)行g(shù)db。你應(yīng)該能看到,每當(dāng)有新的斷點(diǎn)觸發(fā)時(shí),./gti.py就會(huì)應(yīng)用新的數(shù)據(jù)繪制界面。

順便一提,使用curses模塊純粹是為了方便示范。curses提供的接口過于底層,許多細(xì)節(jié)方面都需要自己去摳。如果真的要開發(fā)實(shí)際可用的終端界面程序,建議使用諸如urwid這樣的第三方包。

小結(jié)

如上面的例子所示,我們成功地用python實(shí)現(xiàn)了內(nèi)嵌于gdb的客戶端。該客戶端可以向外界暴露出gdb調(diào)試時(shí)的信息。依據(jù)同樣的思路,我們也可以在gdb內(nèi)實(shí)現(xiàn)內(nèi)嵌的服務(wù)端,這樣外界就能動(dòng)態(tài)修改gdb調(diào)試的方式。當(dāng)然,這一切離不開python這把“瑞士軍刀”。

《用python拓展gdb》系列到此就結(jié)束了。如果你正準(zhǔn)備編寫一個(gè)拓展,希望本教程可以教會(huì)相關(guān)的知識(shí)。如果你是一位C/C++開發(fā)者,希望本教程能夠讓你的工具箱增添新道具。如果你是想了解更多關(guān)于gdb調(diào)試的信息,希望今后遇到相關(guān)問題時(shí)能想起編寫python拓展予以解決。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/38011.html

相關(guān)文章

  • Python 拓展 GDB(一)

    摘要:在末尾,我提到了也可以用來實(shí)現(xiàn)拓展腳本。其中最為常用的是和。接受一個(gè)字符串作為表達(dá)式,并以的形式返回表達(dá)式求值的結(jié)果。當(dāng)觸發(fā)斷點(diǎn)或收到信號(hào)時(shí),就會(huì)調(diào)用事先注冊的回調(diào)函數(shù)。對(duì)應(yīng)的,撤銷回調(diào)函數(shù)的接口是。本教程剩余部分會(huì)提及這一點(diǎn)。 之前寫的《GDB 自動(dòng)化操作的技術(shù)》一文介紹了可在gdb內(nèi)部使用的DSL(領(lǐng)域特定語言)來自動(dòng)化gdb的操作。借助該DSL,我們分別實(shí)現(xiàn)了一個(gè)名為mv的自定義...

    Cheng_Gang 評(píng)論0 收藏0
  • Python 拓展 GDB(三)

    摘要:歡迎來到用拓展的第三篇。它們必須以開頭,以此區(qū)別于來自于上下文的函數(shù)。提供的基類名為。不過有一個(gè)區(qū)別是,的方法通常會(huì)返回一個(gè)對(duì)象,表示調(diào)用該函數(shù)后的返回值。它不能像通常意義上的函數(shù)獨(dú)立使用,只能跟某個(gè)命令搭配。具體實(shí)現(xiàn)參見用拓展第一篇。 歡迎來到《用python拓展gdb》的第三篇。上一篇我們談到了pretty printer,一個(gè)需要python支持的特性。這一篇我們談?wù)摿硪粋€(gè)需要p...

    quietin 評(píng)論0 收藏0
  • Python 拓展 GDB(二)

    摘要:歡迎來到用拓展的第二篇。到目前為止,我們都是在用實(shí)現(xiàn)內(nèi)置領(lǐng)域特定語言也能實(shí)現(xiàn)的效果。這就是的全部要求了。構(gòu)造函數(shù)接收一個(gè)表示被打印的的必選。在后被調(diào)用,可用于打印復(fù)雜的成員。能通過來自定義打印方式,無疑為的使用打開新的大門。 歡迎來到《用python拓展gdb》的第二篇。在上一篇,我們學(xué)習(xí)了gdb提供的常用python接口,并用python實(shí)現(xiàn)了自定義命令和調(diào)試腳本。 到目前為止,我們...

    AbnerMing 評(píng)論0 收藏0
  • Python 調(diào)試方法

    摘要:背景這幾天一直在查一個(gè)線上程序住的問題這個(gè)程序總是在運(yùn)行分鐘后住通過以下的一些調(diào)試手段發(fā)現(xiàn)是打日志的時(shí)候因?yàn)闈M被了日志是默認(rèn)打到的無論日志級(jí)別而我這個(gè)程序是被另一個(gè)程序調(diào)起的父進(jìn)程沒有接收子進(jìn)程的導(dǎo)致了被打滿在調(diào)試的過程中用到了以下幾種調(diào)試 FROM http://kamushin.github.io/debug/python.html 背景 這幾天一直在查一個(gè)線上程序 hang 住的...

    klivitamJ 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<