[Mono-dev] ARM/NativeClient port

Nikolay Igotti olonho at google.com
Wed Jan 30 09:39:20 UTC 2013


  Hi,

 We're working on implementation of Mono JIT/ARM for Native Client, and
want to discuss certain details about design of our solution.
 Native Client's sandboxing mechanism, being a SFI solution, has rather
strict  limitations on how verifiable machine code may look like. To be
precise:

  1. all code/data access has to be in lower 1G range of address space
  2. all branch targets have to be 16 bytes (bundle) aligned, unless
      it's direct branch to the instruction which need no masking (see 3.)
  3. code with register arguments (loads, stores, branches) must explicitly
enforce 1. and 2.
      by masking upper and lower bits (by bic reg, reg, #0xc000000f)
  4. all code must be valid instructions, not matter if reachable or not
  5. the only exception from 4 is 16 bytes data bundles starting with UNDEF
     instruction (0xE125BE70), 12 remaining bytes could be used for anything
  6. no executable code could be easily modified in runtime, unless in data
bundle,
      or immediate argument of MOVT (A1), MOVW (A2), ORR/MOV/MVN
      Even in this case - NaCl runtime call is needed for modifications to
take effect.
  7. No direct PC manipulations allowed (mov, add to PC), it's allowed to
be used
       like x86 PC register (modulo PC-relative loads).
  8. All bl/blx must be bundle-end aligned  and LR is masked before return,
as everything else in 3.
  9. Register R9 is used as TLS base, and could only be accessed as
      ldr rd, [r9] and ldr rd [r9, #4].

 Most troublesome part for porting is using of patchable inline constants
in trampolines.
 Our idea is to emit per-method (or per class?) "jump table" somewhere in
.data, which contains list of all relocations, and use some register to
point to this table.
 So for example, trampoline like this:
        ldr ip, [pc, #0]
b skip
        .word target
      skip:
mov lr, pc
mov pc, ip
would become (if r10 is used as jump table base register):
      .align 4 # for NaCl only
         ldr ip, [r10, #32] # unique (per-method or class) index for every
callsite
         nop  # for NaCl only, to have bl at bundle end
         bic r10, r10, #0xc000000f # for NaCl only
         bl ip # or blx
 r10 could point somewhere in method metadata, where its relocation table
is stored.

 So our question is if someone sees problem with such approach, or could
suggest better alternative. Also advises which register could be used as
the jump table base, and where to store
such a table (maybe patch info?) are very welcome.

 There are few advantages and disadvantages of this solution.
Improvements:
  - easily maintainable code (single trampoline mechnism with simple
patching)
  - no writes to the code being executed
  - smaller code
  - no need to have entries in both i-cache and d-cache for branch
destination
Detriments:
  - extra register used
  - potentially worse cache locality compared to inline cache (although
once jump table cached, it could be used few times)
  - need to init jump table base on entry to every method which uses
trampolines
  - limitation on number of callsites by immediate length in LDR, see
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BABJGHFJ.html;
we
can only use up to 1K of callsites.
If more than 1K of callsites in method - constant pool index shall be
constructed in register.

 If there will be no strong objections, we plan to implement such a
solution under configure/compilation flag for both NaCl and generic ARM
port, and ask Mono maintainers to commit it.

  Thanks,
     Nikolay.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/mono-devel-list/attachments/20130130/893c46e8/attachment.html>


More information about the Mono-devel-list mailing list