Skip to content

Commit d30caa8

Browse files
authored
Merge pull request #271 from vmprof/pypy-resolve-many-addr
PyPy resolve many addr
2 parents b381d92 + 368e73c commit d30caa8

File tree

4 files changed

+54
-8
lines changed

4 files changed

+54
-8
lines changed

vmprof/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,19 @@ def get_profile_path():
135135
if hasattr(_vmprof, 'get_profile_path'):
136136
return _vmprof.get_profile_path()
137137
raise NotImplementedError("get_profile_path not implemented on this platform")
138+
139+
def resolve_many_addr(addrs):
140+
""" Try to symbolicate the function addresses in addrs to triples of
141+
(function_name, line_number or 0, sourcefile or shared library)
142+
returns a dictionary mapping the addresses where that worked to said triples.
143+
"""
144+
if hasattr(_vmprof, 'resolve_many_addr'):
145+
return _vmprof.resolve_many_addr(addrs)
146+
if hasattr(_vmprof, 'resolve_addr'):
147+
res = {}
148+
for addr in addrs:
149+
info = _vmprof.resolve_addr(addr)
150+
if info is not None:
151+
res[addr] = info
152+
return res
153+
return {} # valid result to always know nothing

vmprof/reader.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,24 +310,25 @@ def setup(self):
310310
self.dedup = set()
311311

312312
def finished_reading_profile(self):
313-
import _vmprof
313+
import _vmprof, vmprof
314314
if not hasattr(_vmprof, 'resolve_addr'):
315315
# windows does not implement that!
316316
return
317317

318-
resolve_addr = _vmprof.resolve_addr
319-
from _vmprof import resolve_addr
320318
LogReader.finished_reading_profile(self)
321319
if len(self.dedup) == 0:
322320
return
321+
all_addresses = vmprof.resolve_many_addr(
322+
[addr for addr in self.dedup if isinstance(addr, NativeCode)])
323+
323324
self.fileobj.seek(0, os.SEEK_END)
324325
# must match '<lang>:<name>:<line>:<file>'
325326
# 'n' has been chosen as lang here, because the symbol
326327
# can be generated from several languages (e.g. C, C++, ...)
327328

328329
for addr in self.dedup:
329-
bytelist = [b"\x08"]
330-
result = resolve_addr(addr)
330+
bytelist = [MARKER_NATIVE_SYMBOLS]
331+
result = all_addresses.get(addr)
331332
if result is None:
332333
name, lineno, srcfile = None, 0, None
333334
else:

vmprof/test/test_c_symboltable.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44
from cffi import FFI
55
from array import array
66

7+
import _vmprof
8+
79
if sys.platform != 'win32':
810

911
ffi = FFI()
1012
ffi.cdef("""
1113
//void dump_all_known_symbols(int fd);
1214
int test_extract(char ** name, int * lineno, char ** src);
1315
int test_extract_sofile(char ** name, int * lineno, char ** src);
16+
17+
int somefunc();
18+
void* get_somefunc(int);
1419
""")
1520
with open("src/symboltable.c", "rb") as fd:
1621
source = fd.read().decode()
@@ -36,7 +41,16 @@
3641
return vmp_resolve_addr(&abs, gname, 64,
3742
lineno, gsrc, 128);
3843
}
44+
45+
int somefunc() {return 1;}
46+
void* get_somefunc(int which) {
47+
if (which == 0) return &somefunc;
48+
if (which == 1) return &abs;
49+
return NULL;
50+
}
3951
"""
52+
# replace the name, otherwise we'll get the one built into pypy
53+
source = source.replace('vmp_resolve_addr', 'vmp_resolve_addr_2')
4054
libs = [] #['unwind', 'unwind-x86_64']
4155
includes = ['src']
4256
if sys.platform.startswith('linux'):
@@ -80,7 +94,7 @@ def test_resolve_addr(self):
8094
_lineno = ffi.new("int*")
8195
lib.test_extract(name, _lineno, src)
8296

83-
assert ffi.string(name[0]) == b"vmp_resolve_addr"
97+
assert ffi.string(name[0]) == b"vmp_resolve_addr_2"
8498
srcfile = ffi.string(src[0])
8599
assert b"_test_symboltable" in srcfile
86100
if not srcfile.endswith(b"vmprof/test/_test_symboltable.c"):
@@ -90,7 +104,7 @@ def test_resolve_addr(self):
90104
with open("vmprof/test/_test_symboltable.c", "rb") as fd:
91105
lineno = 1
92106
for line in fd.readlines():
93-
if "int vmp_resolve_addr(void * addr," in line.decode():
107+
if "int vmp_resolve_addr_2(void * addr," in line.decode():
94108
if _lineno[0] == lineno:
95109
break
96110
lineno += 1
@@ -116,3 +130,18 @@ def test_sofile_in_srcfile(self):
116130
elif sys.platform == "darwin":
117131
# osx
118132
assert b"libsystem_c.dylib" in ffi.string(src[0])
133+
134+
@pytest.mark.skipif("not hasattr(_vmprof, 'resolve_addr')")
135+
def test_vmprof_resolve_addr(self):
136+
res = _vmprof.resolve_addr(int(self.ffi.cast('intptr_t', self.lib.get_somefunc(0))))
137+
assert res[0] == 'somefunc'
138+
139+
def test_vmprof_resolve_many_addr(self):
140+
import vmprof
141+
addrs = [int(self.ffi.cast('intptr_t', self.lib.get_somefunc(which))) for which in [0, 1, 2]]
142+
res = vmprof.resolve_many_addr(addrs)
143+
assert len(res) <= 3
144+
if addrs[0] in res:
145+
assert res[addrs[0]][0] == 'somefunc'
146+
if addrs[1] in res:
147+
assert res[addrs[1]][0] == 'abs'

vmprof/test/test_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def read(self, count):
5858
PY3K = True
5959
else:
6060
PY3K = False
61-
if hasattr(os, 'uname') and os.uname().machine == 'ppc64le':
61+
if hasattr(os, 'uname') and os.uname()[4] == 'ppc64le':
6262
PPC64LE = True
6363
else:
6464
PPC64LE = False

0 commit comments

Comments
 (0)