| 107 | } |
| 108 | |
| 109 | void |
| 110 | FrameObject::resolveLocalVariables() |
| 111 | { |
| 112 | LOG(DEBUG) << "Resolving local variables from frame number " << d_frame_no; |
| 113 | if (d_code == nullptr) { |
| 114 | LOG(INFO) << "Frame is a shim frame, skipping local variable resolution"; |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | const size_t n_arguments = d_code->NArguments(); |
| 119 | const size_t n_locals = d_code->Varnames().size(); |
| 120 | Structure<py_frame_v> frame(d_manager, d_addr); |
| 121 | const remote_addr_t locals_addr = frame.getFieldRemoteAddress(&py_frame_v::o_localsplus); |
| 122 | |
| 123 | if (n_locals < n_arguments) { |
| 124 | throw std::runtime_error("Found more arguments than local variables"); |
| 125 | } |
| 126 | |
| 127 | std::vector<remote_addr_t> tuple_buffer(n_locals); |
| 128 | LOG(DEBUG) << "Copying buffer containing local variables"; |
| 129 | d_manager->copyMemoryFromProcess(locals_addr, n_locals * sizeof(remote_addr_t), tuple_buffer.data()); |
| 130 | |
| 131 | auto addLocal = [&](size_t index, auto& map) { |
| 132 | remote_addr_t addr = tuple_buffer[index]; |
| 133 | if (addr == (remote_addr_t) nullptr) { |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | if (d_manager->versionIsAtLeast(3, 14)) { |
| 138 | // In Python 3.14, the local variable is a PyStackRef: a pointer |
| 139 | // with extra flags set in its low bits. Ignore the flags. |
| 140 | addr = addr & (~3); |
| 141 | } |
| 142 | |
| 143 | std::string key = d_code->Varnames()[index]; |
| 144 | |
| 145 | LOG(DEBUG) << "Copying local variable at address " << std::hex << std::showbase << addr; |
| 146 | std::string value = Object(d_manager, addr).toString(); |
| 147 | LOG(DEBUG) << "Local variable resolved to: " << key << ": " << value; |
| 148 | map.insert(std::make_pair(key, value)); |
| 149 | }; |
| 150 | |
| 151 | LOG(DEBUG) << "Copying content of local variables"; |
| 152 | for (size_t i = 0; i < tuple_buffer.size(); ++i) { |
| 153 | if (i < n_arguments) { |
| 154 | addLocal(i, d_arguments); |
| 155 | } else { |
| 156 | addLocal(i, d_locals); |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | ssize_t |
| 162 | FrameObject::FrameNo() const |
nothing calls this directly
no test coverage detected