Skip to content

Commit d10e300

Browse files
committed
Fix decoding Python 3.13 stacks without symbols
The eager `isValid` check that we implemented originally fails when symbols aren't available, as we're unable to look up `PyCode_Type` to compare the type of `f_executable` against it. Instead, let's treat every `f_executable` as though it's a `PyCode_Type` without checking in advance. If it's not able to be interpreted as a `PyCode_Type`, we'll expect a `RemoteMemCopyError` from chasing an invalid pointer at some point, and can handle that the way that we have been handling `!isValid`. Signed-off-by: Matt Wozniski <[email protected]>
1 parent c77eb4f commit d10e300

File tree

3 files changed

+16
-33
lines changed

3 files changed

+16
-33
lines changed

src/pystack/_pystack/pycode.cpp

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -162,41 +162,11 @@ getLocationInfo(
162162
return location_info;
163163
}
164164

165-
static bool
166-
isValid(const std::shared_ptr<const AbstractProcessManager>& manager, remote_addr_t addr)
167-
{
168-
if (manager->versionIsAtLeast(3, 13)) {
169-
// In Python 3.13, the frame f_executable field can be a code object or a bunch
170-
// of other possible types (including None). We consider valid only the cases
171-
// where it is a code object.
172-
remote_addr_t pycodeobject_addr = manager->getAddressFromCache("PyCode_Type");
173-
if (pycodeobject_addr == 0) {
174-
Object code_obj(manager, addr);
175-
if (code_obj.objectType() == Object::ObjectType::CODE) {
176-
manager->registerAddressInCache("PyCode_Type", code_obj.typeAddr());
177-
return true;
178-
}
179-
return false;
180-
} else {
181-
Structure<py_object_v> obj(manager, addr);
182-
return obj.getField(&py_object_v::o_ob_type) == pycodeobject_addr;
183-
}
184-
}
185-
return true;
186-
}
187-
188165
CodeObject::CodeObject(
189166
const std::shared_ptr<const AbstractProcessManager>& manager,
190167
remote_addr_t addr,
191168
uintptr_t lasti)
192169
{
193-
if (!isValid(manager, addr)) {
194-
d_filename = "???";
195-
d_scope = "???";
196-
d_location_info = LocationInfo{0, 0, 0, 0};
197-
d_narguments = 0;
198-
return;
199-
}
200170
LOG(DEBUG) << std::hex << std::showbase << "Copying code struct from address " << addr;
201171
Structure<py_code_v> code(manager, addr);
202172

@@ -235,6 +205,13 @@ CodeObject::CodeObject(
235205
});
236206
}
237207

208+
CodeObject::CodeObject(std::string filename, std::string scope, LocationInfo location_info)
209+
: d_filename(filename)
210+
, d_scope(scope)
211+
, d_location_info(location_info)
212+
{
213+
}
214+
238215
std::string
239216
CodeObject::Filename() const
240217
{

src/pystack/_pystack/pycode.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class CodeObject
2727
const std::shared_ptr<const AbstractProcessManager>& manager,
2828
remote_addr_t addr,
2929
uintptr_t lastli);
30+
CodeObject(std::string filename, std::string scope, LocationInfo location_info);
3031

3132
// Getters
3233
std::string Filename() const;
@@ -41,8 +42,6 @@ class CodeObject
4142
std::string d_scope;
4243
LocationInfo d_location_info;
4344
int d_narguments;
44-
45-
private:
4645
std::vector<std::string> d_varnames;
4746
};
4847
} // namespace pystack

src/pystack/_pystack/pyframe.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,14 @@ FrameObject::getCode(
7171
} else {
7272
last_instruction = frame.getField(&py_frame_v::o_lasti);
7373
}
74-
return std::make_unique<CodeObject>(manager, py_code_addr, last_instruction);
74+
try {
75+
return std::make_unique<CodeObject>(manager, py_code_addr, last_instruction);
76+
} catch (const RemoteMemCopyError& ex) {
77+
// This may not have been a code object at all, or it may have been
78+
// trashed by memory corruption. Either way, indicate that we failed
79+
// to understand what code this frame is running.
80+
return std::make_unique<CodeObject>("???", "???", LocationInfo{0, 0, 0, 0});
81+
}
7582
}
7683

7784
bool

0 commit comments

Comments
 (0)