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:
parent
0badd99faf
commit
246994ce35
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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". */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user