|
4 | 4 |
|
5 | 5 | #include <iostream> |
6 | 6 |
|
| 7 | + |
7 | 8 | namespace pstack::Procman { |
8 | 9 |
|
| 10 | +namespace { |
| 11 | + |
| 12 | +struct FileEntry { |
| 13 | + Elf::Off start; |
| 14 | + Elf::Off end; |
| 15 | + Elf::Off fileOff; |
| 16 | +}; |
| 17 | + |
| 18 | +class FileEntries { |
| 19 | + FileNoteHeader header; |
| 20 | + Reader::csptr entries; |
| 21 | + std::unique_ptr<ReaderArray<FileEntry>> entriesArray; |
| 22 | + Reader::csptr names; |
| 23 | + |
| 24 | +public: |
| 25 | + class sentinel { }; |
| 26 | + class iterator { |
| 27 | + friend class FileEntries; |
| 28 | + const FileEntries &entries; |
| 29 | + void fetch(); |
| 30 | + bool fetched = false; |
| 31 | + size_t nameoff = 0; |
| 32 | + std::pair<std::string, FileEntry> cur; |
| 33 | + ReaderArray<FileEntry>::iterator entriesIterator; |
| 34 | + public: |
| 35 | + iterator(const FileEntries &entries, ReaderArray<FileEntry>::iterator start); |
| 36 | + iterator &operator++(); |
| 37 | + std::pair<std::string, FileEntry> operator *() { fetch(); return cur; } |
| 38 | + bool operator != (const iterator &rhs) const { return entriesIterator != rhs.entriesIterator; } |
| 39 | + bool operator != (const sentinel &) const { return entriesIterator != entries.entriesArray->end(); } |
| 40 | + }; |
| 41 | + FileEntries(const Elf::Object &obj) { |
| 42 | + // find the Notes section. |
| 43 | + for (auto note : obj.notes()) { |
| 44 | + if (note.name() == "CORE" && note.type() == NT_FILE) { |
| 45 | + auto data = note.data(); |
| 46 | + header = data->readObj<FileNoteHeader>(0); |
| 47 | + entries = data->view("FILE note entries", sizeof header, header.count * sizeof (FileEntry)); |
| 48 | + names = data->view("FILE note names", sizeof header + header.count * sizeof (FileEntry)); |
| 49 | + break; |
| 50 | + } |
| 51 | + } |
| 52 | + if (!entries) |
| 53 | + entries = std::make_shared<NullReader>(); |
| 54 | + entriesArray = std::make_unique<ReaderArray<FileEntry>>(*entries); |
| 55 | + } |
| 56 | + iterator begin() const { return iterator(*this, entriesArray->begin()); } |
| 57 | + sentinel end() const { return sentinel{}; } |
| 58 | +}; |
| 59 | +} |
| 60 | + |
| 61 | + |
9 | 62 | CoreProcess::CoreProcess(Context &ctx, Elf::Object::sptr exec, Elf::Object::sptr core) |
10 | 63 | : Process(ctx, std::move(exec), std::make_shared<CoreReader>(this, core)) |
11 | 64 | , prpsinfo{} |
@@ -228,20 +281,25 @@ CoreProcess::addressSpace() const { |
228 | 281 | for (const auto &hdr : coreImage->getSegments(PT_LOAD)) { |
229 | 282 | auto ub = entries.upper_bound(hdr.p_vaddr); |
230 | 283 | std::string name; |
| 284 | + uintmax_t offset = 0; |
| 285 | + uintmax_t inode = 0; |
231 | 286 | if (ub != entries.begin()) { |
232 | 287 | --ub; |
233 | | - if (ub->first >= hdr.p_vaddr && ub->second.second.end <= hdr.p_vaddr + hdr.p_memsz) |
| 288 | + if (ub->first >= hdr.p_vaddr && ub->second.second.end <= hdr.p_vaddr + hdr.p_memsz) { |
234 | 289 | name = ub->second.first; |
| 290 | + offset = ub->second.second.fileOff * getpagesize(); // that's the offset in pages. |
| 291 | + inode = 1; |
| 292 | + } |
235 | 293 | } |
236 | | - std::set<AddressRange::Permission> flags; |
| 294 | + std::set<AddressRange::Permission> permissions; |
237 | 295 | if ((hdr.p_flags & PF_W) != 0) |
238 | | - flags.insert(AddressRange::Permission::write); |
| 296 | + permissions.insert(AddressRange::Permission::write); |
239 | 297 | if ((hdr.p_flags & PF_R) != 0) |
240 | | - flags.insert(AddressRange::Permission::read); |
| 298 | + permissions.insert(AddressRange::Permission::read); |
241 | 299 | if ((hdr.p_flags & PF_X) != 0) |
242 | | - flags.insert(AddressRange::Permission::exec); |
| 300 | + permissions.insert(AddressRange::Permission::exec); |
243 | 301 | rv.push_back( { hdr.p_vaddr, hdr.p_vaddr + hdr.p_memsz, |
244 | | - hdr.p_vaddr + hdr.p_filesz, 0, {0, 0, 0, name}, flags, {}}); |
| 302 | + hdr.p_vaddr + hdr.p_filesz, offset, {0, 0, inode, name}, permissions, {}}); |
245 | 303 | } |
246 | 304 | return rv; |
247 | 305 | } |
@@ -284,11 +342,5 @@ CoreProcess::getSignalInfo() const { |
284 | 342 | return std::nullopt; |
285 | 343 | } |
286 | 344 |
|
287 | | -std::ostream &operator << (std::ostream &os, const JSON<pstack::Procman::FileEntry> &j) { |
288 | | - return JObject(os) |
289 | | - .field("start", j.object.start) |
290 | | - .field("end", j.object.end) |
291 | | - .field("fileOff", j.object.fileOff); |
292 | | -} |
293 | 345 | } |
294 | 346 |
|
0 commit comments