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

Josef Stark j.stark at ...256...
Mon Mar 12 18:19:43 CET 2018


Hi Martin,

On 02/28/2018 04:02 PM, Martin Stein wrote:
> Hi Josef,
 > [...]
> First, I would look at the assembly context at 0x1001bb0 especially what
> is done with R1/R9 in the subsequent instructions. You might also play
> around with explicit register assignment:
> 
> register unsigned my_var asm("r1") = n;
> 
> or inline assembler to get a better understanding what you're actually
> doing wrong in the perspective of the client.
> 
> Maybe the client returns from emulation with a bad IP which you could
> check by adding an assembler instruction with an observable side effect
> directly behind the LDR (or using a debugger).
> 
> You could even write an inline assembler snippet that writes the whole
> GPR state after the LDR to RAM when running without emulation. This way,
> you can compare the GPR states of the emulation case (inside observer)
> and the non-emulation case.

I experimented a bit and after comparing the actual register contents of 
R0-R15 inside the child application with the contents of the 
Thread_state register backup (R0-R15) that is delivered to my fault 
handler, it seems like Genode (or Fiasco.OC or the glue code) delivers 
the registers in a strange mapping, where some original regs are mapped 
to different regs in the backup, and some do not appear at all. The 
mapping is like this:

Thread_state	| Child	| Child - Alternative Possibility
---------------------------------------------------------
R0		| R9	| R7
R1		| R10	| R4
R2		| R11	|
R3		|	|
R4		|	|
R5		|	|
R6		|	|
R7		|	|
R8		| R0	|
R9		| R1	|
R10		| R2	|
R11		| R3	|
R12		| R12	| R5
R13		| R13	|
R14		| R14	|
R15		| R15	|
		| R6	|
		| R8	|

(Alternative Possibility means I couldn't tell which of the two is 
actually correct due to equal values. The Thread_state registers that 
have no mapping contained values that did not match any of the original 
register contents; some of those values appeared in two distinct 
Thread_state registers. I assured myself that the child didn't modify 
the registers before dumping the contents.)
While this looks pretty strange, I verified the 'mapping' on a few 
occasions and after incorporating the mapping into the instruction 
emulator/the redundant memory writer, it does what it should, at least 
for a limited test case (which doesn't access one of the unmapped 
registers).

I should mention that we use a slightly modified Fiasco.OC kernel and 
kernel interface, since in the unmodified Genode 16.08/Fiasco.OC, 
calling Cpu_thread_component::state() [1] internally calls 
Platform_thread::state(), which does not return the contents of all 
registers. Instead our modified Platform_thread::state() calls our own 
method all_regs() [2] which does that. The modified Fiasco.OC kernel 
source files are [3] and [4] with modifications marked with a comment 
mentioning "rtcr". But no remapping or other strange things are done there.

My guess is that this register magic is not happening in the base-hw 
version of Genode (since Vinit instruction emulation is not using any 
remapping and still works), but maybe you still have a clue of what is 
going on there.


Best regards,
Josef


[1] state() repos/base/src/core/cpu_thread_component.cc
[2] all_regs(): 
https://github.com/jmstark/cr-genode/blob/red_mem/repos/base-focnados/src/core/platform_thread.cc
[3] 
https://github.com/argos-research/foc/blob/checkpointRestore/l4/pkg/l4sys/include/thread.h
[4] 
https://github.com/argos-research/foc/blob/checkpointRestore/kernel/fiasco/src/kern/thread_object.cpp




More information about the users mailing list