Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf_counter: Set the CONFIG_PERF_COUNTERS default to y if CONFIG_PROFILING=y perf: Fix read buffer overflow perf top: Add mwait_idle_with_hints to skip_symbols[] perf tools: Fix faulty check perf report: Update for the new FORK/EXIT events perf_counter: Full task tracing perf_counter: Collapse inherit on read() tracing, perf_counter: Add help text to CONFIG_EVENT_PROFILE perf_counter tools: Fix link errors with older toolchains
This commit is contained in:
@@ -181,8 +181,9 @@ struct perf_counter_attr {
|
|||||||
freq : 1, /* use freq, not period */
|
freq : 1, /* use freq, not period */
|
||||||
inherit_stat : 1, /* per task counts */
|
inherit_stat : 1, /* per task counts */
|
||||||
enable_on_exec : 1, /* next exec enables */
|
enable_on_exec : 1, /* next exec enables */
|
||||||
|
task : 1, /* trace fork/exit */
|
||||||
|
|
||||||
__reserved_1 : 51;
|
__reserved_1 : 50;
|
||||||
|
|
||||||
__u32 wakeup_events; /* wakeup every n events */
|
__u32 wakeup_events; /* wakeup every n events */
|
||||||
__u32 __reserved_2;
|
__u32 __reserved_2;
|
||||||
@@ -308,6 +309,15 @@ enum perf_event_type {
|
|||||||
*/
|
*/
|
||||||
PERF_EVENT_COMM = 3,
|
PERF_EVENT_COMM = 3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct {
|
||||||
|
* struct perf_event_header header;
|
||||||
|
* u32 pid, ppid;
|
||||||
|
* u32 tid, ptid;
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
PERF_EVENT_EXIT = 4,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct {
|
* struct {
|
||||||
* struct perf_event_header header;
|
* struct perf_event_header header;
|
||||||
@@ -323,6 +333,7 @@ enum perf_event_type {
|
|||||||
* struct {
|
* struct {
|
||||||
* struct perf_event_header header;
|
* struct perf_event_header header;
|
||||||
* u32 pid, ppid;
|
* u32 pid, ppid;
|
||||||
|
* u32 tid, ptid;
|
||||||
* };
|
* };
|
||||||
*/
|
*/
|
||||||
PERF_EVENT_FORK = 7,
|
PERF_EVENT_FORK = 7,
|
||||||
|
11
init/Kconfig
11
init/Kconfig
@@ -940,6 +940,7 @@ menu "Performance Counters"
|
|||||||
|
|
||||||
config PERF_COUNTERS
|
config PERF_COUNTERS
|
||||||
bool "Kernel Performance Counters"
|
bool "Kernel Performance Counters"
|
||||||
|
default y if PROFILING
|
||||||
depends on HAVE_PERF_COUNTERS
|
depends on HAVE_PERF_COUNTERS
|
||||||
select ANON_INODES
|
select ANON_INODES
|
||||||
help
|
help
|
||||||
@@ -961,9 +962,17 @@ config PERF_COUNTERS
|
|||||||
Say Y if unsure.
|
Say Y if unsure.
|
||||||
|
|
||||||
config EVENT_PROFILE
|
config EVENT_PROFILE
|
||||||
bool "Tracepoint profile sources"
|
bool "Tracepoint profiling sources"
|
||||||
depends on PERF_COUNTERS && EVENT_TRACING
|
depends on PERF_COUNTERS && EVENT_TRACING
|
||||||
default y
|
default y
|
||||||
|
help
|
||||||
|
Allow the use of tracepoints as software performance counters.
|
||||||
|
|
||||||
|
When this is enabled, you can create perf counters based on
|
||||||
|
tracepoints using PERF_TYPE_TRACEPOINT and the tracepoint ID
|
||||||
|
found in debugfs://tracing/events/*/*/id. (The -e/--events
|
||||||
|
option to the perf tool can parse and interpret symbolic
|
||||||
|
tracepoints, in the subsystem:tracepoint_name format.)
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
@@ -1269,6 +1269,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||||||
write_unlock_irq(&tasklist_lock);
|
write_unlock_irq(&tasklist_lock);
|
||||||
proc_fork_connector(p);
|
proc_fork_connector(p);
|
||||||
cgroup_post_fork(p);
|
cgroup_post_fork(p);
|
||||||
|
perf_counter_fork(p);
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
bad_fork_free_pid:
|
bad_fork_free_pid:
|
||||||
@@ -1410,9 +1411,6 @@ long do_fork(unsigned long clone_flags,
|
|||||||
init_completion(&vfork);
|
init_completion(&vfork);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(clone_flags & CLONE_THREAD))
|
|
||||||
perf_counter_fork(p);
|
|
||||||
|
|
||||||
audit_finish_fork(p);
|
audit_finish_fork(p);
|
||||||
tracehook_report_clone(regs, clone_flags, nr, p);
|
tracehook_report_clone(regs, clone_flags, nr, p);
|
||||||
|
|
||||||
|
@@ -42,6 +42,7 @@ static int perf_overcommit __read_mostly = 1;
|
|||||||
static atomic_t nr_counters __read_mostly;
|
static atomic_t nr_counters __read_mostly;
|
||||||
static atomic_t nr_mmap_counters __read_mostly;
|
static atomic_t nr_mmap_counters __read_mostly;
|
||||||
static atomic_t nr_comm_counters __read_mostly;
|
static atomic_t nr_comm_counters __read_mostly;
|
||||||
|
static atomic_t nr_task_counters __read_mostly;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* perf counter paranoia level:
|
* perf counter paranoia level:
|
||||||
@@ -1654,6 +1655,8 @@ static void free_counter(struct perf_counter *counter)
|
|||||||
atomic_dec(&nr_mmap_counters);
|
atomic_dec(&nr_mmap_counters);
|
||||||
if (counter->attr.comm)
|
if (counter->attr.comm)
|
||||||
atomic_dec(&nr_comm_counters);
|
atomic_dec(&nr_comm_counters);
|
||||||
|
if (counter->attr.task)
|
||||||
|
atomic_dec(&nr_task_counters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter->destroy)
|
if (counter->destroy)
|
||||||
@@ -1688,6 +1691,18 @@ static int perf_release(struct inode *inode, struct file *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 perf_counter_read_tree(struct perf_counter *counter)
|
||||||
|
{
|
||||||
|
struct perf_counter *child;
|
||||||
|
u64 total = 0;
|
||||||
|
|
||||||
|
total += perf_counter_read(counter);
|
||||||
|
list_for_each_entry(child, &counter->child_list, child_list)
|
||||||
|
total += perf_counter_read(child);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the performance counter - simple non blocking version for now
|
* Read the performance counter - simple non blocking version for now
|
||||||
*/
|
*/
|
||||||
@@ -1707,7 +1722,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
|
|||||||
|
|
||||||
WARN_ON_ONCE(counter->ctx->parent_ctx);
|
WARN_ON_ONCE(counter->ctx->parent_ctx);
|
||||||
mutex_lock(&counter->child_mutex);
|
mutex_lock(&counter->child_mutex);
|
||||||
values[0] = perf_counter_read(counter);
|
values[0] = perf_counter_read_tree(counter);
|
||||||
n = 1;
|
n = 1;
|
||||||
if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
||||||
values[n++] = counter->total_time_enabled +
|
values[n++] = counter->total_time_enabled +
|
||||||
@@ -2819,10 +2834,12 @@ perf_counter_read_event(struct perf_counter *counter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fork tracking
|
* task tracking -- fork/exit
|
||||||
|
*
|
||||||
|
* enabled by: attr.comm | attr.mmap | attr.task
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct perf_fork_event {
|
struct perf_task_event {
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -2830,37 +2847,42 @@ struct perf_fork_event {
|
|||||||
|
|
||||||
u32 pid;
|
u32 pid;
|
||||||
u32 ppid;
|
u32 ppid;
|
||||||
|
u32 tid;
|
||||||
|
u32 ptid;
|
||||||
} event;
|
} event;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void perf_counter_fork_output(struct perf_counter *counter,
|
static void perf_counter_task_output(struct perf_counter *counter,
|
||||||
struct perf_fork_event *fork_event)
|
struct perf_task_event *task_event)
|
||||||
{
|
{
|
||||||
struct perf_output_handle handle;
|
struct perf_output_handle handle;
|
||||||
int size = fork_event->event.header.size;
|
int size = task_event->event.header.size;
|
||||||
struct task_struct *task = fork_event->task;
|
struct task_struct *task = task_event->task;
|
||||||
int ret = perf_output_begin(&handle, counter, size, 0, 0);
|
int ret = perf_output_begin(&handle, counter, size, 0, 0);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fork_event->event.pid = perf_counter_pid(counter, task);
|
task_event->event.pid = perf_counter_pid(counter, task);
|
||||||
fork_event->event.ppid = perf_counter_pid(counter, task->real_parent);
|
task_event->event.ppid = perf_counter_pid(counter, task->real_parent);
|
||||||
|
|
||||||
perf_output_put(&handle, fork_event->event);
|
task_event->event.tid = perf_counter_tid(counter, task);
|
||||||
|
task_event->event.ptid = perf_counter_tid(counter, task->real_parent);
|
||||||
|
|
||||||
|
perf_output_put(&handle, task_event->event);
|
||||||
perf_output_end(&handle);
|
perf_output_end(&handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_counter_fork_match(struct perf_counter *counter)
|
static int perf_counter_task_match(struct perf_counter *counter)
|
||||||
{
|
{
|
||||||
if (counter->attr.comm || counter->attr.mmap)
|
if (counter->attr.comm || counter->attr.mmap || counter->attr.task)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_counter_fork_ctx(struct perf_counter_context *ctx,
|
static void perf_counter_task_ctx(struct perf_counter_context *ctx,
|
||||||
struct perf_fork_event *fork_event)
|
struct perf_task_event *task_event)
|
||||||
{
|
{
|
||||||
struct perf_counter *counter;
|
struct perf_counter *counter;
|
||||||
|
|
||||||
@@ -2869,19 +2891,19 @@ static void perf_counter_fork_ctx(struct perf_counter_context *ctx,
|
|||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
|
list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
|
||||||
if (perf_counter_fork_match(counter))
|
if (perf_counter_task_match(counter))
|
||||||
perf_counter_fork_output(counter, fork_event);
|
perf_counter_task_output(counter, task_event);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_counter_fork_event(struct perf_fork_event *fork_event)
|
static void perf_counter_task_event(struct perf_task_event *task_event)
|
||||||
{
|
{
|
||||||
struct perf_cpu_context *cpuctx;
|
struct perf_cpu_context *cpuctx;
|
||||||
struct perf_counter_context *ctx;
|
struct perf_counter_context *ctx;
|
||||||
|
|
||||||
cpuctx = &get_cpu_var(perf_cpu_context);
|
cpuctx = &get_cpu_var(perf_cpu_context);
|
||||||
perf_counter_fork_ctx(&cpuctx->ctx, fork_event);
|
perf_counter_task_ctx(&cpuctx->ctx, task_event);
|
||||||
put_cpu_var(perf_cpu_context);
|
put_cpu_var(perf_cpu_context);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@@ -2891,32 +2913,40 @@ static void perf_counter_fork_event(struct perf_fork_event *fork_event)
|
|||||||
*/
|
*/
|
||||||
ctx = rcu_dereference(current->perf_counter_ctxp);
|
ctx = rcu_dereference(current->perf_counter_ctxp);
|
||||||
if (ctx)
|
if (ctx)
|
||||||
perf_counter_fork_ctx(ctx, fork_event);
|
perf_counter_task_ctx(ctx, task_event);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void perf_counter_task(struct task_struct *task, int new)
|
||||||
|
{
|
||||||
|
struct perf_task_event task_event;
|
||||||
|
|
||||||
|
if (!atomic_read(&nr_comm_counters) &&
|
||||||
|
!atomic_read(&nr_mmap_counters) &&
|
||||||
|
!atomic_read(&nr_task_counters))
|
||||||
|
return;
|
||||||
|
|
||||||
|
task_event = (struct perf_task_event){
|
||||||
|
.task = task,
|
||||||
|
.event = {
|
||||||
|
.header = {
|
||||||
|
.type = new ? PERF_EVENT_FORK : PERF_EVENT_EXIT,
|
||||||
|
.misc = 0,
|
||||||
|
.size = sizeof(task_event.event),
|
||||||
|
},
|
||||||
|
/* .pid */
|
||||||
|
/* .ppid */
|
||||||
|
/* .tid */
|
||||||
|
/* .ptid */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
perf_counter_task_event(&task_event);
|
||||||
|
}
|
||||||
|
|
||||||
void perf_counter_fork(struct task_struct *task)
|
void perf_counter_fork(struct task_struct *task)
|
||||||
{
|
{
|
||||||
struct perf_fork_event fork_event;
|
perf_counter_task(task, 1);
|
||||||
|
|
||||||
if (!atomic_read(&nr_comm_counters) &&
|
|
||||||
!atomic_read(&nr_mmap_counters))
|
|
||||||
return;
|
|
||||||
|
|
||||||
fork_event = (struct perf_fork_event){
|
|
||||||
.task = task,
|
|
||||||
.event = {
|
|
||||||
.header = {
|
|
||||||
.type = PERF_EVENT_FORK,
|
|
||||||
.misc = 0,
|
|
||||||
.size = sizeof(fork_event.event),
|
|
||||||
},
|
|
||||||
/* .pid */
|
|
||||||
/* .ppid */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
perf_counter_fork_event(&fork_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3875,6 +3905,8 @@ done:
|
|||||||
atomic_inc(&nr_mmap_counters);
|
atomic_inc(&nr_mmap_counters);
|
||||||
if (counter->attr.comm)
|
if (counter->attr.comm)
|
||||||
atomic_inc(&nr_comm_counters);
|
atomic_inc(&nr_comm_counters);
|
||||||
|
if (counter->attr.task)
|
||||||
|
atomic_inc(&nr_task_counters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
@@ -4236,8 +4268,10 @@ void perf_counter_exit_task(struct task_struct *child)
|
|||||||
struct perf_counter_context *child_ctx;
|
struct perf_counter_context *child_ctx;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (likely(!child->perf_counter_ctxp))
|
if (likely(!child->perf_counter_ctxp)) {
|
||||||
|
perf_counter_task(child, 0);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
/*
|
/*
|
||||||
@@ -4255,15 +4289,22 @@ void perf_counter_exit_task(struct task_struct *child)
|
|||||||
* incremented the context's refcount before we do put_ctx below.
|
* incremented the context's refcount before we do put_ctx below.
|
||||||
*/
|
*/
|
||||||
spin_lock(&child_ctx->lock);
|
spin_lock(&child_ctx->lock);
|
||||||
child->perf_counter_ctxp = NULL;
|
|
||||||
/*
|
/*
|
||||||
* If this context is a clone; unclone it so it can't get
|
* If this context is a clone; unclone it so it can't get
|
||||||
* swapped to another process while we're removing all
|
* swapped to another process while we're removing all
|
||||||
* the counters from it.
|
* the counters from it.
|
||||||
*/
|
*/
|
||||||
unclone_ctx(child_ctx);
|
unclone_ctx(child_ctx);
|
||||||
spin_unlock(&child_ctx->lock);
|
spin_unlock_irqrestore(&child_ctx->lock, flags);
|
||||||
local_irq_restore(flags);
|
|
||||||
|
/*
|
||||||
|
* Report the task dead after unscheduling the counters so that we
|
||||||
|
* won't get any samples after PERF_EVENT_EXIT. We can however still
|
||||||
|
* get a few PERF_EVENT_READ events.
|
||||||
|
*/
|
||||||
|
perf_counter_task(child, 0);
|
||||||
|
|
||||||
|
child->perf_counter_ctxp = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can recurse on the same lock type through:
|
* We can recurse on the same lock type through:
|
||||||
|
@@ -345,7 +345,7 @@ BUILTIN_OBJS += builtin-stat.o
|
|||||||
BUILTIN_OBJS += builtin-top.o
|
BUILTIN_OBJS += builtin-top.o
|
||||||
|
|
||||||
PERFLIBS = $(LIB_FILE)
|
PERFLIBS = $(LIB_FILE)
|
||||||
EXTLIBS = -lbfd
|
EXTLIBS = -lbfd -liberty
|
||||||
|
|
||||||
#
|
#
|
||||||
# Platform specific tweaks
|
# Platform specific tweaks
|
||||||
|
@@ -99,6 +99,7 @@ struct comm_event {
|
|||||||
struct fork_event {
|
struct fork_event {
|
||||||
struct perf_event_header header;
|
struct perf_event_header header;
|
||||||
u32 pid, ppid;
|
u32 pid, ppid;
|
||||||
|
u32 tid, ptid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lost_event {
|
struct lost_event {
|
||||||
@@ -252,7 +253,7 @@ static int strcommon(const char *pathname)
|
|||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
while (pathname[n] == cwd[n] && n < cwdlen)
|
while (n < cwdlen && pathname[n] == cwd[n])
|
||||||
++n;
|
++n;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@@ -1608,15 +1609,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_fork_event(event_t *event, unsigned long offset, unsigned long head)
|
process_task_event(event_t *event, unsigned long offset, unsigned long head)
|
||||||
{
|
{
|
||||||
struct thread *thread = threads__findnew(event->fork.pid);
|
struct thread *thread = threads__findnew(event->fork.pid);
|
||||||
struct thread *parent = threads__findnew(event->fork.ppid);
|
struct thread *parent = threads__findnew(event->fork.ppid);
|
||||||
|
|
||||||
dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
|
dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
|
||||||
(void *)(offset + head),
|
(void *)(offset + head),
|
||||||
(void *)(long)(event->header.size),
|
(void *)(long)(event->header.size),
|
||||||
event->fork.pid, event->fork.ppid);
|
event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
|
||||||
|
event->fork.pid, event->fork.tid,
|
||||||
|
event->fork.ppid, event->fork.ptid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A thread clone will have the same PID for both
|
||||||
|
* parent and child.
|
||||||
|
*/
|
||||||
|
if (thread == parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (event->header.type == PERF_EVENT_EXIT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!thread || !parent || thread__fork(thread, parent)) {
|
if (!thread || !parent || thread__fork(thread, parent)) {
|
||||||
dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
|
dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
|
||||||
@@ -1706,7 +1719,8 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
|
|||||||
return process_comm_event(event, offset, head);
|
return process_comm_event(event, offset, head);
|
||||||
|
|
||||||
case PERF_EVENT_FORK:
|
case PERF_EVENT_FORK:
|
||||||
return process_fork_event(event, offset, head);
|
case PERF_EVENT_EXIT:
|
||||||
|
return process_task_event(event, offset, head);
|
||||||
|
|
||||||
case PERF_EVENT_LOST:
|
case PERF_EVENT_LOST:
|
||||||
return process_lost_event(event, offset, head);
|
return process_lost_event(event, offset, head);
|
||||||
|
@@ -285,6 +285,7 @@ static const char *skip_symbols[] = {
|
|||||||
"enter_idle",
|
"enter_idle",
|
||||||
"exit_idle",
|
"exit_idle",
|
||||||
"mwait_idle",
|
"mwait_idle",
|
||||||
|
"mwait_idle_with_hints",
|
||||||
"ppc64_runlatch_off",
|
"ppc64_runlatch_off",
|
||||||
"pseries_dedicated_idle_sleep",
|
"pseries_dedicated_idle_sleep",
|
||||||
NULL
|
NULL
|
||||||
|
@@ -318,7 +318,7 @@ char *quote_path_relative(const char *in, int len,
|
|||||||
strbuf_addch(out, '"');
|
strbuf_addch(out, '"');
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
while (prefix[off] && off < len && prefix[off] == in[off])
|
while (off < len && prefix[off] && prefix[off] == in[off])
|
||||||
if (prefix[off] == '/') {
|
if (prefix[off] == '/') {
|
||||||
prefix += off + 1;
|
prefix += off + 1;
|
||||||
in += off + 1;
|
in += off + 1;
|
||||||
|
@@ -565,7 +565,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
|
|||||||
goto out_elf_end;
|
goto out_elf_end;
|
||||||
|
|
||||||
secstrs = elf_getdata(sec_strndx, NULL);
|
secstrs = elf_getdata(sec_strndx, NULL);
|
||||||
if (symstrs == NULL)
|
if (secstrs == NULL)
|
||||||
goto out_elf_end;
|
goto out_elf_end;
|
||||||
|
|
||||||
nr_syms = shdr.sh_size / shdr.sh_entsize;
|
nr_syms = shdr.sh_size / shdr.sh_entsize;
|
||||||
|
Reference in New Issue
Block a user