perf tools: decoding capailitity for CoreSight traces

Added user space perf functionality for CoreSight trace decoding.
This commit is contained in:
tor-jeremiassen 2016-02-09 10:34:51 -06:00 committed by Mathieu Poirier
parent 56139d02e2
commit 1265cc36fb
15 changed files with 2237 additions and 9 deletions

View file

@ -77,6 +77,9 @@ include config/utilities.mak
# Define NO_AUXTRACE if you do not want AUX area tracing support
#
# Define NO_LIBBPF if you do not want BPF support
#
# Define NO_CSTRACE if you do not want CoreSight trace decoding support
#
# As per kernel Makefile, avoid funny character set dependencies
unexport LC_ALL

View file

@ -92,7 +92,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_ADDR |
PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD,

View file

@ -433,6 +433,24 @@ endif
grep-libs = $(filter -l%,$(1))
strip-libs = $(filter-out -l%,$(1))
ifdef CSTRACE_PATH
ifeq (${IS_64_BIT}, 1)
CSTRACE_LNX = linux64
else
CSTRACE_LNX = linux
endif
ifdef DEBUG
LIBCSTRACE = -lcstraced_c_api -lcstraced
CSTRACE_LIB_PATH = $(CSTRACE_PATH)/lib/$(CSTRACE_LNX)/dbg
else
LIBCSTRACE = -lcstrace_c_api -lcstrace
CSTRACE_LIB_PATH = $(CSTRACE_PATH)/lib/$(CSTRACE_LNX)/rel
endif
$(call detected,CSTRACE)
$(call detected_var,CSTRACE_PATH)
EXTLIBS += -L$(CSTRACE_LIB_PATH) $(LIBCSTRACE) -lstdc++
endif
ifdef NO_LIBPERL
CFLAGS += -DNO_LIBPERL
else

View file

@ -84,6 +84,8 @@ libperf-$(CONFIG_AUXTRACE) += auxtrace.o
libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
libperf-$(CONFIG_AUXTRACE) += intel-pt.o
libperf-$(CONFIG_AUXTRACE) += intel-bts.o
libperf-$(CONFIG_AUXTRACE) += cs-etm.o
libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder/
libperf-y += parse-branch-options.o
libperf-y += parse-regs-options.o

View file

@ -49,6 +49,7 @@
#include "intel-pt.h"
#include "intel-bts.h"
#include "cs-etm.h"
int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
struct auxtrace_mmap_params *mp,
@ -893,6 +894,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
case PERF_AUXTRACE_INTEL_BTS:
return intel_bts_process_auxtrace_info(event, session);
case PERF_AUXTRACE_CS_ETM:
return cs_etm__process_auxtrace_info(event, session);
case PERF_AUXTRACE_UNKNOWN:
default:
return -EINVAL;

View file

