| 98 | } |
| 99 | |
| 100 | std::vector<u8> uread_cstring(const Engine& eng, const Process& p, |
| 101 | PAddr cached_pgd_pa, |
| 102 | VAddr va, std::size_t maxlen) |
| 103 | { |
| 104 | std::vector<u8> out; |
| 105 | if (va == 0) return out; |
| 106 | // Read in chunks (PGD walks are page-granular anyway). |
| 107 | constexpr std::size_t kChunk = 256; |
| 108 | std::vector<u8> buf(kChunk); |
| 109 | VAddr cur = va; |
| 110 | while (out.size() < maxlen) { |
| 111 | std::size_t want = std::min(kChunk, maxlen - out.size()); |
| 112 | if (!uread(eng, p, cur, buf.data(), want, cached_pgd_pa)) break; |
| 113 | for (std::size_t i = 0; i < want; ++i) { |
| 114 | if (buf[i] == 0) { |
| 115 | out.insert(out.end(), buf.begin(), buf.begin() + i); |
| 116 | return out; |
| 117 | } |
| 118 | } |
| 119 | out.insert(out.end(), buf.begin(), buf.begin() + want); |
| 120 | cur += want; |
| 121 | } |
| 122 | return out; |
| 123 | } |
| 124 | |
| 125 | bool is_heap_va(VAddr va, VAddr start_brk, VAddr brk) { |
| 126 | return va >= start_brk && va < brk; |