日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 读取内存颗粒,Linux虚拟内存地址转化成物理内存地址

發(fā)布時(shí)間:2023/12/2 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 读取内存颗粒,Linux虚拟内存地址转化成物理内存地址 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

背景

現(xiàn)代手機(jī)這種SOC(system on chip),因?yàn)楣?、Modem等功能soc上集成了很多core,他們還可以是獨(dú)立的系統(tǒng)在運(yùn)轉(zhuǎn)。

比如ADSP簡介ADSP(Application Digital Signal Processing)就是高通的Hexagon DSP ,就是獨(dú)立運(yùn)轉(zhuǎn)的一個(gè)core+system。這樣做不僅可以使用soc上的專用核處理專業(yè)的事情,比如上面說的ADSP就可以處理音頻解碼,當(dāng)然它的DSP特性還可以處理sensor融合算法,比起通用處理器(cortex a72 a53 a17 a9 a8這些核)處理效率更高,更省電。

當(dāng)然出于成本因素我們不會(huì)為它單獨(dú)焊上一個(gè)內(nèi)存顆粒,它共享了主存的一部分,比如從地址0xc0000000 - 0xc0100000 1MB的空間,此時(shí)內(nèi)核(Linux運(yùn)行在通用處理器上)將不再觸碰這塊內(nèi)存。

但是多核共享同一個(gè)地址空間也有個(gè)弊端,就是如果程序有問題(野指針,數(shù)組越界)可能會(huì)寫別的core管理的內(nèi)存空間,這樣給我們帶來的問題就是程序的值莫名其妙的被改變了。我們?yōu)榱伺挪檫@種問題,才考慮把應(yīng)用程序的虛擬地址轉(zhuǎn)化為物理地址,進(jìn)行print debug以便于統(tǒng)一分析。

實(shí)現(xiàn)

kernel 在2.6.25的時(shí)候加入了這樣一個(gè)功能/proc/self/pagemap 也就是在每個(gè)進(jìn)程的/proc里面都有一個(gè)pagemap通過讀取里面的內(nèi)容就可以算出當(dāng)前虛擬地址對應(yīng)的物理頁,然后加入page_offset就可以知道當(dāng)前虛擬地址對應(yīng)的物理地址。

pagemap需要你的應(yīng)用有root權(quán)限才能使用。 #include???#include???#include???#include???#include???#include???#include???#include???#include???#include???#include???#include???//?參考??//?https://www.kernel.org/doc/Documentation/vm/pagemap.txt??#define????page_map_file?????"/proc/self/pagemap"??#define????PFN_MASK??????????((((uint64_t)1)<<55)-1)??#define????PFN_PRESENT_FLAG??(((uint64_t)1)<<63)??int?mem_addr_vir2phy(unsigned?long?vir,?unsigned?long?*phy)??{??int?fd;??int?page_size=getpagesize();??unsigned?long?vir_page_idx?=?vir/page_size;??unsigned?long?pfn_item_offset?=?vir_page_idx*sizeof(uint64_t);??uint64_t?pfn_item;??fd?=?open(page_map_file,?O_RDONLY);??if?(fd<0)??{??fprintf(stderr,?"open?%s?failed",?page_map_file);??return?-1;??}??if?((off_t)-1?==?lseek(fd,?pfn_item_offset,?SEEK_SET))??{??fprintf(stderr,?"lseek?%s?failed",?page_map_file);??return?-1;??}??if?(sizeof(uint64_t)?!=?read(fd,?&pfn_item,?sizeof(uint64_t)))??{??fprintf(stderr,?"read?%s?failed",?page_map_file);??return?-1;??}??if?(0==(pfn_item?&?PFN_PRESENT_FLAG))??{??fprintf(stderr,?"page?is?not?present");??return?-1;??}??*phy?=?(pfn_item?&?PFN_MASK)*page_size?+?vir?%?page_size;??return?0;??}??int?main(int?argc,?char*?argv[])?{??unsigned?long?a?=?0xffbbccaa;??unsigned?long?vir?=?reinterpret_cast(&a);??unsigned?long?phy?=?0;??fprintf(stderr,?"sizeof(unsigned?long):%lu,?sizeof(unsigned?long*):%lu

",?sizeof(unsigned?long),?sizeof(unsigned?long*));??mem_addr_vir2phy(vir,?&phy);??fprintf(stderr,?"1?vir:0x%lx,?phy:?0x%lx?getchar?to?continue

",?vir,?phy);??getchar();??a?=?0x11111111;??fprintf(stderr,?"2?vir:0x%lx,?phy:?0x%lx?getchar?to?continue

",?vir,?phy);??getchar();??fprintf(stderr,?"3?vir:0x%lx,?phy:?0x%lx?a:0x%lx

",?vir,?phy,?a);??}

如何驗(yàn)證

你需要開啟kernel如下模塊

CONFIG_DEVMEM=y

關(guān)閉如下模塊

CONFIG_STRICT_DEVMEM=n

一般的Android 都有/system/bin/r(源碼在system/core/toolbox/r.c)這個(gè)命令,這個(gè)命令類似devmem之類的嵌入式工具,通過/dev/mem(物理內(nèi)存)mmap來讀取物理內(nèi)存的值,當(dāng)然你也可以修改該地址的值

上面的例子他們通過getchar() 阻止程序的運(yùn)行,以便你有足夠的時(shí)間來敲/system/bin/r命令和參數(shù)

命令用法,上面的例子我們?nèi)×艘粋€(gè)棧上變量的虛擬地址,轉(zhuǎn)換成物理地址。然后你就可以通過/system/bin/r來讀取和修改這個(gè)地址的值了。

讀取0x9a6f0b20地址的值 adb?shell?/system/bin/r?0x9a6f0b20

修改0x9a6f0b20地址的值為0xffbbccaa adb?shell?/system/bin/r?0x9a6f0b20?0xffbbccaa

源碼可以直接git clone git@github.com:green130181/kernel-study.git

工程里的 pagemap直接拷貝到aosp的任意目錄

然后aosp的根目錄執(zhí)行 source?build/envsetup.sh??lunch?"your?select"??cd?pagemap?dir??mm

之后adb push 到你的機(jī)器,即可開始驗(yàn)證。

當(dāng)然還有很多先進(jìn)的比如ramdump Trace32來實(shí)現(xiàn)內(nèi)存地址查看,不過上面的對于一個(gè)應(yīng)用來講足夠輕量級,夠用就好!

點(diǎn)贊 0

總結(jié)

以上是生活随笔為你收集整理的linux 读取内存颗粒,Linux虚拟内存地址转化成物理内存地址的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。