(ql: Qiling, address_map: Mapping[str, int])
| 10 | |
| 11 | |
| 12 | def init_linux_traps(ql: Qiling, address_map: Mapping[str, int]) -> None: |
| 13 | # If the compiler for the target does not provides some primitives for some |
| 14 | # reasons (e.g. target limitations), the kernel is responsible to assist |
| 15 | # with these operations. |
| 16 | # |
| 17 | # The following is some `kuser` helpers, which can be found here: |
| 18 | # https://elixir.bootlin.com/linux/latest/source/arch/arm/kernel/entry-armv.S#L899 |
| 19 | |
| 20 | trap_map = { |
| 21 | # @ 0xffff0fa0 |
| 22 | 'memory_barrier': bytes.fromhex( |
| 23 | 'ba 0f 07 ee' # mcr p15, 0, r0, c7, c10, 5 |
| 24 | '00 f0 20 e3' # nop |
| 25 | '0e f0 a0 e1' # mov pc, lr |
| 26 | ), |
| 27 | |
| 28 | # @ 0xffff0fc0 |
| 29 | 'cmpxchg': bytes.fromhex( |
| 30 | '00 30 92 e5' # ldr r3, [r2] |
| 31 | '00 30 53 e0' # subs r3, r3, r0 |
| 32 | '00 10 82 05' # streq r1, [r2] |
| 33 | '00 00 73 e2' # rsbs r0, r3, #0 |
| 34 | '0e f0 a0 e1' # mov pc, lr |
| 35 | ), |
| 36 | |
| 37 | # @ 0xffff0fe0 |
| 38 | 'get_tls': bytes.fromhex( |
| 39 | '08 00 9f e5' # ldr r0, [pc, #(16 - 8)] |
| 40 | '0e f0 a0 e1' # mov pc, lr |
| 41 | '70 0f 1d ee' # mrc p15, 0, r0, c13, c0, 3 |
| 42 | 'e7 fd de f1' # padding (e7 fd de f1) |
| 43 | '00 00 00 00' # data |
| 44 | '00 00 00 00' # data |
| 45 | '00 00 00 00' # data |
| 46 | ) |
| 47 | } |
| 48 | |
| 49 | if address_map: |
| 50 | # Find min / max address in address_map |
| 51 | lower_bound = min(address_map.values()) |
| 52 | # Get max address in address_map and its trap name |
| 53 | upper_trap = max(address_map, key=address_map.get) |
| 54 | base = ql.mem.align(lower_bound) |
| 55 | # size to map = start of upper_trap + len of upper_trap - start of lower_trap |
| 56 | size = ql.mem.align_up(address_map[upper_trap] - lower_bound + len(trap_map[upper_trap])) |
| 57 | |
| 58 | ql.mem.map(base, size, info="[arm_traps]") |
| 59 | |
| 60 | for trap_name, trap_code in trap_map.items(): |
| 61 | if ql.arch.endian is QL_ENDIAN.EB: |
| 62 | trap_code = swap_endianness(trap_code) |
| 63 | |
| 64 | if trap_name in address_map: |
| 65 | ql.mem.write(address_map[trap_name], trap_code) |
| 66 | |
| 67 | ql.log.debug(f'Setting kernel trap {trap_name} at {address_map[trap_name]:#x}') |
| 68 | |
| 69 |
nothing calls this directly
no test coverage detected