欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Linux如何處理變量

這篇文章主要介紹了Linux如何處理變量,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都創(chuàng)新互聯(lián)公司 - 成都棕樹(shù)電信機(jī)房,四川服務(wù)器租用,成都服務(wù)器租用,四川網(wǎng)通托管,綿陽(yáng)服務(wù)器托管,德陽(yáng)服務(wù)器托管,遂寧服務(wù)器托管,綿陽(yáng)服務(wù)器托管,四川云主機(jī),成都云主機(jī),西南云主機(jī),成都棕樹(shù)電信機(jī)房,西南服務(wù)器托管,四川/成都大帶寬,機(jī)柜大帶寬,四川老牌IDC服務(wù)商

DWARF 位置

某一給定時(shí)刻的內(nèi)存中變量的位置使用 DW_AT_location 屬性編碼在 DWARF  信息中。位置描述可以是單個(gè)位置描述、復(fù)合位置描述或位置列表。

  • 簡(jiǎn)單位置描述:描述了對(duì)象的一個(gè)連續(xù)的部分(通常是所有部分)的位置。簡(jiǎn)單位置描述可以描述可尋址存儲(chǔ)器或寄存器中的位置,或缺少位置(具有或不具有已知值)。比如,DW_OP_fbreg  -32: 一個(gè)整個(gè)存儲(chǔ)的變量 - 從堆棧幀基址開(kāi)始的32個(gè)字節(jié)。

  • 復(fù)合位置描述:根據(jù)片段描述對(duì)象,每個(gè)對(duì)象可以包含在寄存器的一部分中或存儲(chǔ)在與其他片段無(wú)關(guān)的存儲(chǔ)器位置中。比如, DW_OP_reg3  DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2:前四個(gè)字節(jié)位于寄存器 3 中,后兩個(gè)字節(jié)位于寄存器 10 中的一個(gè)變量。

  • 位置列表:描述了具有有限生存期或在生存期內(nèi)更改位置的對(duì)象。比如:

    • [ 0]<lowpc=0x2e00><highpc=0x2e19>DW_OP_reg0

    • [ 1]<lowpc=0x2e19><highpc=0x2e3f>DW_OP_reg3

    • [ 2]<lowpc=0x2ec4><highpc=0x2ec7>DW_OP_reg2

    • <loclist with 3 entries follows>

    • 根據(jù)程序計(jì)數(shù)器的當(dāng)前值,位置在寄存器之間移動(dòng)的變量。

根據(jù)位置描述的種類,DW_AT_location 以三種不同的方式進(jìn)行編碼。exprloc 編碼簡(jiǎn)單和復(fù)合的位置描述。它們由一個(gè)字節(jié)長(zhǎng)度組成,后跟一個(gè)  DWARF 表達(dá)式或位置描述。loclist 和 loclistptr 的編碼位置列表,它們?cè)?.debug_loclists  部分中提供索引或偏移量,該部分描述了實(shí)際的位置列表。

DWARF 表達(dá)式

使用 DWARF 表達(dá)式計(jì)算變量的實(shí)際位置。這包括操作堆棧值的一系列操作。有很多 DWARF  操作可用,所以我不會(huì)詳細(xì)解釋它們。相反,我會(huì)從每一個(gè)表達(dá)式中給出一些例子,給你一個(gè)可用的東西。另外,不要害怕這些;libelfin  將為我們處理所有這些復(fù)雜性。

  • 字面編碼

    • 將無(wú)符號(hào)值壓入堆棧

    • 將地址操作數(shù)壓入堆棧

    • 將字面量壓入堆棧

    • DW_OP_lit0、DW_OP_lit1&hellip;&hellip;DW_OP_lit31

    • DW_OP_addr <addr>

    • DW_OP_constu <unsigned>

  • 寄存器值

    • 將給定寄存器的內(nèi)容加上給定的偏移量壓入堆棧

    • 壓入在堆棧幀基址找到的值,偏移給定值

    • DW_OP_fbreg <offset>

    • DW_OP_breg0、DW_OP_breg1&hellip;&hellip; DW_OP_breg31 <offset>

  • 堆棧操作

    • 將堆棧頂部視為內(nèi)存地址,并將其替換為該地址的內(nèi)容

    • 復(fù)制堆棧頂部的值

    • DW_OP_dup

    • DW_OP_deref

  • 算術(shù)和邏輯運(yùn)算

    • 與 DW_OP_and 相同,但是會(huì)添加值

    • 彈出堆棧頂部的兩個(gè)值,并壓回它們的邏輯 AND

    • DW_OP_and

    • DW_OP_plus

  • 控制流操作

    • 條件分支:如果堆棧的頂部不是 0,則通過(guò) offset 在表達(dá)式中向后或向后跳過(guò)

    • 彈出前兩個(gè)值,比較它們,并且如果條件為真,則壓入 1,否則為 0

    • DW_OP_le、DW_OP_eq、DW_OP_gt 等

    • DW_OP_bra <offset>

  • 輸入轉(zhuǎn)化

    • 將堆棧頂部的值轉(zhuǎn)換為不同的類型,它由給定偏移量的 DWARF 信息條目描述

    • DW_OP_convert <DIE offset>

  • 特殊操作

    • 什么都不做!

    • DW_OP_nop

