提交 0dcb7b6f 编写于 作者: L Linus Torvalds

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "Mostly tooling fixes, but also start/stop filter related fixes, a perf
  event read() fix, a fix uncovered by fuzzing, and an uprobes leak fix"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/core: Check return value of the perf_event_read() IPI
  perf/core: Enable mapping of the stop filters
  perf/core: Update filters only on executable mmap
  perf/core: Fix file name handling for start/stop filters
  perf/core: Fix event_function_local()
  uprobes: Fix the memcg accounting
  perf intel-pt: Fix occasional decoding errors when tracing system-wide
  tools: Sync kvm related header files for arm64 and s390
  perf probe: Release resources on error when handling exit paths
  perf probe: Check for dup and fdopen failures
  perf symbols: Fix annotation of objects with debuginfo files
  perf script: Don't disable use_callchain if input is pipe
  perf script: Show proper message when failed list scripts
  perf jitdump: Add the right header to get the major()/minor() definitions
  perf ppc64le: Fix build failure when libelf is not present
  perf tools mem: Fix -t store option for record command
  perf intel-pt: Fix ip compression
...@@ -242,18 +242,6 @@ static int event_function(void *info) ...@@ -242,18 +242,6 @@ static int event_function(void *info)
return ret; return ret;
} }
static void event_function_local(struct perf_event *event, event_f func, void *data)
{
struct event_function_struct efs = {
.event = event,
.func = func,
.data = data,
};
int ret = event_function(&efs);
WARN_ON_ONCE(ret);
}
static void event_function_call(struct perf_event *event, event_f func, void *data) static void event_function_call(struct perf_event *event, event_f func, void *data)
{ {
struct perf_event_context *ctx = event->ctx; struct perf_event_context *ctx = event->ctx;
...@@ -303,6 +291,54 @@ static void event_function_call(struct perf_event *event, event_f func, void *da ...@@ -303,6 +291,54 @@ static void event_function_call(struct perf_event *event, event_f func, void *da
raw_spin_unlock_irq(&ctx->lock); raw_spin_unlock_irq(&ctx->lock);
} }
/*
* Similar to event_function_call() + event_function(), but hard assumes IRQs
* are already disabled and we're on the right CPU.
*/
static void event_function_local(struct perf_event *event, event_f func, void *data)
{
struct perf_event_context *ctx = event->ctx;
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
struct task_struct *task = READ_ONCE(ctx->task);
struct perf_event_context *task_ctx = NULL;
WARN_ON_ONCE(!irqs_disabled());
if (task) {
if (task == TASK_TOMBSTONE)
return;
task_ctx = ctx;
}
perf_ctx_lock(cpuctx, task_ctx);
task = ctx->task;
if (task == TASK_TOMBSTONE)
goto unlock;
if (task) {
/*
* We must be either inactive or active and the right task,
* otherwise we're screwed, since we cannot IPI to somewhere
* else.
*/
if (ctx->is_active) {
if (WARN_ON_ONCE(task != current))
goto unlock;
if (WARN_ON_ONCE(cpuctx->task_ctx != ctx))
goto unlock;
}
} else {
WARN_ON_ONCE(&cpuctx->ctx != ctx);
}
func(event, cpuctx, ctx, data);
unlock:
perf_ctx_unlock(cpuctx, task_ctx);
}
#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ #define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
PERF_FLAG_FD_OUTPUT |\ PERF_FLAG_FD_OUTPUT |\
PERF_FLAG_PID_CGROUP |\ PERF_FLAG_PID_CGROUP |\
...@@ -3513,9 +3549,10 @@ static int perf_event_read(struct perf_event *event, bool group) ...@@ -3513,9 +3549,10 @@ static int perf_event_read(struct perf_event *event, bool group)
.group = group, .group = group,
.ret = 0, .ret = 0,
}; };
smp_call_function_single(event->oncpu, ret = smp_call_function_single(event->oncpu, __perf_event_read, &data, 1);
__perf_event_read, &data, 1); /* The event must have been read from an online CPU: */
ret = data.ret; WARN_ON_ONCE(ret);
ret = ret ? : data.ret;
} else if (event->state == PERF_EVENT_STATE_INACTIVE) { } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
struct perf_event_context *ctx = event->ctx; struct perf_event_context *ctx = event->ctx;
unsigned long flags; unsigned long flags;
...@@ -6583,15 +6620,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) ...@@ -6583,15 +6620,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
kfree(buf); kfree(buf);
} }
/*
* Whether this @filter depends on a dynamic object which is not loaded
* yet or its load addresses are not known.
*/
static bool perf_addr_filter_needs_mmap(struct perf_addr_filter *filter)
{
return filter->filter && filter->inode;
}
/* /*
* Check whether inode and address range match filter criteria. * Check whether inode and address range match filter criteria.
*/ */
...@@ -6653,6 +6681,13 @@ static void perf_addr_filters_adjust(struct vm_area_struct *vma) ...@@ -6653,6 +6681,13 @@ static void perf_addr_filters_adjust(struct vm_area_struct *vma)
struct perf_event_context *ctx; struct perf_event_context *ctx;
int ctxn; int ctxn;
/*
* Data tracing isn't supported yet and as such there is no need
* to keep track of anything that isn't related to executable code:
*/
if (!(vma->vm_flags & VM_EXEC))
return;
rcu_read_lock(); rcu_read_lock();
for_each_task_context_nr(ctxn) { for_each_task_context_nr(ctxn) {
ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
...@@ -7805,7 +7840,11 @@ static void perf_event_addr_filters_apply(struct perf_event *event) ...@@ -7805,7 +7840,11 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
list_for_each_entry(filter, &ifh->list, entry) { list_for_each_entry(filter, &ifh->list, entry) {
event->addr_filters_offs[count] = 0; event->addr_filters_offs[count] = 0;
if (perf_addr_filter_needs_mmap(filter)) /*
* Adjust base offset if the filter is associated to a binary
* that needs to be mapped:
*/
if (filter->inode)
event->addr_filters_offs[count] = event->addr_filters_offs[count] =
perf_addr_filter_apply(filter, mm); perf_addr_filter_apply(filter, mm);
...@@ -7936,8 +7975,10 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr, ...@@ -7936,8 +7975,10 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
goto fail; goto fail;
} }
if (token == IF_SRC_FILE) { if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
filename = match_strdup(&args[2]); int fpos = filter->range ? 2 : 1;
filename = match_strdup(&args[fpos]);
if (!filename) { if (!filename) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail; goto fail;
......
...@@ -172,8 +172,10 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, ...@@ -172,8 +172,10 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
err = -EAGAIN; err = -EAGAIN;
ptep = page_check_address(page, mm, addr, &ptl, 0); ptep = page_check_address(page, mm, addr, &ptl, 0);
if (!ptep) if (!ptep) {
mem_cgroup_cancel_charge(kpage, memcg, false);
goto unlock; goto unlock;
}
get_page(kpage); get_page(kpage);
page_add_new_anon_rmap(kpage, vma, addr, false); page_add_new_anon_rmap(kpage, vma, addr, false);
...@@ -200,7 +202,6 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, ...@@ -200,7 +202,6 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
err = 0; err = 0;
unlock: unlock:
mem_cgroup_cancel_charge(kpage, memcg, false);
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
unlock_page(page); unlock_page(page);
return err; return err;
......
...@@ -87,9 +87,11 @@ struct kvm_regs { ...@@ -87,9 +87,11 @@ struct kvm_regs {
/* Supported VGICv3 address types */ /* Supported VGICv3 address types */
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2 #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3 #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
#define KVM_VGIC_ITS_ADDR_TYPE 4
#define KVM_VGIC_V3_DIST_SIZE SZ_64K #define KVM_VGIC_V3_DIST_SIZE SZ_64K
#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K) #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
......
...@@ -93,6 +93,47 @@ struct kvm_s390_vm_cpu_machine { ...@@ -93,6 +93,47 @@ struct kvm_s390_vm_cpu_machine {
__u64 fac_list[256]; __u64 fac_list[256];
}; };
#define KVM_S390_VM_CPU_PROCESSOR_FEAT 2
#define KVM_S390_VM_CPU_MACHINE_FEAT 3
#define KVM_S390_VM_CPU_FEAT_NR_BITS 1024
#define KVM_S390_VM_CPU_FEAT_ESOP 0
#define KVM_S390_VM_CPU_FEAT_SIEF2 1
#define KVM_S390_VM_CPU_FEAT_64BSCAO 2
#define KVM_S390_VM_CPU_FEAT_SIIF 3
#define KVM_S390_VM_CPU_FEAT_GPERE 4
#define KVM_S390_VM_CPU_FEAT_GSLS 5
#define KVM_S390_VM_CPU_FEAT_IB 6
#define KVM_S390_VM_CPU_FEAT_CEI 7
#define KVM_S390_VM_CPU_FEAT_IBS 8
#define KVM_S390_VM_CPU_FEAT_SKEY 9
#define KVM_S390_VM_CPU_FEAT_CMMA 10
#define KVM_S390_VM_CPU_FEAT_PFMFI 11
#define KVM_S390_VM_CPU_FEAT_SIGPIF 12
struct kvm_s390_vm_cpu_feat {
__u64 feat[16];
};
#define KVM_S390_VM_CPU_PROCESSOR_SUBFUNC 4
#define KVM_S390_VM_CPU_MACHINE_SUBFUNC 5
/* for "test bit" instructions MSB 0 bit ordering, for "query" raw blocks */
struct kvm_s390_vm_cpu_subfunc {
__u8 plo[32]; /* always */
__u8 ptff[16]; /* with TOD-clock steering */
__u8 kmac[16]; /* with MSA */
__u8 kmc[16]; /* with MSA */
__u8 km[16]; /* with MSA */
__u8 kimd[16]; /* with MSA */
__u8 klmd[16]; /* with MSA */
__u8 pckmo[16]; /* with MSA3 */
__u8 kmctr[16]; /* with MSA4 */
__u8 kmf[16]; /* with MSA4 */
__u8 kmo[16]; /* with MSA4 */
__u8 pcc[16]; /* with MSA4 */
__u8 ppno[16]; /* with MSA5 */
__u8 reserved[1824];
};
/* kvm attributes for crypto */ /* kvm attributes for crypto */
#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0 #define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
exit_code_ipa0(0xB2, 0x4c, "TAR"), \ exit_code_ipa0(0xB2, 0x4c, "TAR"), \
exit_code_ipa0(0xB2, 0x50, "CSP"), \ exit_code_ipa0(0xB2, 0x50, "CSP"), \
exit_code_ipa0(0xB2, 0x54, "MVPG"), \ exit_code_ipa0(0xB2, 0x54, "MVPG"), \
exit_code_ipa0(0xB2, 0x56, "STHYI"), \
exit_code_ipa0(0xB2, 0x58, "BSG"), \ exit_code_ipa0(0xB2, 0x58, "BSG"), \
exit_code_ipa0(0xB2, 0x5a, "BSA"), \ exit_code_ipa0(0xB2, 0x5a, "BSA"), \
exit_code_ipa0(0xB2, 0x5f, "CHSC"), \ exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
......
...@@ -97,6 +97,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev, ...@@ -97,6 +97,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
} }
} }
#ifdef HAVE_LIBELF_SUPPORT
void arch__post_process_probe_trace_events(struct perf_probe_event *pev, void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
int ntevs) int ntevs)
{ {
...@@ -118,5 +119,6 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev, ...@@ -118,5 +119,6 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
} }
} }
} }
#endif /* HAVE_LIBELF_SUPPORT */
#endif #endif
...@@ -501,7 +501,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ...@@ -501,7 +501,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
struct intel_pt_recording *ptr = struct intel_pt_recording *ptr =
container_of(itr, struct intel_pt_recording, itr); container_of(itr, struct intel_pt_recording, itr);
struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
bool have_timing_info; bool have_timing_info, need_immediate = false;
struct perf_evsel *evsel, *intel_pt_evsel = NULL; struct perf_evsel *evsel, *intel_pt_evsel = NULL;
const struct cpu_map *cpus = evlist->cpus; const struct cpu_map *cpus = evlist->cpus;
bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
...@@ -655,6 +655,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ...@@ -655,6 +655,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
ptr->have_sched_switch = 3; ptr->have_sched_switch = 3;
} else { } else {
opts->record_switch_events = true; opts->record_switch_events = true;
need_immediate = true;
if (cpu_wide) if (cpu_wide)
ptr->have_sched_switch = 3; ptr->have_sched_switch = 3;
else else
...@@ -700,6 +701,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ...@@ -700,6 +701,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
tracking_evsel->attr.freq = 0; tracking_evsel->attr.freq = 0;
tracking_evsel->attr.sample_period = 1; tracking_evsel->attr.sample_period = 1;
if (need_immediate)
tracking_evsel->immediate = true;
/* In per-cpu case, always need the time of mmap events etc */ /* In per-cpu case, always need the time of mmap events etc */
if (!cpu_map__empty(cpus)) { if (!cpu_map__empty(cpus)) {
perf_evsel__set_sample_bit(tracking_evsel, TIME); perf_evsel__set_sample_bit(tracking_evsel, TIME);
......
...@@ -88,6 +88,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) ...@@ -88,6 +88,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
if (mem->operation & MEM_OPERATION_LOAD) if (mem->operation & MEM_OPERATION_LOAD)
perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
if (mem->operation & MEM_OPERATION_STORE)
perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
rec_argv[i++] = "-W"; rec_argv[i++] = "-W";
......
...@@ -371,14 +371,16 @@ static int perf_session__check_output_opt(struct perf_session *session) ...@@ -371,14 +371,16 @@ static int perf_session__check_output_opt(struct perf_session *session)
if (!no_callchain) { if (!no_callchain) {
bool use_callchain = false; bool use_callchain = false;
bool not_pipe = false;
evlist__for_each_entry(session->evlist, evsel) { evlist__for_each_entry(session->evlist, evsel) {
not_pipe = true;
if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
use_callchain = true; use_callchain = true;
break; break;
} }
} }
if (!use_callchain) if (not_pipe && !use_callchain)
symbol_conf.use_callchain = false; symbol_conf.use_callchain = false;
} }
...@@ -1690,8 +1692,13 @@ static int list_available_scripts(const struct option *opt __maybe_unused, ...@@ -1690,8 +1692,13 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path()); snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
scripts_dir = opendir(scripts_path); scripts_dir = opendir(scripts_path);
if (!scripts_dir) if (!scripts_dir) {
return -1; fprintf(stdout,
"open(%s) failed.\n"
"Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
scripts_path);
exit(-1);
}
for_each_lang(scripts_path, scripts_dir, lang_dirent) { for_each_lang(scripts_path, scripts_dir, lang_dirent) {
snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
......
...@@ -123,8 +123,6 @@ struct intel_pt_decoder { ...@@ -123,8 +123,6 @@ struct intel_pt_decoder {
bool have_calc_cyc_to_tsc; bool have_calc_cyc_to_tsc;
int exec_mode; int exec_mode;
unsigned int insn_bytes; unsigned int insn_bytes;
uint64_t sign_bit;
uint64_t sign_bits;
uint64_t period; uint64_t period;
enum intel_pt_period_type period_type; enum intel_pt_period_type period_type;
uint64_t tot_insn_cnt; uint64_t tot_insn_cnt;
...@@ -191,9 +189,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) ...@@ -191,9 +189,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
decoder->data = params->data; decoder->data = params->data;
decoder->return_compression = params->return_compression; decoder->return_compression = params->return_compression;
decoder->sign_bit = (uint64_t)1 << 47;
decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
decoder->period = params->period; decoder->period = params->period;
decoder->period_type = params->period_type; decoder->period_type = params->period_type;
...@@ -362,21 +357,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen) ...@@ -362,21 +357,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
return 0; return 0;
} }
static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
const struct intel_pt_pkt *packet,
uint64_t last_ip) uint64_t last_ip)
{ {
uint64_t ip; uint64_t ip;
switch (packet->count) { switch (packet->count) {
case 2: case 1:
ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) | ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
packet->payload; packet->payload;
break; break;
case 4: case 2:
ip = (last_ip & (uint64_t)0xffffffff00000000ULL) | ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
packet->payload; packet->payload;
break; break;
case 3:
ip = packet->payload;
/* Sign-extend 6-byte ip */
if (ip & (uint64_t)0x800000000000ULL)
ip |= (uint64_t)0xffff000000000000ULL;
break;
case 4:
ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
packet->payload;
break;
case 6: case 6:
ip = packet->payload; ip = packet->payload;
break; break;
...@@ -384,16 +388,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, ...@@ -384,16 +388,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
return 0; return 0;
} }
if (ip & decoder->sign_bit)
return ip | decoder->sign_bits;
return ip; return ip;
} }
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
{ {
decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet, decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
decoder->last_ip);
} }
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
...@@ -1657,6 +1657,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) ...@@ -1657,6 +1657,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
} }
} }
static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
{
return decoder->last_ip || decoder->packet.count == 0 ||
decoder->packet.count == 3 || decoder->packet.count == 6;
}
/* Walk PSB+ packets to get in sync. */ /* Walk PSB+ packets to get in sync. */
static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
{ {
...@@ -1677,8 +1683,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) ...@@ -1677,8 +1683,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
case INTEL_PT_FUP: case INTEL_PT_FUP:
decoder->pge = true; decoder->pge = true;
if (decoder->last_ip || decoder->packet.count == 6 || if (intel_pt_have_ip(decoder)) {
decoder->packet.count == 0) {
uint64_t current_ip = decoder->ip; uint64_t current_ip = decoder->ip;
intel_pt_set_ip(decoder); intel_pt_set_ip(decoder);
...@@ -1767,8 +1772,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) ...@@ -1767,8 +1772,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
case INTEL_PT_TIP_PGE: case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP: case INTEL_PT_TIP:
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
if (decoder->last_ip || decoder->packet.count == 6 || if (intel_pt_have_ip(decoder))
decoder->packet.count == 0)
intel_pt_set_ip(decoder); intel_pt_set_ip(decoder);
if (decoder->ip) if (decoder->ip)
return 0; return 0;
...@@ -1776,9 +1780,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) ...@@ -1776,9 +1780,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
case INTEL_PT_FUP: case INTEL_PT_FUP:
if (decoder->overflow) { if (decoder->overflow) {
if (decoder->last_ip || if (intel_pt_have_ip(decoder))
decoder->packet.count == 6 ||
decoder->packet.count == 0)
intel_pt_set_ip(decoder); intel_pt_set_ip(decoder);
if (decoder->ip) if (decoder->ip)
return 0; return 0;
......
...@@ -292,36 +292,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, ...@@ -292,36 +292,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
const unsigned char *buf, size_t len, const unsigned char *buf, size_t len,
struct intel_pt_pkt *packet) struct intel_pt_pkt *packet)
{ {
switch (byte >> 5) { int ip_len;
packet->count = byte >> 5;
switch (packet->count) {
case 0: case 0:
packet->count = 0; ip_len = 0;
break; break;
case 1: case 1:
if (len < 3) if (len < 3)
return INTEL_PT_NEED_MORE_BYTES; return INTEL_PT_NEED_MORE_BYTES;
packet->count = 2; ip_len = 2;
packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
break; break;
case 2: case 2:
if (len < 5) if (len < 5)
return INTEL_PT_NEED_MORE_BYTES; return INTEL_PT_NEED_MORE_BYTES;
packet->count = 4; ip_len = 4;
packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
break; break;
case 3: case 3:
case 6: case 4:
if (len < 7) if (len < 7)
return INTEL_PT_NEED_MORE_BYTES; return INTEL_PT_NEED_MORE_BYTES;
packet->count = 6; ip_len = 6;
memcpy_le64(&packet->payload, buf + 1, 6); memcpy_le64(&packet->payload, buf + 1, 6);
break; break;
case 6:
if (len < 9)
return INTEL_PT_NEED_MORE_BYTES;
ip_len = 8;
packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
break;
default: default:
return INTEL_PT_BAD_PACKET; return INTEL_PT_BAD_PACKET;
} }
packet->type = type; packet->type = type;
return packet->count + 1; return ip_len + 1;
} }
static int intel_pt_get_mode(const unsigned char *buf, size_t len, static int intel_pt_get_mode(const unsigned char *buf, size_t len,
......
#include <sys/sysmacros.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
...@@ -133,7 +133,7 @@ int probe_file__open_both(int *kfd, int *ufd, int flag) ...@@ -133,7 +133,7 @@ int probe_file__open_both(int *kfd, int *ufd, int flag)
/* Get raw string list of current kprobe_events or uprobe_events */ /* Get raw string list of current kprobe_events or uprobe_events */
struct strlist *probe_file__get_rawlist(int fd) struct strlist *probe_file__get_rawlist(int fd)
{ {
int ret, idx; int ret, idx, fddup;
FILE *fp; FILE *fp;
char buf[MAX_CMDLEN]; char buf[MAX_CMDLEN];
char *p; char *p;
...@@ -143,8 +143,17 @@ struct strlist *probe_file__get_rawlist(int fd) ...@@ -143,8 +143,17 @@ struct strlist *probe_file__get_rawlist(int fd)
return NULL; return NULL;
sl = strlist__new(NULL, NULL); sl = strlist__new(NULL, NULL);
if (sl == NULL)
return NULL;
fddup = dup(fd);
if (fddup < 0)
goto out_free_sl;
fp = fdopen(fddup, "r");
if (!fp)
goto out_close_fddup;
fp = fdopen(dup(fd), "r");
while (!feof(fp)) { while (!feof(fp)) {
p = fgets(buf, MAX_CMDLEN, fp); p = fgets(buf, MAX_CMDLEN, fp);
if (!p) if (!p)
...@@ -156,13 +165,21 @@ struct strlist *probe_file__get_rawlist(int fd) ...@@ -156,13 +165,21 @@ struct strlist *probe_file__get_rawlist(int fd)
ret = strlist__add(sl, buf); ret = strlist__add(sl, buf);
if (ret < 0) { if (ret < 0) {
pr_debug("strlist__add failed (%d)\n", ret); pr_debug("strlist__add failed (%d)\n", ret);
strlist__delete(sl); goto out_close_fp;
return NULL;
} }
} }
fclose(fp); fclose(fp);
return sl; return sl;
out_close_fp:
fclose(fp);
goto out_free_sl;
out_close_fddup:
close(fddup);
out_free_sl:
strlist__delete(sl);
return NULL;
} }
static struct strlist *__probe_file__get_namelist(int fd, bool include_group) static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
...@@ -447,12 +464,17 @@ static int probe_cache__load(struct probe_cache *pcache) ...@@ -447,12 +464,17 @@ static int probe_cache__load(struct probe_cache *pcache)
{ {
struct probe_cache_entry *entry = NULL; struct probe_cache_entry *entry = NULL;
char buf[MAX_CMDLEN], *p; char buf[MAX_CMDLEN], *p;
int ret = 0; int ret = 0, fddup;
FILE *fp; FILE *fp;
fp = fdopen(dup(pcache->fd), "r"); fddup = dup(pcache->fd);
if (!fp) if (fddup < 0)
return -errno;
fp = fdopen(fddup, "r");
if (!fp) {
close(fddup);
return -EINVAL; return -EINVAL;
}
while (!feof(fp)) { while (!feof(fp)) {
if (!fgets(buf, MAX_CMDLEN, fp)) if (!fgets(buf, MAX_CMDLEN, fp))
......
...@@ -837,7 +837,8 @@ int dso__load_sym(struct dso *dso, struct map *map, ...@@ -837,7 +837,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
sec = syms_ss->symtab; sec = syms_ss->symtab;
shdr = syms_ss->symshdr; shdr = syms_ss->symshdr;
if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL)) if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr,
".text", NULL))
dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;
if (runtime_ss->opdsec) if (runtime_ss->opdsec)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册