_iterkeys = "keys"
_iteritems = "items"
+ _itervalues = "values"
+
+ def bytes2str(b): return b.decode('latin-1')
+ def str2bytes(s): return s.encode('latin-1')
+ def int2byte(i):return bytes((i,))
+ def byte2int(b): return b
+
+ ifilter = filter
else:
import cStringIO
StringIO = BytesIO = cStringIO.StringIO
_iterkeys = "iterkeys"
_iteritems = "iteritems"
+ _itervalues = "itervalues"
+
+ def bytes2str(b): return b
+ def str2bytes(s): return s
+ int2byte = chr
+ byte2int = ord
+
+ from itertools import ifilter
def iterkeys(d):
"""Return an iterator over the keys of a dictionary."""
return getattr(d, _iterkeys)()
+def itervalues(d):
+ """Return an iterator over the values of a dictionary."""
+ return getattr(d, _itervalues)()
+
def iteritems(d):
"""Return an iterator over the items of a dictionary."""
return getattr(d, _iteritems)()
#-------------------------------------------------------------------------------
from contextlib import contextmanager
from .exceptions import ELFParseError, ELFError, DWARFError
+from .py3compat import int2byte
from ..construct import ConstructError
def bytelist2string(bytelist):
- """ Convert a list of byte values (e.g. [0x10 0x20 0x00]) to a string
- (e.g. '\x10\x20\x00').
+ """ Convert a list of byte values (e.g. [0x10 0x20 0x00]) to a bytes object
+ (e.g. b'\x10\x20\x00').
"""
- return ''.join(chr(b) for b in bytelist)
+ return b''.join(int2byte(b) for b in bytelist)
def struct_parse(struct, stream, stream_pos=None):
found = False
while True:
chunk = stream.read(CHUNKSIZE)
- end_index = chunk.find('\x00')
+ end_index = chunk.find(b'\x00')
if end_index >= 0:
chunks.append(chunk[:end_index])
found = True
chunks.append(chunk)
if len(chunk) < CHUNKSIZE:
break
- return ''.join(chunks) if found else None
+ return b''.join(chunks) if found else None
def elf_assert(cond, msg=''):
from .dwarf_expr import GenericExprVisitor
from .die import DIE
from ..common.utils import preserve_stream_pos, dwarf_assert
+from ..common.py3compat import bytes2str
from .callframe import instruction_name, CIE, FDE
return '0x%x 0x%x' % (low_word, high_word)
def _describe_attr_strp(attr, die, section_offset):
- return '(indirect string, offset: 0x%x): %s' % (attr.raw_value, attr.value)
+ return '(indirect string, offset: 0x%x): %s' % (
+ attr.raw_value, bytes2str(attr.value))
+
+def _describe_attr_string(attr, die, section_offset):
+ return bytes2str(attr.value)
def _describe_attr_debool(attr, die, section_offset):
""" To be consistent with readelf, generate 1 for True flags, 0 for False
DW_FORM_data2=_describe_attr_value_passthrough,
DW_FORM_sdata=_describe_attr_value_passthrough,
DW_FORM_udata=_describe_attr_value_passthrough,
- DW_FORM_string=_describe_attr_value_passthrough,
+ DW_FORM_string=_describe_attr_string,
DW_FORM_strp=_describe_attr_strp,
DW_FORM_block1=_describe_attr_block,
DW_FORM_block2=_describe_attr_block,
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
-from ..common.py3compat import StringIO, iteritems
+from ..common.py3compat import BytesIO, iteritems
from ..common.utils import struct_parse, bytelist2string
""" Process (visit) a DWARF expression. expr should be a list of
(integer) byte values.
"""
- self.stream = StringIO(bytelist2string(expr))
+ self.stream = BytesIO(bytelist2string(expr))
while True:
# Get the next opcode from the stream. If nothing is left in the
if opcode >= self.header['opcode_base']:
# Special opcode (follow the recipe in 6.2.5.1)
adjusted_opcode = opcode - self['opcode_base']
- address_addend = ((adjusted_opcode / self['line_range']) *
+ address_addend = ((adjusted_opcode // self['line_range']) *
self['minimum_instruction_length'])
state.address += address_addend
line_addend = (self['line_base'] +
add_entry_old_state(opcode, [operand])
elif opcode == DW_LNS_const_add_pc:
adjusted_opcode = 255 - self['opcode_base']
- address_addend = ((adjusted_opcode / self['line_range']) *
+ address_addend = ((adjusted_opcode // self['line_range']) *
self['minimum_instruction_length'])
state.address += address_addend
add_entry_old_state(opcode, [address_addend])
Array(lambda ctx: ctx['opcode_base'] - 1,
self.Dwarf_uint8('standard_opcode_lengths')),
RepeatUntilExcluding(
- lambda obj, ctx: obj == '',
+ lambda obj, ctx: obj == b'',
CString('include_directory')),
RepeatUntilExcluding(
lambda obj, ctx: len(obj.name) == 0,
#-------------------------------------------------------------------------------
from .enums import ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
from .constants import P_FLAGS, SH_FLAGS
+from ..common.py3compat import iteritems
def describe_ei_class(x):
)
_DESCR_RELOC_TYPE_i386 = dict(
- (v, k) for k, v in ENUM_RELOC_TYPE_i386.iteritems())
+ (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_i386))
_DESCR_RELOC_TYPE_x64 = dict(
- (v, k) for k, v in ENUM_RELOC_TYPE_x64.iteritems())
+ (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_x64))
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
-from ..common.py3compat import StringIO
+from ..common.py3compat import BytesIO
from ..common.exceptions import ELFError
from ..common.utils import struct_parse, elf_assert
from ..construct import ConstructError
We assume that if it has the debug_info section, it has all theother
required sections as well.
"""
- return bool(self.get_section_by_name('.debug_info'))
+ return bool(self.get_section_by_name(b'.debug_info'))
def get_dwarf_info(self, relocate_dwarf_sections=True):
""" Return a DWARFInfo object representing the debugging information in
# Sections that aren't found will be passed as None to DWARFInfo.
#
debug_sections = {}
- for secname in ('.debug_info', '.debug_abbrev', '.debug_str',
- '.debug_line', '.debug_frame', '.debug_loc',
- '.debug_ranges'):
+ for secname in (b'.debug_info', b'.debug_abbrev', b'.debug_str',
+ b'.debug_line', b'.debug_frame', b'.debug_loc',
+ b'.debug_ranges'):
section = self.get_section_by_name(secname)
if section is None:
debug_sections[secname] = None
little_endian=self.little_endian,
default_address_size=self.elfclass / 8,
machine_arch=self.get_machine_arch()),
- debug_info_sec=debug_sections['.debug_info'],
- debug_abbrev_sec=debug_sections['.debug_abbrev'],
- debug_frame_sec=debug_sections['.debug_frame'],
- debug_str_sec=debug_sections['.debug_str'],
- debug_loc_sec=debug_sections['.debug_loc'],
- debug_ranges_sec=debug_sections['.debug_ranges'],
- debug_line_sec=debug_sections['.debug_line'])
+ debug_info_sec=debug_sections[b'.debug_info'],
+ debug_abbrev_sec=debug_sections[b'.debug_abbrev'],
+ debug_frame_sec=debug_sections[b'.debug_frame'],
+ debug_str_sec=debug_sections[b'.debug_str'],
+ debug_loc_sec=debug_sections[b'.debug_loc'],
+ debug_ranges_sec=debug_sections[b'.debug_ranges'],
+ debug_line_sec=debug_sections[b'.debug_line'])
def get_machine_arch(self):
""" Return the machine architecture, as detected from the ELF header.
"""
self.stream.seek(section['sh_offset'])
# The section data is read into a new stream, for processing
- section_stream = StringIO()
- # Using .write instead of initializing StringIO with the string because
- # such a StringIO from cStringIO is read-only.
+ section_stream = BytesIO()
section_stream.write(self.stream.read(section['sh_size']))
if relocate_dwarf_sections:
found.
"""
reloc_section_names = (
- '.rel' + section.name,
- '.rela' + section.name)
+ b'.rel' + section.name,
+ b'.rela' + section.name)
# Find the relocation section aimed at this one. Currently assume
# that either .rel or .rela section exists for this section, but
# not both.
# This code is in the public domain
#-------------------------------------------------------------------------------
from ..construct import CString
-from ..common.utils import struct_parse, elf_assert
+from ..common.utils import struct_parse, elf_assert, parse_cstring_from_stream
class Section(object):
""" Get the string stored at the given offset in this string table.
"""
table_offset = self['sh_offset']
- return struct_parse(
- CString(''),
- self.stream,
- stream_pos=table_offset + offset)
+ s = parse_cstring_from_stream(self.stream, table_offset + offset)
+ return s
class SymbolTableSection(Section):
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import bytes2str
from elftools.elf.elffile import ELFFile
# is done transparently by the library, and such a value will be
# simply given as a string.
name_attr = top_DIE.attributes['DW_AT_name']
- print(' name=%s' % name_attr.value)
+ print(' name=%s' % bytes2str(name_attr.value))
# Display DIEs recursively starting with top_DIE
die_info_rec(top_DIE)
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import itervalues
from elftools.elf.elffile import ELFFile
from elftools.dwarf.descriptions import (
describe_DWARF_expr, set_global_machine_arch)
# Go over all attributes of the DIE. Each attribute is an
# AttributeValue object (from elftools.dwarf.die), which we
# can examine.
- for attr in DIE.attributes.itervalues():
+ for attr in itervalues(DIE.attributes):
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
attr.name,
show_loclist(loclist, dwarfinfo, indent=' ')))
+
def show_loclist(loclist, dwarfinfo, indent):
""" Display a location list nicely, decoding the DWARF expressions
contained within.
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import itervalues
from elftools.elf.elffile import ELFFile
from elftools.dwarf.descriptions import (
describe_DWARF_expr, set_global_machine_arch)
# Go over all attributes of the DIE. Each attribute is an
# AttributeValue object (from elftools.dwarf.die), which we
# can examine.
- for attr in DIE.attributes.itervalues():
+ for attr in itervalues(DIE.attributes):
if attribute_has_range_list(attr):
# This is a range list. Its value is an offset into
# the .debug_ranges section, so we can use the range
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import bytes2str
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
elffile = ELFFile(stream)
# Just use the public methods of ELFFile to get what we need
+ # Note that section names, like everything read from the file, are bytes
+ # objects.
print(' %s sections' % elffile.num_sections())
- section = elffile.get_section_by_name('.symtab')
+ section = elffile.get_section_by_name(b'.symtab')
if not section:
print(' No symbol table found. Perhaps this ELF has been stripped?')
# A section type is in its header, but the name was decoded and placed in
# a public attribute.
+ # bytes2str is used to print the name of the section for consistency of
+ # output between Python 2 and 3. The section name is a bytes object.
print(' Section name: %s, type: %s' %(
- section.name, section['sh_type']))
+ bytes2str(section.name), section['sh_type']))
# But there's more... If this section is a symbol table section (which is
# the case in the sample ELF file that comes with the examples), we can
num_symbols = section.num_symbols()
print(" It's a symbol section with %s symbols" % num_symbols)
print(" The name of the last symbol in the section is: %s" % (
- section.get_symbol(num_symbols - 1).name))
+ bytes2str(section.get_symbol(num_symbols - 1).name)))
if __name__ == '__main__':
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import bytes2str
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
# Read the .rela.dyn section from the file, by explicitly asking
# ELFFile for this section
- reladyn_name = '.rela.dyn'
+ # Recall that section names are bytes objects
+ reladyn_name = b'.rela.dyn'
reladyn = elffile.get_section_by_name(reladyn_name)
if not isinstance(reladyn, RelocationSection):
- print(' The file has no %s section' % reladyn_name)
+ print(' The file has no %s section' % bytes2str(reladyn_name))
print(' %s section with %s relocations' % (
- reladyn_name, reladyn.num_relocations()))
+ bytes2str(reladyn_name), reladyn.num_relocations()))
for reloc in reladyn.iter_relocations():
print(' Relocation (%s)' % 'RELA' if reloc.is_RELA() else 'REL')
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import bytes2str
from elftools.elf.elffile import ELFFile
elffile = ELFFile(f)
for section in elffile.iter_sections():
- if section.name.startswith('.debug'):
- print(' ' + section.name)
+ # Section names are bytes objects
+ if section.name.startswith(b'.debug'):
+ print(' ' + bytes2str(section.name))
if __name__ == '__main__':
except ImportError:
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import bytes2str
from elftools.elf.elffile import ELFFile
# is done transparently by the library, and such a value will be
# simply given as a string.
name_attr = top_DIE.attributes['DW_AT_name']
- print(' name=%s' % name_attr.value)
+ print(' name=%s' % bytes2str(name_attr.value))
if __name__ == '__main__':
for filename in sys.argv[1:]:
#-------------------------------------------------------------------------------
import os, sys
from optparse import OptionParser
-from itertools import ifilter
import string
# If elftools is not installed, maybe we're running from the root or scripts
from elftools import __version__
from elftools.common.exceptions import ELFError
+from elftools.common.py3compat import (
+ ifilter, byte2int, bytes2str, itervalues, str2bytes)
from elftools.elf.elffile import ELFFile
from elftools.elf.segments import InterpSegment
from elftools.elf.sections import SymbolTableSection
"""
self._emitline('ELF Header:')
self._emit(' Magic: ')
- self._emitline(' '.join('%2.2x' % ord(b)
+ self._emitline(' '.join('%2.2x' % byte2int(b)
for b in self.elffile.e_ident_raw))
header = self.elffile.header
e_ident = header['e_ident']
if isinstance(segment, InterpSegment):
self._emitline(' [Requesting program interpreter: %s]' %
- segment.get_interp_name())
+ bytes2str(segment.get_interp_name()))
# Sections to segments mapping
#
for section in self.elffile.iter_sections():
if ( not section.is_null() and
segment.section_in_segment(section)):
- self._emit('%s ' % section.name)
+ self._emit('%s ' % bytes2str(section.name))
self._emitline('')
#
for nsec, section in enumerate(self.elffile.iter_sections()):
self._emit(' [%2u] %-17.17s %-15.15s ' % (
- nsec, section.name, describe_sh_type(section['sh_type'])))
+ nsec, bytes2str(section.name), describe_sh_type(section['sh_type'])))
if self.elffile.elfclass == 32:
self._emitline('%s %s %s %s %3s %2s %3s %2s' % (
if section['sh_entsize'] == 0:
self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % (
- section.name))
+ bytes2str(section.name)))
continue
self._emitline("\nSymbol table '%s' contains %s entries:" % (
- section.name, section.num_symbols()))
+ bytes2str(section.name), section.num_symbols()))
if self.elffile.elfclass == 32:
self._emitline(' Num: Value Size Type Bind Vis Ndx Name')
describe_symbol_bind(symbol['st_info']['bind']),
describe_symbol_visibility(symbol['st_other']['visibility']),
describe_symbol_shndx(symbol['st_shndx']),
- symbol.name))
+ bytes2str(symbol.name)))
def display_relocations(self):
""" Display the relocations contained in the file
has_relocation_sections = True
self._emitline("\nRelocation section '%s' at offset %s contains %s entries:" % (
- section.name,
+ bytes2str(section.name),
self._format_hex(section['sh_offset']),
section.num_relocations()))
if section.is_RELA():
symbol['st_value'],
fullhex=True, lead0x=False),
' ' if self.elffile.elfclass == 32 else '',
- symbol_name))
+ bytes2str(symbol_name)))
if section.is_RELA():
self._emit(' %s %x' % (
'+' if rel['r_addend'] >= 0 else '-',
section_spec))
return
- self._emitline("\nHex dump of section '%s':" % section.name)
+ self._emitline("\nHex dump of section '%s':" % bytes2str(section.name))
self._note_relocs_for_section(section)
addr = section['sh_addr']
data = section.data()
self._emit(' %s ' % self._format_hex(addr, fieldsize=8))
for i in range(16):
if i < linebytes:
- self._emit('%2.2x' % ord(data[dataptr + i]))
+ self._emit('%2.2x' % byte2int(data[dataptr + i]))
else:
self._emit(' ')
if i % 4 == 3:
self._emit(' ')
for i in range(linebytes):
- c = data[dataptr + i]
- if c >= ' ' and ord(c) < 0x7f:
- self._emit(c)
+ c = data[dataptr + i : dataptr + i + 1]
+ if byte2int(c[0]) >= 32 and byte2int(c[0]) < 0x7f:
+ self._emit(bytes2str(c))
else:
- self._emit('.')
+ self._emit(bytes2str(b'.'))
self._emitline()
addr += linebytes
section_spec))
return
- printables = set(string.printable)
- self._emitline("\nString dump of section '%s':" % section.name)
+ self._emitline("\nString dump of section '%s':" % bytes2str(section.name))
found = False
data = section.data()
dataptr = 0
while dataptr < len(data):
- while dataptr < len(data) and data[dataptr] not in printables:
+ while ( dataptr < len(data) and
+ not (32 <= byte2int(data[dataptr]) <= 127)):
dataptr += 1
if dataptr >= len(data):
break
endptr = dataptr
- while endptr < len(data) and data[endptr] != '\x00':
+ while endptr < len(data) and byte2int(data[endptr]) != 0:
endptr += 1
found = True
self._emitline(' [%6x] %s' % (
- dataptr, data[dataptr:endptr]))
+ dataptr, bytes2str(data[dataptr:endptr])))
dataptr = endptr
return None
except ValueError:
# Not a number. Must be a name then
- return self.elffile.get_section_by_name(spec)
+ return self.elffile.get_section_by_name(str2bytes(spec))
def _note_relocs_for_section(self, section):
""" If there are relocation sections pointing to the givne section,
die.abbrev_code,
die.tag))
- for attr in die.attributes.itervalues():
+ for attr in itervalues(die.attributes):
name = attr.name
# Unknown attribute values are passed-through as integers
if isinstance(name, int):
cu_filename = ''
if len(lineprogram['include_directory']) > 0:
cu_filename = '%s/%s' % (
- lineprogram['include_directory'][0],
- lineprogram['file_entry'][0].name)
+ bytes2str(lineprogram['include_directory'][0]),
+ bytes2str(lineprogram['file_entry'][0].name))
else:
- cu_filename = lineprogram['file_entry'][0].name
+ cu_filename = bytes2str(lineprogram['file_entry'][0].name)
self._emitline('CU: %s:' % cu_filename)
self._emitline('File name Line number Starting address')
if file_entry.dir_index == 0:
# current directory
self._emitline('\n./%s:[++]' % (
- file_entry.name))
+ bytes2str(file_entry.name)))
else:
self._emitline('\n%s/%s:' % (
- lineprogram['include_directory'][file_entry.dir_index - 1],
- file_entry.name))
+ bytes2str(lineprogram['include_directory'][file_entry.dir_index - 1]),
+ bytes2str(file_entry.name)))
elif entry.command == DW_LNE_define_file:
self._emitline('%s:' % (
- lineprogram['include_directory'][entry.args[0].dir_index]))
+ bytes2str(lineprogram['include_directory'][entry.args[0].dir_index])))
elif not state.end_sequence:
# readelf doesn't print the state after end_sequence
# instructions. I think it's a bug but to be compatible
# I don't print them too.
self._emitline('%-35s %11d %18s' % (
- lineprogram['file_entry'][state.file - 1].name,
+ bytes2str(lineprogram['file_entry'][state.file - 1].name),
state.line,
'0' if state.address == 0 else
self._format_hex(state.address)))
self._emitline('\n%08x %08x %08x CIE' % (
entry.offset, entry['length'], entry['CIE_id']))
self._emitline(' Version: %d' % entry['version'])
- self._emitline(' Augmentation: "%s"' % entry['augmentation'])
+ self._emitline(' Augmentation: "%s"' % bytes2str(entry['augmentation']))
self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
self._emitline(' Return address column: %d' % entry['return_address_register'])
entry.offset,
entry['length'],
entry['CIE_id'],
- entry['augmentation'],
+ bytes2str(entry['augmentation']),
entry['code_alignment_factor'],
entry['data_alignment_factor'],
entry['return_address_register']))
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
+from __future__ import print_function
+
try:
import unittest2 as unittest
except ImportError:
tests = unittest.TestLoader().discover('test', 'test*.py', 'test')
unittest.TextTestRunner().run(tests)
except ImportError as err:
- print err
- print '!! Please execute from the root directory of pyelftools'
+ print(err)
+ print('!! Please execute from the root directory of pyelftools')
+
except ImportError:
import unittest
import sys
-from cStringIO import StringIO
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import BytesIO
from elftools.dwarf.callframe import (
CallFrameInfo, CIE, FDE, instruction_name, CallFrameInstruction,
RegisterRule)
def test_spec_sample_d6(self):
# D.6 sample in DWARFv3
- s = StringIO()
- data = ('' +
+ s = BytesIO()
+ data = (b'' +
# first comes the CIE
- '\x20\x00\x00\x00' + # length
- '\xff\xff\xff\xff' + # CIE_id
- '\x03\x00\x04\x7c' + # version, augmentation, caf, daf
- '\x08' + # return address
- '\x0c\x07\x00' +
- '\x08\x00' +
- '\x07\x01' +
- '\x07\x02' +
- '\x07\x03' +
- '\x08\x04' +
- '\x08\x05' +
- '\x08\x06' +
- '\x08\x07' +
- '\x09\x08\x01' +
- '\x00' +
+ b'\x20\x00\x00\x00' + # length
+ b'\xff\xff\xff\xff' + # CIE_id
+ b'\x03\x00\x04\x7c' + # version, augmentation, caf, daf
+ b'\x08' + # return address
+ b'\x0c\x07\x00' +
+ b'\x08\x00' +
+ b'\x07\x01' +
+ b'\x07\x02' +
+ b'\x07\x03' +
+ b'\x08\x04' +
+ b'\x08\x05' +
+ b'\x08\x06' +
+ b'\x08\x07' +
+ b'\x09\x08\x01' +
+ b'\x00' +
# then comes the FDE
- '\x28\x00\x00\x00' + # length
- '\x00\x00\x00\x00' + # CIE_pointer (to CIE at 0)
- '\x44\x33\x22\x11' + # initial_location
- '\x54\x00\x00\x00' + # address range
- '\x41' +
- '\x0e\x0c' + '\x41' +
- '\x88\x01' + '\x41' +
- '\x86\x02' + '\x41' +
- '\x0d\x06' + '\x41' +
- '\x84\x03' + '\x4b' +
- '\xc4' + '\x41' +
- '\xc6' +
- '\x0d\x07' + '\x41' +
- '\xc8' + '\x41' +
- '\x0e\x00' +
- '\x00\x00'
+ b'\x28\x00\x00\x00' + # length
+ b'\x00\x00\x00\x00' + # CIE_pointer (to CIE at 0)
+ b'\x44\x33\x22\x11' + # initial_location
+ b'\x54\x00\x00\x00' + # address range
+ b'\x41' +
+ b'\x0e\x0c' + b'\x41' +
+ b'\x88\x01' + b'\x41' +
+ b'\x86\x02' + b'\x41' +
+ b'\x0d\x06' + b'\x41' +
+ b'\x84\x03' + b'\x4b' +
+ b'\xc4' + b'\x41' +
+ b'\xc6' +
+ b'\x0d\x07' + b'\x41' +
+ b'\xc8' + b'\x41' +
+ b'\x0e\x00' +
+ b'\x00\x00'
)
s.write(data)
def test_describe_CFI_instructions(self):
# The data here represents a single CIE
- data = ('' +
- '\x16\x00\x00\x00' + # length
- '\xff\xff\xff\xff' + # CIE_id
- '\x03\x00\x04\x7c' + # version, augmentation, caf, daf
- '\x08' + # return address
- '\x0c\x07\x02' +
- '\x10\x02\x07\x03\x01\x02\x00\x00\x06\x06')
- s = StringIO(data)
+ data = (b'' +
+ b'\x16\x00\x00\x00' + # length
+ b'\xff\xff\xff\xff' + # CIE_id
+ b'\x03\x00\x04\x7c' + # version, augmentation, caf, daf
+ b'\x08' + # return address
+ b'\x0c\x07\x02' +
+ b'\x10\x02\x07\x03\x01\x02\x00\x00\x06\x06')
+ s = BytesIO(data)
structs = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4)
cfi = CallFrameInfo(s, len(data), structs)
except ImportError:
import unittest
import sys
-from cStringIO import StringIO
sys.path.extend(('..', '.'))
from elftools.dwarf.descriptions import ExprDumper, set_global_machine_arch
except ImportError:
import unittest
import sys
-from cStringIO import StringIO
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import BytesIO, iteritems
from elftools.dwarf.lineprogram import LineProgram, LineState, LineProgramEntry
from elftools.dwarf.structs import DWARFStructs
from elftools.dwarf.constants import *
"""
ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4)
header = ds.Dwarf_lineprog_header.parse(
- '\x04\x10\x00\x00' + # initial lenght
- '\x03\x00' + # version
- '\x20\x00\x00\x00' + # header length
- '\x01\x01\x01\x0F' + # flags
- '\x0A' + # opcode_base
- '\x00\x01\x04\x08\x0C\x01\x01\x01\x00' + # standard_opcode_lengths
+ b'\x04\x10\x00\x00' + # initial lenght
+ b'\x03\x00' + # version
+ b'\x20\x00\x00\x00' + # header length
+ b'\x01\x01\x01\x0F' + # flags
+ b'\x0A' + # opcode_base
+ b'\x00\x01\x04\x08\x0C\x01\x01\x01\x00' + # standard_opcode_lengths
# 2 dir names followed by a NULL
- '\x61\x62\x00\x70\x00\x00' +
+ b'\x61\x62\x00\x70\x00\x00' +
# a file entry
- '\x61\x72\x00\x0C\x0D\x0F' +
+ b'\x61\x72\x00\x0C\x0D\x0F' +
# and another entry
- '\x45\x50\x51\x00\x86\x12\x07\x08' +
+ b'\x45\x50\x51\x00\x86\x12\x07\x08' +
# followed by NULL
- '\x00')
+ b'\x00')
lp = LineProgram(header, stream, ds, 0, len(stream.getvalue()))
return lp
""" Assert that the state attributes specified in kwargs have the given
values (the rest are default).
"""
- for k, v in kwargs.iteritems():
+ for k, v in iteritems(kwargs):
self.assertEqual(getattr(state, k), v)
def test_spec_sample_59(self):
# Sample in figure 59 of DWARFv3
- s = StringIO()
+ s = BytesIO()
s.write(
- '\x02\xb9\x04' +
- '\x0b' +
- '\x38' +
- '\x82' +
- '\x73' +
- '\x02\x02' +
- '\x00\x01\x01')
+ b'\x02\xb9\x04' +
+ b'\x0b' +
+ b'\x38' +
+ b'\x82' +
+ b'\x73' +
+ b'\x02\x02' +
+ b'\x00\x01\x01')
lp = self._make_program_in_stream(s)
linetable = lp.get_entries()
def test_spec_sample_60(self):
# Sample in figure 60 of DWARFv3
- s = StringIO()
+ s = BytesIO()
s.write(
- '\x09\x39\x02' +
- '\x0b' +
- '\x09\x03\x00' +
- '\x0b' +
- '\x09\x08\x00' +
- '\x0a' +
- '\x09\x07\x00' +
- '\x0a' +
- '\x09\x02\x00' +
- '\x00\x01\x01')
+ b'\x09\x39\x02' +
+ b'\x0b' +
+ b'\x09\x03\x00' +
+ b'\x0b' +
+ b'\x09\x08\x00' +
+ b'\x0a' +
+ b'\x09\x07\x00' +
+ b'\x0a' +
+ b'\x09\x02\x00' +
+ b'\x00\x01\x01')
lp = self._make_program_in_stream(s)
linetable = lp.get_entries()
ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4)
c = ds.Dwarf_lineprog_header.parse(
- '\x04\x10\x00\x00' + # initial lenght
- '\x05\x02' + # version
- '\x20\x00\x00\x00' + # header length
- '\x05\x10\x40\x50' + # until and including line_range
- '\x06' + # opcode_base
- '\x00\x01\x04\x08\x0C' + # standard_opcode_lengths
+ b'\x04\x10\x00\x00' + # initial lenght
+ b'\x05\x02' + # version
+ b'\x20\x00\x00\x00' + # header length
+ b'\x05\x10\x40\x50' + # until and including line_range
+ b'\x06' + # opcode_base
+ b'\x00\x01\x04\x08\x0C' + # standard_opcode_lengths
# 2 dir names followed by a NULL
- '\x61\x62\x00\x70\x00\x00' +
+ b'\x61\x62\x00\x70\x00\x00' +
# a file entry
- '\x61\x72\x00\x0C\x0D\x0F' +
+ b'\x61\x72\x00\x0C\x0D\x0F' +
# and another entry
- '\x45\x50\x51\x00\x86\x12\x07\x08' +
+ b'\x45\x50\x51\x00\x86\x12\x07\x08' +
# followed by NULL
- '\x00')
+ b'\x00')
self.assertEqual(c.version, 0x205)
self.assertEqual(c.opcode_base, 6)
self.assertEqual(c.standard_opcode_lengths, [0, 1, 4, 8, 12])
- self.assertEqual(c.include_directory, ['ab', 'p'])
+ self.assertEqual(c.include_directory, [b'ab', b'p'])
self.assertEqual(len(c.file_entry), 2)
- self.assertEqual(c.file_entry[0].name, 'ar')
- self.assertEqual(c.file_entry[1].name, 'EPQ')
+ self.assertEqual(c.file_entry[0].name, b'ar')
+ self.assertEqual(c.file_entry[1].name, b'EPQ')
self.assertEqual(c.file_entry[1].dir_index, 0x12 * 128 + 6)
except ImportError:
import unittest
import sys
-from cStringIO import StringIO
from random import randint
sys.path.extend(['.', '..'])
+from elftools.common.py3compat import int2byte, BytesIO
from elftools.common.utils import (parse_cstring_from_stream,
preserve_stream_pos)
class Test_parse_cstring_from_stream(unittest.TestCase):
- def _make_random_string(self, n):
- return ''.join(chr(randint(32, 127)) for i in range(n))
+ def _make_random_bytes(self, n):
+ return b''.join(int2byte(randint(32, 127)) for i in range(n))
def test_small1(self):
- sio = StringIO('abcdefgh\x0012345')
- self.assertEqual(parse_cstring_from_stream(sio), 'abcdefgh')
- self.assertEqual(parse_cstring_from_stream(sio, 2), 'cdefgh')
- self.assertEqual(parse_cstring_from_stream(sio, 8), '')
+ sio = BytesIO(b'abcdefgh\x0012345')
+ self.assertEqual(parse_cstring_from_stream(sio), b'abcdefgh')
+ self.assertEqual(parse_cstring_from_stream(sio, 2), b'cdefgh')
+ self.assertEqual(parse_cstring_from_stream(sio, 8), b'')
def test_small2(self):
- sio = StringIO('12345\x006789\x00abcdefg\x00iii')
- self.assertEqual(parse_cstring_from_stream(sio), '12345')
- self.assertEqual(parse_cstring_from_stream(sio, 5), '')
- self.assertEqual(parse_cstring_from_stream(sio, 6), '6789')
+ sio = BytesIO(b'12345\x006789\x00abcdefg\x00iii')
+ self.assertEqual(parse_cstring_from_stream(sio), b'12345')
+ self.assertEqual(parse_cstring_from_stream(sio, 5), b'')
+ self.assertEqual(parse_cstring_from_stream(sio, 6), b'6789')
def test_large1(self):
- text = 'i' * 400 + '\x00' + 'bb'
- sio = StringIO(text)
- self.assertEqual(parse_cstring_from_stream(sio), 'i' * 400)
- self.assertEqual(parse_cstring_from_stream(sio, 150), 'i' * 250)
+ text = b'i' * 400 + b'\x00' + b'bb'
+ sio = BytesIO(text)
+ self.assertEqual(parse_cstring_from_stream(sio), b'i' * 400)
+ self.assertEqual(parse_cstring_from_stream(sio, 150), b'i' * 250)
def test_large2(self):
- text = self._make_random_string(5000) + '\x00' + 'jujajaja'
- sio = StringIO(text)
+ text = self._make_random_bytes(5000) + b'\x00' + b'jujajaja'
+ sio = BytesIO(text)
self.assertEqual(parse_cstring_from_stream(sio), text[:5000])
self.assertEqual(parse_cstring_from_stream(sio, 2348), text[2348:5000])
class Test_preserve_stream_pos(object):
def test_basic(self):
- sio = StringIO('abcdef')
+ sio = BytesIO('abcdef')
with preserve_stream_pos(sio):
sio.seek(4)
self.assertEqual(stream.tell(), 0)
# This code is in the public domain
#-------------------------------------------------------------------------------
import os, subprocess, tempfile
+from elftools.common.py3compat import bytes2str
def run_exe(exe_path, args):
popen_cmd.insert(0, 'python')
proc = subprocess.Popen(popen_cmd, stdout=subprocess.PIPE)
proc_stdout = proc.communicate()[0]
- return proc.returncode, proc_stdout
+ return proc.returncode, bytes2str(proc_stdout)
def is_in_rootdir():
[tox]
-envlist = py27,py26
+envlist = py27,py26,py32
[testenv]
commands =