blob: 2ce6746506ad954878426133e3e93e101e6e0da7 [file] [log] [blame]
Eli Benderskye0735d52011-09-08 20:12:44 +03001#-------------------------------------------------------------------------------
2# elftools: common/utils.py
3#
4# Miscellaneous utilities for elftools
5#
6# Eli Bendersky (eliben@gmail.com)
7# This code is in the public domain
8#-------------------------------------------------------------------------------
eliben033b44f2011-09-19 15:48:39 +03009from .exceptions import ELFParseError, ELFError, DWARFError
elibena7c25472011-09-18 17:31:10 +030010from ..construct import ConstructError
Eli Benderskye0735d52011-09-08 20:12:44 +030011
12
Eli Benderskyebe51162011-10-27 17:34:02 +020013def bytelist2string(bytelist):
14 """ Convert a list of byte values (e.g. [0x10 0x20 0x00]) to a string
15 (e.g. '\x10\x20\x00').
16 """
17 return ''.join(chr(b) for b in bytelist)
18
19
Eli Benderskye0735d52011-09-08 20:12:44 +030020def struct_parse(struct, stream, stream_pos=None):
Eli Bendersky3f4de3e2011-09-14 05:58:06 +030021 """ Convenience function for using the given struct to parse a stream.
Eli Benderskye0735d52011-09-08 20:12:44 +030022 If stream_pos is provided, the stream is seeked to this position before
Eli Bendersky3f4de3e2011-09-14 05:58:06 +030023 the parsing is done. Otherwise, the current position of the stream is
24 used.
25 Wraps the error thrown by construct with ELFParseError.
Eli Benderskye0735d52011-09-08 20:12:44 +030026 """
27 try:
28 if stream_pos is not None:
29 stream.seek(stream_pos)
30 return struct.parse_stream(stream)
31 except ConstructError as e:
32 raise ELFParseError(e.message)
33
34
Eli Bendersky4a489752011-11-27 06:34:47 +020035def parse_cstring_from_stream(stream, stream_pos=None):
36 """ Parse a C-string from the given stream. The string is returned without
37 the terminating \x00 byte.
38 If stream_pos is provided, the stream is seeked to this position before
39 the parsing is done. Otherwise, the current position of the stream is
40 used.
41 """
42 # I could've just used construct.CString, but this function is 4x faster.
43 # Since it's needed a lot, I created it as an optimization.
44 if stream_pos is not None:
45 stream.seek(stream_pos)
46 return ''.join(iter(lambda: stream.read(1), '\x00'))
47
48
eliben116899e2011-09-08 17:15:53 +030049def elf_assert(cond, msg=''):
Eli Benderskye0735d52011-09-08 20:12:44 +030050 """ Assert that cond is True, otherwise raise ELFError(msg)
51 """
eliben44556512011-09-19 12:54:32 +030052 _assert_with_exception(cond, msg, ELFError)
Eli Benderskye0735d52011-09-08 20:12:44 +030053
eliben44556512011-09-19 12:54:32 +030054
55def dwarf_assert(cond, msg=''):
56 """ Assert that cond is True, otherwise raise DWARFError(msg)
57 """
58 _assert_with_exception(cond, msg, DWARFError)
59
60
61def _assert_with_exception(cond, msg, exception_type):
62 if not cond:
eliben033b44f2011-09-19 15:48:39 +030063 raise exception_type(msg)
64
eliben3b9ad822011-09-22 11:46:26 +030065
66from contextlib import contextmanager
67
68@contextmanager
69def preserve_stream_pos(stream):
70 """ Usage:
71
72 # stream has some position FOO (return value of stream.tell())
73 with preserve_stream_pos(stream):
74 # do stuff that manipulates the stream
75 # stream still has position FOO
76 """
77 saved_pos = stream.tell()
78 yield
79 stream.seek(saved_pos)