@@ -55,88 +55,79 @@ findPthreadTidOffset(
5555 remote_addr_t interp_state_addr)
5656{
5757 LOG (DEBUG) << " Attempting to locate tid offset in pthread structure" ;
58+ Structure<py_is_v> is (manager, interp_state_addr);
5859
59- // If interp_state_addr does not point to the main interpreter (id 0) we won't find the
60- // PID == TID in the interpreter threads. Hence, we traverse the linked list of interpreters. The
61- // main interpreter is not necessarily the head of the linked lists of interpreters.
60+ auto current_thread_addr = is.getField (&py_is_v::o_tstate_head);
6261
63- while (interp_state_addr != 0 ) {
64- Structure<py_is_v> is (manager, interp_state_addr);
62+ auto thread_head = current_thread_addr;
6563
66- auto current_thread_addr = is.getField (&py_is_v::o_tstate_head);
67-
68- auto thread_head = current_thread_addr;
69-
70- // Iterate over all Python threads until we find a thread that has a tid equal to
71- // the process pid. This works because in the main thread the tid is equal to the pid,
72- // so when this happens it has to happen on the main thread. Note that the main thread
73- // is not necessarily at the head of the Python thread linked list
64+ // Iterate over all Python threads until we find a thread that has a tid equal to
65+ // the process pid. This works because in the main thread the tid is equal to the pid,
66+ // so when this happens it has to happen on the main thread. Note that the main thread
67+ // is not necessarily at the head of the Python thread linked list
7468
7569#if defined(__GLIBC__)
76- // If we detect GLIBC, we can try the two main known structs for 'struct
77- // pthread' that we know about to avoid having to do guess-work by doing a
78- // linear scan over the struct.
79- while (current_thread_addr != (remote_addr_t ) nullptr ) {
80- Structure<py_thread_v> current_thread (manager, current_thread_addr);
81- auto pthread_id_addr = current_thread.getField (&py_thread_v::o_thread_id);
82-
83- pid_t the_tid;
84- std::vector<off_t > glibc_pthread_offset_candidates = {
85- offsetof (_pthread_structure_with_simple_header, tid),
86- offsetof (_pthread_structure_with_tcbhead, tid)};
87- for (off_t candidate : glibc_pthread_offset_candidates) {
88- manager->copyObjectFromProcess ((remote_addr_t )(pthread_id_addr + candidate), &the_tid);
89- if (the_tid == manager->Pid ()) {
90- LOG (DEBUG) << " Tid offset located using GLIBC offsets at offset " << std::showbase
91- << std::hex << candidate << " in pthread structure" ;
92- return candidate;
93- }
94- }
95- remote_addr_t next_thread_addr = current_thread.getField (&py_thread_v::o_next);
96- if (next_thread_addr == current_thread_addr) {
97- break ;
70+ // If we detect GLIBC, we can try the two main known structs for 'struct
71+ // pthread' that we know about to avoid having to do guess-work by doing a
72+ // linear scan over the struct.
73+ while (current_thread_addr != (remote_addr_t ) nullptr ) {
74+ Structure<py_thread_v> current_thread (manager, current_thread_addr);
75+ auto pthread_id_addr = current_thread.getField (&py_thread_v::o_thread_id);
76+
77+ pid_t the_tid;
78+ std::vector<off_t > glibc_pthread_offset_candidates = {
79+ offsetof (_pthread_structure_with_simple_header, tid),
80+ offsetof (_pthread_structure_with_tcbhead, tid)};
81+ for (off_t candidate : glibc_pthread_offset_candidates) {
82+ manager->copyObjectFromProcess ((remote_addr_t )(pthread_id_addr + candidate), &the_tid);
83+ if (the_tid == manager->Pid ()) {
84+ LOG (DEBUG) << " Tid offset located using GLIBC offsets at offset " << std::showbase
85+ << std::hex << candidate << " in pthread structure" ;
86+ return candidate;
9887 }
99- current_thread_addr = next_thread_addr;
10088 }
89+ remote_addr_t next_thread_addr = current_thread.getField (&py_thread_v::o_next);
90+ if (next_thread_addr == current_thread_addr) {
91+ break ;
92+ }
93+ current_thread_addr = next_thread_addr;
94+ }
10195#endif
10296
103- current_thread_addr = thread_head;
104-
105- while (current_thread_addr != (remote_addr_t ) nullptr ) {
106- Structure<py_thread_v> current_thread (manager, current_thread_addr);
107- auto pthread_id_addr = current_thread.getField (&py_thread_v::o_thread_id);
108-
109- // Attempt to locate a field in the pthread struct that's equal to the pid.
110- uintptr_t buffer[100 ];
111- size_t buffer_size = sizeof (buffer);
112- while (buffer_size > 0 ) {
113- try {
114- LOG (DEBUG) << " Trying to copy a buffer of " << buffer_size
115- << " bytes to get pthread ID" ;
116- manager->copyMemoryFromProcess (pthread_id_addr, buffer_size, &buffer);
117- break ;
118- } catch (const RemoteMemCopyError& ex) {
119- LOG (DEBUG) << " Failed to copy buffer to get pthread ID" ;
120- buffer_size /= 2 ;
121- }
122- }
123- LOG (DEBUG) << " Copied a buffer of " << buffer_size << " bytes to get pthread ID" ;
124- for (size_t i = 0 ; i < buffer_size / sizeof (uintptr_t ); i++) {
125- if (static_cast <pid_t >(buffer[i]) == manager->Pid ()) {
126- off_t offset = sizeof (uintptr_t ) * i;
127- LOG (DEBUG) << " Tid offset located by scanning at offset " << std::showbase
128- << std::hex << offset << " in pthread structure" ;
129- return offset;
130- }
131- }
97+ current_thread_addr = thread_head;
98+
99+ while (current_thread_addr != (remote_addr_t ) nullptr ) {
100+ Structure<py_thread_v> current_thread (manager, current_thread_addr);
101+ auto pthread_id_addr = current_thread.getField (&py_thread_v::o_thread_id);
132102
133- remote_addr_t next_thread_addr = current_thread.getField (&py_thread_v::o_next);
134- if (next_thread_addr == current_thread_addr) {
103+ // Attempt to locate a field in the pthread struct that's equal to the pid.
104+ uintptr_t buffer[100 ];
105+ size_t buffer_size = sizeof (buffer);
106+ while (buffer_size > 0 ) {
107+ try {
108+ LOG (DEBUG) << " Trying to copy a buffer of " << buffer_size << " bytes to get pthread ID" ;
109+ manager->copyMemoryFromProcess (pthread_id_addr, buffer_size, &buffer);
135110 break ;
111+ } catch (const RemoteMemCopyError& ex) {
112+ LOG (DEBUG) << " Failed to copy buffer to get pthread ID" ;
113+ buffer_size /= 2 ;
114+ }
115+ }
116+ LOG (DEBUG) << " Copied a buffer of " << buffer_size << " bytes to get pthread ID" ;
117+ for (size_t i = 0 ; i < buffer_size / sizeof (uintptr_t ); i++) {
118+ if (static_cast <pid_t >(buffer[i]) == manager->Pid ()) {
119+ off_t offset = sizeof (uintptr_t ) * i;
120+ LOG (DEBUG) << " Tid offset located by scanning at offset " << std::showbase << std::hex
121+ << offset << " in pthread structure" ;
122+ return offset;
136123 }
137- current_thread_addr = next_thread_addr;
138124 }
139- interp_state_addr = InterpreterUtils::getNextInterpreter (manager, interp_state_addr);
125+
126+ remote_addr_t next_thread_addr = current_thread.getField (&py_thread_v::o_next);
127+ if (next_thread_addr == current_thread_addr) {
128+ break ;
129+ }
130+ current_thread_addr = next_thread_addr;
140131 }
141132 LOG (ERROR) << " Could not find tid offset in pthread structure" ;
142133 return 0 ;
@@ -155,8 +146,9 @@ PyThread::PyThread(const std::shared_ptr<const AbstractProcessManager>& manager,
155146 LOG (DEBUG) << std::hex << std::showbase << " Attempting to construct frame from address "
156147 << frame_addr;
157148 d_first_frame = std::make_unique<FrameObject>(manager, frame_addr, 0 );
149+
150+ d_stack_anchor = getStackAnchor (manager, frame_addr);
158151 }
159- d_stack_anchor = getStackAnchor (manager, frame_addr);
160152
161153 d_addr = addr;
162154 remote_addr_t candidate_next_addr = ts.getField (&py_thread_v::o_next);
@@ -418,7 +410,7 @@ getThreadFromInterpreterState(
418410 const std::shared_ptr<const AbstractProcessManager>& manager,
419411 remote_addr_t addr)
420412{
421- if (tid_offset_in_pthread_struct == 0 ) {
413+ if (tid_offset_in_pthread_struct == 0 && !manager-> versionIsAtLeast ( 3 , 11 ) ) {
422414 tid_offset_in_pthread_struct = findPthreadTidOffset (manager, addr);
423415 }
424416
0 commit comments