DWARF 類型

DWARF  類型的表示需要足夠強(qiáng)大來(lái)為調(diào)試器用戶提供有用的變量表示。用戶經(jīng)常希望能夠在應(yīng)用程序級(jí)別進(jìn)行調(diào)試,而不是在機(jī)器級(jí)別進(jìn)行調(diào)試,并且他們需要了解他們的變量正在做什么。

DWARF 類型與大多數(shù)其他調(diào)試信息一起編碼在 DIE  中。它們可以具有指示其名稱、編碼、大小、字節(jié)等的屬性。無(wú)數(shù)的類型標(biāo)簽可用于表示指針、數(shù)組、結(jié)構(gòu)體、typedef 以及 C 或 C++  程序中可以看到的任何其他內(nèi)容。

以這個(gè)簡(jiǎn)單的結(jié)構(gòu)體為例:

struct test{     int i;     float j;     int k[42];     test* next; };

這個(gè)結(jié)構(gòu)體的父 DIE 是這樣的:

< 1><0x0000002a>    DW_TAG_structure_type                       DW_AT_name                  "test"                       DW_AT_byte_size             0x000000b8                       DW_AT_decl_file             0x00000001 test.cpp                       DW_AT_decl_line             0x00000001

上面說(shuō)的是我們有一個(gè)叫做 test 的結(jié)構(gòu)體,大小為 0xb8,在 test.cpp 的第 1 行聲明。接下來(lái)有許多描述成員的子 DIE。

< 2><0x00000032>      DW_TAG_member                         DW_AT_name                  "i"                         DW_AT_type                  <0x00000063>                         DW_AT_decl_file             0x00000001 test.cpp                         DW_AT_decl_line             0x00000002                         DW_AT_data_member_location  0 < 2><0x0000003e>      DW_TAG_member                         DW_AT_name                  "j"                         DW_AT_type                  <0x0000006a>                         DW_AT_decl_file             0x00000001 test.cpp                         DW_AT_decl_line             0x00000003                         DW_AT_data_member_location  4 < 2><0x0000004a>      DW_TAG_member                         DW_AT_name                  "k"                         DW_AT_type                  <0x00000071>                         DW_AT_decl_file             0x00000001 test.cpp                         DW_AT_decl_line             0x00000004                         DW_AT_data_member_location  8 < 2><0x00000056>      DW_TAG_member                         DW_AT_name                  "next"                         DW_AT_type                  <0x00000084>                         DW_AT_decl_file             0x00000001 test.cpp                         DW_AT_decl_line             0x00000005                         DW_AT_data_member_location  176(as signed = -80)

每個(gè)成員都有一個(gè)名稱、一個(gè)類型(它是一個(gè) DIE 偏移量)、一個(gè)聲明文件和行,以及一個(gè)指向其成員所在的結(jié)構(gòu)體的字節(jié)偏移。其類型指向如下。

< 1><0x00000063>    DW_TAG_base_type                       DW_AT_name                  "int"                       DW_AT_encoding              DW_ATE_signed                       DW_AT_byte_size             0x00000004 < 1><0x0000006a>    DW_TAG_base_type                       DW_AT_name                  "float"                       DW_AT_encoding              DW_ATE_float                       DW_AT_byte_size             0x00000004 < 1><0x00000071>    DW_TAG_array_type                       DW_AT_type                  <0x00000063> < 2><0x00000076>      DW_TAG_subrange_type                         DW_AT_type                  <0x0000007d>                         DW_AT_count                 0x0000002a < 1><0x0000007d>    DW_TAG_base_type                       DW_AT_name                  "sizetype"                       DW_AT_byte_size             0x00000008                       DW_AT_encoding              DW_ATE_unsigned < 1><0x00000084>    DW_TAG_pointer_type                       DW_AT_type                  <0x0000002a>

