MCPcopy Create free account
hub / github.com/bloomberg/pystack / findPthreadTidOffset

Function findPthreadTidOffset

src/pystack/_pystack/pythread.cpp:44–126  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

42off_t tid_offset_in_pthread_struct = 0;
43
44static off_t
45findPthreadTidOffset(
46 const std::shared_ptr<const AbstractProcessManager>& manager,
47 remote_addr_t interp_state_addr)
48{
49 LOG(DEBUG) << "Attempting to locate tid offset in pthread structure";
50 Structure<py_is_v> is(manager, interp_state_addr);
51
52 auto current_thread_addr = is.getField(&py_is_v::o_tstate_head);
53
54 auto thread_head = current_thread_addr;
55
56 // Iterate over all Python threads until we find a thread that has a tid equal to
57 // the process pid. This works because in the main thread the tid is equal to the pid,
58 // so when this happens it has to happen on the main thread. Note that the main thread
59 // is not necessarily at the head of the Python thread linked list
60
61#if defined(__GLIBC__)
62 // If we detect GLIBC, we can try the two main known structs for 'struct
63 // pthread' that we know about to avoid having to do guess-work by doing a
64 // linear scan over the struct.
65 while (current_thread_addr != (remote_addr_t) nullptr) {
66 Structure<py_thread_v> current_thread(manager, current_thread_addr);
67 auto pthread_id_addr = current_thread.getField(&py_thread_v::o_thread_id);
68
69 pid_t the_tid;
70 std::vector<off_t> glibc_pthread_offset_candidates = {
71 offsetof(_pthread_structure_with_simple_header, tid),
72 offsetof(_pthread_structure_with_tcbhead, tid)};
73 for (off_t candidate : glibc_pthread_offset_candidates) {
74 manager->copyObjectFromProcess((remote_addr_t)(pthread_id_addr + candidate), &the_tid);
75 if (the_tid == manager->Pid()) {
76 LOG(DEBUG) << "Tid offset located using GLIBC offsets at offset " << std::showbase
77 << std::hex << candidate << " in pthread structure";
78 return candidate;
79 }
80 }
81 remote_addr_t next_thread_addr = current_thread.getField(&py_thread_v::o_next);
82 if (next_thread_addr == current_thread_addr) {
83 break;
84 }
85 current_thread_addr = next_thread_addr;
86 }
87#endif
88
89 current_thread_addr = thread_head;
90
91 while (current_thread_addr != (remote_addr_t) nullptr) {
92 Structure<py_thread_v> current_thread(manager, current_thread_addr);
93 auto pthread_id_addr = current_thread.getField(&py_thread_v::o_thread_id);
94
95 // Attempt to locate a field in the pthread struct that's equal to the pid.
96 uintptr_t buffer[100];
97 size_t buffer_size = sizeof(buffer);
98 while (buffer_size > 0) {
99 try {
100 LOG(DEBUG) << "Trying to copy a buffer of " << buffer_size << " bytes to get pthread ID";
101 manager->copyMemoryFromProcess(pthread_id_addr, buffer_size, &buffer);

Callers 1

Calls 4

LOGClass · 0.85
copyObjectFromProcessMethod · 0.80
PidMethod · 0.45
copyMemoryFromProcessMethod · 0.45

Tested by

no test coverage detected