Move aarch64_relocate_instruction to arch/aarch64-insn.c

This patch moves aarch64_relocate_instruction and visitor class to
arch/aarch64-insn.c, so that both GDB and GDBserver can use it.

gdb:

2015-10-12  Yao Qi  <yao.qi@linaro.org>

	* arch/aarch64-insn.c (aarch64_decode_ldr_literal): Moved from
	gdbserver/linux-aarch64-low.c.
	(aarch64_relocate_instruction): Likewise.
	* arch/aarch64-insn.h (aarch64_decode_ldr_literal): Declare.
	(struct aarch64_insn_data): Moved from
	gdbserver/linux-aarch64-low.c.
	(struct aarch64_insn_visitor): Likewise.
	(aarch64_relocate_instruction): Declare.

gdb/gdbserver:

2015-10-12  Yao Qi  <yao.qi@linaro.org>

	* linux-aarch64-low.c (extract_signed_bitfield): Remove.
	(aarch64_decode_ldr_literal): Move to gdb/arch/aarch64-insn.c.
	(aarch64_relocate_instruction): Likewise.
	(struct aarch64_insn_data): Move to gdb/arch/aarch64-insn.h.
	(struct aarch64_insn_visitor): Likewise.
This commit is contained in:
Yao Qi 2015-10-12 11:28:38 +01:00
parent 0badd99faf
commit 246994ce35
5 changed files with 162 additions and 155 deletions

View File

@ -1,3 +1,14 @@
2015-10-12 Yao Qi <yao.qi@linaro.org>
* arch/aarch64-insn.c (aarch64_decode_ldr_literal): Moved from
gdbserver/linux-aarch64-low.c.
(aarch64_relocate_instruction): Likewise.
* arch/aarch64-insn.h (aarch64_decode_ldr_literal): Declare.
(struct aarch64_insn_data): Moved from
gdbserver/linux-aarch64-low.c.
(struct aarch64_insn_visitor): Likewise.
(aarch64_relocate_instruction): Declare.
2015-10-12 Pierre-Marie de Rodat <derodat@adacore.com>
* eval.c (evaluate_subexp_standard) <STRUCTOP_STRUCT>: If

View File

@ -235,3 +235,96 @@ aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz,
}
return 0;
}
/* Decode an opcode if it represents an LDR or LDRSW instruction taking a
literal offset from the current PC.
ADDR specifies the address of the opcode.
INSN specifies the opcode to test.
IS_W is set if the instruction is LDRSW.
IS64 receives size field from the decoded instruction.
RT receives the 'rt' field from the decoded instruction.
OFFSET receives the 'imm' field from the decoded instruction.
Return 1 if the opcodes matches and is decoded, otherwise 0. */
int
aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w,
int *is64, unsigned *rt, int32_t *offset)
{
/* LDR 0T01 1000 iiii iiii iiii iiii iiir rrrr */
/* LDRSW 1001 1000 iiii iiii iiii iiii iiir rrrr */
if ((insn & 0x3f000000) == 0x18000000)
{
*is_w = (insn >> 31) & 0x1;
if (*is_w)
{
/* LDRSW always takes a 64-bit destination registers. */
*is64 = 1;
}
else
*is64 = (insn >> 30) & 0x1;
*rt = (insn >> 0) & 0x1f;
*offset = extract_signed_bitfield (insn, 19, 5) << 2;
if (aarch64_debug)
debug_printf ("decode: %s 0x%x %s %s%u, #?\n",
core_addr_to_string_nz (addr), insn,
*is_w ? "ldrsw" : "ldr",
*is64 ? "x" : "w", *rt);
return 1;
}
return 0;
}
/* Visit an instruction INSN by VISITOR with all needed information in DATA.
PC relative instructions need to be handled specifically:
- B/BL
- B.COND
- CBZ/CBNZ
- TBZ/TBNZ
- ADR/ADRP
- LDR/LDRSW (literal) */
void
aarch64_relocate_instruction (uint32_t insn,
const struct aarch64_insn_visitor *visitor,
struct aarch64_insn_data *data)
{
int is_bl;
int is64;
int is_sw;
int is_cbnz;
int is_tbnz;
int is_adrp;
unsigned rn;
unsigned rt;
unsigned rd;
unsigned cond;
unsigned bit;
int32_t offset;
if (aarch64_decode_b (data->insn_addr, insn, &is_bl, &offset))
visitor->b (is_bl, offset, data);
else if (aarch64_decode_bcond (data->insn_addr, insn, &cond, &offset))
visitor->b_cond (cond, offset, data);
else if (aarch64_decode_cb (data->insn_addr, insn, &is64, &is_cbnz, &rn,
&offset))
visitor->cb (offset, is_cbnz, rn, is64, data);
else if (aarch64_decode_tb (data->insn_addr, insn, &is_tbnz, &bit, &rt,
&offset))
visitor->tb (offset, is_tbnz, rt, bit, data);
else if (aarch64_decode_adr (data->insn_addr, insn, &is_adrp, &rd, &offset))
visitor->adr (offset, rd, is_adrp, data);
else if (aarch64_decode_ldr_literal (data->insn_addr, insn, &is_sw, &is64,
&rt, &offset))
visitor->ldr_literal (offset, is_sw, rt, is64, data);
else
visitor->others (insn, data);
}

