Add support for fast tracepoints
This patch adds support for fast tracepoints for aarch64-linux. With this
implementation, a tracepoint can only be placed in a +/- 128MB range of
the jump pad. This is due to the unconditional branch instruction
being limited to a (26 bit << 2) offset from the current PC.
Three target operations are implemented:
- target_install_fast_tracepoint_jump_pad
Building the jump pad the biggest change of this patch. We need to add
functions to emit all instructions needed to save and restore the
current state when the tracepoint is hit. As well as implementing a
lock and creating a collecting_t object identifying the current thread.
Steps performed by the jump pad:
* Save the current state on the stack.
* Push a collecting_t object on the stack. We read the special
tpidr_el0 system register to get the thread ID.
* Spin-lock on the shared memory location of all tracing threads. We
write the address of our collecting_t object there once we have the
lock.
* Call gdb_collect.
* Release the lock.
* Restore the state.
* Execute the replaced instruction which will have been relocated.
* Jump back to the program.
- target_get_thread_area
As implemented in ps_get_thread_area, target_get_thread_area uses ptrace
to fetch the NT_ARM_TLS register. At the architecture level, NT_ARM_TLS
represents the tpidr_el0 system register.
So this ptrace call (if lwpid is the current thread):
~~~
ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec);
~~~
Is equivalent to the following instruction:
~~~
msr x0, tpidr_el0
~~~
This instruction is used when creating the collecting_t object that
GDBserver can read to know if a given thread is currently tracing.
So target_get_thread_area must get the same thread IDs as what the jump
pad writes into its collecting_t object.
- target_get_min_fast_tracepoint_insn_len
This just returns 4.
gdb/gdbserver/ChangeLog:
* Makefile.in (linux-aarch64-ipa.o, aarch64-ipa.o): New rules.
* configure.srv (aarch64*-*-linux*): Add linux-aarch64-ipa.o and
aarch64-ipa.o.
* linux-aarch64-ipa.c: New file.
* linux-aarch64-low.c: Include arch/aarch64-insn.h, inttypes.h
and endian.h.
(aarch64_get_thread_area): New target method.
(extract_signed_bitfield): New helper function.
(aarch64_decode_ldr_literal): New function.
(enum aarch64_opcodes): New enum.
(struct aarch64_register): New struct.
(struct aarch64_operand): New struct.
(x0): New static global.
(x1): Likewise.
(x2): Likewise.
(x3): Likewise.
(x4): Likewise.
(w2): Likewise.
(ip0): Likewise.
(sp): Likewise.
(xzr): Likewise.
(aarch64_register): New helper function.
(register_operand): Likewise.
(immediate_operand): Likewise.
(struct aarch64_memory_operand): New struct.
(offset_memory_operand): New helper function.
(preindex_memory_operand): Likewise.
(enum aarch64_system_control_registers): New enum.
(ENCODE): New macro.
(emit_insn): New helper function.
(emit_b): New function.
(emit_bcond): Likewise.
(emit_cb): Likewise.
(emit_tb): Likewise.
(emit_blr): Likewise.
(emit_stp): Likewise.
(emit_ldp_q_offset): Likewise.
(emit_stp_q_offset): Likewise.
(emit_load_store): Likewise.
(emit_ldr): Likewise.
(emit_ldrsw): Likewise.
(emit_str): Likewise.
(emit_ldaxr): Likewise.
(emit_stxr): Likewise.
(emit_stlr): Likewise.
(emit_data_processing_reg): Likewise.
(emit_data_processing): Likewise.
(emit_add): Likewise.
(emit_sub): Likewise.
(emit_mov): Likewise.
(emit_movk): Likewise.
(emit_mov_addr): Likewise.
(emit_mrs): Likewise.
(emit_msr): Likewise.
(emit_sevl): Likewise.
(emit_wfe): Likewise.
(append_insns): Likewise.
(can_encode_int32_in): New helper function.
(aarch64_relocate_instruction): New function.
(aarch64_install_fast_tracepoint_jump_pad): Likewise.
(aarch64_get_min_fast_tracepoint_insn_len): Likewise.
(struct linux_target_ops): Install aarch64_get_thread_area,
aarch64_install_fast_tracepoint_jump_pad and
aarch64_get_min_fast_tracepoint_insn_len.