a bit of refactoring in the test/ dir + completed dwarf_location_lists example
diff --git a/examples/dwarf_location_lists.py b/examples/dwarf_location_lists.py
index 266bceb..a9f22bb 100644
--- a/examples/dwarf_location_lists.py
+++ b/examples/dwarf_location_lists.py
@@ -18,6 +18,9 @@
sys.path.extend(['.', '..'])
from elftools.elf.elffile import ELFFile
+from elftools.dwarf.descriptions import (
+ describe_DWARF_expr, set_global_machine_arch)
+from elftools.dwarf.locationlists import LocationEntry
def process_file(filename):
@@ -37,6 +40,10 @@
# section, and returned here as a LocationLists object.
location_lists = dwarfinfo.location_lists()
+ # This is required for the descriptions module to correctly decode
+ # register names contained in DWARF expressions.
+ set_global_machine_arch(elffile.get_machine_arch())
+
for CU in dwarfinfo.iter_CUs():
# DWARFInfo allows to iterate over the compile units contained in
# the .debug_info section. CU is a CompileUnit object, with some
@@ -52,17 +59,45 @@
# AttributeValue object (from elftools.dwarf.die), which we
# can examine.
for attr in DIE.attributes.itervalues():
- if ( attr.name == 'DW_AT_location' and
- attr.form in ('DW_FORM_data4', 'DW_FORM_data8')):
+ if attribute_has_location_list(attr):
# This is a location list. Its value is an offset into
# the .debug_loc section, so we can use the location
# lists object to decode it.
loclist = location_lists.get_location_list_at_offset(
attr.value)
- print(' DIE %s. attr %s.\n %s' % (
+
+ print(' DIE %s. attr %s.\n%s' % (
DIE.tag,
attr.name,
- loclist))
+ show_loclist(loclist, dwarfinfo, indent=' ')))
+
+def show_loclist(loclist, dwarfinfo, indent):
+ """ Display a location list nicely, decoding the DWARF expressions
+ contained within.
+ """
+ d = []
+ for loc_entity in loclist:
+ if isinstance(loc_entity, LocationEntry):
+ d.append('%s <<%s>>' % (
+ loc_entity,
+ describe_DWARF_expr(loc_entity.loc_expr, dwarfinfo.structs)))
+ else:
+ d.append(str(loc_entity))
+ return '\n'.join(indent + s for s in d)
+
+
+def attribute_has_location_list(attr):
+ """ Only some attributes can have location list values, if they have the
+ required DW_FORM (loclistptr "class" in DWARF spec v3)
+ """
+ if (attr.name in ( 'DW_AT_location', 'DW_AT_string_length',
+ 'DW_AT_const_value', 'DW_AT_return_addr',
+ 'DW_AT_data_member_location', 'DW_AT_frame_base',
+ 'DW_AT_segment', 'DW_AT_static_link',
+ 'DW_AT_use_location', 'DW_AT_vtable_elem_location')):
+ if attr.form in ('DW_FORM_data4', 'DW_FORM_data8'):
+ return True
+ return False
if __name__ == '__main__':
diff --git a/test/__init__.py b/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/__init__.py
diff --git a/test/utils/Makefile b/test/external_tools/Makefile
similarity index 100%
rename from test/utils/Makefile
rename to test/external_tools/Makefile
diff --git a/test/utils/README.txt b/test/external_tools/README.txt
similarity index 100%
rename from test/utils/README.txt
rename to test/external_tools/README.txt
diff --git a/test/utils/elf_creator.c b/test/external_tools/elf_creator.c
similarity index 100%
rename from test/utils/elf_creator.c
rename to test/external_tools/elf_creator.c
diff --git a/test/run_readelf_tests.py b/test/run_readelf_tests.py
index 5effd5f..9ffa519 100755
--- a/test/run_readelf_tests.py
+++ b/test/run_readelf_tests.py
@@ -12,9 +12,9 @@
from difflib import SequenceMatcher
from optparse import OptionParser
import logging
-import subprocess
import tempfile
import platform
+from test.utils import run_exe, is_in_rootdir
# Create a global logger object
@@ -33,19 +33,6 @@
yield os.path.join(rootdir, filename)
-def run_exe(exe_path, args):
- """ Runs the given executable as a subprocess, given the
- list of arguments. Captures its return code (rc) and stdout and
- returns a pair: rc, stdout_str
- """
- popen_cmd = [exe_path] + args
- if os.path.splitext(exe_path)[1] == '.py':
- popen_cmd.insert(0, 'python')
- proc = subprocess.Popen(popen_cmd, stdout=subprocess.PIPE)
- proc_stdout = proc.communicate()[0]
- return proc.returncode, proc_stdout
-
-
def run_test_on_file(filename, verbose=False):
""" Runs a test on the given input filename. Return True if all test
runs succeeded.
@@ -173,21 +160,10 @@
testlog.info('@@ Output #%s dumped to file: %s' % (i + 1, path))
-def die(msg):
- testlog.error('Error: %s' % msg)
- sys.exit(1)
-
-
-def is_in_rootdir():
- """ Check whether the current dir is the root dir of pyelftools
- """
- dirstuff = os.listdir('.')
- return 'test' in dirstuff and 'elftools' in dirstuff
-
-
def main():
if not is_in_rootdir():
- die('Please run me from the root dir of pyelftools!')
+ testlog.error('Error: Please run me from the root dir of pyelftools!')
+ return 1
optparser = OptionParser(
usage='usage: %prog [options] [file] [file] ...',
diff --git a/test/utils.py b/test/utils.py
new file mode 100644
index 0000000..e09521c
--- /dev/null
+++ b/test/utils.py
@@ -0,0 +1,22 @@
+import os, subprocess
+
+
+def run_exe(exe_path, args):
+ """ Runs the given executable as a subprocess, given the
+ list of arguments. Captures its return code (rc) and stdout and
+ returns a pair: rc, stdout_str
+ """
+ popen_cmd = [exe_path] + args
+ if os.path.splitext(exe_path)[1] == '.py':
+ popen_cmd.insert(0, 'python')
+ proc = subprocess.Popen(popen_cmd, stdout=subprocess.PIPE)
+ proc_stdout = proc.communicate()[0]
+ return proc.returncode, proc_stdout
+
+
+def is_in_rootdir():
+ """ Check whether the current dir is the root dir of pyelftools
+ """
+ dirstuff = os.listdir('.')
+ return 'test' in dirstuff and 'elftools' in dirstuff
+
diff --git a/z.py b/z.py
index f04c4cd..02d4f3f 100644
--- a/z.py
+++ b/z.py
@@ -21,8 +21,10 @@
from elftools.dwarf.locationlists import LocationLists
from elftools.dwarf.descriptions import describe_DWARF_expr
llists = LocationLists(dinfo.debug_loc_sec.stream, dinfo.structs)
-for li in llists.get_location_list_at_offset(0):
- print li
- print describe_DWARF_expr(li.loc_expr, dinfo.structs)
+for loclist in llists.iter_location_lists():
+ print '----> loclist!'
+ for li in loclist:
+ print li
+ print describe_DWARF_expr(li.loc_expr, dinfo.structs)