View File

@ -36,4 +36,54 @@ int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64,
int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz,
unsigned *bit, unsigned *rt, int32_t *imm);
int aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w,
int *is64, unsigned *rt, int32_t *offset);
/* Data passed to each method of aarch64_insn_visitor. */
struct aarch64_insn_data
{
/* The instruction address. */
CORE_ADDR insn_addr;
};
/* Visit different instructions by different methods. */
struct aarch64_insn_visitor
{
/* Visit instruction B/BL OFFSET. */
void (*b) (const int is_bl, const int32_t offset,
struct aarch64_insn_data *data);
/* Visit instruction B.COND OFFSET. */
void (*b_cond) (const unsigned cond, const int32_t offset,
struct aarch64_insn_data *data);
/* Visit instruction CBZ/CBNZ Rn, OFFSET. */
void (*cb) (const int32_t offset, const int is_cbnz,
const unsigned rn, int is64,
struct aarch64_insn_data *data);
/* Visit instruction TBZ/TBNZ Rt, #BIT, OFFSET. */
void (*tb) (const int32_t offset, int is_tbnz,
const unsigned rt, unsigned bit,
struct aarch64_insn_data *data);
/* Visit instruction ADR/ADRP Rd, OFFSET. */
void (*adr) (const int32_t offset, const unsigned rd,
const int is_adrp, struct aarch64_insn_data *data);
/* Visit instruction LDR/LDRSW Rt, OFFSET. */
void (*ldr_literal) (const int32_t offset, const int is_sw,
const unsigned rt, const int is64,
struct aarch64_insn_data *data);
/* Visit instruction INSN of other kinds. */
void (*others) (const uint32_t insn, struct aarch64_insn_data *data);
};
void aarch64_relocate_instruction (uint32_t insn,
const struct aarch64_insn_visitor *visitor,
struct aarch64_insn_data *data);
#endif

View File

@ -1,3 +1,11 @@
2015-10-12 Yao Qi <yao.qi@linaro.org>
* linux-aarch64-low.c (extract_signed_bitfield): Remove.
(aarch64_decode_ldr_literal): Move to gdb/arch/aarch64-insn.c.
(aarch64_relocate_instruction): Likewise.
(struct aarch64_insn_data): Move to gdb/arch/aarch64-insn.h.
(struct aarch64_insn_visitor): Likewise.
2015-10-12 Yao Qi <yao.qi@linaro.org>
* linux-aarch64-low.c (struct aarch64_insn_data): New.

View File