@ -145,7 +145,7 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
return ret;
}
static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
{
char *tmp = bf;
int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,

View file

@ -11,6 +11,7 @@
extern struct perf_tool build_id__mark_dso_hit_ops;
struct dso;
char *build_id__filename(const char *sbuild_id, char *bf, size_t size);
int build_id__sprintf(const u8 *build_id, int len, char *bf);
int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
int filename__sprintf_build_id(const char *pathname, char *sbuild_id);

View file

@ -0,0 +1,7 @@
ifeq ($(CSTRACE_PATH),)
libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder-stub.o
else
CFLAGS_cs-etm-decoder.o += -I$(CSTRACE_PATH)/include
libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder.o
endif

View file

@ -0,0 +1,91 @@
/*
*
* Copyright(C) 2015 Linaro Limited. All rights reserved.
* Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU GEneral Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "cs-etm-decoder.h"
#include "../util.h"
struct cs_etm_decoder
{
void *state;
int dummy;
};
int cs_etm_decoder__flush(struct cs_etm_decoder *decoder)
{
(void) decoder;
return -1;
}
int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *decoder, uint64_t offset, uint64_t address, uint64_t len, const char *fname)
{
(void) decoder;
(void) offset;
(void) address;
(void) len;
(void) fname;
return -1;
}
const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
uint64_t indx,
const uint8_t *buf,
size_t len,
size_t *consumed)
{
(void) decoder;
(void) indx;
(void) buf;
(void) len;
(void) consumed;
return NULL;
}
int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, uint64_t address, uint64_t len, cs_etm_mem_cb_type cb_func)
{
(void) decoder;
(void) address;
(void) len;
(void) cb_func;
return -1;
}
int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
struct cs_etm_packet *packet)
{
(void) decoder;
(void) packet;
return -1;
}
struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params t_params[])
{
(void) num_cpu;
(void) d_params;
(void) t_params;
return NULL;
}
void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
{
(void) decoder;
return;
}

View file

@ -0,0 +1,488 @@
/*
*
* Copyright(C) 2015 Linaro Limited. All rights reserved.
* Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU GEneral Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "cs-etm-decoder.h"
#include "../util.h"
#include "c_api/rctdl_c_api.h"
#include "rctdl_if_types.h"
#include "etmv4/trc_pkt_types_etmv4.h"
#define MAX_BUFFER 1024
struct cs_etm_decoder
{
struct cs_etm_state state;
dcd_tree_handle_t dcd_tree;
void (*packet_printer)(const char *);
cs_etm_mem_cb_type mem_access;
rctdl_datapath_resp_t prev_return;
size_t prev_processed;
bool trace_on;
bool discontinuity;
struct cs_etm_packet packet_buffer[MAX_BUFFER];
uint32_t packet_count;
uint32_t head;
uint32_t tail;
uint32_t end_tail;
};
static uint32_t cs_etm_decoder__mem_access(const void *context,
const rctdl_vaddr_t address,
const rctdl_mem_space_acc_t mem_space,
const uint32_t req_size,
uint8_t *buffer)
{
struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
(void) mem_space;
return decoder->mem_access(decoder->state.data,address,req_size,buffer);
}
static int cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
rctdl_etmv4_cfg *config)
{
config->reg_configr = params->reg_configr;
config->reg_traceidr = params->reg_traceidr;
config->reg_idr0 = params->reg_idr0;
config->reg_idr1 = params->reg_idr1;
config->reg_idr2 = params->reg_idr2;
config->reg_idr8 = params->reg_idr8;
config->reg_idr9 = 0;
config->reg_idr10 = 0;
config->reg_idr11 = 0;
config->reg_idr12 = 0;
config->reg_idr13 = 0;
config->arch_ver = ARCH_V8;
config->core_prof = profile_CortexA;
return 0;
}
static int cs_etm_decoder__flush_packet(struct cs_etm_decoder *decoder)
{
int err = 0;
if (decoder == NULL) return -1;
if (decoder->packet_count >= 31) return -1;
if (decoder->tail != decoder->end_tail) {
decoder->tail = (decoder->tail + 1) & (MAX_BUFFER - 1);
decoder->packet_count++;
}
return err;
}
int cs_etm_decoder__flush(struct cs_etm_decoder *decoder)
{
return cs_etm_decoder__flush_packet(decoder);
}
static int cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, const rctdl_generic_trace_elem *elem, enum cs_etm_sample_type sample_type)
{
int err = 0;
uint32_t et = 0;
if (decoder == NULL) return -1;
if (decoder->packet_count >= 31) return -1;
err = cs_etm_decoder__flush_packet(decoder);
if (err) return err;
et = decoder->end_tail;
decoder->packet_buffer[et].sample_type = sample_type;
decoder->packet_buffer[et].start_addr = elem->st_addr;
decoder->packet_buffer[et].end_addr = elem->en_addr;
decoder->packet_buffer[et].exc = false;
decoder->packet_buffer[et].exc_ret = false;
et = (et + 1) & (MAX_BUFFER - 1);
decoder->end_tail = et;
return err;
}
static int cs_etm_decoder__mark_exception(struct cs_etm_decoder *decoder)
{
int err = 0;
if (decoder == NULL) return -1;
decoder->packet_buffer[decoder->end_tail].exc = true;
return err;
}
static int cs_etm_decoder__mark_exception_return(struct cs_etm_decoder *decoder)
{
int err = 0;
if (decoder == NULL) return -1;
decoder->packet_buffer[decoder->end_tail].exc_ret = true;
return err;
}
static rctdl_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
const void *context,
const rctdl_trc_index_t indx,
const uint8_t trace_chan_id,
const rctdl_generic_trace_elem *elem)
{
rctdl_datapath_resp_t resp = RCTDL_RESP_CONT;
struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
(void) indx;
(void) trace_chan_id;
switch (elem->elem_type) {
case RCTDL_GEN_TRC_ELEM_UNKNOWN:
break;
case RCTDL_GEN_TRC_ELEM_NO_SYNC:
decoder->trace_on = false;
break;
case RCTDL_GEN_TRC_ELEM_TRACE_ON:
decoder->trace_on = true;
break;
//case RCTDL_GEN_TRC_ELEM_TRACE_OVERFLOW:
//decoder->trace_on = false;
//decoder->discontinuity = true;
//break;
case RCTDL_GEN_TRC_ELEM_INSTR_RANGE:
cs_etm_decoder__buffer_packet(decoder,elem, CS_ETM_RANGE);
resp = RCTDL_RESP_WAIT;
break;
case RCTDL_GEN_TRC_ELEM_EXCEPTION:
cs_etm_decoder__mark_exception(decoder);
break;
case RCTDL_GEN_TRC_ELEM_EXCEPTION_RET:
cs_etm_decoder__mark_exception_return(decoder);
break;
case RCTDL_GEN_TRC_ELEM_PE_CONTEXT:
case RCTDL_GEN_TRC_ELEM_EO_TRACE:
case RCTDL_GEN_TRC_ELEM_ADDR_NACC:
case RCTDL_GEN_TRC_ELEM_TIMESTAMP:
case RCTDL_GEN_TRC_ELEM_CYCLE_COUNT:
//case RCTDL_GEN_TRC_ELEM_TS_WITH_CC:
case RCTDL_GEN_TRC_ELEM_EVENT:
default:
break;
}
decoder->state.err = 0;
return resp;
}
static rctdl_datapath_resp_t cs_etm_decoder__etmv4i_packet_printer(
const void *context,
const rctdl_datapath_op_t op,
const rctdl_trc_index_t indx,
const rctdl_etmv4_i_pkt *pkt)
{
const size_t PACKET_STR_LEN = 1024;
rctdl_datapath_resp_t ret = RCTDL_RESP_CONT;
char packet_str[PACKET_STR_LEN];
size_t offset;
struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
sprintf(packet_str,"%ld: ", (long int) indx);
offset = strlen(packet_str);
switch(op) {
case RCTDL_OP_DATA:
if (rctdl_pkt_str(RCTDL_PROTOCOL_ETMV4I,
(void *)pkt,
packet_str+offset,
PACKET_STR_LEN-offset) != RCTDL_OK)
ret = RCTDL_RESP_FATAL_INVALID_PARAM;
break;
case RCTDL_OP_EOT:
sprintf(packet_str,"**** END OF TRACE ****\n");
break;
case RCTDL_OP_FLUSH:
case RCTDL_OP_RESET:
default:
break;
}
decoder->packet_printer(packet_str);
return ret;
}
static int cs_etm_decoder__create_etmv4i_packet_printer(struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params *t_params,
struct cs_etm_decoder *decoder)
{
rctdl_etmv4_cfg trace_config;
int ret = 0;
if (d_params->packet_printer == NULL)
return -1;
ret = cs_etm_decoder__gen_etmv4_config(t_params,&trace_config);
if (ret != 0)
return -1;
decoder->packet_printer = d_params->packet_printer;
ret = rctdl_dt_create_etmv4i_pkt_proc(decoder->dcd_tree,
&trace_config,
cs_etm_decoder__etmv4i_packet_printer,
decoder);
return ret;
}
static int cs_etm_decoder__create_etmv4i_packet_decoder(struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params *t_params,
struct cs_etm_decoder *decoder)
{
rctdl_etmv4_cfg trace_config;
int ret = 0;
decoder->packet_printer = d_params->packet_printer;
ret = cs_etm_decoder__gen_etmv4_config(t_params,&trace_config);
if (ret != 0)
return -1;
ret = rctdl_dt_create_etmv4i_decoder(decoder->dcd_tree,&trace_config);
if (ret != RCTDL_OK)
return -1;
ret = rctdl_dt_set_gen_elem_outfn(decoder->dcd_tree,
cs_etm_decoder__gen_trace_elem_printer, decoder);
return ret;
}
int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, uint64_t address, uint64_t len, cs_etm_mem_cb_type cb_func)
{
int err;
decoder->mem_access = cb_func;
err = rctdl_dt_add_callback_mem_acc(decoder->dcd_tree,
address,
address+len-1,
RCTDL_MEM_SPACE_ANY,
cs_etm_decoder__mem_access,
decoder);
return err;
}
int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *decoder, uint64_t offset, uint64_t address, uint64_t len, const char *fname)
{
int err = 0;
file_mem_region_t region;
(void) len;
if (NULL == decoder)
return -1;
if (NULL == decoder->dcd_tree)
return -1;
region.file_offset = offset;
region.start_address = address;
region.region_size = len;
err = rctdl_dt_add_binfile_region_mem_acc(decoder->dcd_tree,
&region,
1,
RCTDL_MEM_SPACE_ANY,
fname);
return err;
}
const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
uint64_t indx,
const uint8_t *buf,
size_t len,
size_t *consumed)
{
int ret = 0;
rctdl_datapath_resp_t dp_ret = decoder->prev_return;
size_t processed = 0;
if (decoder->packet_count > 0) {
decoder->state.err = ret;
*consumed = processed;
return &(decoder->state);
}
while ((processed < len) && (0 == ret)) {
if (RCTDL_DATA_RESP_IS_CONT(dp_ret)) {
uint32_t count;
dp_ret = rctdl_dt_process_data(decoder->dcd_tree,
RCTDL_OP_DATA,
indx+processed,
len - processed,
&buf[processed],
&count);
processed += count;
} else if (RCTDL_DATA_RESP_IS_WAIT(dp_ret)) {
dp_ret = rctdl_dt_process_data(decoder->dcd_tree,
RCTDL_OP_FLUSH,
0,
0,
NULL,
NULL);
break;
} else {
ret = -1;
}
}
if (RCTDL_DATA_RESP_IS_WAIT(dp_ret)) {
if (RCTDL_DATA_RESP_IS_CONT(decoder->prev_return)) {
decoder->prev_processed = processed;
}
processed = 0;
} else if (RCTDL_DATA_RESP_IS_WAIT(decoder->prev_return)) {
processed = decoder->prev_processed;
decoder->prev_processed = 0;
}
*consumed = processed;
decoder->prev_return = dp_ret;
decoder->state.err = ret;
return &(decoder->state);
}
int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
struct cs_etm_packet *packet)
{
if (decoder->packet_count == 0) return -1;
if (packet == NULL) return -1;
*packet = decoder->packet_buffer[decoder->head];
decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
decoder->packet_count--;
return 0;
}
static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
{
unsigned i;
decoder->head = 0;
decoder->tail = 0;
decoder->end_tail = 0;
decoder->packet_count = 0;
for (i = 0; i < MAX_BUFFER; i++) {
decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
decoder->packet_buffer[i].exc = false;
decoder->packet_buffer[i].exc_ret = false;
}
}
struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params t_params[])
{
struct cs_etm_decoder *decoder;
rctdl_dcd_tree_src_t format;
uint32_t flags;
int ret;
size_t i;
if ((t_params == NULL) || (d_params == 0)) {
return NULL;
}
decoder = zalloc(sizeof(struct cs_etm_decoder));
if (decoder == NULL) {
return NULL;
}
decoder->state.data = d_params->data;
decoder->prev_return = RCTDL_RESP_CONT;
cs_etm_decoder__clear_buffer(decoder);
format = (d_params->formatted ? RCTDL_TRC_SRC_FRAME_FORMATTED :
RCTDL_TRC_SRC_SINGLE);
flags = 0;
flags |= (d_params->fsyncs ? RCTDL_DFRMTR_HAS_FSYNCS : 0);
flags |= (d_params->hsyncs ? RCTDL_DFRMTR_HAS_HSYNCS : 0);
flags |= (d_params->frame_aligned ? RCTDL_DFRMTR_FRAME_MEM_ALIGN : 0);
/* Create decode tree for the data source */
decoder->dcd_tree = rctdl_create_dcd_tree(format,flags);
if (decoder->dcd_tree == 0) {
goto err_free_decoder;
}
for (i = 0; i < num_cpu; ++i) {
switch (t_params[i].protocol)
{
case CS_ETM_PROTO_ETMV4i:
if (d_params->operation == CS_ETM_OPERATION_PRINT) {
ret = cs_etm_decoder__create_etmv4i_packet_printer(d_params,&t_params[i],decoder);
} else if (d_params->operation == CS_ETM_OPERATION_DECODE) {
ret = cs_etm_decoder__create_etmv4i_packet_decoder(d_params,&t_params[i],decoder);
} else {
ret = -CS_ETM_ERR_PARAM;
}
if (ret != 0) {
goto err_free_decoder_tree;
}
break;
default:
goto err_free_decoder_tree;
break;
}
}
return decoder;
err_free_decoder_tree:
rctdl_destroy_dcd_tree(decoder->dcd_tree);
err_free_decoder:
free(decoder);
return NULL;
}
void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
{
if (decoder == NULL) return;
rctdl_destroy_dcd_tree(decoder->dcd_tree);
decoder->dcd_tree = NULL;
free(decoder);
}

