perf/core improvements and fixes:
objtool: Josh Poimboeuf: - Move x86 insn decoder to a common location. Arnaldo Carvalho de Melo: - Ignore intentional differences for the x86 insn decoder. build: Arnaldo Carvalho de Melo: - Ignore intentional differences for the x86 insn decoder. Intel PT: Josh Poimboeuf: - Use shared x86 insn decoder. metric groups: Jin Yao: - Scale the metric result. - Support multiple events. perf c2c: Jiri Olsa: - Display proper cpu count in nodes column. Miscellaneous: Kyle Meyer: - Replace MAX_NR_CPUS with perf_env::nr_cpus_online, i.e. with the number of online CPUs as detected at tool start and/or recorded in the perf.data file. libtraceevent: Tzvetomir Stoyanov: - Simplify the tep_print_event_* APIs. - Remove tep_register_trace_clock(). - Change users plugin directory. Cleanups: Arnaldo Carvalho de Melo: - Continue taming the includes hell: remove needless include directives, fix the fallout, rinse, repeat. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCXWu3MwAKCRCyPKLppCJ+ Jyk2AQDGk7TZ6e/fjzi/kvgC0kqjtL47G7q9BySx1Ih3FUFVhAD/dS1fVHnANGDz fxeTqtMCUV4b2a2srOwYtf93jqIxSQI= =OfXP -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-5.4-20190901' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: objtool: Josh Poimboeuf: - Move x86 insn decoder to a common location. Arnaldo Carvalho de Melo: - Ignore intentional differences for the x86 insn decoder. build: Arnaldo Carvalho de Melo: - Ignore intentional differences for the x86 insn decoder. Intel PT: Josh Poimboeuf: - Use shared x86 insn decoder. metric groups: Jin Yao: - Scale the metric result. - Support multiple events. perf c2c: Jiri Olsa: - Display proper cpu count in nodes column. Miscellaneous: Kyle Meyer: - Replace MAX_NR_CPUS with perf_env::nr_cpus_online, i.e. with the number of online CPUs as detected at tool start and/or recorded in the perf.data file. libtraceevent: Tzvetomir Stoyanov: - Simplify the tep_print_event_* APIs. - Remove tep_register_trace_clock(). - Change users plugin directory. Cleanups: Arnaldo Carvalho de Melo: - Continue taming the includes hell: remove needless include directives, fix the fallout, rinse, repeat. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
2c58167877
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Written by Masami Hiramatsu <mhiramat@redhat.com>
|
||||
*/
|
||||
#include <asm/insn.h>
|
||||
#include "../include/asm/insn.h"
|
||||
|
||||
/* Attribute tables are generated from opcode map */
|
||||
#include "inat-tables.c"
|
|
@ -10,8 +10,8 @@
|
|||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "inat.h"
|
||||
#include "insn.h"
|
||||
#include "../include/asm/inat.h"
|
||||
#include "../include/asm/insn.h"
|
||||
|
||||
/* Verify next sizeof(t) bytes can be on the same instruction */
|
||||
#define validate_next(t, insn, n) \
|
|
@ -62,15 +62,15 @@ set_plugin_dir := 1
|
|||
|
||||
# Set plugin_dir to preffered global plugin location
|
||||
# If we install under $HOME directory we go under
|
||||
# $(HOME)/.traceevent/plugins
|
||||
# $(HOME)/.local/lib/traceevent/plugins
|
||||
#
|
||||
# We dont set PLUGIN_DIR in case we install under $HOME
|
||||
# directory, because by default the code looks under:
|
||||
# $(HOME)/.traceevent/plugins by default.
|
||||
# $(HOME)/.local/lib/traceevent/plugins by default.
|
||||
#
|
||||
ifeq ($(plugin_dir),)
|
||||
ifeq ($(prefix),$(HOME))
|
||||
override plugin_dir = $(HOME)/.traceevent/plugins
|
||||
override plugin_dir = $(HOME)/.local/lib/traceevent/plugins
|
||||
set_plugin_dir := 0
|
||||
else
|
||||
override plugin_dir = $(libdir)/traceevent/plugins
|
||||
|
|
|
@ -302,33 +302,6 @@ void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian)
|
|||
tep->host_bigendian = endian;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_is_latency_format - get if the latency output format is configured
|
||||
* @tep: a handle to the tep_handle
|
||||
*
|
||||
* This returns true if the latency output format is configured
|
||||
* If @tep is NULL, false is returned.
|
||||
*/
|
||||
bool tep_is_latency_format(struct tep_handle *tep)
|
||||
{
|
||||
if (tep)
|
||||
return (tep->latency_format);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_set_latency_format - set the latency output format
|
||||
* @tep: a handle to the tep_handle
|
||||
* @lat: non zero for latency output format
|
||||
*
|
||||
* This sets the latency output format
|
||||
*/
|
||||
void tep_set_latency_format(struct tep_handle *tep, int lat)
|
||||
{
|
||||
if (tep)
|
||||
tep->latency_format = lat;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_is_old_format - get if an old kernel is used
|
||||
* @tep: a handle to the tep_handle
|
||||
|
@ -344,19 +317,6 @@ bool tep_is_old_format(struct tep_handle *tep)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_set_print_raw - set a flag to force print in raw format
|
||||
* @tep: a handle to the tep_handle
|
||||
* @print_raw: the new value of the print_raw flag
|
||||
*
|
||||
* This sets a flag to force print in raw format
|
||||
*/
|
||||
void tep_set_print_raw(struct tep_handle *tep, int print_raw)
|
||||
{
|
||||
if (tep)
|
||||
tep->print_raw = print_raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_set_test_filters - set a flag to test a filter string
|
||||
* @tep: a handle to the tep_handle
|
||||
|
|
|
@ -28,8 +28,6 @@ struct tep_handle {
|
|||
enum tep_endian file_bigendian;
|
||||
enum tep_endian host_bigendian;
|
||||
|
||||
int latency_format;
|
||||
|
||||
int old_format;
|
||||
|
||||
int cpus;
|
||||
|
@ -70,8 +68,6 @@ struct tep_handle {
|
|||
int ld_offset;
|
||||
int ld_size;
|
||||
|
||||
int print_raw;
|
||||
|
||||
int test_filters;
|
||||
|
||||
int flags;
|
||||
|
@ -85,8 +81,6 @@ struct tep_handle {
|
|||
|
||||
/* cache */
|
||||
struct tep_event *last_event;
|
||||
|
||||
char *trace_clock;
|
||||
};
|
||||
|
||||
void tep_free_event(struct tep_event *event);
|
||||
|
|
|
@ -393,16 +393,6 @@ int tep_override_comm(struct tep_handle *tep, const char *comm, int pid)
|
|||
return _tep_register_comm(tep, comm, pid, true);
|
||||
}
|
||||
|
||||
int tep_register_trace_clock(struct tep_handle *tep, const char *trace_clock)
|
||||
{
|
||||
tep->trace_clock = strdup(trace_clock);
|
||||
if (!tep->trace_clock) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct func_map {
|
||||
unsigned long long addr;
|
||||
char *func;
|
||||
|
@ -5212,24 +5202,20 @@ out_failed:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_data_latency_format - parse the data for the latency format
|
||||
* @tep: a handle to the trace event parser context
|
||||
* @s: the trace_seq to write to
|
||||
* @record: the record to read from
|
||||
*
|
||||
/*
|
||||
* This parses out the Latency format (interrupts disabled,
|
||||
* need rescheduling, in hard/soft interrupt, preempt count
|
||||
* and lock depth) and places it into the trace_seq.
|
||||
*/
|
||||
void tep_data_latency_format(struct tep_handle *tep,
|
||||
struct trace_seq *s, struct tep_record *record)
|
||||
static void data_latency_format(struct tep_handle *tep, struct trace_seq *s,
|
||||
char *format, struct tep_record *record)
|
||||
{
|
||||
static int check_lock_depth = 1;
|
||||
static int check_migrate_disable = 1;
|
||||
static int lock_depth_exists;
|
||||
static int migrate_disable_exists;
|
||||
unsigned int lat_flags;
|
||||
struct trace_seq sq;
|
||||
unsigned int pc;
|
||||
int lock_depth = 0;
|
||||
int migrate_disable = 0;
|
||||
|
@ -5237,6 +5223,7 @@ void tep_data_latency_format(struct tep_handle *tep,
|
|||
int softirq;
|
||||
void *data = record->data;
|
||||
|
||||
trace_seq_init(&sq);
|
||||
lat_flags = parse_common_flags(tep, data);
|
||||
pc = parse_common_pc(tep, data);
|
||||
/* lock_depth may not always exist */
|
||||
|
@ -5264,7 +5251,7 @@ void tep_data_latency_format(struct tep_handle *tep,
|
|||
hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
|
||||
softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
|
||||
|
||||
trace_seq_printf(s, "%c%c%c",
|
||||
trace_seq_printf(&sq, "%c%c%c",
|
||||
(lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
|
||||
(lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
|
||||
'X' : '.',
|
||||
|
@ -5274,24 +5261,32 @@ void tep_data_latency_format(struct tep_handle *tep,
|
|||
hardirq ? 'h' : softirq ? 's' : '.');
|
||||
|
||||
if (pc)
|
||||
trace_seq_printf(s, "%x", pc);
|
||||
trace_seq_printf(&sq, "%x", pc);
|
||||
else
|
||||
trace_seq_putc(s, '.');
|
||||
trace_seq_printf(&sq, ".");
|
||||
|
||||
if (migrate_disable_exists) {
|
||||
if (migrate_disable < 0)
|
||||
trace_seq_putc(s, '.');
|
||||
trace_seq_printf(&sq, ".");
|
||||
else
|
||||
trace_seq_printf(s, "%d", migrate_disable);
|
||||
trace_seq_printf(&sq, "%d", migrate_disable);
|
||||
}
|
||||
|
||||
if (lock_depth_exists) {
|
||||
if (lock_depth < 0)
|
||||
trace_seq_putc(s, '.');
|
||||
trace_seq_printf(&sq, ".");
|
||||
else
|
||||
trace_seq_printf(s, "%d", lock_depth);
|
||||
trace_seq_printf(&sq, "%d", lock_depth);
|
||||
}
|
||||
|
||||
if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) {
|
||||
s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
trace_seq_terminate(&sq);
|
||||
trace_seq_puts(s, sq.buffer);
|
||||
trace_seq_destroy(&sq);
|
||||
trace_seq_terminate(s);
|
||||
}
|
||||
|
||||
|
@ -5452,21 +5447,16 @@ int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)
|
|||
return cmdline->pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_event_info - parse the data into the print format
|
||||
* @s: the trace_seq to write to
|
||||
* @event: the handle to the event
|
||||
* @record: the record to read from
|
||||
*
|
||||
/*
|
||||
* This parses the raw @data using the given @event information and
|
||||
* writes the print format into the trace_seq.
|
||||
*/
|
||||
void tep_event_info(struct trace_seq *s, struct tep_event *event,
|
||||
struct tep_record *record)
|
||||
static void print_event_info(struct trace_seq *s, char *format, bool raw,
|
||||
struct tep_event *event, struct tep_record *record)
|
||||
{
|
||||
int print_pretty = 1;
|
||||
|
||||
if (event->tep->print_raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
|
||||
if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
|
||||
tep_print_fields(s, record->data, record->size, event);
|
||||
else {
|
||||
|
||||
|
@ -5481,20 +5471,6 @@ void tep_event_info(struct trace_seq *s, struct tep_event *event,
|
|||
trace_seq_terminate(s);
|
||||
}
|
||||
|
||||
static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
|
||||
{
|
||||
if (!trace_clock || !use_trace_clock)
|
||||
return true;
|
||||
|
||||
if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
|
||||
|| !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf")
|
||||
|| !strncmp(trace_clock, "mono", 4))
|
||||
return true;
|
||||
|
||||
/* trace_clock is setting in tsc or counter mode */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_find_event_by_record - return the event from a given record
|
||||
* @tep: a handle to the trace event parser context
|
||||
|
@ -5518,129 +5494,195 @@ tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)
|
|||
return tep_find_event(tep, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_print_event_task - Write the event task comm, pid and CPU
|
||||
* @tep: a handle to the trace event parser context
|
||||
* @s: the trace_seq to write to
|
||||
* @event: the handle to the record's event
|
||||
* @record: The record to get the event from
|
||||
*
|
||||
* Writes the tasks comm, pid and CPU to @s.
|
||||
/*
|
||||
* Writes the timestamp of the record into @s. Time divisor and precision can be
|
||||
* specified as part of printf @format string. Example:
|
||||
* "%3.1000d" - divide the time by 1000 and print the first 3 digits
|
||||
* before the dot. Thus, the timestamp "123456000" will be printed as
|
||||
* "123.456"
|
||||
*/
|
||||
void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
static void print_event_time(struct tep_handle *tep, struct trace_seq *s,
|
||||
char *format, struct tep_event *event,
|
||||
struct tep_record *record)
|
||||
{
|
||||
void *data = record->data;
|
||||
unsigned long long time;
|
||||
char *divstr;
|
||||
int prec = 0, pr;
|
||||
int div = 0;
|
||||
int p10 = 1;
|
||||
|
||||
if (isdigit(*(format + 1)))
|
||||
prec = atoi(format + 1);
|
||||
divstr = strchr(format, '.');
|
||||
if (divstr && isdigit(*(divstr + 1)))
|
||||
div = atoi(divstr + 1);
|
||||
time = record->ts;
|
||||
if (div)
|
||||
time /= div;
|
||||
pr = prec;
|
||||
while (pr--)
|
||||
p10 *= 10;
|
||||
|
||||
if (p10 > 1 && p10 < time)
|
||||
trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10);
|
||||
else
|
||||
trace_seq_printf(s, "%12llu\n", time);
|
||||
}
|
||||
|
||||
struct print_event_type {
|
||||
enum {
|
||||
EVENT_TYPE_INT = 1,
|
||||
EVENT_TYPE_STRING,
|
||||
EVENT_TYPE_UNKNOWN,
|
||||
} type;
|
||||
char format[32];
|
||||
};
|
||||
|
||||
static void print_string(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_record *record, struct tep_event *event,
|
||||
const char *arg, struct print_event_type *type)
|
||||
{
|
||||
const char *comm;
|
||||
int pid;
|
||||
|
||||
pid = parse_common_pid(tep, data);
|
||||
if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) {
|
||||
data_latency_format(tep, s, type->format, record);
|
||||
} else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) {
|
||||
pid = parse_common_pid(tep, record->data);
|
||||
comm = find_cmdline(tep, pid);
|
||||
|
||||
if (tep->latency_format)
|
||||
trace_seq_printf(s, "%8.8s-%-5d %3d", comm, pid, record->cpu);
|
||||
else
|
||||
trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_print_event_time - Write the event timestamp
|
||||
* @tep: a handle to the trace event parser context
|
||||
* @s: the trace_seq to write to
|
||||
* @event: the handle to the record's event
|
||||
* @record: The record to get the event from
|
||||
* @use_trace_clock: Set to parse according to the @tep->trace_clock
|
||||
*
|
||||
* Writes the timestamp of the record into @s.
|
||||
*/
|
||||
void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
struct tep_record *record,
|
||||
bool use_trace_clock)
|
||||
{
|
||||
unsigned long secs;
|
||||
unsigned long usecs;
|
||||
unsigned long nsecs;
|
||||
int p;
|
||||
bool use_usec_format;
|
||||
|
||||
use_usec_format = is_timestamp_in_us(tep->trace_clock, use_trace_clock);
|
||||
if (use_usec_format) {
|
||||
secs = record->ts / NSEC_PER_SEC;
|
||||
nsecs = record->ts - secs * NSEC_PER_SEC;
|
||||
}
|
||||
|
||||
if (tep->latency_format) {
|
||||
tep_data_latency_format(tep, s, record);
|
||||
}
|
||||
|
||||
if (use_usec_format) {
|
||||
if (tep->flags & TEP_NSEC_OUTPUT) {
|
||||
usecs = nsecs;
|
||||
p = 9;
|
||||
trace_seq_printf(s, type->format, comm);
|
||||
} else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) {
|
||||
print_event_info(s, type->format, true, event, record);
|
||||
} else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) {
|
||||
print_event_info(s, type->format, false, event, record);
|
||||
} else if (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) {
|
||||
trace_seq_printf(s, type->format, event->name);
|
||||
} else {
|
||||
usecs = (nsecs + 500) / NSEC_PER_USEC;
|
||||
/* To avoid usecs larger than 1 sec */
|
||||
if (usecs >= USEC_PER_SEC) {
|
||||
usecs -= USEC_PER_SEC;
|
||||
secs++;
|
||||
}
|
||||
p = 6;
|
||||
trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg);
|
||||
}
|
||||
|
||||
trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs);
|
||||
} else
|
||||
trace_seq_printf(s, " %12llu:", record->ts);
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_print_event_data - Write the event data section
|
||||
* @tep: a handle to the trace event parser context
|
||||
* @s: the trace_seq to write to
|
||||
* @event: the handle to the record's event
|
||||
* @record: The record to get the event from
|
||||
*
|
||||
* Writes the parsing of the record's data to @s.
|
||||
*/
|
||||
void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
struct tep_record *record)
|
||||
static void print_int(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_record *record, struct tep_event *event,
|
||||
int arg, struct print_event_type *type)
|
||||
{
|
||||
static const char *spaces = " "; /* 20 spaces */
|
||||
int len;
|
||||
int param;
|
||||
|
||||
trace_seq_printf(s, " %s: ", event->name);
|
||||
|
||||
/* Space out the event names evenly. */
|
||||
len = strlen(event->name);
|
||||
if (len < 20)
|
||||
trace_seq_printf(s, "%.*s", 20 - len, spaces);
|
||||
|
||||
tep_event_info(s, event, record);
|
||||
}
|
||||
|
||||
void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_record *record, bool use_trace_clock)
|
||||
{
|
||||
struct tep_event *event;
|
||||
|
||||
event = tep_find_event_by_record(tep, record);
|
||||
if (!event) {
|
||||
int i;
|
||||
int type = trace_parse_common_type(tep, record->data);
|
||||
|
||||
do_warning("ug! no event found for type %d", type);
|
||||
trace_seq_printf(s, "[UNKNOWN TYPE %d]", type);
|
||||
for (i = 0; i < record->size; i++)
|
||||
trace_seq_printf(s, " %02x",
|
||||
((unsigned char *)record->data)[i]);
|
||||
switch (arg) {
|
||||
case TEP_PRINT_CPU:
|
||||
param = record->cpu;
|
||||
break;
|
||||
case TEP_PRINT_PID:
|
||||
param = parse_common_pid(tep, record->data);
|
||||
break;
|
||||
case TEP_PRINT_TIME:
|
||||
return print_event_time(tep, s, type->format, event, record);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
trace_seq_printf(s, type->format, param);
|
||||
}
|
||||
|
||||
tep_print_event_task(tep, s, event, record);
|
||||
tep_print_event_time(tep, s, event, record, use_trace_clock);
|
||||
tep_print_event_data(tep, s, event, record);
|
||||
static int tep_print_event_param_type(char *format,
|
||||
struct print_event_type *type)
|
||||
{
|
||||
char *str = format + 1;
|
||||
int i = 1;
|
||||
|
||||
type->type = EVENT_TYPE_UNKNOWN;
|
||||
while (*str) {
|
||||
switch (*str) {
|
||||
case 'd':
|
||||
case 'u':
|
||||
case 'i':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'o':
|
||||
type->type = EVENT_TYPE_INT;
|
||||
break;
|
||||
case 's':
|
||||
type->type = EVENT_TYPE_STRING;
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
i++;
|
||||
if (type->type != EVENT_TYPE_UNKNOWN)
|
||||
break;
|
||||
}
|
||||
memset(type->format, 0, 32);
|
||||
memcpy(type->format, format, i < 32 ? i : 31);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* tep_print_event - Write various event information
|
||||
* @tep: a handle to the trace event parser context
|
||||
* @s: the trace_seq to write to
|
||||
* @record: The record to get the event from
|
||||
* @format: a printf format string. Supported event fileds:
|
||||
* TEP_PRINT_PID, "%d" - event PID
|
||||
* TEP_PRINT_CPU, "%d" - event CPU
|
||||
* TEP_PRINT_COMM, "%s" - event command string
|
||||
* TEP_PRINT_NAME, "%s" - event name
|
||||
* TEP_PRINT_LATENCY, "%s" - event latency
|
||||
* TEP_PRINT_TIME, %d - event time stamp. A divisor and precision
|
||||
* can be specified as part of this format string:
|
||||
* "%precision.divisord". Example:
|
||||
* "%3.1000d" - divide the time by 1000 and print the first
|
||||
* 3 digits before the dot. Thus, the time stamp
|
||||
* "123456000" will be printed as "123.456"
|
||||
* TEP_PRINT_INFO, "%s" - event information. If any width is specified in
|
||||
* the format string, the event information will be printed
|
||||
* in raw format.
|
||||
* Writes the specified event information into @s.
|
||||
*/
|
||||
void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_record *record, const char *fmt, ...)
|
||||
{
|
||||
struct print_event_type type;
|
||||
char *format = strdup(fmt);
|
||||
char *current = format;
|
||||
char *str = format;
|
||||
int offset;
|
||||
va_list args;
|
||||
struct tep_event *event;
|
||||
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
event = tep_find_event_by_record(tep, record);
|
||||
va_start(args, fmt);
|
||||
while (*current) {
|
||||
current = strchr(str, '%');
|
||||
if (!current) {
|
||||
trace_seq_puts(s, str);
|
||||
break;
|
||||
}
|
||||
memset(&type, 0, sizeof(type));
|
||||
offset = tep_print_event_param_type(current, &type);
|
||||
*current = '\0';
|
||||
trace_seq_puts(s, str);
|
||||
current += offset;
|
||||
switch (type.type) {
|
||||
case EVENT_TYPE_STRING:
|
||||
print_string(tep, s, record, event,
|
||||
va_arg(args, char*), &type);
|
||||
break;
|
||||
case EVENT_TYPE_INT:
|
||||
print_int(tep, s, record, event,
|
||||
va_arg(args, int), &type);
|
||||
break;
|
||||
case EVENT_TYPE_UNKNOWN:
|
||||
default:
|
||||
trace_seq_printf(s, "[UNKNOWN TYPE]");
|
||||
break;
|
||||
}
|
||||
str = current;
|
||||
|
||||
}
|
||||
va_end(args);
|
||||
free(format);
|
||||
}
|
||||
|
||||
static int events_id_cmp(const void *a, const void *b)
|
||||
|
@ -7005,7 +7047,6 @@ void tep_free(struct tep_handle *tep)
|
|||
free_handler(handle);
|
||||
}
|
||||
|
||||
free(tep->trace_clock);
|
||||
free(tep->events);
|
||||
free(tep->sort_events);
|
||||
free(tep->func_resolver);
|
||||
|
|
|
@ -435,25 +435,24 @@ int tep_set_function_resolver(struct tep_handle *tep,
|
|||
void tep_reset_function_resolver(struct tep_handle *tep);
|
||||
int tep_register_comm(struct tep_handle *tep, const char *comm, int pid);
|
||||
int tep_override_comm(struct tep_handle *tep, const char *comm, int pid);
|
||||
int tep_register_trace_clock(struct tep_handle *tep, const char *trace_clock);
|
||||
int tep_register_function(struct tep_handle *tep, char *name,
|
||||
unsigned long long addr, char *mod);
|
||||
int tep_register_print_string(struct tep_handle *tep, const char *fmt,
|
||||
unsigned long long addr);
|
||||
bool tep_is_pid_registered(struct tep_handle *tep, int pid);
|
||||
|
||||
void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
struct tep_record *record);
|
||||
void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
struct tep_record *record,
|
||||
bool use_trace_clock);
|
||||
void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_event *event,
|
||||
struct tep_record *record);
|
||||
#define TEP_PRINT_INFO "INFO"
|
||||
#define TEP_PRINT_INFO_RAW "INFO_RAW"
|
||||
#define TEP_PRINT_COMM "COMM"
|
||||
#define TEP_PRINT_LATENCY "LATENCY"
|
||||
#define TEP_PRINT_NAME "NAME"
|
||||
#define TEP_PRINT_PID 1U
|
||||
#define TEP_PRINT_TIME 2U
|
||||
#define TEP_PRINT_CPU 3U
|
||||
|
||||
void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
|
||||
struct tep_record *record, bool use_trace_clock);
|
||||
struct tep_record *record, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 4, 5)));
|
||||
|
||||
int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,
|
||||
int long_size);
|
||||
|
@ -525,8 +524,6 @@ tep_find_event_by_name(struct tep_handle *tep, const char *sys, const char *name
|
|||
struct tep_event *
|
||||
tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record);
|
||||
|
||||
void tep_data_latency_format(struct tep_handle *tep,
|
||||
struct trace_seq *s, struct tep_record *record);
|
||||
int tep_data_type(struct tep_handle *tep, struct tep_record *rec);
|
||||
int tep_data_pid(struct tep_handle *tep, struct tep_record *rec);
|
||||
int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec);
|
||||
|
@ -541,8 +538,6 @@ void tep_print_field(struct trace_seq *s, void *data,
|
|||
struct tep_format_field *field);
|
||||
void tep_print_fields(struct trace_seq *s, void *data,
|
||||
int size __maybe_unused, struct tep_event *event);
|
||||
void tep_event_info(struct trace_seq *s, struct tep_event *event,
|
||||
struct tep_record *record);
|
||||
int tep_strerror(struct tep_handle *tep, enum tep_errno errnum,
|
||||
char *buf, size_t buflen);
|
||||
|
||||
|
@ -566,12 +561,9 @@ bool tep_is_file_bigendian(struct tep_handle *tep);
|
|||
void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian);
|
||||
bool tep_is_local_bigendian(struct tep_handle *tep);
|
||||
void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian);
|
||||
bool tep_is_latency_format(struct tep_handle *tep);
|
||||
void tep_set_latency_format(struct tep_handle *tep, int lat);
|
||||
int tep_get_header_page_size(struct tep_handle *tep);
|
||||
int tep_get_header_timestamp_size(struct tep_handle *tep);
|
||||
bool tep_is_old_format(struct tep_handle *tep);
|
||||
void tep_set_print_raw(struct tep_handle *tep, int print_raw);
|
||||
void tep_set_test_filters(struct tep_handle *tep, int test_filters);
|
||||
|
||||
struct tep_handle *tep_alloc(void);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "event-utils.h"
|
||||
#include "trace-seq.h"
|
||||
|
||||
#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
|
||||
#define LOCAL_PLUGIN_DIR ".local/lib/traceevent/plugins/"
|
||||
|
||||
static struct registered_plugin_options {
|
||||
struct registered_plugin_options *next;
|
||||
|
|
|
@ -33,7 +33,7 @@ all: $(OBJTOOL)
|
|||
|
||||
INCLUDES := -I$(srctree)/tools/include \
|
||||
-I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \
|
||||
-I$(srctree)/tools/objtool/arch/$(ARCH)/include
|
||||
-I$(srctree)/tools/arch/$(ARCH)/include
|
||||
WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed
|
||||
CFLAGS += -Werror $(WARNINGS) $(KBUILD_HOSTCFLAGS) -g $(INCLUDES) $(LIBELF_FLAGS)
|
||||
LDFLAGS += $(LIBELF_LIBS) $(LIBSUBCMD) $(KBUILD_HOSTLDFLAGS)
|
||||
|
@ -60,7 +60,7 @@ $(LIBSUBCMD): fixdep FORCE
|
|||
clean:
|
||||
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
|
||||
$(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
|
||||
$(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep
|
||||
$(Q)$(RM) $(OUTPUT)arch/x86/inat-tables.c $(OUTPUT)fixdep
|
||||
|
||||
FORCE:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
objtool-y += decode.o
|
||||
|
||||
inat_tables_script = arch/x86/tools/gen-insn-attr-x86.awk
|
||||
inat_tables_maps = arch/x86/lib/x86-opcode-map.txt
|
||||
inat_tables_script = ../arch/x86/tools/gen-insn-attr-x86.awk
|
||||
inat_tables_maps = ../arch/x86/lib/x86-opcode-map.txt
|
||||
|
||||
$(OUTPUT)arch/x86/lib/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
|
||||
$(call rule_mkdir)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
#define unlikely(cond) (cond)
|
||||
#include <asm/insn.h>
|
||||
#include "lib/inat.c"
|
||||
#include "lib/insn.c"
|
||||
#include "../../../arch/x86/lib/inat.c"
|
||||
#include "../../../arch/x86/lib/insn.c"
|
||||
|
||||
#include "../../elf.h"
|
||||
#include "../../arch.h"
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _ASM_X86_INAT_H
|
||||
#define _ASM_X86_INAT_H
|
||||
/*
|
||||
* x86 instruction attributes
|
||||
*
|
||||
* Written by Masami Hiramatsu <mhiramat@redhat.com>
|
||||
*/
|
||||
#include <asm/inat_types.h>
|
||||
|
||||
/*
|
||||
* Internal bits. Don't use bitmasks directly, because these bits are
|
||||
* unstable. You should use checking functions.
|
||||
*/
|
||||
|
||||
#define INAT_OPCODE_TABLE_SIZE 256
|
||||
#define INAT_GROUP_TABLE_SIZE 8
|
||||
|
||||
/* Legacy last prefixes */
|
||||
#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
|
||||
#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
|
||||
#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
|
||||
/* Other Legacy prefixes */
|
||||
#define INAT_PFX_LOCK 4 /* 0xF0 */
|
||||
#define INAT_PFX_CS 5 /* 0x2E */
|
||||
#define INAT_PFX_DS 6 /* 0x3E */
|
||||
#define INAT_PFX_ES 7 /* 0x26 */
|
||||
#define INAT_PFX_FS 8 /* 0x64 */
|
||||
#define INAT_PFX_GS 9 /* 0x65 */
|
||||
#define INAT_PFX_SS 10 /* 0x36 */
|
||||
#define INAT_PFX_ADDRSZ 11 /* 0x67 */
|
||||
/* x86-64 REX prefix */
|
||||
#define INAT_PFX_REX 12 /* 0x4X */
|
||||
/* AVX VEX prefixes */
|
||||
#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
|
||||
#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
|
||||
#define INAT_PFX_EVEX 15 /* EVEX prefix */
|
||||
|
||||
#define INAT_LSTPFX_MAX 3
|
||||
#define INAT_LGCPFX_MAX 11
|
||||
|
||||
/* Immediate size */
|
||||
#define INAT_IMM_BYTE 1
|
||||
#define INAT_IMM_WORD 2
|
||||
#define INAT_IMM_DWORD 3
|
||||
#define INAT_IMM_QWORD 4
|
||||
#define INAT_IMM_PTR 5
|
||||
#define INAT_IMM_VWORD32 6
|
||||
#define INAT_IMM_VWORD 7
|
||||
|
||||
/* Legacy prefix */
|
||||
#define INAT_PFX_OFFS 0
|
||||
#define INAT_PFX_BITS 4
|
||||
#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
|
||||
#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
|
||||
/* Escape opcodes */
|
||||
#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
|
||||
#define INAT_ESC_BITS 2
|
||||
#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
|
||||
#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
|
||||
/* Group opcodes (1-16) */
|
||||
#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
|
||||
#define INAT_GRP_BITS 5
|
||||
#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
|
||||
#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
|
||||
/* Immediates */
|
||||
#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
|
||||
#define INAT_IMM_BITS 3
|
||||
#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
|
||||
/* Flags */
|
||||
#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
|
||||
#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
|
||||
#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
|
||||
#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
|
||||
#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
|
||||
#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
|
||||
#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
|
||||
#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
|
||||
#define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7))
|
||||
/* Attribute making macros for attribute tables */
|
||||
#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
|
||||
#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
|
||||
#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
|
||||
#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
|
||||
|
||||
/* Identifiers for segment registers */
|
||||
#define INAT_SEG_REG_IGNORE 0
|
||||
#define INAT_SEG_REG_DEFAULT 1
|
||||
#define INAT_SEG_REG_CS 2
|
||||
#define INAT_SEG_REG_SS 3
|
||||
#define INAT_SEG_REG_DS 4
|
||||
#define INAT_SEG_REG_ES 5
|
||||
#define INAT_SEG_REG_FS 6
|
||||
#define INAT_SEG_REG_GS 7
|
||||
|
||||
/* Attribute search APIs */
|
||||
extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
|
||||
extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
|
||||
extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
|
||||
int lpfx_id,
|
||||
insn_attr_t esc_attr);
|
||||
extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
|
||||
int lpfx_id,
|
||||
insn_attr_t esc_attr);
|
||||
extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
|
||||
insn_byte_t vex_m,
|
||||
insn_byte_t vex_pp);
|
||||
|
||||
/* Attribute checking functions */
|
||||
static inline int inat_is_legacy_prefix(insn_attr_t attr)
|
||||
{
|
||||
attr &= INAT_PFX_MASK;
|
||||
return attr && attr <= INAT_LGCPFX_MAX;
|
||||
}
|
||||
|
||||
static inline int inat_is_address_size_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
|
||||
}
|
||||
|
||||
static inline int inat_is_operand_size_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
|
||||
}
|
||||
|
||||
static inline int inat_is_rex_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
|
||||
}
|
||||
|
||||
static inline int inat_last_prefix_id(insn_attr_t attr)
|
||||
{
|
||||
if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
|
||||
return 0;
|
||||
else
|
||||
return attr & INAT_PFX_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_is_vex_prefix(insn_attr_t attr)
|
||||
{
|
||||
attr &= INAT_PFX_MASK;
|
||||
return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 ||
|
||||
attr == INAT_PFX_EVEX;
|
||||
}
|
||||
|
||||
static inline int inat_is_evex_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX;
|
||||
}
|
||||
|
||||
static inline int inat_is_vex3_prefix(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
|
||||
}
|
||||
|
||||
static inline int inat_is_escape(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_ESC_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_escape_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_is_group(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_GRP_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_group_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_group_common_attribute(insn_attr_t attr)
|
||||
{
|
||||
return attr & ~INAT_GRP_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_has_immediate(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_IMM_MASK;
|
||||
}
|
||||
|
||||
static inline int inat_immediate_size(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
|
||||
}
|
||||
|
||||
static inline int inat_has_modrm(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_MODRM;
|
||||
}
|
||||
|
||||
static inline int inat_is_force64(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_FORCE64;
|
||||
}
|
||||
|
||||
static inline int inat_has_second_immediate(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_SCNDIMM;
|
||||
}
|
||||
|
||||
static inline int inat_has_moffset(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_MOFFSET;
|
||||
}
|
||||
|
||||
static inline int inat_has_variant(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VARIANT;
|
||||
}
|
||||
|
||||
static inline int inat_accept_vex(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VEXOK;
|
||||
}
|
||||
|
||||
static inline int inat_must_vex(insn_attr_t attr)
|
||||
{
|
||||
return attr & (INAT_VEXONLY | INAT_EVEXONLY);
|
||||
}
|
||||
|
||||
static inline int inat_must_evex(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_EVEXONLY;
|
||||
}
|
||||
#endif
|
|
@ -1,216 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _ASM_X86_INSN_H
|
||||
#define _ASM_X86_INSN_H
|
||||
/*
|
||||
* x86 instruction analysis
|
||||
*
|
||||
* Copyright (C) IBM Corporation, 2009
|
||||
*/
|
||||
|
||||
/* insn_attr_t is defined in inat.h */
|
||||
#include <asm/inat.h>
|
||||
|
||||
struct insn_field {
|
||||
union {
|
||||
insn_value_t value;
|
||||
insn_byte_t bytes[4];
|
||||
};
|
||||
/* !0 if we've run insn_get_xxx() for this field */
|
||||
unsigned char got;
|
||||
unsigned char nbytes;
|
||||
};
|
||||
|
||||
struct insn {
|
||||
struct insn_field prefixes; /*
|
||||
* Prefixes
|
||||
* prefixes.bytes[3]: last prefix
|
||||
*/
|
||||
struct insn_field rex_prefix; /* REX prefix */
|
||||
struct insn_field vex_prefix; /* VEX prefix */
|
||||
struct insn_field opcode; /*
|
||||
* opcode.bytes[0]: opcode1
|
||||
* opcode.bytes[1]: opcode2
|
||||
* opcode.bytes[2]: opcode3
|
||||
*/
|
||||
struct insn_field modrm;
|
||||
struct insn_field sib;
|
||||
struct insn_field displacement;
|
||||
union {
|
||||
struct insn_field immediate;
|
||||
struct insn_field moffset1; /* for 64bit MOV */
|
||||
struct insn_field immediate1; /* for 64bit imm or off16/32 */
|
||||
};
|
||||
union {
|
||||
struct insn_field moffset2; /* for 64bit MOV */
|
||||
struct insn_field immediate2; /* for 64bit imm or seg16 */
|
||||
};
|
||||
|
||||
insn_attr_t attr;
|
||||
unsigned char opnd_bytes;
|
||||
unsigned char addr_bytes;
|
||||
unsigned char length;
|
||||
unsigned char x86_64;
|
||||
|
||||
const insn_byte_t *kaddr; /* kernel address of insn to analyze */
|
||||
const insn_byte_t *end_kaddr; /* kernel address of last insn in buffer */
|
||||
const insn_byte_t *next_byte;
|
||||
};
|
||||
|
||||
#define MAX_INSN_SIZE 15
|
||||
|
||||
#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
|
||||
#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
|
||||
#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
|
||||
|
||||
#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
|
||||
#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
|
||||
#define X86_SIB_BASE(sib) ((sib) & 0x07)
|
||||
|
||||
#define X86_REX_W(rex) ((rex) & 8)
|
||||
#define X86_REX_R(rex) ((rex) & 4)
|
||||
#define X86_REX_X(rex) ((rex) & 2)
|
||||
#define X86_REX_B(rex) ((rex) & 1)
|
||||
|
||||
/* VEX bit flags */
|
||||
#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
|
||||
#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
|
||||
#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
|
||||
#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
|
||||
#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
/* VEX bit fields */
|
||||
#define X86_EVEX_M(vex) ((vex) & 0x03) /* EVEX Byte1 */
|
||||
#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
|
||||
#define X86_VEX2_M 1 /* VEX2.M always 1 */
|
||||
#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
|
||||
#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
|
||||
|
||||
extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
|
||||
extern void insn_get_prefixes(struct insn *insn);
|
||||
extern void insn_get_opcode(struct insn *insn);
|
||||
extern void insn_get_modrm(struct insn *insn);
|
||||
extern void insn_get_sib(struct insn *insn);
|
||||
extern void insn_get_displacement(struct insn *insn);
|
||||
extern void insn_get_immediate(struct insn *insn);
|
||||
extern void insn_get_length(struct insn *insn);
|
||||
|
||||
/* Attribute will be determined after getting ModRM (for opcode groups) */
|
||||
static inline void insn_get_attribute(struct insn *insn)
|
||||
{
|
||||
insn_get_modrm(insn);
|
||||
}
|
||||
|
||||
/* Instruction uses RIP-relative addressing */
|
||||
extern int insn_rip_relative(struct insn *insn);
|
||||
|
||||
/* Init insn for kernel text */
|
||||
static inline void kernel_insn_init(struct insn *insn,
|
||||
const void *kaddr, int buf_len)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
insn_init(insn, kaddr, buf_len, 1);
|
||||
#else /* CONFIG_X86_32 */
|
||||
insn_init(insn, kaddr, buf_len, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int insn_is_avx(struct insn *insn)
|
||||
{
|
||||
if (!insn->prefixes.got)
|
||||
insn_get_prefixes(insn);
|
||||
return (insn->vex_prefix.value != 0);
|
||||
}
|
||||
|
||||
static inline int insn_is_evex(struct insn *insn)
|
||||
{
|
||||
if (!insn->prefixes.got)
|
||||
insn_get_prefixes(insn);
|
||||
return (insn->vex_prefix.nbytes == 4);
|
||||
}
|
||||
|
||||
/* Ensure this instruction is decoded completely */
|
||||
static inline int insn_complete(struct insn *insn)
|
||||
{
|
||||
return insn->opcode.got && insn->modrm.got && insn->sib.got &&
|
||||
insn->displacement.got && insn->immediate.got;
|
||||
}
|
||||
|
||||
static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
|
||||
{
|
||||
if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
|
||||
return X86_VEX2_M;
|
||||
else if (insn->vex_prefix.nbytes == 3) /* 3 bytes VEX */
|
||||
return X86_VEX3_M(insn->vex_prefix.bytes[1]);
|
||||
else /* EVEX */
|
||||
return X86_EVEX_M(insn->vex_prefix.bytes[1]);
|
||||
}
|
||||
|
||||
static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
|
||||
{
|
||||
if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
|
||||
return X86_VEX_P(insn->vex_prefix.bytes[1]);
|
||||
else
|
||||
return X86_VEX_P(insn->vex_prefix.bytes[2]);
|
||||
}
|
||||
|
||||
/* Get the last prefix id from last prefix or VEX prefix */
|
||||
static inline int insn_last_prefix_id(struct insn *insn)
|
||||
{
|
||||
if (insn_is_avx(insn))
|
||||
return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
|
||||
|
||||
if (insn->prefixes.bytes[3])
|
||||
return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Offset of each field from kaddr */
|
||||
static inline int insn_offset_rex_prefix(struct insn *insn)
|
||||
{
|
||||
return insn->prefixes.nbytes;
|
||||
}
|
||||
static inline int insn_offset_vex_prefix(struct insn *insn)
|
||||
{
|
||||
return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
|
||||
}
|
||||
static inline int insn_offset_opcode(struct insn *insn)
|
||||
{
|
||||
return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
|
||||
}
|
||||
static inline int insn_offset_modrm(struct insn *insn)
|
||||
{
|
||||
return insn_offset_opcode(insn) + insn->opcode.nbytes;
|
||||
}
|
||||
static inline int insn_offset_sib(struct insn *insn)
|
||||
{
|
||||
return insn_offset_modrm(insn) + insn->modrm.nbytes;
|
||||
}
|
||||
static inline int insn_offset_displacement(struct insn *insn)
|
||||
{
|
||||
return insn_offset_sib(insn) + insn->sib.nbytes;
|
||||
}
|
||||
static inline int insn_offset_immediate(struct insn *insn)
|
||||
{
|
||||
return insn_offset_displacement(insn) + insn->displacement.nbytes;
|
||||
}
|
||||
|
||||
#define POP_SS_OPCODE 0x1f
|
||||
#define MOV_SREG_OPCODE 0x8e
|
||||
|
||||
/*
|
||||
* Intel SDM Vol.3A 6.8.3 states;
|
||||
* "Any single-step trap that would be delivered following the MOV to SS
|
||||
* instruction or POP to SS instruction (because EFLAGS.TF is 1) is
|
||||
* suppressed."
|
||||
* This function returns true if @insn is MOV SS or POP SS. On these
|
||||
* instructions, single stepping is suppressed.
|
||||
*/
|
||||
static inline int insn_masking_exception(struct insn *insn)
|
||||
{
|
||||
return insn->opcode.bytes[0] == POP_SS_OPCODE ||
|
||||
(insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
|
||||
X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_INSN_H */
|
|
@ -1,593 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* x86 instruction analysis
|
||||
*
|
||||
* Copyright (C) IBM Corporation, 2002, 2004, 2009
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/string.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include <asm/inat.h>
|
||||
#include <asm/insn.h>
|
||||
|
||||
/* Verify next sizeof(t) bytes can be on the same instruction */
|
||||
#define validate_next(t, insn, n) \
|
||||
((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
|
||||
|
||||
#define __get_next(t, insn) \
|
||||
({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
|
||||
|
||||
#define __peek_nbyte_next(t, insn, n) \
|
||||
({ t r = *(t*)((insn)->next_byte + n); r; })
|
||||
|
||||
#define get_next(t, insn) \
|
||||
({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
|
||||
|
||||
#define peek_nbyte_next(t, insn, n) \
|
||||
({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
|
||||
|
||||
#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
|
||||
|
||||
/**
|
||||
* insn_init() - initialize struct insn
|
||||
* @insn: &struct insn to be initialized
|
||||
* @kaddr: address (in kernel memory) of instruction (or copy thereof)
|
||||
* @x86_64: !0 for 64-bit kernel or 64-bit app
|
||||
*/
|
||||
void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
|
||||
{
|
||||
/*
|
||||
* Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid
|
||||
* even if the input buffer is long enough to hold them.
|
||||
*/
|
||||
if (buf_len > MAX_INSN_SIZE)
|
||||
buf_len = MAX_INSN_SIZE;
|
||||
|
||||
memset(insn, 0, sizeof(*insn));
|
||||
insn->kaddr = kaddr;
|
||||
insn->end_kaddr = kaddr + buf_len;
|
||||
insn->next_byte = kaddr;
|
||||
insn->x86_64 = x86_64 ? 1 : 0;
|
||||
insn->opnd_bytes = 4;
|
||||
if (x86_64)
|
||||
insn->addr_bytes = 8;
|
||||
else
|
||||
insn->addr_bytes = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_prefixes - scan x86 instruction prefix bytes
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* Populates the @insn->prefixes bitmap, and updates @insn->next_byte
|
||||
* to point to the (first) opcode. No effect if @insn->prefixes.got
|
||||
* is already set.
|
||||
*/
|
||||
void insn_get_prefixes(struct insn *insn)
|
||||
{
|
||||
struct insn_field *prefixes = &insn->prefixes;
|
||||
insn_attr_t attr;
|
||||
insn_byte_t b, lb;
|
||||
int i, nb;
|
||||
|
||||
if (prefixes->got)
|
||||
return;
|
||||
|
||||
nb = 0;
|
||||
lb = 0;
|
||||
b = peek_next(insn_byte_t, insn);
|
||||
attr = inat_get_opcode_attribute(b);
|
||||
while (inat_is_legacy_prefix(attr)) {
|
||||
/* Skip if same prefix */
|
||||
for (i = 0; i < nb; i++)
|
||||
if (prefixes->bytes[i] == b)
|
||||
goto found;
|
||||
if (nb == 4)
|
||||
/* Invalid instruction */
|
||||
break;
|
||||
prefixes->bytes[nb++] = b;
|
||||
if (inat_is_address_size_prefix(attr)) {
|
||||
/* address size switches 2/4 or 4/8 */
|
||||
if (insn->x86_64)
|
||||
insn->addr_bytes ^= 12;
|
||||
else
|
||||
insn->addr_bytes ^= 6;
|
||||
} else if (inat_is_operand_size_prefix(attr)) {
|
||||
/* oprand size switches 2/4 */
|
||||
insn->opnd_bytes ^= 6;
|
||||
}
|
||||
found:
|
||||
prefixes->nbytes++;
|
||||
insn->next_byte++;
|
||||
lb = b;
|
||||
b = peek_next(insn_byte_t, insn);
|
||||
attr = inat_get_opcode_attribute(b);
|
||||
}
|
||||
/* Set the last prefix */
|
||||
if (lb && lb != insn->prefixes.bytes[3]) {
|
||||
if (unlikely(insn->prefixes.bytes[3])) {
|
||||
/* Swap the last prefix */
|
||||
b = insn->prefixes.bytes[3];
|
||||
for (i = 0; i < nb; i++)
|
||||
if (prefixes->bytes[i] == lb)
|
||||
prefixes->bytes[i] = b;
|
||||
}
|
||||
insn->prefixes.bytes[3] = lb;
|
||||
}
|
||||
|
||||
/* Decode REX prefix */
|
||||
if (insn->x86_64) {
|
||||
b = peek_next(insn_byte_t, insn);
|
||||
attr = inat_get_opcode_attribute(b);
|
||||
if (inat_is_rex_prefix(attr)) {
|
||||
insn->rex_prefix.value = b;
|
||||
insn->rex_prefix.nbytes = 1;
|
||||
insn->next_byte++;
|
||||
if (X86_REX_W(b))
|
||||
/* REX.W overrides opnd_size */
|
||||
insn->opnd_bytes = 8;
|
||||
}
|
||||
}
|
||||
insn->rex_prefix.got = 1;
|
||||
|
||||
/* Decode VEX prefix */
|
||||
b = peek_next(insn_byte_t, insn);
|
||||
attr = inat_get_opcode_attribute(b);
|
||||
if (inat_is_vex_prefix(attr)) {
|
||||
insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
|
||||
if (!insn->x86_64) {
|
||||
/*
|
||||
* In 32-bits mode, if the [7:6] bits (mod bits of
|
||||
* ModRM) on the second byte are not 11b, it is
|
||||
* LDS or LES or BOUND.
|
||||
*/
|
||||
if (X86_MODRM_MOD(b2) != 3)
|
||||
goto vex_end;
|
||||
}
|
||||
insn->vex_prefix.bytes[0] = b;
|
||||
insn->vex_prefix.bytes[1] = b2;
|
||||
if (inat_is_evex_prefix(attr)) {
|
||||
b2 = peek_nbyte_next(insn_byte_t, insn, 2);
|
||||
insn->vex_prefix.bytes[2] = b2;
|
||||
b2 = peek_nbyte_next(insn_byte_t, insn, 3);
|
||||
insn->vex_prefix.bytes[3] = b2;
|
||||
insn->vex_prefix.nbytes = 4;
|
||||
insn->next_byte += 4;
|
||||
if (insn->x86_64 && X86_VEX_W(b2))
|
||||
/* VEX.W overrides opnd_size */
|
||||
insn->opnd_bytes = 8;
|
||||
} else if (inat_is_vex3_prefix(attr)) {
|
||||
b2 = peek_nbyte_next(insn_byte_t, insn, 2);
|
||||
insn->vex_prefix.bytes[2] = b2;
|
||||
insn->vex_prefix.nbytes = 3;
|
||||
insn->next_byte += 3;
|
||||
if (insn->x86_64 && X86_VEX_W(b2))
|
||||
/* VEX.W overrides opnd_size */
|
||||
insn->opnd_bytes = 8;
|
||||
} else {
|
||||
/*
|
||||
* For VEX2, fake VEX3-like byte#2.
|
||||
* Makes it easier to decode vex.W, vex.vvvv,
|
||||
* vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.
|
||||
*/
|
||||
insn->vex_prefix.bytes[2] = b2 & 0x7f;
|
||||
insn->vex_prefix.nbytes = 2;
|
||||
insn->next_byte += 2;
|
||||
}
|
||||
}
|
||||
vex_end:
|
||||
insn->vex_prefix.got = 1;
|
||||
|
||||
prefixes->got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_opcode - collect opcode(s)
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* Populates @insn->opcode, updates @insn->next_byte to point past the
|
||||
* opcode byte(s), and set @insn->attr (except for groups).
|
||||
* If necessary, first collects any preceding (prefix) bytes.
|
||||
* Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got
|
||||
* is already 1.
|
||||
*/
|
||||
void insn_get_opcode(struct insn *insn)
|
||||
{
|
||||
struct insn_field *opcode = &insn->opcode;
|
||||
insn_byte_t op;
|
||||
int pfx_id;
|
||||
if (opcode->got)
|
||||
return;
|
||||
if (!insn->prefixes.got)
|
||||
insn_get_prefixes(insn);
|
||||
|
||||
/* Get first opcode */
|
||||
op = get_next(insn_byte_t, insn);
|
||||
opcode->bytes[0] = op;
|
||||
opcode->nbytes = 1;
|
||||
|
||||
/* Check if there is VEX prefix or not */
|
||||
if (insn_is_avx(insn)) {
|
||||
insn_byte_t m, p;
|
||||
m = insn_vex_m_bits(insn);
|
||||
p = insn_vex_p_bits(insn);
|
||||
insn->attr = inat_get_avx_attribute(op, m, p);
|
||||
if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
|
||||
(!inat_accept_vex(insn->attr) &&
|
||||
!inat_is_group(insn->attr)))
|
||||
insn->attr = 0; /* This instruction is bad */
|
||||
goto end; /* VEX has only 1 byte for opcode */
|
||||
}
|
||||
|
||||
insn->attr = inat_get_opcode_attribute(op);
|
||||
while (inat_is_escape(insn->attr)) {
|
||||
/* Get escaped opcode */
|
||||
op = get_next(insn_byte_t, insn);
|
||||
opcode->bytes[opcode->nbytes++] = op;
|
||||
pfx_id = insn_last_prefix_id(insn);
|
||||
insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
|
||||
}
|
||||
if (inat_must_vex(insn->attr))
|
||||
insn->attr = 0; /* This instruction is bad */
|
||||
end:
|
||||
opcode->got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_modrm - collect ModRM byte, if any
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* Populates @insn->modrm and updates @insn->next_byte to point past the
|
||||
* ModRM byte, if any. If necessary, first collects the preceding bytes
|
||||
* (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1.
|
||||
*/
|
||||
void insn_get_modrm(struct insn *insn)
|
||||
{
|
||||
struct insn_field *modrm = &insn->modrm;
|
||||
insn_byte_t pfx_id, mod;
|
||||
if (modrm->got)
|
||||
return;
|
||||
if (!insn->opcode.got)
|
||||
insn_get_opcode(insn);
|
||||
|
||||
if (inat_has_modrm(insn->attr)) {
|
||||
mod = get_next(insn_byte_t, insn);
|
||||
modrm->value = mod;
|
||||
modrm->nbytes = 1;
|
||||
if (inat_is_group(insn->attr)) {
|
||||
pfx_id = insn_last_prefix_id(insn);
|
||||
insn->attr = inat_get_group_attribute(mod, pfx_id,
|
||||
insn->attr);
|
||||
if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
|
||||
insn->attr = 0; /* This is bad */
|
||||
}
|
||||
}
|
||||
|
||||
if (insn->x86_64 && inat_is_force64(insn->attr))
|
||||
insn->opnd_bytes = 8;
|
||||
modrm->got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* insn_rip_relative() - Does instruction use RIP-relative addressing mode?
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* If necessary, first collects the instruction up to and including the
|
||||
* ModRM byte. No effect if @insn->x86_64 is 0.
|
||||
*/
|
||||
int insn_rip_relative(struct insn *insn)
|
||||
{
|
||||
struct insn_field *modrm = &insn->modrm;
|
||||
|
||||
if (!insn->x86_64)
|
||||
return 0;
|
||||
if (!modrm->got)
|
||||
insn_get_modrm(insn);
|
||||
/*
|
||||
* For rip-relative instructions, the mod field (top 2 bits)
|
||||
* is zero and the r/m field (bottom 3 bits) is 0x5.
|
||||
*/
|
||||
return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_sib() - Get the SIB byte of instruction
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* If necessary, first collects the instruction up to and including the
|
||||
* ModRM byte.
|
||||
*/
|
||||
void insn_get_sib(struct insn *insn)
|
||||
{
|
||||
insn_byte_t modrm;
|
||||
|
||||
if (insn->sib.got)
|
||||
return;
|
||||
if (!insn->modrm.got)
|
||||
insn_get_modrm(insn);
|
||||
if (insn->modrm.nbytes) {
|
||||
modrm = (insn_byte_t)insn->modrm.value;
|
||||
if (insn->addr_bytes != 2 &&
|
||||
X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
|
||||
insn->sib.value = get_next(insn_byte_t, insn);
|
||||
insn->sib.nbytes = 1;
|
||||
}
|
||||
}
|
||||
insn->sib.got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* insn_get_displacement() - Get the displacement of instruction
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* If necessary, first collects the instruction up to and including the
|
||||
* SIB byte.
|
||||
* Displacement value is sign-expanded.
|
||||
*/
|
||||
void insn_get_displacement(struct insn *insn)
|
||||
{
|
||||
insn_byte_t mod, rm, base;
|
||||
|
||||
if (insn->displacement.got)
|
||||
return;
|
||||
if (!insn->sib.got)
|
||||
insn_get_sib(insn);
|
||||
if (insn->modrm.nbytes) {
|
||||
/*
|
||||
* Interpreting the modrm byte:
|
||||
* mod = 00 - no displacement fields (exceptions below)
|
||||
* mod = 01 - 1-byte displacement field
|
||||
* mod = 10 - displacement field is 4 bytes, or 2 bytes if
|
||||
* address size = 2 (0x67 prefix in 32-bit mode)
|
||||
* mod = 11 - no memory operand
|
||||
*
|
||||
* If address size = 2...
|
||||
* mod = 00, r/m = 110 - displacement field is 2 bytes
|
||||
*
|
||||
* If address size != 2...
|
||||
* mod != 11, r/m = 100 - SIB byte exists
|
||||
* mod = 00, SIB base = 101 - displacement field is 4 bytes
|
||||
* mod = 00, r/m = 101 - rip-relative addressing, displacement
|
||||
* field is 4 bytes
|
||||
*/
|
||||
mod = X86_MODRM_MOD(insn->modrm.value);
|
||||
rm = X86_MODRM_RM(insn->modrm.value);
|
||||
base = X86_SIB_BASE(insn->sib.value);
|
||||
if (mod == 3)
|
||||
goto out;
|
||||
if (mod == 1) {
|
||||
insn->displacement.value = get_next(signed char, insn);
|
||||
insn->displacement.nbytes = 1;
|
||||
} else if (insn->addr_bytes == 2) {
|
||||
if ((mod == 0 && rm == 6) || mod == 2) {
|
||||
insn->displacement.value =
|
||||
get_next(short, insn);
|
||||
insn->displacement.nbytes = 2;
|
||||
}
|
||||
} else {
|
||||
if ((mod == 0 && rm == 5) || mod == 2 ||
|
||||
(mod == 0 && base == 5)) {
|
||||
insn->displacement.value = get_next(int, insn);
|
||||
insn->displacement.nbytes = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
insn->displacement.got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decode moffset16/32/64. Return 0 if failed */
|
||||
static int __get_moffset(struct insn *insn)
|
||||
{
|
||||
switch (insn->addr_bytes) {
|
||||
case 2:
|
||||
insn->moffset1.value = get_next(short, insn);
|
||||
insn->moffset1.nbytes = 2;
|
||||
break;
|
||||
case 4:
|
||||
insn->moffset1.value = get_next(int, insn);
|
||||
insn->moffset1.nbytes = 4;
|
||||
break;
|
||||
case 8:
|
||||
insn->moffset1.value = get_next(int, insn);
|
||||
insn->moffset1.nbytes = 4;
|
||||
insn->moffset2.value = get_next(int, insn);
|
||||
insn->moffset2.nbytes = 4;
|
||||
break;
|
||||
default: /* opnd_bytes must be modified manually */
|
||||
goto err_out;
|
||||
}
|
||||
insn->moffset1.got = insn->moffset2.got = 1;
|
||||
|
||||
return 1;
|
||||
|
||||
err_out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode imm v32(Iz). Return 0 if failed */
|
||||
static int __get_immv32(struct insn *insn)
|
||||
{
|
||||
switch (insn->opnd_bytes) {
|
||||
case 2:
|
||||
insn->immediate.value = get_next(short, insn);
|
||||
insn->immediate.nbytes = 2;
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
insn->immediate.value = get_next(int, insn);
|
||||
insn->immediate.nbytes = 4;
|
||||
break;
|
||||
default: /* opnd_bytes must be modified manually */
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err_out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode imm v64(Iv/Ov), Return 0 if failed */
|
||||
static int __get_immv(struct insn *insn)
|
||||
{
|
||||
switch (insn->opnd_bytes) {
|
||||
case 2:
|
||||
insn->immediate1.value = get_next(short, insn);
|
||||
insn->immediate1.nbytes = 2;
|
||||
break;
|
||||
case 4:
|
||||
insn->immediate1.value = get_next(int, insn);
|
||||
insn->immediate1.nbytes = 4;
|
||||
break;
|
||||
case 8:
|
||||
insn->immediate1.value = get_next(int, insn);
|
||||
insn->immediate1.nbytes = 4;
|
||||
insn->immediate2.value = get_next(int, insn);
|
||||
insn->immediate2.nbytes = 4;
|
||||
break;
|
||||
default: /* opnd_bytes must be modified manually */
|
||||
goto err_out;
|
||||
}
|
||||
insn->immediate1.got = insn->immediate2.got = 1;
|
||||
|
||||
return 1;
|
||||
err_out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decode ptr16:16/32(Ap) */
|
||||
static int __get_immptr(struct insn *insn)
|
||||
{
|
||||
switch (insn->opnd_bytes) {
|
||||
case 2:
|
||||
insn->immediate1.value = get_next(short, insn);
|
||||
insn->immediate1.nbytes = 2;
|
||||
break;
|
||||
case 4:
|
||||
insn->immediate1.value = get_next(int, insn);
|
||||
insn->immediate1.nbytes = 4;
|
||||
break;
|
||||
case 8:
|
||||
/* ptr16:64 is not exist (no segment) */
|
||||
return 0;
|
||||
default: /* opnd_bytes must be modified manually */
|
||||
goto err_out;
|
||||
}
|
||||
insn->immediate2.value = get_next(unsigned short, insn);
|
||||
insn->immediate2.nbytes = 2;
|
||||
insn->immediate1.got = insn->immediate2.got = 1;
|
||||
|
||||
return 1;
|
||||
err_out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_immediate() - Get the immediates of instruction
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* If necessary, first collects the instruction up to and including the
|
||||
* displacement bytes.
|
||||
* Basically, most of immediates are sign-expanded. Unsigned-value can be
|
||||
* get by bit masking with ((1 << (nbytes * 8)) - 1)
|
||||
*/
|
||||
void insn_get_immediate(struct insn *insn)
|
||||
{
|
||||
if (insn->immediate.got)
|
||||
return;
|
||||
if (!insn->displacement.got)
|
||||
insn_get_displacement(insn);
|
||||
|
||||
if (inat_has_moffset(insn->attr)) {
|
||||
if (!__get_moffset(insn))
|
||||
goto err_out;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!inat_has_immediate(insn->attr))
|
||||
/* no immediates */
|
||||
goto done;
|
||||
|
||||
switch (inat_immediate_size(insn->attr)) {
|
||||
case INAT_IMM_BYTE:
|
||||
insn->immediate.value = get_next(signed char, insn);
|
||||
insn->immediate.nbytes = 1;
|
||||
break;
|
||||
case INAT_IMM_WORD:
|
||||
insn->immediate.value = get_next(short, insn);
|
||||
insn->immediate.nbytes = 2;
|
||||
break;
|
||||
case INAT_IMM_DWORD:
|
||||
insn->immediate.value = get_next(int, insn);
|
||||
insn->immediate.nbytes = 4;
|
||||
break;
|
||||
case INAT_IMM_QWORD:
|
||||
insn->immediate1.value = get_next(int, insn);
|
||||
insn->immediate1.nbytes = 4;
|
||||
insn->immediate2.value = get_next(int, insn);
|
||||
insn->immediate2.nbytes = 4;
|
||||
break;
|
||||
case INAT_IMM_PTR:
|
||||
if (!__get_immptr(insn))
|
||||
goto err_out;
|
||||
break;
|
||||
case INAT_IMM_VWORD32:
|
||||
if (!__get_immv32(insn))
|
||||
goto err_out;
|
||||
break;
|
||||
case INAT_IMM_VWORD:
|
||||
if (!__get_immv(insn))
|
||||
goto err_out;
|
||||
break;
|
||||
default:
|
||||
/* Here, insn must have an immediate, but failed */
|
||||
goto err_out;
|
||||
}
|
||||
if (inat_has_second_immediate(insn->attr)) {
|
||||
insn->immediate2.value = get_next(signed char, insn);
|
||||
insn->immediate2.nbytes = 1;
|
||||
}
|
||||
done:
|
||||
insn->immediate.got = 1;
|
||||
|
||||
err_out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_length() - Get the length of instruction
|
||||
* @insn: &struct insn containing instruction
|
||||
*
|
||||
* If necessary, first collects the instruction up to and including the
|
||||
* immediates bytes.
|
||||
*/
|
||||
void insn_get_length(struct insn *insn)
|
||||
{
|
||||
if (insn->length)
|
||||
return;
|
||||
if (!insn->immediate.got)
|
||||
insn_get_immediate(insn);
|
||||
insn->length = (unsigned char)((unsigned long)insn->next_byte
|
||||
- (unsigned long)insn->kaddr);
|
||||
}
|
|
@ -2,28 +2,50 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
FILES='
|
||||
arch/x86/lib/insn.c
|
||||
arch/x86/lib/inat.c
|
||||
arch/x86/lib/x86-opcode-map.txt
|
||||
arch/x86/tools/gen-insn-attr-x86.awk
|
||||
arch/x86/include/asm/insn.h
|
||||
arch/x86/include/asm/inat.h
|
||||
arch/x86/include/asm/inat_types.h
|
||||
arch/x86/include/asm/orc_types.h
|
||||
arch/x86/lib/x86-opcode-map.txt
|
||||
arch/x86/tools/gen-insn-attr-x86.awk
|
||||
'
|
||||
|
||||
check()
|
||||
{
|
||||
local file=$1
|
||||
check_2 () {
|
||||
file1=$1
|
||||
file2=$2
|
||||
|
||||
diff $file ../../$file > /dev/null ||
|
||||
echo "Warning: synced file at 'tools/objtool/$file' differs from latest kernel version at '$file'"
|
||||
shift
|
||||
shift
|
||||
|
||||
cmd="diff $* $file1 $file2 > /dev/null"
|
||||
|
||||
test -f $file2 && {
|
||||
eval $cmd || {
|
||||
echo "Warning: Kernel ABI header at '$file1' differs from latest version at '$file2'" >&2
|
||||
echo diff -u $file1 $file2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check () {
|
||||
file=$1
|
||||
|
||||
shift
|
||||
|
||||
check_2 tools/$file $file $*
|
||||
}
|
||||
|
||||
if [ ! -d ../../kernel ] || [ ! -d ../../tools ] || [ ! -d ../objtool ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
|
||||
for i in $FILES; do
|
||||
check $i
|
||||
done
|
||||
|
||||
check arch/x86/include/asm/inat.h '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"'
|
||||
check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"'
|
||||
check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"'
|
||||
check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]"'
|
||||
|
||||
cd -
|
||||
|
|
|
@ -34,3 +34,6 @@ arch/*/include/generated/
|
|||
trace/beauty/generated/
|
||||
pmu-events/pmu-events.c
|
||||
pmu-events/jevents
|
||||
feature/
|
||||
fixdep
|
||||
libtraceevent-dynamic-list
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <linux/zalloc.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct arm_annotate {
|
||||
regex_t call_insn,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/zalloc.h>
|
||||
|
||||
#include "../../util/auxtrace.h"
|
||||
#include "../../util/debug.h"
|
||||
#include "../../util/evlist.h"
|
||||
#include "../../util/pmu.h"
|
||||
#include "cs-etm.h"
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
#include <linux/coresight-pmu.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
#include "cs-etm.h"
|
||||
#include "../../util/debug.h"
|
||||
#include "../../util/record.h"
|
||||
#include "../../util/auxtrace.h"
|
||||
#include "../../util/cpumap.h"
|
||||
|
@ -22,9 +24,9 @@
|
|||
#include "../../util/evlist.h"
|
||||
#include "../../util/evsel.h"
|
||||
#include "../../util/pmu.h"
|
||||
#include "../../util/thread_map.h"
|
||||
#include "../../util/cs-etm.h"
|
||||
#include "../../util/util.h"
|
||||
#include "../../util/session.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct arm64_annotate {
|
||||
regex_t call_insn,
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
* Copyright (C) 2015 Naveen N. Rao, IBM Corporation
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "symbol.h"
|
||||
#include "map.h"
|
||||
#include "probe-event.h"
|
||||
#include "probe-file.h"
|
||||
#include "symbol.h" // for the elf__needs_adjust_symbols() prototype
|
||||
#include <stdbool.h>
|
||||
#include <gelf.h>
|
||||
|
||||
#ifdef HAVE_LIBELF_SUPPORT
|
||||
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "common.h"
|
||||
#include "../util/env.h"
|
||||
#include "../util/debug.h"
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#ifndef ARCH_PERF_COMMON_H
|
||||
#define ARCH_PERF_COMMON_H
|
||||
|
||||
#include "../util/env.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
struct perf_env;
|
||||
|
||||
int perf_env__lookup_objdump(struct perf_env *env, const char **path);
|
||||
bool perf_env__single_address_space(struct perf_env *env);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "map_symbol.h"
|
||||
#include "mem-events.h"
|
||||
|
||||
/* PowerPC does not support 'ldlat' parameter. */
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <regex.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
#include "../../perf.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
#include "../../util/debug.h"
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "dso.h"
|
||||
#include "symbol.h"
|
||||
#include "map.h"
|
||||
#include "probe-event.h"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <elfutils/libdwfl.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "../../util/unwind-libdw.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
#include "../../util/event.h"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/types.h>
|
||||
#include "../../../../arch/x86/include/asm/insn.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "tests/tests.h"
|
||||
#include "arch-tests.h"
|
||||
|
||||
#include "intel-pt-decoder/insn.h"
|
||||
#include "intel-pt-decoder/intel-pt-insn-decoder.h"
|
||||
|
||||
struct test_data {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "tests/tests.h"
|
||||
#include "perf.h"
|
||||
#include "cloexec.h"
|
||||
#include "debug.h"
|
||||
#include "evlist.h"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
@ -9,6 +10,7 @@
|
|||
#include <perf/cpumap.h>
|
||||
#include <perf/evlist.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "parse-events.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include "perf.h"
|
||||
#include "perf-sys.h"
|
||||
#include "debug.h"
|
||||
#include "tests/tests.h"
|
||||
#include "cloexec.h"
|
||||
#include "event.h"
|
||||
#include "util.h"
|
||||
#include "arch-tests.h"
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "perf.h"
|
||||
#include "../../../../arch/x86/include/asm/insn.h"
|
||||
#include "archinsn.h"
|
||||
#include "util/intel-pt-decoder/insn.h"
|
||||
#include "machine.h"
|
||||
#include "thread.h"
|
||||
#include "symbol.h"
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
#include "../../perf.h"
|
||||
#include "../../perf-sys.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
#include "../../util/debug.h"
|
||||
#include "../../util/event.h"
|
||||
|
||||
const struct sample_reg sample_reg_masks[] = {
|
||||
SMPL_REG(AX, PERF_REG_X86_AX),
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#include <linux/stddef.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include "../../../perf.h"
|
||||
#include <linux/types.h>
|
||||
#include <asm/barrier.h>
|
||||
#include "../../../util/debug.h"
|
||||
#include "../../../util/tsc.h"
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <sys/time.h>
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
/* For the CLR_() macros */
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "../perf.h"
|
||||
#include "../perf-sys.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "../util/header.h"
|
||||
#include "../util/cloexec.h"
|
||||
|
@ -20,6 +20,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <linux/time64.h>
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
/* For the CLR_() macros */
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../perf.h"
|
||||
#include "../builtin.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "../util/cloexec.h"
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "../perf.h"
|
||||
#include "../util/util.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "../builtin.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
|
||||
* Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
|
||||
*/
|
||||
#include "../perf.h"
|
||||
#include "../util/util.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "../builtin.h"
|
||||
|
|
|
@ -24,15 +24,17 @@
|
|||
#include "util/event.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/parse-events.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/sort.h"
|
||||
#include "util/hist.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/map.h"
|
||||
#include "util/session.h"
|
||||
#include "util/tool.h"
|
||||
#include "util/data.h"
|
||||
#include "arch/common.h"
|
||||
#include "util/block-range.h"
|
||||
#include "util/map_symbol.h"
|
||||
#include "util/branch.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* futex ... Futex performance
|
||||
* epoll ... Event poll performance
|
||||
*/
|
||||
#include "perf.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "builtin.h"
|
||||
#include "bench/bench.h"
|
||||
|
|
|
@ -14,19 +14,20 @@
|
|||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "namespaces.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/header.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/strlist.h"
|
||||
#include "util/build-id.h"
|
||||
#include "util/session.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/time-utils.h"
|
||||
#include "util/util.h"
|
||||
#include "util/probe-file.h"
|
||||
#include <linux/string.h>
|
||||
|
||||
static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* builtin-buildid-list.c
|
||||
*
|
||||
|
@ -11,8 +10,9 @@
|
|||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "util/build-id.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/session.h"
|
||||
#include "util/symbol.h"
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include <sys/param.h>
|
||||
#include "debug.h"
|
||||
#include "builtin.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "map_symbol.h"
|
||||
#include "mem-events.h"
|
||||
#include "session.h"
|
||||
#include "hist.h"
|
||||
|
@ -35,6 +37,9 @@
|
|||
#include "thread.h"
|
||||
#include "mem2node.h"
|
||||
#include "symbol.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui/progress.h"
|
||||
#include "../perf.h"
|
||||
|
||||
struct c2c_hists {
|
||||
struct hists hists;
|
||||
|
@ -1107,7 +1112,7 @@ node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
|
|||
break;
|
||||
case 1:
|
||||
{
|
||||
int num = bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt);
|
||||
int num = bitmap_weight(set, c2c.cpus_cnt);
|
||||
struct c2c_stats *stats = &c2c_he->node_stats[node];
|
||||
|
||||
ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
*/
|
||||
#include "builtin.h"
|
||||
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/cache.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/util.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/config.h"
|
||||
#include <linux/string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool use_system_config, use_user_config;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/compiler.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "debug.h"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* DSOs and symbol information, sort them and produce a diff.
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/debug.h"
|
||||
#include "util/event.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "util/annotate.h"
|
||||
#include "util/map.h"
|
||||
#include <linux/zalloc.h>
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
|
|
@ -6,16 +6,18 @@
|
|||
*/
|
||||
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include <api/fs/tracing_path.h>
|
||||
#include "evlist.h"
|
||||
|
@ -25,7 +27,6 @@
|
|||
#include "util/cap.h"
|
||||
#include "util/config.h"
|
||||
|
||||
|
||||
#define DEFAULT_TRACER "function_graph"
|
||||
|
||||
struct perf_ftrace {
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
*
|
||||
* Builtin help command
|
||||
*/
|
||||
#include "perf.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/config.h"
|
||||
#include "util/strbuf.h"
|
||||
#include "builtin.h"
|
||||
#include <subcmd/exec-cmd.h>
|
||||
#include "common-cmds.h"
|
||||
|
@ -14,10 +15,12 @@
|
|||
#include <subcmd/help.h>
|
||||
#include "util/debug.h"
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
*/
|
||||
#include "builtin.h"
|
||||
|
||||
#include "perf.h"
|
||||
#include "util/color.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/map.h"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "debug.h"
|
||||
#include "dso.h"
|
||||
#include "machine.h"
|
||||
#include "map.h"
|
||||
#include "symbol.h"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/dso.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/config.h"
|
||||
|
@ -14,6 +15,7 @@
|
|||
#include "util/callchain.h"
|
||||
#include "util/time-utils.h"
|
||||
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/trace-event.h"
|
||||
#include "util/data.h"
|
||||
|
@ -749,7 +751,8 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
|
|||
}
|
||||
|
||||
trace_seq_init(&seq);
|
||||
tep_event_info(&seq, evsel->tp_format, &record);
|
||||
tep_print_event(evsel->tp_format->tep,
|
||||
&seq, &record, "%s", TEP_PRINT_INFO);
|
||||
|
||||
str = strtok_r(seq.buffer, " ", &pos);
|
||||
while (str) {
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/build-id.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/term.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/header.h"
|
||||
#include "util/session.h"
|
||||
#include "util/intlist.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/trace-event.h"
|
||||
#include "util/debug.h"
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include "util/top.h"
|
||||
#include "util/data.h"
|
||||
#include "util/ordered-events.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
|
@ -30,6 +32,7 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -10,14 +10,13 @@
|
|||
*/
|
||||
#include "builtin.h"
|
||||
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/parse-events.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/pmu.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/metricgroup.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool desc_flag = true;
|
||||
static bool details_flag;
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/evlist.h"
|
||||
#include "util/evlist.h" // for struct evsel_str_handler
|
||||
#include "util/evsel.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/header.h"
|
||||
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/trace-event.h"
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include "util/tool.h"
|
||||
#include "util/session.h"
|
||||
#include "util/data.h"
|
||||
#include "util/map_symbol.h"
|
||||
#include "util/mem-events.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
|
||||
|
|
|
@ -16,17 +16,18 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "perf.h"
|
||||
#include "builtin.h"
|
||||
#include "namespaces.h"
|
||||
#include "util/build-id.h"
|
||||
#include "util/strlist.h"
|
||||
#include "util/strfilter.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/symbol_conf.h"
|
||||
#include "util/debug.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/probe-finder.h"
|
||||
#include "util/probe-event.h"
|
||||
#include "util/probe-file.h"
|
||||
#include <linux/string.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "util/units.h"
|
||||
#include "util/bpf-event.h"
|
||||
#include "asm/bug.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -52,6 +53,7 @@
|
|||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
|
|
|
@ -12,12 +12,16 @@
|
|||
|
||||
#include "util/annotate.h"
|
||||
#include "util/color.h"
|
||||
#include "util/dso.h"
|
||||
#include <linux/list.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/map_symbol.h"
|
||||
#include "util/mem-events.h"
|
||||
#include "util/branch.h"
|
||||
#include "util/callchain.h"
|
||||
#include "util/values.h"
|
||||
|
||||
|
@ -45,6 +49,8 @@
|
|||
#include "util/units.h"
|
||||
#include "util/branch.h"
|
||||
#include "util/util.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui/progress.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
@ -53,6 +59,7 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <signal.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/time64.h>
|
||||
#include <sys/types.h>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "perf-sys.h"
|
||||
|
||||
#include "util/evlist.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/thread.h"
|
||||
|
@ -18,6 +18,7 @@
|
|||
#include "util/callchain.h"
|
||||
#include "util/time-utils.h"
|
||||
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/trace-event.h"
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "builtin.h"
|
||||
|
||||
#include "util/cache.h"
|
||||
#include "util/counts.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include <subcmd/exec-cmd.h>
|
||||
#include "util/header.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include "util/thread-stack.h"
|
||||
#include "util/time-utils.h"
|
||||
#include "util/path.h"
|
||||
#include "ui/ui.h"
|
||||
#include "print_binary.h"
|
||||
#include "archinsn.h"
|
||||
#include <linux/bitmap.h>
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include <perf/evlist.h>
|
||||
#include "util/record.h"
|
||||
#include "util/util.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include <linux/ctype.h>
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
*/
|
||||
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "util/cgroup.h"
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/parse-events.h"
|
||||
|
@ -53,7 +54,6 @@
|
|||
#include "util/stat.h"
|
||||
#include "util/header.h"
|
||||
#include "util/cpumap.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/thread_map.h"
|
||||
#include "util/counts.h"
|
||||
#include "util/group.h"
|
||||
|
@ -62,6 +62,7 @@
|
|||
#include "util/string2.h"
|
||||
#include "util/metricgroup.h"
|
||||
#include "util/target.h"
|
||||
#include "util/time-utils.h"
|
||||
#include "util/top.h"
|
||||
#include "asm/bug.h"
|
||||
|
||||
|
|
|
@ -10,13 +10,11 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <traceevent/event-parse.h>
|
||||
|
||||
#include "builtin.h"
|
||||
#include "util/color.h"
|
||||
#include <linux/list.h>
|
||||
#include "util/cache.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/evlist.h" // for struct evsel_str_handler
|
||||
#include "util/evsel.h"
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
@ -28,6 +26,7 @@
|
|||
|
||||
#include "perf.h"
|
||||
#include "util/header.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/parse-events.h"
|
||||
#include "util/event.h"
|
||||
|
@ -1518,10 +1517,7 @@ static int process_header(struct perf_file_section *section __maybe_unused,
|
|||
if (!tchart->topology)
|
||||
break;
|
||||
|
||||
if (svg_build_topology_map(ph->env.sibling_cores,
|
||||
ph->env.nr_sibling_cores,
|
||||
ph->env.sibling_threads,
|
||||
ph->env.nr_sibling_threads))
|
||||
if (svg_build_topology_map(&ph->env))
|
||||
fprintf(stderr, "problem building topology\n");
|
||||
break;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "util/bpf-event.h"
|
||||
#include "util/config.h"
|
||||
#include "util/color.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/event.h"
|
||||
|
@ -31,13 +32,12 @@
|
|||
#include "util/map.h"
|
||||
#include "util/session.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/thread_map.h"
|
||||
#include "util/top.h"
|
||||
#include "util/util.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
#include "util/parse-events.h"
|
||||
#include "util/callchain.h"
|
||||
#include "util/cpumap.h"
|
||||
#include "util/sort.h"
|
||||
#include "util/string2.h"
|
||||
|
@ -45,6 +45,7 @@
|
|||
#include "util/intlist.h"
|
||||
#include "util/parse-branch-options.h"
|
||||
#include "arch/common.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include "util/debug.h"
|
||||
#include "util/ordered-events.h"
|
||||
|
|
|
@ -25,10 +25,12 @@
|
|||
#include "util/color.h"
|
||||
#include "util/config.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/env.h"
|
||||
#include "util/event.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/evswitch.h"
|
||||
#include <subcmd/pager.h>
|
||||
#include <subcmd/exec-cmd.h>
|
||||
#include "util/machine.h"
|
||||
#include "util/map.h"
|
||||
|
@ -41,6 +43,7 @@
|
|||
#include "util/intlist.h"
|
||||
#include "util/thread_map.h"
|
||||
#include "util/stat.h"
|
||||
#include "util/tool.h"
|
||||
#include "util/util.h"
|
||||
#include "trace/beauty/beauty.h"
|
||||
#include "trace-event.h"
|
||||
|
@ -51,6 +54,7 @@
|
|||
#include "string2.h"
|
||||
#include "syscalltbl.h"
|
||||
#include "rb_resort.h"
|
||||
#include "../perf.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "color.h"
|
||||
#include <linux/compiler.h>
|
||||
#include <tools/config.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <subcmd/parse-options.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
HEADERS='
|
||||
FILES='
|
||||
include/uapi/linux/const.h
|
||||
include/uapi/drm/drm.h
|
||||
include/uapi/drm/i915_drm.h
|
||||
|
@ -26,7 +26,10 @@ include/uapi/linux/hw_breakpoint.h
|
|||
arch/x86/include/asm/disabled-features.h
|
||||
arch/x86/include/asm/required-features.h
|
||||
arch/x86/include/asm/cpufeatures.h
|
||||
arch/x86/include/asm/inat_types.h
|
||||
arch/x86/include/uapi/asm/prctl.h
|
||||
arch/x86/lib/x86-opcode-map.txt
|
||||
arch/x86/tools/gen-insn-attr-x86.awk
|
||||
arch/arm/include/uapi/asm/perf_regs.h
|
||||
arch/arm64/include/uapi/asm/perf_regs.h
|
||||
arch/powerpc/include/uapi/asm/perf_regs.h
|
||||
|
@ -98,7 +101,7 @@ test -d ../../include || exit 0
|
|||
cd ../..
|
||||
|
||||
# simple diff check
|
||||
for i in $HEADERS; do
|
||||
for i in $FILES; do
|
||||
check $i -B
|
||||
done
|
||||
|
||||
|
@ -109,6 +112,10 @@ check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman
|
|||
check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"'
|
||||
check include/linux/ctype.h '-I "isdigit("'
|
||||
check lib/ctype.c '-I "^EXPORT_SYMBOL" -I "^#include <linux/export.h>" -B'
|
||||
check arch/x86/include/asm/inat.h '-I "^#include [\"<]\(asm/\)*inat_types.h[\">]"'
|
||||
check arch/x86/include/asm/insn.h '-I "^#include [\"<]\(asm/\)*inat.h[\">]"'
|
||||
check arch/x86/lib/inat.c '-I "^#include [\"<]\(../include/\)*asm/insn.h[\">]"'
|
||||
check arch/x86/lib/insn.c '-I "^#include [\"<]\(../include/\)*asm/in\(at\|sn\).h[\">]"'
|
||||
|
||||
# diff non-symmetric files
|
||||
check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
|
||||
|
|
|
@ -100,6 +100,9 @@ struct perf_cpu_map *perf_cpu_map__read(FILE *file)
|
|||
if (prev >= 0) {
|
||||
int new_max = nr_cpus + cpu - prev - 1;
|
||||
|
||||
WARN_ONCE(new_max >= MAX_NR_CPUS, "Perf can support %d CPUs. "
|
||||
"Consider raising MAX_NR_CPUS\n", MAX_NR_CPUS);
|
||||
|
||||
if (new_max >= max_entries) {
|
||||
max_entries = new_max + MAX_NR_CPUS / 2;
|
||||
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
|
||||
|
@ -192,6 +195,9 @@ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
|
|||
end_cpu = start_cpu;
|
||||
}
|
||||
|
||||
WARN_ONCE(end_cpu >= MAX_NR_CPUS, "Perf can support %d CPUs. "
|
||||
"Consider raising MAX_NR_CPUS\n", MAX_NR_CPUS);
|
||||
|
||||
for (; start_cpu <= end_cpu; start_cpu++) {
|
||||
/* check for duplicates */
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
|
|
|
@ -5,54 +5,17 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/barrier.h>
|
||||
|
||||
#ifdef __powerpc__
|
||||
#define CPUINFO_PROC {"cpu"}
|
||||
#endif
|
||||
struct perf_event_attr;
|
||||
|
||||
#ifdef __s390__
|
||||
#define CPUINFO_PROC {"vendor_id"}
|
||||
#endif
|
||||
extern bool test_attr__enabled;
|
||||
void test_attr__ready(void);
|
||||
void test_attr__init(void);
|
||||
void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
|
||||
int fd, int group_fd, unsigned long flags);
|
||||
|
||||
#ifdef __sh__
|
||||
#define CPUINFO_PROC {"cpu type"}
|
||||
#endif
|
||||
|
||||
#ifdef __hppa__
|
||||
#define CPUINFO_PROC {"cpu"}
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
#define CPUINFO_PROC {"cpu"}
|
||||
#endif
|
||||
|
||||
#ifdef __alpha__
|
||||
#define CPUINFO_PROC {"cpu model"}
|
||||
#endif
|
||||
|
||||
#ifdef __arm__
|
||||
#define CPUINFO_PROC {"model name", "Processor"}
|
||||
#endif
|
||||
|
||||
#ifdef __mips__
|
||||
#define CPUINFO_PROC {"cpu model"}
|
||||
#endif
|
||||
|
||||
#ifdef __arc__
|
||||
#define CPUINFO_PROC {"Processor"}
|
||||
#endif
|
||||
|
||||
#ifdef __xtensa__
|
||||
#define CPUINFO_PROC {"core ID"}
|
||||
#endif
|
||||
|
||||
#ifndef CPUINFO_PROC
|
||||
#define CPUINFO_PROC { "model name", }
|
||||
#endif
|
||||
#define HAVE_ATTR_TEST
|
||||
|
||||
static inline int
|
||||
sys_perf_event_open(struct perf_event_attr *attr,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* perf.c
|
||||
*
|
||||
|
@ -8,7 +7,10 @@
|
|||
* perf top, perf record, perf report, etc.) are started.
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
|
||||
#include "util/build-id.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/env.h"
|
||||
#include <subcmd/exec-cmd.h>
|
||||
#include "util/config.h"
|
||||
|
@ -19,6 +21,8 @@
|
|||
#include "util/debug.h"
|
||||
#include "util/event.h"
|
||||
#include "util/util.h"
|
||||
#include "ui/ui.h"
|
||||
#include "perf-sys.h"
|
||||
#include <api/fs/fs.h>
|
||||
#include <api/fs/tracing_path.h>
|
||||
#include <errno.h>
|
||||
|
@ -30,6 +34,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
const char perf_usage_string[] =
|
||||
|
|
|
@ -2,28 +2,7 @@
|
|||
#ifndef _PERF_PERF_H
|
||||
#define _PERF_PERF_H
|
||||
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
extern bool test_attr__enabled;
|
||||
void test_attr__ready(void);
|
||||
void test_attr__init(void);
|
||||
void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
|
||||
int fd, int group_fd, unsigned long flags);
|
||||
|
||||
#define HAVE_ATTR_TEST
|
||||
#include "perf-sys.h"
|
||||
|
||||
static inline unsigned long long rdclock(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
||||
}
|
||||
|
||||
#ifndef MAX_NR_CPUS
|
||||
#define MAX_NR_CPUS 2048
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
#include "../../../perf.h"
|
||||
#include "../../../util/trace-event.h"
|
||||
|
||||
#ifndef PERL_UNUSED_VAR
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "../../../perf.h"
|
||||
#include "../../../util/trace-event.h"
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
|
|
@ -30,8 +30,9 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "../perf.h"
|
||||
#include "../perf-sys.h"
|
||||
#include <subcmd/exec-cmd.h>
|
||||
#include "event.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define ENV "PERF_TEST_ATTR"
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#include "record.h"
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "parse-events.h"
|
||||
#include <errno.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define NR_ITERS 111
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "perf.h"
|
||||
#include "event.h"
|
||||
#include "../perf-sys.h"
|
||||
#include "cloexec.h"
|
||||
|
||||
volatile long the_var;
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "perf.h"
|
||||
#include "event.h"
|
||||
#include "perf-sys.h"
|
||||
#include "cloexec.h"
|
||||
|
||||
static int fd1;
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "perf.h"
|
||||
#include "event.h"
|
||||
#include "../perf-sys.h"
|
||||
#include "cloexec.h"
|
||||
|
||||
static int overflows;
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
#include <linux/bpf.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <api/fs/fs.h>
|
||||
#include <bpf/bpf.h>
|
||||
#include "tests.h"
|
||||
#include "llvm.h"
|
||||
#include "debug.h"
|
||||
#include "parse-events.h"
|
||||
#define NR_ITERS 111
|
||||
#define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test"
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
#include <perf/cpumap.h>
|
||||
#include <perf/evlist.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dso.h"
|
||||
#include "env.h"
|
||||
#include "parse-events.h"
|
||||
#include "trace-event.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
#include "thread_map.h"
|
||||
|
@ -494,6 +498,10 @@ static void fs_something(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __s390x__
|
||||
#include "header.h" // for get_cpuid()
|
||||
#endif
|
||||
|
||||
static const char *do_determine_event(bool excl_kernel)
|
||||
{
|
||||
const char *event = excl_kernel ? "cycles:u" : "cycles";
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <api/fs/fs.h>
|
||||
#include "dso.h"
|
||||
#include "util.h"
|
||||
#include "machine.h"
|
||||
#include "symbol.h"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/string.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
@ -10,6 +11,7 @@
|
|||
#include "evsel.h"
|
||||
#include "util.h"
|
||||
#include "debug.h"
|
||||
#include "parse-events.h"
|
||||
#include "thread_map.h"
|
||||
#include "target.h"
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/compiler.h>
|
||||
#include <perf/cpumap.h>
|
||||
#include <string.h>
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
#include "header.h"
|
||||
#include "machine.h"
|
||||
#include "tool.h"
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "util/expr.h"
|
||||
#include "tests.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/zalloc.h>
|
||||
|
||||
static int test(struct parse_ctx *ctx, const char *e, double val2)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <inttypes.h>
|
||||
#include "perf.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
#include "util/sort.h"
|
||||
#include "util/evsel.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/machine.h"
|
||||
#include "util/thread.h"
|
||||
#include "tests/hists_common.h"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "perf.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/event.h"
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "perf.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
|
@ -8,7 +7,6 @@
|
|||
#include "util/event.h"
|
||||
#include "util/evlist.h"
|
||||
#include "util/machine.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "tests/tests.h"
|
||||
#include "tests/hists_common.h"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "perf.h"
|
||||
#include "tests.h"
|
||||
#include "debug.h"
|
||||
#include "symbol.h"
|
||||
|
@ -7,7 +6,6 @@
|
|||
#include "evsel.h"
|
||||
#include "evlist.h"
|
||||
#include "machine.h"
|
||||
#include "thread.h"
|
||||
#include "parse-events.h"
|
||||
#include "hists_common.h"
|
||||
#include <errno.h>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "perf.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/dso.h"
|
||||
#include "util/event.h"
|
||||
#include "util/map.h"
|
||||
#include "util/symbol.h"
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/types.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <perf/cpumap.h>
|
||||
#include <perf/evlist.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "parse-events.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue