| 102 | } |
| 103 | |
| 104 | static LocationInfo |
| 105 | getLocationInfo( |
| 106 | const std::shared_ptr<const AbstractProcessManager>& manager, |
| 107 | remote_addr_t code_addr, |
| 108 | Structure<py_code_v>& code, |
| 109 | uintptr_t last_instruction_index, |
| 110 | int tlbc_index) |
| 111 | { |
| 112 | int code_lineno = code.getField(&py_code_v::o_firstlineno); |
| 113 | remote_addr_t lnotab_addr = code.getField(&py_code_v::o_lnotab); |
| 114 | LOG(DEBUG) << std::hex << std::showbase << "Copying lnotab data from address " << lnotab_addr; |
| 115 | std::string lnotab = manager->getBytesFromAddress(lnotab_addr); |
| 116 | |
| 117 | assert(manager->versionIsAtLeast(3, 11) || lnotab.size() % 2 == 0); |
| 118 | std::string::size_type last_executed_instruction = last_instruction_index; |
| 119 | |
| 120 | LocationInfo location_info = LocationInfo{0, 0, 0, 0}; |
| 121 | |
| 122 | // Check out https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt for the format of |
| 123 | // the lnotab table in different versions of the interpreter. |
| 124 | if (manager->versionIsAtLeast(3, 14) && manager->isFreeThreaded()) { |
| 125 | uintptr_t code_adaptive = code.getFieldRemoteAddress(&py_code_v::o_code_adaptive); |
| 126 | uintptr_t tlbc_entries_addr = code_adaptive - sizeof(void*); |
| 127 | uintptr_t tlbc_entries; |
| 128 | manager->copyMemoryFromProcess(tlbc_entries_addr, sizeof(tlbc_entries), &tlbc_entries); |
| 129 | Py_ssize_t tlbc_size; |
| 130 | manager->copyMemoryFromProcess(tlbc_entries, sizeof(tlbc_size), &tlbc_size); |
| 131 | std::vector<uintptr_t> vec(tlbc_size); |
| 132 | manager->copyMemoryFromProcess( |
| 133 | tlbc_entries + sizeof(tlbc_size), |
| 134 | tlbc_size * sizeof(uintptr_t), |
| 135 | vec.data()); |
| 136 | LOG(DEBUG) << "tlbc_index=" << tlbc_index << " tlbc_size=" << tlbc_size; |
| 137 | uintptr_t code_adaptive_actual = vec[tlbc_index]; |
| 138 | ptrdiff_t addrq = |
| 139 | (reinterpret_cast<uint16_t*>(last_instruction_index) |
| 140 | - reinterpret_cast<uint16_t*>(code_adaptive_actual)); |
| 141 | LocationInfo posinfo; |
| 142 | bool ret = parse_linetable(addrq, lnotab, code_lineno, &posinfo); |
| 143 | if (ret) { |
| 144 | location_info.lineno = posinfo.lineno; |
| 145 | location_info.end_lineno = posinfo.end_lineno; |
| 146 | location_info.column = posinfo.column; |
| 147 | location_info.end_column = posinfo.end_column; |
| 148 | } |
| 149 | } else if (manager->versionIsAtLeast(3, 11)) { |
| 150 | uintptr_t code_adaptive = code.getFieldRemoteAddress(&py_code_v::o_code_adaptive); |
| 151 | ptrdiff_t addrq = |
| 152 | (reinterpret_cast<uint16_t*>(last_instruction_index) |
| 153 | - reinterpret_cast<uint16_t*>(code_adaptive)); |
| 154 | LocationInfo posinfo; |
| 155 | bool ret = parse_linetable(addrq, lnotab, code_lineno, &posinfo); |
| 156 | if (ret) { |
| 157 | location_info.lineno = posinfo.lineno; |
| 158 | location_info.end_lineno = posinfo.end_lineno; |
| 159 | location_info.column = posinfo.column; |
| 160 | location_info.end_column = posinfo.end_column; |
| 161 | } |
no test coverage detected