Commit cbaf89a8 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf annotate: Parse x86 segment register location

Add a segment field in the struct annotated_insn_loc and save it for the
segment based addressing like %gs:0x28.  For simplicity it now handles
%gs register only.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20240319055115.4063940-17-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent bdc80ace
...@@ -94,6 +94,7 @@ struct arch { ...@@ -94,6 +94,7 @@ struct arch {
char skip_functions_char; char skip_functions_char;
char register_char; char register_char;
char memory_ref_char; char memory_ref_char;
char imm_char;
} objdump; } objdump;
}; };
...@@ -211,6 +212,7 @@ static struct arch architectures[] = { ...@@ -211,6 +212,7 @@ static struct arch architectures[] = {
.comment_char = '#', .comment_char = '#',
.register_char = '%', .register_char = '%',
.memory_ref_char = '(', .memory_ref_char = '(',
.imm_char = '$',
}, },
}, },
{ {
...@@ -3585,6 +3587,12 @@ static int extract_reg_offset(struct arch *arch, const char *str, ...@@ -3585,6 +3587,12 @@ static int extract_reg_offset(struct arch *arch, const char *str,
* %gs:0x18(%rbx). In that case it should skip the part. * %gs:0x18(%rbx). In that case it should skip the part.
*/ */
if (*str == arch->objdump.register_char) { if (*str == arch->objdump.register_char) {
if (arch__is(arch, "x86")) {
/* FIXME: Handle other segment registers */
if (!strncmp(str, "%gs:", 4))
op_loc->segment = INSN_SEG_X86_GS;
}
while (*str && !isdigit(*str) && while (*str && !isdigit(*str) &&
*str != arch->objdump.memory_ref_char) *str != arch->objdump.memory_ref_char)
str++; str++;
...@@ -3681,12 +3689,32 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl, ...@@ -3681,12 +3689,32 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
op_loc->multi_regs = multi_regs; op_loc->multi_regs = multi_regs;
extract_reg_offset(arch, insn_str, op_loc); extract_reg_offset(arch, insn_str, op_loc);
} else { } else {
char *s = strdup(insn_str); char *s, *p = NULL;
if (s) { if (arch__is(arch, "x86")) {
/* FIXME: Handle other segment registers */
if (!strncmp(insn_str, "%gs:", 4)) {
op_loc->segment = INSN_SEG_X86_GS;
op_loc->offset = strtol(insn_str + 4,
&p, 0);
if (p && p != insn_str + 4)
op_loc->imm = true;
continue;
}
}
s = strdup(insn_str);
if (s == NULL)
return -1;
if (*s == arch->objdump.register_char)
op_loc->reg1 = get_dwarf_regnum(s, 0); op_loc->reg1 = get_dwarf_regnum(s, 0);
free(s); else if (*s == arch->objdump.imm_char) {
op_loc->offset = strtol(s + 1, &p, 0);
if (p && p != s + 1)
op_loc->imm = true;
} }
free(s);
} }
} }
...@@ -3881,7 +3909,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) ...@@ -3881,7 +3909,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
.op = op_loc, .op = op_loc,
}; };
if (!op_loc->mem_ref) if (!op_loc->mem_ref && op_loc->segment == INSN_SEG_NONE)
continue; continue;
/* Recalculate IP because of LOCK prefix or insn fusion */ /* Recalculate IP because of LOCK prefix or insn fusion */
......
...@@ -511,15 +511,19 @@ int annotate_check_args(void); ...@@ -511,15 +511,19 @@ int annotate_check_args(void);
* @reg1: First register in the operand * @reg1: First register in the operand
* @reg2: Second register in the operand * @reg2: Second register in the operand
* @offset: Memory access offset in the operand * @offset: Memory access offset in the operand
* @segment: Segment selector register
* @mem_ref: Whether the operand accesses memory * @mem_ref: Whether the operand accesses memory
* @multi_regs: Whether the second register is used * @multi_regs: Whether the second register is used
* @imm: Whether the operand is an immediate value (in offset)
*/ */
struct annotated_op_loc { struct annotated_op_loc {
int reg1; int reg1;
int reg2; int reg2;
int offset; int offset;
u8 segment;
bool mem_ref; bool mem_ref;
bool multi_regs; bool multi_regs;
bool imm;
}; };
enum annotated_insn_ops { enum annotated_insn_ops {
...@@ -529,6 +533,17 @@ enum annotated_insn_ops { ...@@ -529,6 +533,17 @@ enum annotated_insn_ops {
INSN_OP_MAX, INSN_OP_MAX,
}; };
enum annotated_x86_segment {
INSN_SEG_NONE = 0,
INSN_SEG_X86_CS,
INSN_SEG_X86_DS,
INSN_SEG_X86_ES,
INSN_SEG_X86_FS,
INSN_SEG_X86_GS,
INSN_SEG_X86_SS,
};
/** /**
* struct annotated_insn_loc - Location info of instruction * struct annotated_insn_loc - Location info of instruction
* @ops: Array of location info for source and target operands * @ops: Array of location info for source and target operands
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment