0

I want to use QEMU to run a multithreaded program, and I want to record the execution path of each thread in QEMU without modifying the source code, represented by the first address of the basic block. However, I have found that even in the QEMU user mode, even for multithreaded programs, I print CPU ->thread_ The id has always been the same value.

My work environment is Ubuntu 22.10.

I write a multithreaded program with c++ as follow:

#include <thread>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>

using namespace std;

void func1(){
    while(1){
        std::cout<<"thread 1\n";
        sleep(1);
    }
    return;
}
void func2(){
    while(1){
        std::cout<<"thread 2\n";
        sleep(1);
    }
    return;
}
void func3(){
    while(1){
        std::cout<<"thread 3\n";
        sleep(1);
    }
    return;
}
void func4(){
    while(1){
        std::cout<<"thread 4\n";
        sleep(1);
    }
    return;
}

int main(){
    thread t1=thread(func1);
    thread t2=thread(func2);
    thread t3=thread(func3);
    thread t4=thread(func4);
    cout<<"this is main\n";
    t1.join();
    t2.join();
    t3.join();
    t4.join();
}

The version of qemu I used is 6.0.0,and I add some code in the /qemu-6.0.0/accel/tcg/ecp-exec.c file.

The function I operatored is cpu_tb_exec,the code I added as follow:

const void *tb_ptr = itb->tc.ptr;
+    static unsigned int count=0;
+    {
+        char filename[100]={0};
+        sprintf(filename,"/home/admin/work/qemu/log/log_%d",cpu->thread_id);
+        FILE *fp=fopen(filename,"a");
+        if(fp==NULL) {
+            exit(1);
+        }
+        lseek(fp,0,SEEK_END);
+        fprintf(fp,"%d: 0x%08x\n",count++,(unsigned long long)itb->pc);
+        fclose(fp);
+     }
    
    //fprintf(stderr,"0x%08x\n",(unsigned long long)itb->pc);
    
    qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
                           "Trace %d: %p ["
                           TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
                           cpu->cpu_index, itb->tc.ptr,
                           itb->cs_base, itb->pc, itb->flags,
                           lookup_symbol(itb->pc));
Arashimu
  • 1
  • 1

1 Answers1

0

In that exec trace, the first number after "Trace" is the CPU index. In user-mode, each thread gets its own CPU, and so each thread has its own number; you can use that to identify which trace is for which thread.

(The cpu->thread_id() you were trying to print is the ID of the host QEMU thread. If you are running QEMU in a setup where it runs one guest thread per host thread then this will differ per-guest thread, but if you're running QEMU in a setup where all guest threads run on the same host thread then it will be the same value for every guest thread.)

Peter Maydell
  • 9,707
  • 1
  • 19
  • 25
  • Thank you for your answer. I changed the cpu->thread_id to itb->trace_vcpu_dstate,but the suffix of the log file is still 0 – Arashimu Sep 01 '23 at 06:35
  • or maybe I run the command "qemu-x86_64 -trace [option] ./binary" with a specific option. – Arashimu Sep 01 '23 at 06:49
  • You shouldn't need to change anything in QEMU, the logging of -d exec includes the "Trace 0:", "Trace 1:" already. – Peter Maydell Sep 01 '23 at 11:33