Re: Error record and replay target doesn't support syscall number 435

Guinevere Larsen via Gdb <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
Re-adding gdb list, since you mentioned you dropped on accident
On 5/13/24 12:13, Navin P wrote:
> On Mon, May 13, 2024 at 6:40 PM Guinevere Larsen <[email protected]> wrote:
>> On 5/13/24 08:06, Navin P wrote:
>>> Hi,
>> Hi! :)
>>> On Fri, May 10, 2024 at 7:29 PM Guinevere Larsen <[email protected]> wrote:
>>>> On 5/10/24 05:07, Navin P via Gdb wrote:
>>>>> Hi,
>>>>>         I tried to record a program calling C++ threads and then did a
>>>>> break on main , then record and continue it throws the error message
>>>>> "record and replay target doesn't support syscall number 435" . What
>>>>> should I do to support syscall number 435 ?
>>>> Hi!
>>>>
>>>> I can't answer everything, since I'm not too familiar with syscalls
>>>> specifically, but I'll do my best!
>>>>
>>>> My first road bump with this is that we record that a clone has
>>>> happened, but we can only record the process that GDB is following
>>>> (parent or child, depending on follow-fork-mode). This is
>>>> counter-intuitive to me, since I would have expected the full inferior
>>>> to be replayed.
>>> To get this working you need minimum changes of current_inferior to
>>> for each inferior in all_inferiors() and execute that function for
>>> each inferior.
>>> return values have to be captured in a list. Similarly for each return value
>>> you have to perform the actions in a loop.
>> There is an extra complication, the recording subsystem was added before
>> GDB could handle multiple inferiors, so it works on the assumption that
>> you only need one global history. Meaning if we did record for all
>> inferiors or all processes, the history would be mangled, jumping from
>> one inferior to the next. It is already a problem in handling
>> multi-threaded inferiors, so a proper fix would require having a
>> per-thread history, and possibly some way to serialize the execution.
>>
>> I added the explanation more as a motivator to why I think we should
>> warn the user of the counter-intuitive behavior, at least in the
>> documentation.
>>
>>> It is going to definitely slow down execution by orders of magnitude.
>> Absolutely! I'm almost wondering if we should try to spawn a recording
>> thread per process or thread, to at least make multi-threaded recording
>> not worse. But that is far in the future, unrelated to this change
> static void
> record_full_core_open_1 ()
> {
>    regcache *regcache = get_thread_regcache (inferior_thread ())
>
> In record-full.c we have inferior_thread() which is the current thread,
>   so only 1 thread is recorded ?  That is my observation too.
I am not sure if only thread 1 is recorded, or if it is mixing 
instructions from all threads, but only changing register values for one 
of the threads. You can disassemble thread 1, then reverse-stepi to see 
if the PC changes wildly or if phantom instructions show up.
> If so, what is required to fix it for all threads.
I haven't fully accounted for everything that is required to make record 
work for multi-threaded inferiors. What I know we strictly need to 
either double-check or improve is:
     * If you check gdb/record-full.c:197, you'll see how we store the 
full history. Its a single global variable for everything that is 
recorded. This needs to be turned into a thread specific member.
     * I think the way GDB handles step means multiple threads will all 
be handled by a single record target, in a single thread. This needs to 
be verified, and if I'm right, we need to find a way to serialize the 
threads, so that we can replay thread in the correct order.
     * There's an open bug for gdb not properly handling (at least) 
sigtrap when an inferior is added: 
https://sourceware.org/bugzilla/show_bug.cgi?id=30025. We need to fix 
that if multiple processes are handled like multiple inferiors as you 
mentioned.

Properly handling multi-threaded has been in my backlog for a bit, but I 
have one task for record that's much more important - adding support to 
AVX instructions - and I have limited time for record stuff, unfortunately.
> Here there is only
> one process
> with multiple threads. I expect it to catch the segfault in thread 2
> but it fails
> and goes into an infinite loop.

Instead of a global variable, try using a counter on the while loops, 
and set it to a small value like 3-4. The current slowdown for execution 
is unbelievable (was also a backlogged thing for me).

Also, I don't know if your system doesn't use a libc++ that's very 
optimized, but I can't record the creation of std::thread objects. 
That's because std::thread::_M_start_thread uses memset somewhere, and 
my glibc has the optimized avx512 version of memset, an instruction gdb 
can't disassemble yet. So we can add "supporting newer x86_64 
instructions" to the list of tasks to do if we want to _properly_ 
support multi-threading. And if you want to double check what I 
mentioned above, I'd also recommend not printing, because that's also 
libc++, so likely to be using optimized instructions.

-- 
Cheers,
Guinevere Larsen
She/Her/Hers

>
> #include<thread>
> #include<iostream>
> #include<unistd.h>
> using namespace std;
> bool run=true;
> int i=6;
> int *p=&i,g;
>
> void t1() {
> while(run){
>       g++;
>       if(g>=16)
>            p=nullptr;
>        cout <<"t1 "<<g<<endl;
>    }
> }
>
> void t2(){
> int t=0;
> while(run){
>         g++;
>         t=*p + 5;
>         cout <<"t2 "<<g<<endl;
>    }
> }
>
>
> int main(){
> thread x1{t1},x2{t2};
> sleep(5);
> run=false;
> x1.join();x2.join();
> }
>
>
> Regards,
> Navin
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.