@ -584,70 +584,6 @@ aarch64_get_thread_area (int lwpid, CORE_ADDR *addrp)
return 0;
}
/* Extract a signed value from a bit field within an instruction
encoding.
INSN is the instruction opcode.
WIDTH specifies the width of the bit field to extract (in bits).
OFFSET specifies the least significant bit of the field where bits
are numbered zero counting from least to most significant. */
static int32_t
extract_signed_bitfield (uint32_t insn, unsigned width, unsigned offset)
{
unsigned shift_l = sizeof (int32_t) * 8 - (offset + width);
unsigned shift_r = sizeof (int32_t) * 8 - width;
return ((int32_t) insn << shift_l) >> shift_r;
}
/* Decode an opcode if it represents an LDR or LDRSW instruction taking a
literal offset from the current PC.
ADDR specifies the address of the opcode.
INSN specifies the opcode to test.
IS_W is set if the instruction is LDRSW.
IS64 receives size field from the decoded instruction.
RT receives the 'rt' field from the decoded instruction.
OFFSET receives the 'imm' field from the decoded instruction.
Return 1 if the opcodes matches and is decoded, otherwise 0. */
int
aarch64_decode_ldr_literal (CORE_ADDR addr, uint32_t insn, int *is_w,
int *is64, unsigned *rt, int32_t *offset)
{
/* LDR 0T01 1000 iiii iiii iiii iiii iiir rrrr */
/* LDRSW 1001 1000 iiii iiii iiii iiii iiir rrrr */
if ((insn & 0x3f000000) == 0x18000000)
{
*is_w = (insn >> 31) & 0x1;
if (*is_w)
{
/* LDRSW always takes a 64-bit destination registers. */
*is64 = 1;
}
else
*is64 = (insn >> 30) & 0x1;
*rt = (insn >> 0) & 0x1f;
*offset = extract_signed_bitfield (insn, 19, 5) << 2;
if (aarch64_debug)
debug_printf ("decode: %s 0x%x %s %s%u, #?\n",
core_addr_to_string_nz (addr), insn,
*is_w ? "ldrsw" : "ldr",
*is64 ? "x" : "w", *rt);
return 1;
}
return 0;
}
/* List of opcodes that we need for building the jump pad and relocating
an instruction. */
@ -1924,49 +1860,6 @@ can_encode_int32 (int32_t val, unsigned bits)
return rest == 0 || rest == -1;
}
/* Data passed to each method of aarch64_insn_visitor. */
struct aarch64_insn_data
{
/* The instruction address. */
CORE_ADDR insn_addr;
};
/* Visit different instructions by different methods. */
struct aarch64_insn_visitor
{
/* Visit instruction B/BL OFFSET. */
void (*b) (const int is_bl, const int32_t offset,
struct aarch64_insn_data *data);
/* Visit instruction B.COND OFFSET. */
void (*b_cond) (const unsigned cond, const int32_t offset,
struct aarch64_insn_data *data);
/* Visit instruction CBZ/CBNZ Rn, OFFSET. */
void (*cb) (const int32_t offset, const int is_cbnz,
const unsigned rn, int is64,
struct aarch64_insn_data *data);
/* Visit instruction TBZ/TBNZ Rt, #BIT, OFFSET. */
void (*tb) (const int32_t offset, int is_tbnz,
const unsigned rt, unsigned bit,
struct aarch64_insn_data *data);
/* Visit instruction ADR/ADRP Rd, OFFSET. */
void (*adr) (const int32_t offset, const unsigned rd,
const int is_adrp, struct aarch64_insn_data *data);
/* Visit instruction LDR/LDRSW Rt, OFFSET. */
void (*ldr_literal) (const int32_t offset, const int is_sw,
const unsigned rt, const int is64,
struct aarch64_insn_data *data);
/* Visit instruction INSN of other kinds. */
void (*others) (const uint32_t insn, struct aarch64_insn_data *data);
};
/* Sub-class of struct aarch64_insn_data, store information of
instruction relocation for fast tracepoint. Visitor can
relocate an instruction from BASE.INSN_ADDR to NEW_ADDR and save
@ -2195,54 +2088,6 @@ static const struct aarch64_insn_visitor visitor =
aarch64_ftrace_insn_reloc_others,
};
/* Visit an instruction INSN by VISITOR with all needed information in DATA.
PC relative instructions need to be handled specifically:
- B/BL
- B.COND
- CBZ/CBNZ
- TBZ/TBNZ
- ADR/ADRP
- LDR/LDRSW (literal) */
static void
aarch64_relocate_instruction (uint32_t insn,
const struct aarch64_insn_visitor *visitor,
struct aarch64_insn_data *data)
{
int is_bl;
int is64;
int is_sw;
int is_cbnz;
int is_tbnz;
int is_adrp;
unsigned rn;
unsigned rt;
unsigned rd;
unsigned cond;
unsigned bit;
int32_t offset;
if (aarch64_decode_b (data->insn_addr, insn, &is_bl, &offset))
visitor->b (is_bl, offset, data);
else if (aarch64_decode_bcond (data->insn_addr, insn, &cond, &offset))
visitor->b_cond (cond, offset, data);
else if (aarch64_decode_cb (data->insn_addr, insn, &is64, &is_cbnz, &rn,
&offset))
visitor->cb (offset, is_cbnz, rn, is64, data);
else if (aarch64_decode_tb (data->insn_addr, insn, &is_tbnz, &bit, &rt,
&offset))
visitor->tb (offset, is_tbnz, rt, bit, data);
else if (aarch64_decode_adr (data->insn_addr, insn, &is_adrp, &rd, &offset))
visitor->adr (offset, rd, is_adrp, data);
else if (aarch64_decode_ldr_literal (data->insn_addr, insn, &is_sw, &is64,
&rt, &offset))
visitor->ldr_literal (offset, is_sw, rt, is64, data);
else
visitor->others (insn, data);
}
/* Implementation of linux_target_ops method
"install_fast_tracepoint_jump_pad". */