如你所見(jiàn),我筆記本電腦上的 int 是一個(gè) 4 字節(jié)的有符號(hào)整數(shù)類型,float是一個(gè) 4 字節(jié)的浮點(diǎn)數(shù)。整數(shù)數(shù)組類型通過(guò)指向 int  類型作為其元素類型,sizetype(可以認(rèn)為是 size_t)作為索引類型,它具有 2a 個(gè)元素。 test * 類型是  DW_TAG_pointer_type,它引用 test DIE。

實(shí)現(xiàn)簡(jiǎn)單的變量讀取器

如上所述,libelfin  將為我們處理大部分復(fù)雜性。但是,它并沒(méi)有實(shí)現(xiàn)用于表示可變位置的所有方法,并且在我們的代碼中處理這些將變得非常復(fù)雜。因此,我現(xiàn)在選擇只支持  exprloc。請(qǐng)根據(jù)需要添加對(duì)更多類型表達(dá)式的支持。如果你真的有勇氣,請(qǐng)?zhí)峤谎a(bǔ)丁到 libelfin 中來(lái)幫助完成必要的支持!

處理變量主要是將不同部分定位在存儲(chǔ)器或寄存器中,讀取或?qū)懭肱c之前一樣。為了簡(jiǎn)單起見(jiàn),我只會(huì)告訴你如何實(shí)現(xiàn)讀取。

首先我們需要告訴 libelfin 如何從我們的進(jìn)程中讀取寄存器。我們創(chuàng)建一個(gè)繼承自 expr_context 的類并使用 ptrace  來(lái)處理所有內(nèi)容:

class ptrace_expr_context : public dwarf::expr_context { public:     ptrace_expr_context (pid_t pid) : m_pid{pid} {}     dwarf::taddr reg (unsigned regnum) override {         return get_register_value_from_dwarf_register(m_pid, regnum);     }     dwarf::taddr pc() override {         struct user_regs_struct regs;         ptrace(PTRACE_GETREGS, m_pid, nullptr, &regs);         return regs.rip;     }     dwarf::taddr deref_size (dwarf::taddr address, unsigned size) override {         //TODO take into account size         return ptrace(PTRACE_PEEKDATA, m_pid, address, nullptr);     } private:     pid_t m_pid; };

讀取將由我們 debugger 類中的 read_variables 函數(shù)處理:

void debugger::read_variables() {     using namespace dwarf;     auto func = get_function_from_pc(get_pc());     //... }

我們上面做的***件事是找到我們目前進(jìn)入的函數(shù),然后我們需要循環(huán)訪問(wèn)該函數(shù)中的條目來(lái)尋找變量:

for (const auto& die : func) {     if (die.tag == DW_TAG::variable) {         //...     } }

我們通過(guò)查找 DIE 中的 DW_AT_location 條目獲取位置信息:

auto loc_val = die[DW_AT::location];

接著我們確保它是一個(gè) exprloc,并請(qǐng)求 libelfin 來(lái)評(píng)估我們的表達(dá)式:

if (loc_val.get_type() == value::type::exprloc) {     ptrace_expr_context context {m_pid};     auto result = loc_val.as_exprloc().evaluate(&context);

現(xiàn)在我們已經(jīng)評(píng)估了表達(dá)式,我們需要讀取變量的內(nèi)容。它可以在內(nèi)存或寄存器中,因此我們將處理這兩種情況:

switch (result.location_type) {                 case expr_result::type::address:                 {                     auto value = read_memory(result.value);                     std::cout << at_name(die) << " (0x" << std::hex << result.value << ") = "                               << value << std::endl;                     break;                 }                 case expr_result::type::reg:                 {                     auto value = get_register_value_from_dwarf_register(m_pid, result.value);                     std::cout << at_name(die) << " (reg " << result.value << ") = "                               << value << std::endl;                     break;                 }                 default:                     throw std::runtime_error{"Unhandled variable location"};                 }

你可以看到,我根據(jù)變量的類型,打印輸出了值而沒(méi)有解釋。希望通過(guò)這個(gè)代碼,你可以看到如何支持編寫(xiě)變量,或者用給定的名字搜索變量。

***我們可以將它添加到我們的命令解析器中:

else if(is_prefix(command, "variables")) {     read_variables(); }

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Linux如何處理變量”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

本文標(biāo)題:Linux如何處理變量
瀏覽地址:http://www.chinadenli.net/article30/gcipso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名App開(kāi)發(fā)營(yíng)銷型網(wǎng)站建設(shè)做網(wǎng)站品牌網(wǎng)站建設(shè)用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)