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:
Ingo Molnar 2019-09-02 09:12:40 +02:00
commit 2c58167877
267 changed files with 1331 additions and 3590 deletions

View File

@ -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"

View File

@ -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) \

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 -

View File

@ -34,3 +34,6 @@ arch/*/include/generated/
trace/beauty/generated/
pmu-events/pmu-events.c
pmu-events/jevents
feature/
fixdep
libtraceevent-dynamic-list

View File

@ -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,

View File

@ -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"

View File

@ -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>

View File

@ -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,

View File

@ -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)

View File

@ -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"

View File

@ -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);

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "map_symbol.h"
#include "mem-events.h"
/* PowerPC does not support 'ldlat' parameter. */

View File

@ -4,7 +4,6 @@
#include <regex.h>
#include <linux/zalloc.h>
#include "../../perf.h"
#include "../../util/perf_regs.h"
#include "../../util/debug.h"

View File

@ -5,6 +5,7 @@
*/
#include "debug.h"
#include "dso.h"
#include "symbol.h"
#include "map.h"
#include "probe-event.h"

View File

@ -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"

View File

@ -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>

View File

@ -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 {

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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),

View File

@ -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"

View File

@ -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>

View File

@ -63,6 +63,7 @@
/* For the CLR_() macros */
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>

View File

@ -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>

View File

@ -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"

View File

@ -10,7 +10,6 @@
*
*/
#include "../perf.h"
#include "../util/util.h"
#include <subcmd/parse-options.h>
#include "../builtin.h"

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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)
{

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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>

View File

@ -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 {

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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) {

View File

@ -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>

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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_*"

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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++)

View File

@ -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,

View File

@ -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[] =

View File

@ -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

View File

@ -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

View File

@ -6,7 +6,6 @@
*/
#include <Python.h>
#include "../../../perf.h"
#include "../../../util/trace-event.h"
#if PY_MAJOR_VERSION < 3

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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>

View File

@ -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";

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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