📄 exmap.cpp
字号:
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 + -