Memory write tracing/logging of an application / Watchpoints in Genode/Fiasco.OC

Josef Stark j.stark at ...256...
Mon Feb 26 21:26:58 CET 2018


Hello,

I circumvented the problem of finding the correct dataspace by letting
the pagefault handler open another ROM connection to the binary at its
instantiation. The ELF file contains the VM address of the code section,
which allows me to fetch the correct instruction when a pagefault
happens.

Then, I can use the instruction decoder (see Vinit @ [1]):
 > bool ldst = Instruction::load_store(instr, writes, state.format,
 >    state.reg);
 > size_t access_size = state.format == Region_map::LSB8 ? 1 :
 >    (state.format == Region_map::LSB16 ? 2 : 4);

With this information I should be able to emulate the instruction:
 > if(!writes) {
 >     state.value = 0;
 >     memcpy(&state.value,addr + state.addr,access_size);
 >     thread_state.set_gpr(state.reg,state.value);
 > }
 > else {
 >     thread_state.get_gpr(state.reg, state.value);
 >     memcpy(addr + state.addr,&state.value,access_size);
 > }
(For set_gpr() and get_gpr() see Vinit @ [2])

I have a simple sample application that for now only reads repeatedly a
memory value and prints it:
 > unsigned n = 0x12abcdef
 > while(1) {
 >     log(n, " sheep");
 >     timer.msleep(1000);
 > }

I let this app run normally for a few seconds and then detach the
dataspace to see if emulation is working... it isn't.

The register write - i.e. the simulated load (memory read) instruction -
results in weird app behavior: The app outputs "0 sheep" - wrong number
- without pausing 1 second. If I comment out the register write, it
outputs the same but pauses 1 second like it should.
The instruction decoder gives the following info (pf IP is 0x1001bb0):
 > instruction: e599116c, load, LSB32, reg: 1
Which conforms with what objdump tells me:
 > 1001bb0:       e599116c        ldr     r1, [r9, #364]  ; 0x16c

Still, it doesn't work. By trial and error (going through all regs) I
found out that writing to r9 instead of r1 (in the pf handler) gives me
the desired behaviour: Printing the correct number and waiting 1 second.

But I have no idea why my code above doesn't work (and why r9 does). I
know the target register number and write the value into it. Vinit also
seems to do it like this: [3]
Isn't this exactly what the processor would do?
What could I be missing?

Best regards,
Josef


[1] os/src/vinit/arm_v7a/instruction.h
[2] base-hw/include/arm_v7/base/thread_state.h
[3] state() & processed() in os/src/vinit/include/rm_session/component.h




More information about the users mailing list