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
This commit is contained in:
Коммит
0dcb7b6f8f
|
@ -242,18 +242,6 @@ unlock:
|
|||
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)
|
||||
{
|
||||
struct perf_event_context *ctx = event->ctx;
|
||||
|
@ -303,6 +291,54 @@ again:
|
|||
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 |\
|
||||
PERF_FLAG_FD_OUTPUT |\
|
||||
PERF_FLAG_PID_CGROUP |\
|
||||
|
@ -3513,9 +3549,10 @@ static int perf_event_read(struct perf_event *event, bool group)
|
|||
.group = group,
|
||||
.ret = 0,
|
||||
};
|
||||
smp_call_function_single(event->oncpu,
|
||||
__perf_event_read, &data, 1);
|
||||
ret = data.ret;
|
||||
ret = smp_call_function_single(event->oncpu, __perf_event_read, &data, 1);
|
||||
/* The event must have been read from an online CPU: */
|
||||
WARN_ON_ONCE(ret);
|
||||
ret = ret ? : data.ret;
|
||||
} else if (event->state == PERF_EVENT_STATE_INACTIVE) {
|
||||
struct perf_event_context *ctx = event->ctx;
|
||||
unsigned long flags;
|
||||
|
@ -6583,15 +6620,6 @@ got_name:
|
|||
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.
|
||||
*/
|
||||
|
@ -6653,6 +6681,13 @@ static void perf_addr_filters_adjust(struct vm_area_struct *vma)
|
|||
struct perf_event_context *ctx;
|
||||
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();
|
||||
for_each_task_context_nr(ctxn) {
|
||||
ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
|
||||
|
@ -7805,7 +7840,11 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
|
|||
list_for_each_entry(filter, &ifh->list, entry) {
|
||||
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] =
|
||||
perf_addr_filter_apply(filter, mm);
|
||||
|
||||
|
@ -7936,8 +7975,10 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (token == IF_SRC_FILE) {
|
||||
filename = match_strdup(&args[2]);
|
||||
if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
|
||||
int fpos = filter->range ? 2 : 1;
|
||||
|
||||
filename = match_strdup(&args[fpos]);
|
||||
if (!filename) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
|
|
|
@ -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);
|
||||
err = -EAGAIN;
|
||||
ptep = page_check_address(page, mm, addr, &ptl, 0);
|
||||
if (!ptep)
|
||||
if (!ptep) {
|
||||
mem_cgroup_cancel_charge(kpage, memcg, false);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
get_page(kpage);
|
||||
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,
|
|||
|
||||
err = 0;
|
||||
unlock:
|
||||
mem_cgroup_cancel_charge(kpage, memcg, false);
|
||||
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
|
||||
unlock_page(page);
|
||||
return err;
|
||||
|
|
|
@ -87,9 +87,11 @@ struct kvm_regs {
|
|||
/* Supported VGICv3 address types */
|
||||
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
|
||||
#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_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_EL1_32BIT 1 /* CPU running a 32bit VM */
|
||||
|
|
|
@ -93,6 +93,47 @@ struct kvm_s390_vm_cpu_machine {
|
|||
__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 */
|
||||
#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
|
||||
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
exit_code_ipa0(0xB2, 0x4c, "TAR"), \
|
||||
exit_code_ipa0(0xB2, 0x50, "CSP"), \
|
||||
exit_code_ipa0(0xB2, 0x54, "MVPG"), \
|
||||
exit_code_ipa0(0xB2, 0x56, "STHYI"), \
|
||||
exit_code_ipa0(0xB2, 0x58, "BSG"), \
|
||||
exit_code_ipa0(0xB2, 0x5a, "BSA"), \
|
||||
exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
|
||||
|
|
|
@ -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,
|
||||
int ntevs)
|
||||
{
|
||||
|
@ -118,5 +119,6 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBELF_SUPPORT */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -501,7 +501,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
struct intel_pt_recording *ptr =
|
||||
container_of(itr, struct intel_pt_recording, itr);
|
||||
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;
|
||||
const struct cpu_map *cpus = evlist->cpus;
|
||||
bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
|
||||
|
@ -655,6 +655,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
ptr->have_sched_switch = 3;
|
||||
} else {
|
||||
opts->record_switch_events = true;
|
||||
need_immediate = true;
|
||||
if (cpu_wide)
|
||||
ptr->have_sched_switch = 3;
|
||||
else
|
||||
|
@ -700,6 +701,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
tracking_evsel->attr.freq = 0;
|
||||
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 */
|
||||
if (!cpu_map__empty(cpus)) {
|
||||
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)
|
|||
if (mem->operation & MEM_OPERATION_LOAD)
|
||||
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)
|
||||
rec_argv[i++] = "-W";
|
||||
|
||||
|
|
|
@ -371,14 +371,16 @@ static int perf_session__check_output_opt(struct perf_session *session)
|
|||
|
||||
if (!no_callchain) {
|
||||
bool use_callchain = false;
|
||||
bool not_pipe = false;
|
||||
|
||||
evlist__for_each_entry(session->evlist, evsel) {
|
||||
not_pipe = true;
|
||||
if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
|
||||
use_callchain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!use_callchain)
|
||||
if (not_pipe && !use_callchain)
|
||||
symbol_conf.use_callchain = false;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
||||
scripts_dir = opendir(scripts_path);
|
||||
if (!scripts_dir)
|
||||
return -1;
|
||||
if (!scripts_dir) {
|
||||
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) {
|
||||
snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
|
||||
|
|
|
@ -123,8 +123,6 @@ struct intel_pt_decoder {
|
|||
bool have_calc_cyc_to_tsc;
|
||||
int exec_mode;
|
||||
unsigned int insn_bytes;
|
||||
uint64_t sign_bit;
|
||||
uint64_t sign_bits;
|
||||
uint64_t period;
|
||||
enum intel_pt_period_type period_type;
|
||||
uint64_t tot_insn_cnt;
|
||||
|
@ -191,9 +189,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|||
decoder->data = params->data;
|
||||
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_type = params->period_type;
|
||||
|
||||
|
@ -362,21 +357,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
|
||||
const struct intel_pt_pkt *packet,
|
||||
static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
|
||||
uint64_t last_ip)
|
||||
{
|
||||
uint64_t ip;
|
||||
|
||||
switch (packet->count) {
|
||||
case 2:
|
||||
case 1:
|
||||
ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
|
||||
packet->payload;
|
||||
break;
|
||||
case 4:
|
||||
case 2:
|
||||
ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
|
||||
packet->payload;
|
||||
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:
|
||||
ip = packet->payload;
|
||||
break;
|
||||
|
@ -384,16 +388,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (ip & decoder->sign_bit)
|
||||
return ip | decoder->sign_bits;
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
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);
|
||||
decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
|
||||
}
|
||||
|
||||
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
|
||||
|
@ -1657,6 +1657,12 @@ next:
|
|||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
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:
|
||||
decoder->pge = true;
|
||||
if (decoder->last_ip || decoder->packet.count == 6 ||
|
||||
decoder->packet.count == 0) {
|
||||
if (intel_pt_have_ip(decoder)) {
|
||||
uint64_t current_ip = decoder->ip;
|
||||
|
||||
intel_pt_set_ip(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:
|
||||
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
|
||||
if (decoder->last_ip || decoder->packet.count == 6 ||
|
||||
decoder->packet.count == 0)
|
||||
if (intel_pt_have_ip(decoder))
|
||||
intel_pt_set_ip(decoder);
|
||||
if (decoder->ip)
|
||||
return 0;
|
||||
|
@ -1776,9 +1780,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|||
|
||||
case INTEL_PT_FUP:
|
||||
if (decoder->overflow) {
|
||||
if (decoder->last_ip ||
|
||||
decoder->packet.count == 6 ||
|
||||
decoder->packet.count == 0)
|
||||
if (intel_pt_have_ip(decoder))
|
||||
intel_pt_set_ip(decoder);
|
||||
if (decoder->ip)
|
||||
return 0;
|
||||
|
|
|
@ -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,
|
||||
struct intel_pt_pkt *packet)
|
||||
{
|
||||
switch (byte >> 5) {
|
||||
int ip_len;
|
||||
|
||||
packet->count = byte >> 5;
|
||||
|
||||
switch (packet->count) {
|
||||
case 0:
|
||||
packet->count = 0;
|
||||
ip_len = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (len < 3)
|
||||
return INTEL_PT_NEED_MORE_BYTES;
|
||||
packet->count = 2;
|
||||
ip_len = 2;
|
||||
packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
|
||||
break;
|
||||
case 2:
|
||||
if (len < 5)
|
||||
return INTEL_PT_NEED_MORE_BYTES;
|
||||
packet->count = 4;
|
||||
ip_len = 4;
|
||||
packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
case 4:
|
||||
if (len < 7)
|
||||
return INTEL_PT_NEED_MORE_BYTES;
|
||||
packet->count = 6;
|
||||
ip_len = 6;
|
||||
memcpy_le64(&packet->payload, buf + 1, 6);
|
||||
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:
|
||||
return INTEL_PT_BAD_PACKET;
|
||||
}
|
||||
|
||||
packet->type = type;
|
||||
|
||||
return packet->count + 1;
|
||||
return ip_len + 1;
|
||||
}
|
||||
|
||||
static int intel_pt_get_mode(const unsigned char *buf, size_t len,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -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 */
|
||||
struct strlist *probe_file__get_rawlist(int fd)
|
||||
{
|
||||
int ret, idx;
|
||||
int ret, idx, fddup;
|
||||
FILE *fp;
|
||||
char buf[MAX_CMDLEN];
|
||||
char *p;
|
||||
|
@ -143,8 +143,17 @@ struct strlist *probe_file__get_rawlist(int fd)
|
|||
return 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)) {
|
||||
p = fgets(buf, MAX_CMDLEN, fp);
|
||||
if (!p)
|
||||
|
@ -156,13 +165,21 @@ struct strlist *probe_file__get_rawlist(int fd)
|
|||
ret = strlist__add(sl, buf);
|
||||
if (ret < 0) {
|
||||
pr_debug("strlist__add failed (%d)\n", ret);
|
||||
strlist__delete(sl);
|
||||
return NULL;
|
||||
goto out_close_fp;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
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)
|
||||
|
@ -447,12 +464,17 @@ static int probe_cache__load(struct probe_cache *pcache)
|
|||
{
|
||||
struct probe_cache_entry *entry = NULL;
|
||||
char buf[MAX_CMDLEN], *p;
|
||||
int ret = 0;
|
||||
int ret = 0, fddup;
|
||||
FILE *fp;
|
||||
|
||||
fp = fdopen(dup(pcache->fd), "r");
|
||||
if (!fp)
|
||||
fddup = dup(pcache->fd);
|
||||
if (fddup < 0)
|
||||
return -errno;
|
||||
fp = fdopen(fddup, "r");
|
||||
if (!fp) {
|
||||
close(fddup);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (!feof(fp)) {
|
||||
if (!fgets(buf, MAX_CMDLEN, fp))
|
||||
|
|
|
@ -837,7 +837,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
|
|||
sec = syms_ss->symtab;
|
||||
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;
|
||||
|
||||
if (runtime_ss->opdsec)
|
||||
|
|
Загрузка…
Ссылка в новой задаче