⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exmap.cpp

📁 内存管理工具Exmap。该工具比 ps 或 top 更精确
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    return !(_fname[0] == '[' && _fname[pos-1] == ']');}bool Vma::addr_to_pgnum(Address addr, unsigned int &pgnum){    if (addr > end()) {	warn << hex << addr << " is beyond vma end " << end() << dec << "\n";	return false;    }    Address a = Elf::page_align_down(addr);    if (a < start()) {	warn << hex << addr << " is before vma start "	    << start() << dec << "\n";	return false;    }    a -= start();    pgnum = a / Elf::page_size();    return true;}bool Vma::get_pages_for_range(const RangePtr &mrange,			      std::list<PartialPageInfo> &ppinfo){    ppinfo.clear();        if (mrange->size() <= 0) {	warn << "Vma::get_pages_for_range - invalid range\n";	return false;    }    if (!range()->contains(mrange)) {	warn << "Vma::get_pages_for_range - range "	    << mrange->to_string() << " outside vma " << to_string() << "\n";	return false;    }    unsigned int start_pgnum, end_pgnum;    if (!addr_to_pgnum(mrange->start(), start_pgnum)) {	warn << "Vma::get_pages_for_range - can't get start pgnum\n";	return false;    }    if (!addr_to_pgnum(mrange->end() - 1, end_pgnum)) {	warn << "Vma::get_pages_for_range - can't get end pgnum\n";	return false;    }    if (start_pgnum > end_pgnum) {	warn << "start_pgnum greater than end: "	     << start_pgnum << ", " << end_pgnum << "\n";	return false;    }    if (start_pgnum >= _pages.size()) {	warn << "Vma::get_pages_for_range - start pgnum out of range: "	     << start_pgnum << ", " << _pages.size() << " " << _fname << "\n";	return false;    }    if (end_pgnum >= _pages.size()) {	warn << "Vma::get_pages_for_range - end pgnum out of range: "	     << end_pgnum << ", " << _pages.size() << "\n";	return false;    }    if (start_pgnum == end_pgnum) {	ppinfo.push_back(PartialPageInfo(_pages[start_pgnum], mrange->size()));	return true;    }    Address bytes = Elf::page_size()	- (mrange->start() - Elf::page_align_down(mrange->start()));    ppinfo.push_back(PartialPageInfo(_pages[start_pgnum], bytes));    bytes = mrange->end() - Elf::page_align_down(mrange->end() - 1);    if (bytes > 0) {	ppinfo.push_back(PartialPageInfo(_pages[end_pgnum], bytes));    }    bytes = Elf::page_size();    for (unsigned int pgnum = start_pgnum + 1; pgnum < end_pgnum; ++pgnum) {	ppinfo.push_back(PartialPageInfo(_pages[pgnum], bytes));    }    return true;}	string Vma::to_string() const{    stringstream sstr;    sstr << hex;    sstr << _range << ": " << _offset << " " << _fname;    return sstr.str();}// ------------------------------------------------------------    Page::Page(PageCookie cookie, bool resident, bool writable): _cookie(cookie), _resident(resident), _writable(writable){ }PageCookie Page::cookie() const{    return _cookie;}bool Page::is_mapped() const{    return _cookie != 0;}bool Page::is_resident() const{    return _resident;}bool Page::is_writable() const{    return _writable;}void Page::print(ostream &os) const{    os << "(" << _cookie << ":" << _resident << ":" << _writable << ")";}// ------------------------------------------------------------Sizes::Sizes(){    for (int i = 0; i < NUM_SIZES; ++i) {	_values[i] = 0.0;    }}double Sizes::val(int which){    return _values[which];}double Sizes::sval(int which){    return _values[which] / (double)_scale_factor;}void Sizes::increase(enum Measure which, double amount){    _values[which] += amount;}void Sizes::add(const SizesPtr &other){    for (int i = 0; i < NUM_SIZES; ++i) {	_values[i] += other->_values[i];    }}string Sizes::size_name(int which){    string name = names[which];    if (!_scale_name.empty()) {	name += " (" + _scale_name + ")";    }    return name;}void Sizes::scale_units(){    _scale_factor = 1;    _scale_name = "";}void Sizes::scale_kbytes(){    _scale_factor = 1024;    _scale_name = "K";}void Sizes::scale_mbytes(){    _scale_factor = 1024 * 1024;    _scale_name = "M";}const string Sizes::names[] = {    "Effective Resident",    "Effective Mapped",    "Writable",    "VM",    "Sole Mapped",    "Mapped",    "Resident",    "Num Sizes"};int Sizes::_scale_factor = 1;string Sizes::_scale_name;// ------------------------------------------------------------File::File(const string &fname)    : _fname(fname){    if (file_exists(fname)) {	_elf.reset(new Elf::File);	if (!_elf->load(_fname, false)) {	    _elf.reset((Elf::File *) 0);	}    }}string File::name(){    return _fname;}list<ProcessPtr> File::procs(){    list<ProcessPtr> result(_procs.begin(), _procs.end());    return result;}Elf::FilePtr File::elf(){    return _elf;}bool File::is_elf(){    return _elf != 0;}list<MapPtr> File::maps(){    return _maps;}SizesPtr File::sizes(){    if (_procs.empty()) {	warn << "File::sizes - no processes for file " << name() << "\n";	SizesPtr null_sizes;	return null_sizes;    }    ProcessPtr proc = *(_procs.begin());    return Map::sum_sizes(proc->page_pool(), _maps);}void File::add_maps(const list<MapPtr> &maps){    _maps.insert(_maps.end(), maps.begin(), maps.end());}void File::add_map(const MapPtr &map){    _maps.push_back(map);}void File::add_proc(const ProcessPtr &proc){    _procs.insert(proc);}// ------------------------------------------------------------Map::Map(const VmaPtr &vma,	 const RangePtr &mem_range,	 const RangePtr &elf_range)    : _vma(vma), _mem_range(mem_range), _elf_range(elf_range){    if (mem_range->size() <= 0) {	warn << "Map: zero sized mem range " << to_string() << "\n";    }    if (elf_range && elf_range->size() != mem_range->size()) {	warn << "Map: mismatched elf and mem ranges " << to_string() << "\n";    }}RangePtr Map::mem_range() const{    return _mem_range;}RangePtr Map::elf_range() const{    return _elf_range;}Address Map::elf_to_mem_offset(){    return _mem_range->start() - _elf_range->start();}RangePtr Map::elf_to_mem_range(const RangePtr &elf_range){    if (!_elf_range->contains(elf_range)) {	warn << "Range " << elf_range->to_string()	     << " not contained within " << _elf_range->to_string() << "\n";	return RangePtr((Range *) 0);    }    return elf_range->add(elf_to_mem_offset());}string Map::to_string() const{    stringstream sstr;    sstr << "MAP: MEM " << _mem_range->to_string()	 << " ELF " << (_elf_range ? _elf_range->to_string() : "undef")	 << " FILE " << _vma->fname();    return sstr.str();}SizesPtr Map::sizes_for_mem_range(const PagePoolPtr &pp){    return sizes_for_mem_range(pp, _mem_range);}SizesPtr Map::sizes_for_mem_range(const PagePoolPtr &pp,				  const RangePtr &mrange){    SizesPtr null_sizes;    SizesPtr sizes(new Sizes);    if (!_mem_range->contains(mrange)) {	warn << "Non-overlapping range: " << *mrange	     << " not within " << _mem_range << "\n";	return null_sizes;    }        RangePtr subrange = _mem_range->intersect(*mrange);    if (subrange->size() == 0) { return sizes; }        std::list<Vma::PartialPageInfo> ppi_info;    if (!_vma->get_pages_for_range(subrange, ppi_info)) {	warn << "sizes_for_mem_range: Can't get pages for range "	    << subrange->to_string() << "\n";	return null_sizes;    }    std::list<Vma::PartialPageInfo>::iterator it;    for (it = ppi_info.begin(); it != ppi_info.end(); ++it) {	Page &page = (*it).page;	int count = pp->count((*it).page);	int bytes = (*it).bytes;	dbg << "page: " << hex << page.cookie() << dec	    << " count " << count << " bytes " << bytes << "\n";	if (count <= 0) {	    warn << "Invalid count for page\n";	    continue;	}	sizes->increase(Sizes::VM, bytes);	if (page.is_mapped()) {	    sizes->increase(Sizes::MAPPED, bytes);	    sizes->increase(Sizes::EFFECTIVE_MAPPED, (double) bytes / count);	    if (count == 1) {		sizes->increase(Sizes::SOLE_MAPPED, bytes);	    }	    if (page.is_resident()) {		sizes->increase(Sizes::RESIDENT, bytes);		sizes->increase(Sizes::EFFECTIVE_RESIDENT, (double) bytes / count);		if (page.is_writable()) {		    sizes->increase(Sizes::WRITABLE, bytes);		}	    }	}    }        if (sizes->val(Sizes::VM) != subrange->size()) {	warn << "Size mismatch: vm size " << sizes->val(Sizes::VM)	     << " range " << subrange->to_string() << "\n";	return null_sizes;    }    return sizes;}void Map::print(std::ostream &os) const{    os << to_string();}SizesPtr Map::sum_sizes(const PagePoolPtr &pp,			const list<MapPtr> &maps){    SizesPtr sizes(new Sizes);    list<MapPtr>::const_iterator map_it;    for (map_it = maps.begin(); map_it != maps.end(); ++map_it) {	SizesPtr subsizes = (*map_it)->sizes_for_mem_range(pp);	sizes->add(subsizes);    }    return sizes;}static bool mapptr_is_less_than(const MapPtr &lhs, const MapPtr &rhs){    return lhs->mem_range()->start() < rhs->mem_range()->start();}list<MapPtr> Map::sort(const list<MapPtr> &maplist){    list<MapPtr> result(maplist);    result.sort(mapptr_is_less_than);    return result;}// ------------------------------------------------------------SysInfo::~SysInfo(){ }LinuxSysInfo::~LinuxSysInfo(){ }const std::string LinuxSysInfo::EXMAP_FILE("/proc/exmap");list<pid_t> LinuxSysInfo::accessible_pids(){    list<pid_t> pids;    pid_t pid;    list<string> fnames;    list<string>::iterator it;        if (!read_directory("/proc", fnames)) {	warn << "accessible_pids - can't read /proc\n";	return pids; // empty return    }    for (it = fnames.begin(); it != fnames.end(); ++it) {        if (isdigit((*it)[0])) {	    pid = atoi(it->c_str());	    string mapfile = proc_map_file(pid);	    if (file_readable(mapfile)) {	      pids.push_back(pid);	    }	}    }    return pids;}bool LinuxSysInfo::sanity_check(){    if (!file_exists(EXMAP_FILE)) {	warn << "Can't find file " << EXMAP_FILE	     << ": please check kernel module is loaded\n";	return false;    }    return true;}bool LinuxSysInfo::read_page_info(pid_t pid,				  map<Address, list<Page> > &page_info){    list<string> lines;    page_info.clear();    stringstream sstr;    sstr << pid << "\n";    if (!overwrite_textfile(EXMAP_FILE, sstr.str())) {	warn << "read_page_info - can't write to exmap: "	     << pid <<"\n";	return false;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -