0

What I'm about to ask is a bit hacky (in that it's a very poor method of attacking the problem) - I understand that and do not plan on using this as a long-term solution, only for a proof-of-concept.

That said, I'm working on a project that uses QEMU as a foundation to migrate processes (eventually threads) from one machine to another. I'm starting the process on the native machine, pausing it using ptrace, and then copying the CPU's registers and stack and pushing those values into a newly-created instance of QEMU (with the same underlying architecture, i.e. x86-64 --> x86_64, ARM64 --> ARM64). I then (eventually) resume execution in QEMU.

I've reached the stage where I need to pass the registers + stack into QEMU, but I've hit a bit of a wall; ideally, I would break apart QEMU and compile the entire program as part of my own program, but this is where the proof-of-concept comes into play. QEMU is a massive program, and breaking apart/reconstructing the Makefiles is something I'm not terribly keen on approaching right now. So...

Is it possible for me to fill a struct with the registers + stack in my program, create a pointer to that struct, cast that pointer as a char*, and then pass that char* pointer into execlp, to be recast in (a modified version of) QEMU? The goal is to access those values from within QEMU. For example:

struct regs_and_stack my_struct = {...};
struct regs_and_stack *my_struct_ptr = &my_struct;
execlp("qemu", "qemu", "test", "100000", (char*)my_struct_ptr);

I can post the rest of my code to get a better sense of the big picture, if requested. As always, thank you for the help!!!

EDIT

I've identified the point in the qemu main function (linux-users/main.c) where I can pop the final pointer from argv before it reaches the point where it parses through the options; I'll use this information later in the program's execution. The question is just how to get this struct into the main function in the first place.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
tonysdg
  • 1,335
  • 11
  • 32
  • That question seems to be too broad. Just a small hint: Note that you have to migrate the whole state of a process. That would include the heap and the exact layout of allocate blocks (think about pointers in dynamic structs. – too honest for this site Jun 18 '15 at 17:36
  • 1
    I don't understand what you are trying to do, but I suspect that it won't do it. `execlp` is taking null-terminated strings as the arguments. And `qemu` is expecting specific strings as arguments. So I don't get what you will gain by passing it some binary data. – Eugene Sh. Jun 18 '15 at 17:36
  • @Olaf - I'd forgotten about the heap, but it's doable; the broader project involves a full OS, so I'll have to make it happen and transform the stack/heap as necessary. The question is really about passing the pointer to the struct - sorry for adding too much extraneous info! – tonysdg Jun 18 '15 at 17:45
  • @EugeneSh. - I've identified the main function in qemu that needs to be modified; I plan on popping this pointer off the argv list before passing it through to the rest of the program. I just need to physically get this struct into qemu before I can move forward, and this seemed like a possible quick-and-dirty method. – tonysdg Jun 18 '15 at 17:45
  • 1
    No it won't work. Because 1) It is not the same pointer. 2) The data might not be terminated at all, or terminated in the middle. If you really want to pass some data to qemu via command line - do it textually. – Eugene Sh. Jun 18 '15 at 17:48
  • @EugeneSh. - I think that answers the question then; that's a lot of information to pass into qemu, so I'm going to have to find another solution. Thank you! – tonysdg Jun 18 '15 at 17:49
  • one detail. the 'argv[]' parameter has to end with a NULL entry. It is currently ending with a pointer to some struct – user3629249 Jun 18 '15 at 18:16
  • these Q and As are gonna solve your problem. http://stackoverflow.com/questions/16543519/serialization-of-struct http://stackoverflow.com/questions/1653681/serialization-deserialization-of-a-struct-to-a-char-in-c – FazeL Jul 17 '15 at 01:03
  • Returning to this question 8 years later, I can't help but cringe at how awful it is. Ah well. Time goes on. – tonysdg Apr 18 '23 at 05:57

1 Answers1

0

here if I understood well you want to serialize your structs and then deserialize them on the other end. the following code fragment form answers of this question Serialization of struct is gonna solve problem , you have to edit your own serialize and deserialize functions because they depend to your strut's structuer. just skip the q variable enough to open a place for your structs variable to fit in the text sequence.

#include <iostream>
#include <cstring>

#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)

using namespace std;

typedef struct MSG
{
    int type;
    int priority;
    int sender;
    char message[BUFSIZE];
}MSG;

void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);

int main()
{
    MSG* newMsg = new MSG;
    newMsg->type = 1;
    newMsg->priority = 9;
    newMsg->sender = 2;
    strcpy(newMsg->message, "hello from server\0");
    printMsg(newMsg);

    char data[PACKETSIZE];

    serialize(newMsg, data);

    MSG* temp = new MSG;
    deserialize(data, temp);
    printMsg(temp);

    return 0;
}    

void     serialize(MSG* msgPacket, char *data)
{
    int *q = (int*)data;    
    *q = msgPacket->type;       q++;    
    *q = msgPacket->priority;   q++;    
    *q = msgPacket->sender;     q++;

    char *p = (char*)q;
    int     i = 0;
    while (i < BUFSIZE)
    {
        *p = msgPacket->message[i];
        p++;
        i++;
    }
}

void deserialize(char *data, MSG* msgPacket)
{
    int *q = (int*)data;    
    msgPacket->type = *q;       q++;    
    msgPacket->priority = *q;   q++;    
    msgPacket->sender = *q;     q++;

    char *p = (char*)q;
    int i = 0;
    while (i < BUFSIZE)
    {
        msgPacket->message[i] = *p;
        p++;
        i++;
    }
}

void printMsg(MSG* msgPacket)
{
    cout << msgPacket->type << endl;
    cout << msgPacket->priority << endl;
    cout << msgPacket->sender << endl;
    cout << msgPacket->message << endl;
}

this link would be useful too: stackoverflow.com/questions/1653681/serialization-deserialization-of-a-struct-to-a-char-in-c

Community
  • 1
  • 1
FazeL
  • 916
  • 2
  • 13
  • 30