Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / pyelftools / elftools / common / utils.py
1 #-------------------------------------------------------------------------------
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 #-------------------------------------------------------------------------------
9 from contextlib import contextmanager
10 from .exceptions import ELFParseError, ELFError, DWARFError
11 from .py3compat import int2byte
12 from ..construct import ConstructError
13
14
15 def bytelist2string(bytelist):
16     """ Convert a list of byte values (e.g. [0x10 0x20 0x00]) to a bytes object
17         (e.g. b'\x10\x20\x00').
18     """
19     return b''.join(int2byte(b) for b in bytelist)
20
21
22 def struct_parse(struct, stream, stream_pos=None):
23     """ Convenience function for using the given struct to parse a stream.
24         If stream_pos is provided, the stream is seeked to this position before
25         the parsing is done. Otherwise, the current position of the stream is
26         used.
27         Wraps the error thrown by construct with ELFParseError.
28     """
29     try:
30         if stream_pos is not None:
31             stream.seek(stream_pos)
32         return struct.parse_stream(stream)
33     except ConstructError as e:
34         raise ELFParseError(e.message)
35     
36
37 def parse_cstring_from_stream(stream, stream_pos=None):
38     """ Parse a C-string from the given stream. The string is returned without
39         the terminating \x00 byte. If the terminating byte wasn't found, None
40         is returned (the stream is exhausted).
41         If stream_pos is provided, the stream is seeked to this position before
42         the parsing is done. Otherwise, the current position of the stream is
43         used.
44     """
45     if stream_pos is not None:
46         stream.seek(stream_pos)
47     CHUNKSIZE = 64
48     chunks = []
49     found = False
50     while True:
51         chunk = stream.read(CHUNKSIZE)
52         end_index = chunk.find(b'\x00')
53         if end_index >= 0:
54             chunks.append(chunk[:end_index])
55             found = True
56             break
57         else:
58             chunks.append(chunk)
59         if len(chunk) < CHUNKSIZE:
60             break
61     return b''.join(chunks) if found else None
62
63
64 def elf_assert(cond, msg=''):
65     """ Assert that cond is True, otherwise raise ELFError(msg)
66     """
67     _assert_with_exception(cond, msg, ELFError)
68
69
70 def dwarf_assert(cond, msg=''):
71     """ Assert that cond is True, otherwise raise DWARFError(msg)
72     """
73     _assert_with_exception(cond, msg, DWARFError)
74
75
76 @contextmanager
77 def preserve_stream_pos(stream):
78     """ Usage:
79             
80             # stream has some position FOO (return value of stream.tell())
81             with preserve_stream_pos(stream):
82                 # do stuff that manipulates the stream
83             # stream still has position FOO
84     """
85     saved_pos = stream.tell()
86     yield
87     stream.seek(saved_pos)
88
89
90 #------------------------- PRIVATE -------------------------
91
92 def _assert_with_exception(cond, msg, exception_type):
93     if not cond:
94         raise exception_type(msg)
95