mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 15:36:55 +08:00
Increase use of e_machine by replacing callchain_param_setup's arch argument to be an e_machine typically read from the session. Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Leo Yan <leo.yan@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shimin Guo <shimin.guo@skydio.com> Cc: Yujie Liu <yujie.liu@intel.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
121 lines
2.7 KiB
C
121 lines
2.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#include "sample.h"
|
|
#include "debug.h"
|
|
#include "thread.h"
|
|
#include <elf.h>
|
|
#ifndef EM_CSKY
|
|
#define EM_CSKY 252
|
|
#endif
|
|
#ifndef EM_LOONGARCH
|
|
#define EM_LOONGARCH 258
|
|
#endif
|
|
#include <linux/zalloc.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "../../arch/x86/include/asm/insn.h"
|
|
|
|
void perf_sample__init(struct perf_sample *sample, bool all)
|
|
{
|
|
if (all) {
|
|
memset(sample, 0, sizeof(*sample));
|
|
} else {
|
|
sample->user_regs = NULL;
|
|
sample->intr_regs = NULL;
|
|
}
|
|
}
|
|
|
|
void perf_sample__exit(struct perf_sample *sample)
|
|
{
|
|
free(sample->user_regs);
|
|
free(sample->intr_regs);
|
|
}
|
|
|
|
struct regs_dump *perf_sample__user_regs(struct perf_sample *sample)
|
|
{
|
|
if (!sample->user_regs) {
|
|
sample->user_regs = zalloc(sizeof(*sample->user_regs));
|
|
if (!sample->user_regs)
|
|
pr_err("Failure to allocate sample user_regs");
|
|
}
|
|
return sample->user_regs;
|
|
}
|
|
|
|
|
|
struct regs_dump *perf_sample__intr_regs(struct perf_sample *sample)
|
|
{
|
|
if (!sample->intr_regs) {
|
|
sample->intr_regs = zalloc(sizeof(*sample->intr_regs));
|
|
if (!sample->intr_regs)
|
|
pr_err("Failure to allocate sample intr_regs");
|
|
}
|
|
return sample->intr_regs;
|
|
}
|
|
|
|
static int elf_machine_max_instruction_length(uint16_t e_machine)
|
|
{
|
|
switch (e_machine) {
|
|
/* Fixed 4-byte (32-bit) architectures */
|
|
case EM_AARCH64:
|
|
case EM_PPC:
|
|
case EM_PPC64:
|
|
case EM_MIPS:
|
|
case EM_SPARC:
|
|
case EM_SPARCV9:
|
|
case EM_ALPHA:
|
|
case EM_LOONGARCH:
|
|
case EM_PARISC:
|
|
case EM_SH:
|
|
return 4;
|
|
|
|
/* Variable length or mixed-mode architectures */
|
|
case EM_ARM: /* Variable due to Thumb/Thumb-2 */
|
|
case EM_RISCV: /* Variable due to Compressed (C) extension */
|
|
case EM_CSKY: /* Variable (16 or 32 bit) */
|
|
case EM_ARC: /* Variable (ARCompact) */
|
|
return 4;
|
|
case EM_S390: /* Variable (2, 4, or 6 bytes) */
|
|
return 6;
|
|
case EM_68K:
|
|
return 10;
|
|
case EM_386:
|
|
case EM_X86_64:
|
|
return 15;
|
|
case EM_XTENSA: /* Variable (FLIX) */
|
|
return 16;
|
|
default:
|
|
return MAX_INSN;
|
|
}
|
|
}
|
|
|
|
void perf_sample__fetch_insn(struct perf_sample *sample,
|
|
struct thread *thread,
|
|
struct machine *machine)
|
|
{
|
|
int ret, len;
|
|
bool is64bit = false;
|
|
uint16_t e_machine;
|
|
|
|
if (!sample->ip || sample->insn_len != 0)
|
|
return;
|
|
|
|
e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL);
|
|
len = elf_machine_max_instruction_length(e_machine);
|
|
len = thread__memcpy(thread, machine, sample->insn,
|
|
sample->ip, len,
|
|
&is64bit);
|
|
if (len <= 0)
|
|
return;
|
|
|
|
sample->insn_len = len;
|
|
|
|
if (e_machine == EM_386 || e_machine == EM_X86_64) {
|
|
/* Refine the x86 instruction length with the decoder. */
|
|
struct insn insn;
|
|
|
|
ret = insn_decode(&insn, sample->insn, len,
|
|
is64bit ? INSN_MODE_64 : INSN_MODE_32);
|
|
if (ret >= 0 && insn.length <= len)
|
|
sample->insn_len = insn.length;
|
|
}
|
|
}
|