From: Namhyung Kim <namhyung@kernel.org>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Namhyung Kim <namhyung.kim@lge.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Hyeoncheol Lee <cheol.lee@lge.com>,
Hemant Kumar <hkshaw@linux.vnet.ibm.com>,
LKML <linux-kernel@vger.kernel.org>,
Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
"zhangwei\(Jovi\)" <jovi.zhangwei@huawei.com>,
Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Subject: Re: [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v6)
Date: Tue, 05 Nov 2013 15:58:22 +0900 [thread overview]
Message-ID: <87sivbz65t.fsf@sejong.aot.lge.com> (raw)
In-Reply-To: <20131104184741.GA15945@redhat.com> (Oleg Nesterov's message of "Mon, 4 Nov 2013 19:47:41 +0100")
This is what I have for now:
static void __user *get_user_vaddr(struct pt_regs *regs, unsigned long addr,
struct trace_uprobe *tu)
{
unsigned long base_addr;
unsigned long vaddr;
base_addr = instruction_pointer(regs) - tu->offset;
vaddr = base_addr + addr;
return (void __force __user *) vaddr;
}
When I tested it, it was able to fetch global and bss data from both of
executable and library properly. But it still doesn't work for uretprobes
as you said before.
# perf probe -x ./uprobe-test -a "t1=test1 bss=@0x203000:s32 global=@0x201250:s32 str=@0x201254:string"
# perf probe -x ./uprobe-test -a "t2=test2 bss=@0x203000:s32 global=@0x201250:s32 str=@0x201254:string"
# perf probe -x ./uprobe-test -a "t3=test3 bss=@0x203000:s32 global=@0x201250:s32 str=@0x201254:string"
# perf probe -x ./libfoo.so -a "t4=foo1 bar=@0x201258:s32 baz=@0x203000:s32"
# perf probe -x ./libfoo.so -a "t5=foo2 bar=@0x201258:s32 baz=@0x203000:s32"
# perf probe -x ./libfoo.so -a "t6=foo3 bar=@0x201258:s32 baz=@0x203000:s32"
# perf record -e probe_uprobe:* -e probe_libfoo:* -- ./uprobe-test
# perf script | grep -v ^#
uprobe-test 2997 [002] 13108.308952: probe_uprobe:t1: (400660) bss=0 global=1 str="hello uprobe"
uprobe-test 2997 [002] 13108.322479: probe_uprobe:t2: (400666) bss=0 global=2 str="hello uprobe"
uprobe-test 2997 [002] 13108.335552: probe_uprobe:t3: (40066c) bss=1 global=2 str="hello uprobe"
uprobe-test 2997 [002] 13108.342182: probe_libfoo:t4: (7f5eb977b798) bar=7 baz=0
uprobe-test 2997 [002] 13108.348982: probe_libfoo:t5: (7f5eb977b79e) bar=8 baz=0
uprobe-test 2997 [002] 13108.356041: probe_libfoo:t6: (7f5eb977b7a4) bar=8 baz=9
As you can see symbol offset passed to the uprobes now look like 0x203000
since it's the difference to the base mapping address. For a dso, it's same
as the symbol value, but for an executable the symbol value would be larger
value like 0x603000 since the text segment would be mapped to 0x400000.
But still the difference is same, and I believe this applies to the
randomization too.
This symbol offset calculation was done in the getsymoff which implemented
like below (I'm sure there's a much simpler way to do this, but ...).
And I revised my toy test program like this:
/* ----- 8< ----- test.c ----- 8< ----- */
#include <stdio.h>
#include <stdlib.h>
int global = 1;
char str[] = "hello uprobe";
int bss __attribute__((aligned(4096)));
/* this came from libfoo.so */
extern void foo(void);
void test1(void)
{
/* only for adding probe */
}
void test2(void)
{
/* only for adding probe */
}
void test3(void)
{
/* only for adding probe */
}
int main(void)
{
int local = 3;
char buf[128];
test1();
global = 2;
test2();
bss = 1;
test3();
foo();
// snprintf(buf, sizeof(buf), "cat /proc/%d/maps", getpid());
// system(buf);
return 0;
}
/* ----- 8< ----- foo.c ----- 8< ----- */
int bar = 7;
int baz __attribute__((aligned(4096)));
void foo1(void)
{
/* only for adding probe */
}
void foo2(void)
{
/* only for adding probe */
}
void foo3(void)
{
/* only for adding probe */
}
void foo(void)
{
foo1();
bar = 8;
foo2();
baz = 9;
foo3();
}
/* ----- 8< ----- Makefile ----- 8< ----- */
PERF=/home/namhyung/project/linux/tools/perf/perf
GETSYMOFF=./getsymoff
define make-args
$(eval ARG1 := $(shell echo "bss=@`${GETSYMOFF} uprobe-test bss`:s32"))
$(eval ARG2 := $(shell echo "global=@`${GETSYMOFF} uprobe-test global`:s32"))
$(eval ARG3 := $(shell echo "str=@`${GETSYMOFF} uprobe-test str`:string"))
$(eval ARG4 := $(shell echo "bar=@`${GETSYMOFF} libfoo.so bar`:s32"))
$(eval ARG5 := $(shell echo "baz=@`${GETSYMOFF} libfoo.so baz`:s32"))
endef
all: uprobe-test
uprobe-test: test.c foo.c
gcc -shared -g -fpic -o libfoo.so foo.c
gcc -g -o $@ test.c -Wl,-rpath,. -L. -lfoo
getsymoff: getsymoff.c
gcc -g -o $@ getsymoff.c -lelf
test: uprobe-test getsymoff
$(call make-args)
${PERF} probe -x ./uprobe-test -a "t1=test1 ${ARG1} ${ARG2} ${ARG3}"
${PERF} probe -x ./uprobe-test -a "t2=test2 ${ARG1} ${ARG2} ${ARG3}"
${PERF} probe -x ./uprobe-test -a "t3=test3 ${ARG1} ${ARG2} ${ARG3}"
${PERF} probe -x ./libfoo.so -a "t4=foo1 ${ARG4} ${ARG5}"
${PERF} probe -x ./libfoo.so -a "t5=foo2 ${ARG4} ${ARG5}"
${PERF} probe -x ./libfoo.so -a "t6=foo3 ${ARG4} ${ARG5}"
${PERF} record -e probe_uprobe:* -e probe_libfoo:* -- ./uprobe-test
${PERF} script | grep -v ^#
${PERF} probe -d probe_uprobe:*
${PERF} probe -d probe_libfoo:*
clean:
rm -f uprobe-test libfoo.so getsymoff *.o *~
# ${PERF} probe -d probe_uprobe:* -d probe_libfoo:*
/* ----- 8< ----- getsymoff.c ----- 8< ----- */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <gelf.h>
struct sym {
unsigned long addr;
unsigned long size;
char *name;
};
#define SYMTAB_GROW 16
struct symtab {
struct sym *sym;
size_t nr_sym;
size_t nr_alloc;
};
static struct symtab symtab;
static unsigned long base_addr;
static void usage(void)
{
printf("Usage: %s <file> <symbol>\n", program_invocation_short_name);
exit(0);
}
static int symsort(const void *a, const void *b)
{
const struct sym *syma = a;
const struct sym *symb = b;
return strcmp(syma->name, symb->name);
}
static int symfind(const void *a, const void *b)
{
const struct sym *sym = b;
return strcmp(a, sym->name);
}
static int get_base_addr(Elf *elf)
{
GElf_Ehdr ehdr;
GElf_Phdr phdr;
size_t i;
if (gelf_getehdr(elf, &ehdr) == NULL)
return -1;
for (i = 0; i < ehdr.e_phnum; i++) {
if (gelf_getphdr(elf, i, &phdr) == NULL)
return -1;
if (phdr.p_type != PT_LOAD)
continue;
/* use first loadable segment for the base address */
base_addr = phdr.p_vaddr - phdr.p_offset;
return 0;
}
return -1;
}
static int load_symtab(Elf *elf)
{
int ret = -1;
size_t shstr_idx;
Elf_Scn *shstr_sec, *sym_sec, *str_sec;
Elf_Data *shstr_data, *sym_data, *str_data;
Elf_Scn *sec;
Elf_Data *data;
size_t i, nr_sym;
if (elf_getshdrstrndx(elf, &shstr_idx) < 0)
goto error;
shstr_sec = elf_getscn(elf, shstr_idx);
if (shstr_sec == NULL)
goto error;
shstr_data = elf_getdata(shstr_sec, NULL);
if (shstr_data == NULL)
goto error;
sec = sym_sec = str_sec = NULL;
while ((sec = elf_nextscn(elf, sec)) != NULL) {
char *shstr;
GElf_Shdr shdr;
if (gelf_getshdr(sec, &shdr) == NULL)
goto error;
shstr = ((char *)shstr_data->d_buf) + shdr.sh_name;
if (strcmp(shstr, ".symtab") == 0) {
sym_sec = sec;
nr_sym = shdr.sh_size / shdr.sh_entsize;
}
if (strcmp(shstr, ".strtab") == 0)
str_sec = sec;
}
if (sym_sec == NULL || str_sec == NULL) {
printf("%s: cannot find symbol information. Is it stripped?\n",
__func__);
goto out;
}
sym_data = elf_getdata(sym_sec, NULL);
str_data = elf_getdata(str_sec, NULL);
if (sym_data == NULL || str_data == NULL) {
printf("%s: cannot find symbol information\n", __func__);
goto error;
}
symtab.sym = NULL;
symtab.nr_sym = 0;
symtab.nr_alloc = 0;
for (i = 0; i < nr_sym; i++) {
GElf_Sym elf_sym;
struct sym *sym;
char *name;
if (symtab.nr_sym >= symtab.nr_alloc) {
symtab.nr_alloc += SYMTAB_GROW;
symtab.sym = realloc(symtab.sym,
symtab.nr_alloc * sizeof(*sym));
if (symtab.sym == NULL) {
perror("load_symtab: realloc");
goto out;
}
}
if (gelf_getsym(sym_data, i, &elf_sym) == NULL)
goto error;
if (elf_sym.st_size == 0)
continue;
sym = &symtab.sym[symtab.nr_sym++];
name = ((char *)str_data->d_buf) + elf_sym.st_name;
sym->addr = elf_sym.st_value;
sym->size = elf_sym.st_size;
sym->name = strdup(name);
if (sym->name == NULL) {
perror("load_symtab: strdup");
goto out;
}
}
qsort(symtab.sym, symtab.nr_sym, sizeof(*symtab.sym), symsort);
ret = 0;
out:
return ret;
error:
printf("%s: %s\n", __func__, elf_errmsg(elf_errno()));
goto out;
}
static struct sym * find_symtab(const char *name)
{
return bsearch(name, symtab.sym, symtab.nr_sym,
sizeof(*symtab.sym), symfind);
}
static void unload_symtab(void)
{
size_t i;
for (i = 0; i < symtab.nr_sym; i++) {
struct sym *sym = symtab.sym + i;
free(sym->name);
}
free(symtab.sym);
}
int main(int argc, char *argv[])
{
int fd;
char *filename;
char *symbol;
Elf *elf;
struct sym *sym;
if (argc < 3)
usage();
filename = argv[1];
symbol = argv[2];
elf_version(EV_CURRENT);
fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
printf("%s: %s\n", __func__, elf_errmsg(elf_errno()));
goto out;
}
if (get_base_addr(elf) < 0)
goto out_error;
if (load_symtab(elf) < 0)
goto out_error;
sym = find_symtab(symbol);
if (sym)
printf("%#lx\n", sym->addr - base_addr);
else
printf("cannot find symbol: %s\n", symbol);
out_error:
unload_symtab();
elf_end(elf);
out:
close(fd);
return 0;
}
next prev parent reply other threads:[~2013-11-05 6:58 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-29 6:53 Namhyung Kim
2013-10-29 6:53 ` [PATCH 01/13] tracing/uprobes: Fix documentation of uprobe registration syntax Namhyung Kim
2013-10-29 6:53 ` [PATCH 02/13] tracing/probes: Fix basic print type functions Namhyung Kim
2013-10-29 6:53 ` [PATCH 03/13] tracing/kprobes: Move fetch functions to trace_kprobe.c Namhyung Kim
2013-10-29 6:53 ` [PATCH 04/13] tracing/kprobes: Add fetch{,_size} member into deref fetch method Namhyung Kim
2013-10-29 6:53 ` [PATCH 05/13] tracing/kprobes: Staticize stack and memory fetch functions Namhyung Kim
2013-10-29 6:53 ` [PATCH 06/13] tracing/kprobes: Factor out struct trace_probe Namhyung Kim
2013-10-29 6:53 ` [PATCH 07/13] tracing/uprobes: Convert to " Namhyung Kim
2013-10-29 6:53 ` [PATCH 08/13] tracing/kprobes: Move common functions to trace_probe.h Namhyung Kim
2013-10-29 6:53 ` [PATCH 09/13] tracing/kprobes: Integrate duplicate set_print_fmt() Namhyung Kim
2013-10-29 6:53 ` [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer Namhyung Kim
2013-10-31 18:16 ` Oleg Nesterov
2013-11-01 9:00 ` Namhyung Kim
2013-11-04 8:06 ` Namhyung Kim
2013-11-04 14:35 ` Oleg Nesterov
2013-11-05 1:12 ` Namhyung Kim
2013-11-01 15:09 ` Oleg Nesterov
2013-11-01 15:22 ` Oleg Nesterov
2013-11-03 20:20 ` Oleg Nesterov
2013-11-04 8:11 ` Namhyung Kim
2013-11-04 14:38 ` Oleg Nesterov
2013-11-05 1:17 ` Namhyung Kim
2013-10-29 6:53 ` [PATCH 11/13] tracing/kprobes: Add priv argument to fetch functions Namhyung Kim
2013-11-04 16:09 ` Oleg Nesterov
2013-11-05 2:10 ` Namhyung Kim
2013-10-29 6:53 ` [PATCH 12/13] tracing/uprobes: Add more " Namhyung Kim
2013-10-31 18:22 ` Oleg Nesterov
2013-11-04 8:50 ` Namhyung Kim
2013-11-04 16:44 ` Oleg Nesterov
2013-11-04 17:17 ` Steven Rostedt
2013-11-05 2:19 ` Namhyung Kim
2013-11-05 2:17 ` Namhyung Kim
2013-11-01 17:53 ` Oleg Nesterov
2013-10-29 6:53 ` [PATCH 13/13] tracing/uprobes: Add support for full argument access methods Namhyung Kim
2013-10-30 10:36 ` [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v6) Masami Hiramatsu
2013-11-02 15:54 ` Oleg Nesterov
2013-11-04 8:46 ` Namhyung Kim
2013-11-04 8:59 ` Namhyung Kim
2013-11-04 15:51 ` Oleg Nesterov
2013-11-04 16:22 ` Oleg Nesterov
2013-11-04 18:47 ` Oleg Nesterov
2013-11-04 18:57 ` Oleg Nesterov
2013-11-05 2:51 ` Namhyung Kim
2013-11-05 16:41 ` Oleg Nesterov
2013-11-06 8:37 ` Namhyung Kim
2013-11-05 2:49 ` Namhyung Kim
2013-11-05 6:58 ` Namhyung Kim [this message]
2013-11-05 17:45 ` Oleg Nesterov
2013-11-05 19:24 ` Oleg Nesterov
2013-11-06 8:57 ` Namhyung Kim
2013-11-06 17:37 ` Oleg Nesterov
2013-11-06 18:24 ` Oleg Nesterov
2013-11-07 9:00 ` Namhyung Kim
2013-11-08 17:00 ` Oleg Nesterov
2013-11-12 7:49 ` Namhyung Kim
2013-11-07 8:48 ` Namhyung Kim
2013-11-09 3:18 ` Masami Hiramatsu
2013-11-09 15:23 ` Oleg Nesterov
2013-11-12 8:00 ` Namhyung Kim
2013-11-12 18:44 ` Oleg Nesterov
2013-11-25 6:59 ` Namhyung Kim
2013-11-25 14:12 ` [PATCH] uprobes: Allocate ->utask before handler_chain() for tracing handlers Oleg Nesterov
2013-11-06 8:48 ` [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v6) Namhyung Kim
2013-11-06 16:28 ` Oleg Nesterov
2013-11-07 7:33 ` Namhyung Kim
2013-11-08 16:52 ` Oleg Nesterov
2013-11-05 2:15 ` Namhyung Kim
2013-11-05 16:33 ` Oleg Nesterov
2013-11-06 8:34 ` Namhyung Kim
2013-11-05 1:59 ` Namhyung Kim
2013-11-04 15:01 ` Oleg Nesterov
2013-11-05 1:53 ` Namhyung Kim
2013-11-05 16:28 ` Oleg Nesterov
2013-11-06 8:31 ` Namhyung Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87sivbz65t.fsf@sejong.aot.lge.com \
--to=namhyung@kernel.org \
--cc=acme@ghostprotocols.net \
--cc=cheol.lee@lge.com \
--cc=hkshaw@linux.vnet.ibm.com \
--cc=jovi.zhangwei@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=namhyung.kim@lge.com \
--cc=oleg@redhat.com \
--cc=rostedt@goodmis.org \
--cc=srikar@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome