mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-02 01:08:26 -04:00
perf disasm: Don't include C files from the arch directory
Move the arch instructions.c files into appropriately named files in annotate-arch in the util directory. Don't #include to compile the code, switch to building the files and fix up the #includes accordingly. Move powerpc specific disasm code out of disasm.c and into annotate-powerpc.c. Declarations and static removed as appropriate for the code to compile as separate compilation units. The e_machine and e_flags set up is moved to the disasm.c architectures array so that later patches can sort by them. Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexandre Ghiti <alex@ghiti.fr> Cc: Athira Rajeev <atrajeev@linux.ibm.com> Cc: Bill Wendling <morbo@google.com> Cc: Dr. David Alan Gilbert <linux@treblig.org> Cc: Guo Ren <guoren@kernel.org> Cc: Howard Chu <howardchu95@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Julia Lawall <Julia.Lawall@inria.fr> Cc: Justin Stitt <justinstitt@google.com> Cc: Krzysztof Łopatowski <krzysztof.m.lopatowski@gmail.com> Cc: Leo Yan <leo.yan@linux.dev> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Paul Walmsley <pjw@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sergei Trofimovich <slyich@gmail.com> Cc: Shimin Guo <shimin.guo@skydio.com> Cc: Suchit Karunakaran <suchitkarunakaran@gmail.com> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Tianyou Li <tianyou.li@intel.com> Cc: Will Deacon <will@kernel.org> Cc: Zecheng Li <zecheng@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
9273085273
commit
07b972ff09
@@ -1,6 +1,7 @@
|
||||
include $(srctree)/tools/scripts/Makefile.include
|
||||
include $(srctree)/tools/scripts/utilities.mak
|
||||
|
||||
perf-util-y += annotate-arch/
|
||||
perf-util-y += arm64-frame-pointer-unwind-support.o
|
||||
perf-util-y += addr2line.o
|
||||
perf-util-y += addr_location.o
|
||||
|
||||
11
tools/perf/util/annotate-arch/Build
Normal file
11
tools/perf/util/annotate-arch/Build
Normal file
@@ -0,0 +1,11 @@
|
||||
perf-util-y += annotate-arc.o
|
||||
perf-util-y += annotate-arm.o
|
||||
perf-util-y += annotate-arm64.o
|
||||
perf-util-y += annotate-csky.o
|
||||
perf-util-y += annotate-loongarch.o
|
||||
perf-util-y += annotate-mips.o
|
||||
perf-util-y += annotate-x86.o
|
||||
perf-util-y += annotate-powerpc.o
|
||||
perf-util-y += annotate-riscv64.o
|
||||
perf-util-y += annotate-s390.o
|
||||
perf-util-y += annotate-sparc.o
|
||||
@@ -1,11 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/compiler.h>
|
||||
#include "../disasm.h"
|
||||
|
||||
static int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = ';';
|
||||
arch->e_machine = EM_ARC;
|
||||
arch->e_flags = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <stdlib.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
#include "../annotate.h"
|
||||
#include "../disasm.h"
|
||||
|
||||
struct arm_annotate {
|
||||
regex_t call_insn,
|
||||
@@ -28,7 +29,7 @@ static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, c
|
||||
return ops;
|
||||
}
|
||||
|
||||
static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
struct arm_annotate *arm;
|
||||
int err;
|
||||
@@ -54,8 +55,6 @@ static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
arch->associate_instruction_ops = arm__associate_instruction_ops;
|
||||
arch->objdump.comment_char = ';';
|
||||
arch->objdump.skip_functions_char = '+';
|
||||
arch->e_machine = EM_ARM;
|
||||
arch->e_flags = 0;
|
||||
return 0;
|
||||
|
||||
out_free_call:
|
||||
@@ -1,9 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/compiler.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <regex.h>
|
||||
#include "../annotate.h"
|
||||
#include "../disasm.h"
|
||||
|
||||
struct arm64_annotate {
|
||||
regex_t call_insn,
|
||||
@@ -60,9 +63,6 @@ static int arm64_mov__parse(const struct arch *arch __maybe_unused,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
|
||||
static const struct ins_ops arm64_mov_ops = {
|
||||
.parse = arm64_mov__parse,
|
||||
.scnprintf = mov__scnprintf,
|
||||
@@ -87,7 +87,7 @@ static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch,
|
||||
return ops;
|
||||
}
|
||||
|
||||
static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
struct arm64_annotate *arm;
|
||||
int err;
|
||||
@@ -114,8 +114,6 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
arch->associate_instruction_ops = arm64__associate_instruction_ops;
|
||||
arch->objdump.comment_char = '/';
|
||||
arch->objdump.skip_functions_char = '+';
|
||||
arch->e_machine = EM_AARCH64;
|
||||
arch->e_flags = 0;
|
||||
return 0;
|
||||
|
||||
out_free_call:
|
||||
@@ -1,7 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
|
||||
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../disasm.h"
|
||||
|
||||
static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
|
||||
const char *name)
|
||||
@@ -38,16 +39,10 @@ static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
|
||||
return ops;
|
||||
}
|
||||
|
||||
static int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = '/';
|
||||
arch->associate_instruction_ops = csky__associate_ins_ops;
|
||||
arch->e_machine = EM_CSKY;
|
||||
#if defined(__CSKYABIV2__)
|
||||
arch->e_flags = EF_CSKY_ABIV2;
|
||||
#else
|
||||
arch->e_flags = EF_CSKY_ABIV1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -4,11 +4,17 @@
|
||||
*
|
||||
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../disasm.h"
|
||||
#include "../map.h"
|
||||
#include "../maps.h"
|
||||
#include "../symbol.h"
|
||||
|
||||
static int loongarch_call__parse(const struct arch *arch, struct ins_operands *ops,
|
||||
struct map_symbol *ms,
|
||||
struct disasm_line *dl __maybe_unused)
|
||||
|
||||
{
|
||||
char *c, *endptr, *tok, *name;
|
||||
struct map *map = ms->map;
|
||||
@@ -51,7 +57,7 @@ static int loongarch_call__parse(const struct arch *arch, struct ins_operands *o
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops loongarch_call_ops = {
|
||||
const struct ins_ops loongarch_call_ops = {
|
||||
.parse = loongarch_call__parse,
|
||||
.scnprintf = call__scnprintf,
|
||||
};
|
||||
@@ -100,7 +106,7 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops loongarch_jump_ops = {
|
||||
const struct ins_ops loongarch_jump_ops = {
|
||||
.parse = loongarch_jump__parse,
|
||||
.scnprintf = jump__scnprintf,
|
||||
};
|
||||
@@ -130,15 +136,12 @@ const struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char
|
||||
return ops;
|
||||
}
|
||||
|
||||
static
|
||||
int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->associate_instruction_ops = loongarch__associate_ins_ops;
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = '#';
|
||||
arch->e_machine = EM_LOONGARCH;
|
||||
arch->e_flags = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,4 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../disasm.h"
|
||||
|
||||
static
|
||||
const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
|
||||
@@ -33,15 +36,12 @@ const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *nam
|
||||
return ops;
|
||||
}
|
||||
|
||||
static
|
||||
int mips__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->associate_instruction_ops = mips__associate_ins_ops;
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = '#';
|
||||
arch->e_machine = EM_MIPS;
|
||||
arch->e_flags = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,5 +1,97 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "../annotate-data.h"
|
||||
#include "../debug.h"
|
||||
#include "../disasm.h"
|
||||
|
||||
#define PPC_OP(op) (((op) >> 26) & 0x3F)
|
||||
#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
|
||||
#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
|
||||
|
||||
#define MINUS_EXT_XO_FORM 234
|
||||
#define SUB_EXT_XO_FORM 232
|
||||
#define ADD_ZERO_EXT_XO_FORM 202
|
||||
#define SUB_ZERO_EXT_XO_FORM 200
|
||||
|
||||
static int arithmetic__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
|
||||
ops->raw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the fields: multi_regs and "mem_ref".
|
||||
* "mem_ref" is set for ops->source which is later used to
|
||||
* fill the objdump->memory_ref-char field. This ops is currently
|
||||
* used by powerpc and since binary instruction code is used to
|
||||
* extract opcode, regs and offset, no other parsing is needed here.
|
||||
*
|
||||
* Dont set multi regs for 4 cases since it has only one operand
|
||||
* for source:
|
||||
* - Add to Minus One Extended XO-form ( Ex: addme, addmeo )
|
||||
* - Subtract From Minus One Extended XO-form ( Ex: subfme )
|
||||
* - Add to Zero Extended XO-form ( Ex: addze, addzeo )
|
||||
* - Subtract From Zero Extended XO-form ( Ex: subfze )
|
||||
*/
|
||||
static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
|
||||
struct map_symbol *ms __maybe_unused, struct disasm_line *dl)
|
||||
{
|
||||
int opcode = PPC_OP(dl->raw.raw_insn);
|
||||
|
||||
ops->source.mem_ref = false;
|
||||
if (opcode == 31) {
|
||||
if ((opcode != MINUS_EXT_XO_FORM) && (opcode != SUB_EXT_XO_FORM) &&
|
||||
(opcode != ADD_ZERO_EXT_XO_FORM) && (opcode != SUB_ZERO_EXT_XO_FORM))
|
||||
ops->source.multi_regs = true;
|
||||
}
|
||||
|
||||
ops->target.mem_ref = false;
|
||||
ops->target.multi_regs = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops arithmetic_ops = {
|
||||
.parse = arithmetic__parse,
|
||||
.scnprintf = arithmetic__scnprintf,
|
||||
};
|
||||
|
||||
static int load_store__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
|
||||
ops->raw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the fields: multi_regs and "mem_ref".
|
||||
* "mem_ref" is set for ops->source which is later used to
|
||||
* fill the objdump->memory_ref-char field. This ops is currently
|
||||
* used by powerpc and since binary instruction code is used to
|
||||
* extract opcode, regs and offset, no other parsing is needed here
|
||||
*/
|
||||
static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
|
||||
struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)
|
||||
{
|
||||
ops->source.mem_ref = true;
|
||||
ops->source.multi_regs = false;
|
||||
/* opcode 31 is of X form */
|
||||
if (PPC_OP(dl->raw.raw_insn) == 31)
|
||||
ops->source.multi_regs = true;
|
||||
|
||||
ops->target.mem_ref = false;
|
||||
ops->target.multi_regs = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops load_store_ops = {
|
||||
.parse = load_store__parse,
|
||||
.scnprintf = load_store__scnprintf,
|
||||
};
|
||||
|
||||
static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
|
||||
{
|
||||
@@ -49,10 +141,6 @@ static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arc
|
||||
return ops;
|
||||
}
|
||||
|
||||
#define PPC_OP(op) (((op) >> 26) & 0x3F)
|
||||
#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
|
||||
#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
|
||||
|
||||
struct insn_offset {
|
||||
const char *name;
|
||||
int value;
|
||||
@@ -189,7 +277,7 @@ static int cmp_offset(const void *a, const void *b)
|
||||
return (val1->value - val2->value);
|
||||
}
|
||||
|
||||
static const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
|
||||
const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
|
||||
{
|
||||
int raw_insn = dl->raw.raw_insn;
|
||||
int opcode = PPC_OP(raw_insn);
|
||||
@@ -302,15 +390,16 @@ static void update_insn_state_powerpc(struct type_state *state,
|
||||
}
|
||||
#endif /* HAVE_LIBDW_SUPPORT */
|
||||
|
||||
static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->initialized = true;
|
||||
arch->associate_instruction_ops = powerpc__associate_instruction_ops;
|
||||
arch->objdump.comment_char = '#';
|
||||
annotate_opts.show_asm_raw = true;
|
||||
arch->e_machine = EM_PPC;
|
||||
arch->e_flags = 0;
|
||||
#ifdef HAVE_LIBDW_SUPPORT
|
||||
arch->update_insn_state = update_insn_state_powerpc;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,4 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../disasm.h"
|
||||
|
||||
static
|
||||
const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *name)
|
||||
@@ -21,15 +24,12 @@ const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *
|
||||
return ops;
|
||||
}
|
||||
|
||||
static
|
||||
int riscv64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->associate_instruction_ops = riscv64__associate_ins_ops;
|
||||
arch->initialized = true;
|
||||
arch->objdump.comment_char = '#';
|
||||
arch->e_machine = EM_RISCV;
|
||||
arch->e_flags = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,5 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../debug.h"
|
||||
#include "../disasm.h"
|
||||
#include "../map.h"
|
||||
#include "../maps.h"
|
||||
#include "../symbol.h"
|
||||
#include "../annotate.h"
|
||||
#include "../annotate-data.h"
|
||||
|
||||
static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
|
||||
struct map_symbol *ms,
|
||||
@@ -49,7 +57,7 @@ static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops s390_call_ops = {
|
||||
const struct ins_ops s390_call_ops = {
|
||||
.parse = s390_call__parse,
|
||||
.scnprintf = call__scnprintf,
|
||||
};
|
||||
@@ -159,7 +167,7 @@ static int s390__cpuid_parse(struct arch *arch, char *cpuid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -170,8 +178,7 @@ static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
if (s390__cpuid_parse(arch, cpuid))
|
||||
err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
|
||||
}
|
||||
arch->e_machine = EM_S390;
|
||||
arch->e_flags = 0;
|
||||
arch->objdump.comment_char = '#';
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -1,4 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "../../util/disasm.h"
|
||||
|
||||
static int is_branch_cond(const char *cond)
|
||||
{
|
||||
@@ -157,14 +160,12 @@ static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch,
|
||||
return ops;
|
||||
}
|
||||
|
||||
static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
|
||||
{
|
||||
if (!arch->initialized) {
|
||||
arch->initialized = true;
|
||||
arch->associate_instruction_ops = sparc__associate_instruction_ops;
|
||||
arch->objdump.comment_char = '#';
|
||||
arch->e_machine = EM_SPARC;
|
||||
arch->e_flags = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,4 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <string.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include "../annotate-data.h"
|
||||
#include "../debug.h"
|
||||
#include "../disasm.h"
|
||||
#include "../dso.h"
|
||||
#include "../map.h"
|
||||
#include "../string2.h" // strstarts
|
||||
#include "../symbol.h"
|
||||
|
||||
/*
|
||||
* x86 instruction nmemonic table to parse disasm lines for annotate.
|
||||
* This table is searched twice - one for exact match and another for
|
||||
@@ -191,37 +203,6 @@ static int x86__cpuid_parse(struct arch *arch, char *cpuid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int x86__annotate_init(struct arch *arch, char *cpuid)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (arch->initialized)
|
||||
return 0;
|
||||
|
||||
if (cpuid) {
|
||||
if (x86__cpuid_parse(arch, cpuid))
|
||||
err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
static bool sorted_check;
|
||||
|
||||
if (!sorted_check) {
|
||||
for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
|
||||
assert(strcmp(arch->instructions[i].name,
|
||||
arch->instructions[i + 1].name) <= 0);
|
||||
}
|
||||
sorted_check = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
arch->e_machine = EM_X86_64;
|
||||
arch->e_flags = 0;
|
||||
arch->initialized = true;
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDW_SUPPORT
|
||||
static void update_insn_state_x86(struct type_state *state,
|
||||
struct data_loc_info *dloc, Dwarf_Die *cu_die,
|
||||
@@ -795,3 +776,45 @@ static void update_insn_state_x86(struct type_state *state,
|
||||
/* Case 4. memory to memory transfers (not handled for now) */
|
||||
}
|
||||
#endif
|
||||
|
||||
int x86__annotate_init(struct arch *arch, char *cpuid)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (arch->initialized)
|
||||
return 0;
|
||||
|
||||
if (cpuid) {
|
||||
if (x86__cpuid_parse(arch, cpuid))
|
||||
err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
|
||||
}
|
||||
|
||||
arch->instructions = x86__instructions;
|
||||
arch->nr_instructions = ARRAY_SIZE(x86__instructions);
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
static bool sorted_check;
|
||||
|
||||
if (!sorted_check) {
|
||||
for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
|
||||
assert(strcmp(arch->instructions[i].name,
|
||||
arch->instructions[i + 1].name) <= 0);
|
||||
}
|
||||
sorted_check = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
arch->sorted_instructions = true;
|
||||
arch->objdump.comment_char = '#';
|
||||
arch->objdump.register_char = '%';
|
||||
arch->objdump.memory_ref_char = '(';
|
||||
arch->objdump.imm_char = '$';
|
||||
arch->insn_suffix = "bwlq";
|
||||
arch->e_machine = EM_X86_64;
|
||||
arch->e_flags = 0;
|
||||
arch->initialized = true;
|
||||
#ifdef HAVE_LIBDW_SUPPORT
|
||||
arch->update_insn_state = update_insn_state_x86;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
@@ -33,20 +33,15 @@
|
||||
static regex_t file_lineno;
|
||||
|
||||
/* These can be referred from the arch-dependent code */
|
||||
static const struct ins_ops call_ops;
|
||||
static const struct ins_ops dec_ops;
|
||||
static const struct ins_ops jump_ops;
|
||||
static const struct ins_ops mov_ops;
|
||||
static const struct ins_ops nop_ops;
|
||||
static const struct ins_ops lock_ops;
|
||||
static const struct ins_ops ret_ops;
|
||||
static const struct ins_ops load_store_ops;
|
||||
static const struct ins_ops arithmetic_ops;
|
||||
|
||||
static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
const struct ins_ops call_ops;
|
||||
const struct ins_ops dec_ops;
|
||||
const struct ins_ops jump_ops;
|
||||
const struct ins_ops mov_ops;
|
||||
const struct ins_ops nop_ops;
|
||||
const struct ins_ops lock_ops;
|
||||
const struct ins_ops ret_ops;
|
||||
const struct ins_ops load_store_ops;
|
||||
const struct ins_ops arithmetic_ops;
|
||||
|
||||
static void ins__sort(struct arch *arch);
|
||||
static int disasm_line__parse(char *line, const char **namep, char **rawp);
|
||||
@@ -86,7 +81,7 @@ static int arch__grow_instructions(struct arch *arch)
|
||||
goto out_update_instructions;
|
||||
}
|
||||
|
||||
static int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops)
|
||||
int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops)
|
||||
{
|
||||
struct ins *ins;
|
||||
|
||||
@@ -106,90 +101,66 @@ static int arch__associate_ins_ops(struct arch *arch, const char *name, const st
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "arch/arc/annotate/instructions.c"
|
||||
#include "arch/arm/annotate/instructions.c"
|
||||
#include "arch/arm64/annotate/instructions.c"
|
||||
#include "arch/csky/annotate/instructions.c"
|
||||
#include "arch/loongarch/annotate/instructions.c"
|
||||
#include "arch/mips/annotate/instructions.c"
|
||||
#include "arch/x86/annotate/instructions.c"
|
||||
#include "arch/powerpc/annotate/instructions.c"
|
||||
#include "arch/riscv64/annotate/instructions.c"
|
||||
#include "arch/s390/annotate/instructions.c"
|
||||
#include "arch/sparc/annotate/instructions.c"
|
||||
|
||||
static struct arch architectures[] = {
|
||||
{
|
||||
.name = "arc",
|
||||
.init = arc__annotate_init,
|
||||
.e_machine = EM_ARC,
|
||||
},
|
||||
{
|
||||
.name = "arm",
|
||||
.init = arm__annotate_init,
|
||||
.e_machine = EM_ARM,
|
||||
},
|
||||
{
|
||||
.name = "arm64",
|
||||
.init = arm64__annotate_init,
|
||||
.e_machine = EM_AARCH64,
|
||||
},
|
||||
{
|
||||
.name = "csky",
|
||||
.init = csky__annotate_init,
|
||||
.e_machine = EM_CSKY,
|
||||
#if defined(__CSKYABIV2__)
|
||||
.e_flags = EF_CSKY_ABIV2,
|
||||
#else
|
||||
.e_flags = EF_CSKY_ABIV1,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.name = "mips",
|
||||
.init = mips__annotate_init,
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
.e_machine = EM_MIPS,
|
||||
},
|
||||
{
|
||||
.name = "x86",
|
||||
.init = x86__annotate_init,
|
||||
.instructions = x86__instructions,
|
||||
.nr_instructions = ARRAY_SIZE(x86__instructions),
|
||||
.sorted_instructions = true,
|
||||
.insn_suffix = "bwlq",
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
.register_char = '%',
|
||||
.memory_ref_char = '(',
|
||||
.imm_char = '$',
|
||||
},
|
||||
#ifdef HAVE_LIBDW_SUPPORT
|
||||
.update_insn_state = update_insn_state_x86,
|
||||
#endif
|
||||
.e_machine = EM_X86_64, // TODO: EM_386 too.
|
||||
},
|
||||
{
|
||||
.name = "powerpc",
|
||||
.init = powerpc__annotate_init,
|
||||
#ifdef HAVE_LIBDW_SUPPORT
|
||||
.update_insn_state = update_insn_state_powerpc,
|
||||
#endif
|
||||
.e_machine = EM_PPC, // TODO: EM_PPC64 too.
|
||||
},
|
||||
{
|
||||
.name = "riscv64",
|
||||
.init = riscv64__annotate_init,
|
||||
.e_machine = EM_RISCV,
|
||||
},
|
||||
{
|
||||
.name = "s390",
|
||||
.init = s390__annotate_init,
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
.e_machine = EM_S390,
|
||||
},
|
||||
{
|
||||
.name = "sparc",
|
||||
.init = sparc__annotate_init,
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
.e_machine = EM_SPARC,
|
||||
},
|
||||
{
|
||||
.name = "loongarch",
|
||||
.init = loongarch__annotate_init,
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
.e_machine = EM_LOONGARCH,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -248,14 +219,14 @@ static void ins_ops__delete(struct ins_operands *ops)
|
||||
zfree(&ops->target.name);
|
||||
}
|
||||
|
||||
static int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
|
||||
}
|
||||
|
||||
static int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
if (ins->ops->scnprintf)
|
||||
return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);
|
||||
@@ -326,8 +297,8 @@ static int call__parse(const struct arch *arch, struct ins_operands *ops, struct
|
||||
goto find_target;
|
||||
}
|
||||
|
||||
static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
int call__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
if (ops->target.sym)
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
|
||||
@@ -341,7 +312,7 @@ static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
|
||||
}
|
||||
|
||||
static const struct ins_ops call_ops = {
|
||||
const struct ins_ops call_ops = {
|
||||
.parse = call__parse,
|
||||
.scnprintf = call__scnprintf,
|
||||
};
|
||||
@@ -453,8 +424,8 @@ static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
const char *c;
|
||||
|
||||
@@ -494,7 +465,7 @@ static void jump__delete(struct ins_operands *ops __maybe_unused)
|
||||
*/
|
||||
}
|
||||
|
||||
static const struct ins_ops jump_ops = {
|
||||
const struct ins_ops jump_ops = {
|
||||
.free = jump__delete,
|
||||
.parse = jump__parse,
|
||||
.scnprintf = jump__scnprintf,
|
||||
@@ -586,7 +557,7 @@ static void lock__delete(struct ins_operands *ops)
|
||||
zfree(&ops->target.name);
|
||||
}
|
||||
|
||||
static const struct ins_ops lock_ops = {
|
||||
const struct ins_ops lock_ops = {
|
||||
.free = lock__delete,
|
||||
.parse = lock__parse,
|
||||
.scnprintf = lock__scnprintf,
|
||||
@@ -687,103 +658,19 @@ static int mov__parse(const struct arch *arch, struct ins_operands *ops,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
|
||||
ops->source.name ?: ops->source.raw,
|
||||
ops->target.name ?: ops->target.raw);
|
||||
}
|
||||
|
||||
static const struct ins_ops mov_ops = {
|
||||
const struct ins_ops mov_ops = {
|
||||
.parse = mov__parse,
|
||||
.scnprintf = mov__scnprintf,
|
||||
};
|
||||
|
||||
#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
|
||||
#define MINUS_EXT_XO_FORM 234
|
||||
#define SUB_EXT_XO_FORM 232
|
||||
#define ADD_ZERO_EXT_XO_FORM 202
|
||||
#define SUB_ZERO_EXT_XO_FORM 200
|
||||
|
||||
static int arithmetic__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
|
||||
ops->raw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the fields: multi_regs and "mem_ref".
|
||||
* "mem_ref" is set for ops->source which is later used to
|
||||
* fill the objdump->memory_ref-char field. This ops is currently
|
||||
* used by powerpc and since binary instruction code is used to
|
||||
* extract opcode, regs and offset, no other parsing is needed here.
|
||||
*
|
||||
* Dont set multi regs for 4 cases since it has only one operand
|
||||
* for source:
|
||||
* - Add to Minus One Extended XO-form ( Ex: addme, addmeo )
|
||||
* - Subtract From Minus One Extended XO-form ( Ex: subfme )
|
||||
* - Add to Zero Extended XO-form ( Ex: addze, addzeo )
|
||||
* - Subtract From Zero Extended XO-form ( Ex: subfze )
|
||||
*/
|
||||
static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
|
||||
struct map_symbol *ms __maybe_unused, struct disasm_line *dl)
|
||||
{
|
||||
int opcode = PPC_OP(dl->raw.raw_insn);
|
||||
|
||||
ops->source.mem_ref = false;
|
||||
if (opcode == 31) {
|
||||
if ((opcode != MINUS_EXT_XO_FORM) && (opcode != SUB_EXT_XO_FORM) \
|
||||
&& (opcode != ADD_ZERO_EXT_XO_FORM) && (opcode != SUB_ZERO_EXT_XO_FORM))
|
||||
ops->source.multi_regs = true;
|
||||
}
|
||||
|
||||
ops->target.mem_ref = false;
|
||||
ops->target.multi_regs = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops arithmetic_ops = {
|
||||
.parse = arithmetic__parse,
|
||||
.scnprintf = arithmetic__scnprintf,
|
||||
};
|
||||
|
||||
static int load_store__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name)
|
||||
{
|
||||
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
|
||||
ops->raw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the fields: multi_regs and "mem_ref".
|
||||
* "mem_ref" is set for ops->source which is later used to
|
||||
* fill the objdump->memory_ref-char field. This ops is currently
|
||||
* used by powerpc and since binary instruction code is used to
|
||||
* extract opcode, regs and offset, no other parsing is needed here
|
||||
*/
|
||||
static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
|
||||
struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)
|
||||
{
|
||||
ops->source.mem_ref = true;
|
||||
ops->source.multi_regs = false;
|
||||
/* opcode 31 is of X form */
|
||||
if (PPC_OP(dl->raw.raw_insn) == 31)
|
||||
ops->source.multi_regs = true;
|
||||
|
||||
ops->target.mem_ref = false;
|
||||
ops->target.multi_regs = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ins_ops load_store_ops = {
|
||||
.parse = load_store__parse,
|
||||
.scnprintf = load_store__scnprintf,
|
||||
};
|
||||
|
||||
static int dec__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
|
||||
struct map_symbol *ms __maybe_unused,
|
||||
struct disasm_line *dl __maybe_unused)
|
||||
@@ -820,7 +707,7 @@ static int dec__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
ops->target.name ?: ops->target.raw);
|
||||
}
|
||||
|
||||
static const struct ins_ops dec_ops = {
|
||||
const struct ins_ops dec_ops = {
|
||||
.parse = dec__parse,
|
||||
.scnprintf = dec__scnprintf,
|
||||
};
|
||||
@@ -831,11 +718,11 @@ static int nop__scnprintf(const struct ins *ins __maybe_unused, char *bf, size_t
|
||||
return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
|
||||
}
|
||||
|
||||
static const struct ins_ops nop_ops = {
|
||||
const struct ins_ops nop_ops = {
|
||||
.scnprintf = nop__scnprintf,
|
||||
};
|
||||
|
||||
static const struct ins_ops ret_ops = {
|
||||
const struct ins_ops ret_ops = {
|
||||
.scnprintf = ins__raw_scnprintf,
|
||||
};
|
||||
|
||||
|
||||
@@ -109,6 +109,28 @@ const struct arch *arch__find(const char *name);
|
||||
bool arch__is_x86(const struct arch *arch);
|
||||
bool arch__is_powerpc(const struct arch *arch);
|
||||
|
||||
extern const struct ins_ops call_ops;
|
||||
extern const struct ins_ops dec_ops;
|
||||
extern const struct ins_ops jump_ops;
|
||||
extern const struct ins_ops mov_ops;
|
||||
extern const struct ins_ops nop_ops;
|
||||
extern const struct ins_ops lock_ops;
|
||||
extern const struct ins_ops ret_ops;
|
||||
|
||||
int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops);
|
||||
|
||||
int arc__annotate_init(struct arch *arch, char *cpuid);
|
||||
int arm__annotate_init(struct arch *arch, char *cpuid);
|
||||
int arm64__annotate_init(struct arch *arch, char *cpuid);
|
||||
int csky__annotate_init(struct arch *arch, char *cpuid);
|
||||
int loongarch__annotate_init(struct arch *arch, char *cpuid);
|
||||
int mips__annotate_init(struct arch *arch, char *cpuid);
|
||||
int powerpc__annotate_init(struct arch *arch, char *cpuid);
|
||||
int riscv64__annotate_init(struct arch *arch, char *cpuid);
|
||||
int s390__annotate_init(struct arch *arch, char *cpuid);
|
||||
int sparc__annotate_init(struct arch *arch, char *cpuid);
|
||||
int x86__annotate_init(struct arch *arch, char *cpuid);
|
||||
|
||||
const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
|
||||
|
||||
bool ins__is_call(const struct ins *ins);
|
||||
@@ -117,12 +139,28 @@ bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2);
|
||||
bool ins__is_ret(const struct ins *ins);
|
||||
bool ins__is_lock(const struct ins *ins);
|
||||
|
||||
extern const struct ins_ops s390_call_ops;
|
||||
extern const struct ins_ops loongarch_call_ops;
|
||||
extern const struct ins_ops loongarch_jump_ops;
|
||||
const struct ins_ops *check_ppc_insn(struct disasm_line *dl);
|
||||
|
||||
struct disasm_line *disasm_line__new(struct annotate_args *args);
|
||||
void disasm_line__free(struct disasm_line *dl);
|
||||
|
||||
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size,
|
||||
bool raw, int max_ins_name);
|
||||
|
||||
int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
int call__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
|
||||
struct ins_operands *ops, int max_ins_name);
|
||||
|
||||
int symbol__disassemble(struct symbol *sym, struct annotate_args *args);
|
||||
|
||||
char *expand_tabs(char *line, char **storage, size_t *storage_len);
|
||||
|
||||
Reference in New Issue
Block a user