View file

@ -0,0 +1,117 @@
/*
* Copyright(C) 2015 Linaro Limited. All rights reserved.
* Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU GEneral Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDE__CS_ETM_DECODER_H__
#define INCLUDE__CS_ETM_DECODER_H__
#include <linux/types.h>
#include <stdio.h>
struct cs_etm_decoder;
struct cs_etm_buffer {
const unsigned char *buf;
size_t len;
uint64_t offset;
//bool consecutive;
uint64_t ref_timestamp;
//uint64_t trace_nr;
};
enum cs_etm_sample_type {
CS_ETM_RANGE = 1 << 0,
};
struct cs_etm_state {
int err;
void *data;
unsigned isa;
uint64_t start;
uint64_t end;
uint64_t timestamp;
};
struct cs_etm_packet {
enum cs_etm_sample_type sample_type;
uint64_t start_addr;
uint64_t end_addr;
bool exc;
bool exc_ret;
};
struct cs_etm_queue;
typedef uint32_t (*cs_etm_mem_cb_type)(struct cs_etm_queue *, uint64_t, size_t, uint8_t *);
struct cs_etm_trace_params {
void *etmv4i_packet_handler;
uint32_t reg_idr0;
uint32_t reg_idr1;
uint32_t reg_idr2;
uint32_t reg_idr8;
uint32_t reg_configr;
uint32_t reg_traceidr;
int protocol;
};
struct cs_etm_decoder_params {
int operation;
void (*packet_printer)(const char *);
cs_etm_mem_cb_type mem_acc_cb;
bool formatted;
bool fsyncs;
bool hsyncs;
bool frame_aligned;
void *data;
};
enum {
CS_ETM_PROTO_ETMV3 = 1,
CS_ETM_PROTO_ETMV4i,
CS_ETM_PROTO_ETMV4d,
};
enum {
CS_ETM_OPERATION_PRINT = 1,
CS_ETM_OPERATION_DECODE,
};
enum {
CS_ETM_ERR_NOMEM = 1,
CS_ETM_ERR_NODATA,
CS_ETM_ERR_PARAM,
};
struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *,struct cs_etm_trace_params []);
int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *, uint64_t, uint64_t, cs_etm_mem_cb_type);
int cs_etm_decoder__flush(struct cs_etm_decoder *);
void cs_etm_decoder__free(struct cs_etm_decoder *);
int cs_etm_decoder__get_packet(struct cs_etm_decoder *, struct cs_etm_packet *);
int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *, uint64_t, uint64_t, uint64_t, const char *);
const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *,
uint64_t,
const uint8_t *,
size_t,
size_t *);
#endif /* INCLUDE__CS_ETM_DECODER_H__ */

