Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix decoding Python 3.13 stacks without symbols #209

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 9 additions & 30 deletions src/pystack/_pystack/pycode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,41 +162,11 @@ getLocationInfo(
return location_info;
}

static bool
isValid(const std::shared_ptr<const AbstractProcessManager>& manager, remote_addr_t addr)
{
if (manager->versionIsAtLeast(3, 13)) {
// In Python 3.13, the frame f_executable field can be a code object or a bunch
// of other possible types (including None). We consider valid only the cases
// where it is a code object.
remote_addr_t pycodeobject_addr = manager->getAddressFromCache("PyCode_Type");
if (pycodeobject_addr == 0) {
Object code_obj(manager, addr);
if (code_obj.objectType() == Object::ObjectType::CODE) {
manager->registerAddressInCache("PyCode_Type", code_obj.typeAddr());
return true;
}
return false;
} else {
Structure<py_object_v> obj(manager, addr);
return obj.getField(&py_object_v::o_ob_type) == pycodeobject_addr;
}
}
return true;
}

CodeObject::CodeObject(
const std::shared_ptr<const AbstractProcessManager>& manager,
remote_addr_t addr,
uintptr_t lasti)
{
if (!isValid(manager, addr)) {
d_filename = "???";
d_scope = "???";
d_location_info = LocationInfo{0, 0, 0, 0};
d_narguments = 0;
return;
}
LOG(DEBUG) << std::hex << std::showbase << "Copying code struct from address " << addr;
Structure<py_code_v> code(manager, addr);

Expand Down Expand Up @@ -235,6 +205,15 @@ CodeObject::CodeObject(
});
}

CodeObject::CodeObject(std::string filename, std::string scope, LocationInfo location_info)
: d_filename(filename)
, d_scope(scope)
, d_location_info(location_info)
, d_narguments()
, d_varnames()
{
}

std::string
CodeObject::Filename() const
{
Expand Down
3 changes: 1 addition & 2 deletions src/pystack/_pystack/pycode.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class CodeObject
const std::shared_ptr<const AbstractProcessManager>& manager,
remote_addr_t addr,
uintptr_t lastli);
CodeObject(std::string filename, std::string scope, LocationInfo location_info);

// Getters
std::string Filename() const;
Expand All @@ -41,8 +42,6 @@ class CodeObject
std::string d_scope;
LocationInfo d_location_info;
int d_narguments;

private:
std::vector<std::string> d_varnames;
};
} // namespace pystack
9 changes: 8 additions & 1 deletion src/pystack/_pystack/pyframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,14 @@ FrameObject::getCode(
} else {
last_instruction = frame.getField(&py_frame_v::o_lasti);
}
return std::make_unique<CodeObject>(manager, py_code_addr, last_instruction);
try {
return std::make_unique<CodeObject>(manager, py_code_addr, last_instruction);
} catch (const RemoteMemCopyError& ex) {
// This may not have been a code object at all, or it may have been
// trashed by memory corruption. Either way, indicate that we failed
// to understand what code this frame is running.
return std::make_unique<CodeObject>("???", "???", LocationInfo{0, 0, 0, 0});
}
}

bool
Expand Down
Loading