1472
tools/perf/util/cs-etm.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -71,4 +71,7 @@ static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL;
#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
int cs_etm__process_auxtrace_info(union perf_event *event,
struct perf_session *session);
#endif

View file

@ -1,3 +1,4 @@
#include "build-id.h"
#include "callchain.h"
#include "debug.h"
#include "event.h"
@ -685,8 +686,16 @@ static struct dso *machine__get_kernel(struct machine *machine)
DSO_TYPE_GUEST_KERNEL);
}
if (kernel != NULL && (!kernel->has_build_id))
dso__read_running_kernel_build_id(kernel, machine);
if (kernel != NULL && (!kernel->has_build_id)) {
if (symbol_conf.vmlinux_name != NULL) {
filename__read_build_id(symbol_conf.vmlinux_name,
kernel->build_id,
sizeof(kernel->build_id));
kernel->has_build_id = 1;
} else {
dso__read_running_kernel_build_id(kernel, machine);
}
}
return kernel;
}
@ -700,8 +709,19 @@ static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
{
if (machine__is_default_guest(machine))
scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
else
scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
else {
if (symbol_conf.vmlinux_name != 0) {
unsigned char build_id[BUILD_ID_SIZE];
char build_id_hex[SBUILD_ID_SIZE];
filename__read_build_id(symbol_conf.vmlinux_name,
build_id,
sizeof(build_id));
build_id__sprintf(build_id,sizeof(build_id), build_id_hex);
build_id__filename((char *)build_id_hex,buf,bufsz);
} else {
scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
}
}
}
const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
@ -710,7 +730,7 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
* Returns the name of the start symbol in *symbol_name. Pass in NULL as
* symbol_name if it's not that important.
*/
static u64 machine__get_running_kernel_start(struct machine *machine,
static u64 machine__get_kallsyms_kernel_start(struct machine *machine,
const char **symbol_name)
{
char filename[PATH_MAX];
@ -738,7 +758,7 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
{
enum map_type type;
u64 start = machine__get_running_kernel_start(machine, NULL);
u64 start = machine__get_kallsyms_kernel_start(machine, NULL);
for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap;
@ -1083,7 +1103,8 @@ int machine__create_kernel_maps(struct machine *machine)
{
struct dso *kernel = machine__get_kernel(machine);
const char *name;
u64 addr = machine__get_running_kernel_start(machine, &name);
u64 addr = machine__get_kallsyms_kernel_start(machine, &name);
if (!addr)
return -1;

View file

@ -806,6 +806,8 @@ static void python_process_general_event(struct perf_sample *sample,
PyInt_FromLong(sample->cpu));
pydict_set_item_string_decref(dict_sample, "ip",
PyLong_FromUnsignedLongLong(sample->ip));
pydict_set_item_string_decref(dict_sample, "addr",
PyLong_FromUnsignedLongLong(sample->addr));
pydict_set_item_string_decref(dict_sample, "time",
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",