Gentoo Archives: gentoo-commits

From: "Mike Frysinger (vapier)" <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in dev-python/pyelftools/files: pyelftools-0.22-dyntable.patch pyelftools-0.22-grace-string-dyn.patch
Date: Wed, 04 Jun 2014 22:06:54
Message-Id: 20140604220650.461C72004F@flycatcher.gentoo.org
1 vapier 14/06/04 22:06:50
2
3 Added: pyelftools-0.22-dyntable.patch
4 pyelftools-0.22-grace-string-dyn.patch
5 Log:
6 Version bump #512214 by Ian Delaney.
7
8 (Portage version: 2.2.10/cvs/Linux x86_64, signed Manifest commit with key D2E96200)
9
10 Revision Changes Path
11 1.1 dev-python/pyelftools/files/pyelftools-0.22-dyntable.patch
12
13 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-python/pyelftools/files/pyelftools-0.22-dyntable.patch?rev=1.1&view=markup
14 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-python/pyelftools/files/pyelftools-0.22-dyntable.patch?rev=1.1&content-type=text/plain
15
16 Index: pyelftools-0.22-dyntable.patch
17 ===================================================================
18 From b3157177bde20a2b0d0ada7b2ba44144ee5aea6f Mon Sep 17 00:00:00 2001
19 From: Mike Frysinger <vapier@g.o>
20 Date: Sun, 9 Jun 2013 18:42:40 -0400
21 Subject: [PATCH] support parsing of dynamic ELFs w/out section headers
22 MIME-Version: 1.0
23 Content-Type: text/plain; charset=UTF-8
24 Content-Transfer-Encoding: 8bit
25
26 At runtime, ELFs do not use the section headers at all. Instead, only
27 the program segments and dynamic tags get used. This means you can
28 strip the section table completely from an ELF and have it still work.
29
30 In practice, people rarely do this, but it's not unheard of. Make the
31 Dynamic tags work even in these cases by loading the strings table the
32 same way the runtime loader does:
33 * parse the symtab address from DT_STRTAB
34 * locate the file offset via the program segments
35
36 In order to avoid circular deps (parsing a dyntag requires walking parsed
37 dyntags), add a set of internal funcs for returning the raw values.
38
39 You can see this in action:
40 $ eu-strip -g --strip-sections a.out
41 $ readelf -S a.out
42 <nothing>
43 $ lddtree.py ./a.out
44 a.out (interpreter => /lib64/ld-linux-x86-64.so.2)
45 libïäöëß.so => None
46 libc.so.6 => /lib64/libc.so.6
47
48 Signed-off-by: Mike Frysinger <vapier@g.o>
49 ---
50 elftools/elf/dynamic.py | 81 ++++++++++++++++++---
51 test/test_dynamic.py | 28 ++++++-
52 .../aarch64_super_stripped.elf | Bin 0 -> 4136 bytes
53 3 files changed, 97 insertions(+), 12 deletions(-)
54 create mode 100755 test/testfiles_for_unittests/aarch64_super_stripped.elf
55
56 diff --git a/elftools/elf/dynamic.py b/elftools/elf/dynamic.py
57 index d9db870..ad5111f 100644
58 --- a/elftools/elf/dynamic.py
59 +++ b/elftools/elf/dynamic.py
60 @@ -11,9 +11,22 @@ import itertools
61 from .sections import Section
62 from .segments import Segment
63 from ..common.exceptions import ELFError
64 -from ..common.utils import struct_parse
65 -
66 -from .enums import ENUM_D_TAG
67 +from ..common.utils import struct_parse, parse_cstring_from_stream
68 +
69 +
70 +class _DynamicStringTable(object):
71 + """ Bare string table based on values found via ELF dynamic tags and
72 + loadable segments only. Good enough for get_string() only.
73 + """
74 + def __init__(self, stream, table_offset):
75 + self._stream = stream
76 + self._table_offset = table_offset
77 +
78 + def get_string(self, offset):
79 + """ Get the string stored at the given offset in this string table.
80 + """
81 + return parse_cstring_from_stream(self._stream,
82 + self._table_offset + offset)
83
84
85 class DynamicTag(object):
86 @@ -61,27 +76,71 @@ class Dynamic(object):
87 self._num_tags = -1
88 self._offset = position
89 self._tagsize = self._elfstructs.Elf_Dyn.sizeof()
90 - self._stringtable = stringtable
91 + self.__stringtable = stringtable
92
93 - def iter_tags(self, type=None):
94 - """ Yield all tags (limit to |type| if specified)
95 + @property
96 + def _stringtable(self):
97 + """ Return a string table for looking up dynamic tag related strings.
98 +
99 + This won't be a "full" string table object, but will at least support
100 + the get_string() function.
101 + """
102 + if self.__stringtable:
103 + return self.__stringtable
104 +
105 + # If the ELF has stripped its section table (which is unusual, but
106 + # perfectly valid), we need to use the dynamic tags to locate the
107 + # dynamic string table.
108 + strtab = None
109 + for tag in self._iter_tags(type='DT_STRTAB'):
110 + strtab = tag['d_val']
111 + break
112 + # If we found a dynamic string table, locate the offset in the file
113 + # by using the program headers.
114 + if strtab:
115 + for segment in self._elffile.iter_segments():
116 + if (strtab >= segment['p_vaddr'] and
117 + strtab < segment['p_vaddr'] + segment['p_filesz']):
118 + self.__stringtable = _DynamicStringTable(
119 + self._stream,
120 + segment['p_offset'] + (strtab - segment['p_vaddr']))
121 + return self.__stringtable
122 +
123 + # That didn't work for some reason. Let's use the section header
124 + # even though this ELF is super weird.
125 + self.__stringtable = self._elffile.get_section_by_name(b'.dynstr')
126 +
127 + return self.__stringtable
128 +
129 + def _iter_tags(self, type=None):
130 + """ Yield all raw tags (limit to |type| if specified)
131 """
132 for n in itertools.count():
133 - tag = self.get_tag(n)
134 - if type is None or tag.entry.d_tag == type:
135 + tag = self._get_tag(n)
136 + if type is None or tag['d_tag'] == type:
137 yield tag
138 - if tag.entry.d_tag == 'DT_NULL':
139 + if tag['d_tag'] == 'DT_NULL':
140 break
141
142 - def get_tag(self, n):
143 - """ Get the tag at index #n from the file (DynamicTag object)
144 + def iter_tags(self, type=None):
145 + """ Yield all tags (limit to |type| if specified)
146 + """
147 + for tag in self._iter_tags(type=type):
148 + yield DynamicTag(tag, self._stringtable)
149 +
150 + def _get_tag(self, n):
151 + """ Get the raw tag at index #n from the file
152 """
153 offset = self._offset + n * self._tagsize
154 - entry = struct_parse(
155 + return struct_parse(
156 self._elfstructs.Elf_Dyn,
157 self._stream,
158 stream_pos=offset)
159 - return DynamicTag(entry, self._stringtable)
160 +
161 + def get_tag(self, n):
162 + """ Get the tag at index #n from the file (DynamicTag object)
163 + """
164 + return DynamicTag(self._get_tag(n), self._stringtable)
165
166 def num_tags(self):
167 """ Number of dynamic tags in the file
168 --
169 2.0.0
170
171
172
173
174 1.1 dev-python/pyelftools/files/pyelftools-0.22-grace-string-dyn.patch
175
176 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-python/pyelftools/files/pyelftools-0.22-grace-string-dyn.patch?rev=1.1&view=markup
177 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-python/pyelftools/files/pyelftools-0.22-grace-string-dyn.patch?rev=1.1&content-type=text/plain
178
179 Index: pyelftools-0.22-grace-string-dyn.patch
180 ===================================================================
181 From 80305ad20ebd481dde19fa7ff2d90249269aa588 Mon Sep 17 00:00:00 2001
182 From: Eli Bendersky <eliben@×××××.com>
183 Date: Wed, 23 Apr 2014 16:44:11 -0700
184 Subject: [PATCH] Issue #29: Fail more gracefully when no string table is found
185 for dynamic.
186
187 ---
188 elftools/elf/dynamic.py | 4 ++++
189 test/test_dynamic.py | 25 +++++++++++++++++++++++++
190 2 files changed, 29 insertions(+)
191 create mode 100644 test/test_dynamic.py
192
193 diff --git a/elftools/elf/dynamic.py b/elftools/elf/dynamic.py
194 index e36598e..6f88bf9 100644
195 --- a/elftools/elf/dynamic.py
196 +++ b/elftools/elf/dynamic.py
197 @@ -10,6 +10,7 @@ import itertools
198
199 from .sections import Section
200 from .segments import Segment
201 +from ..common.exceptions import ELFError
202 from ..common.utils import struct_parse
203
204 from .enums import ENUM_D_TAG
205 @@ -29,6 +30,8 @@ class DynamicTag(object):
206 'DT_SUNW_FILTER'])
207
208 def __init__(self, entry, stringtable):
209 + if stringtable is None:
210 + raise ELFError('Creating DynamicTag without string table')
211 self.entry = entry
212 if entry.d_tag in self._HANDLED_TAGS:
213 setattr(self, entry.d_tag[3:].lower(),
214 @@ -114,6 +117,7 @@ class DynamicSegment(Segment, Dynamic):
215 # So we must look for the dynamic section contained in the dynamic
216 # segment, we do so by searching for the dynamic section whose content
217 # is located at the same offset as the dynamic segment
218 + stringtable = None
219 for section in elffile.iter_sections():
220 if (isinstance(section, DynamicSection) and
221 section['sh_offset'] == header['p_offset']):
222 diff --git a/test/test_dynamic.py b/test/test_dynamic.py
223 new file mode 100644
224 index 0000000..0ee9b35
225 --- /dev/null
226 +++ b/test/test_dynamic.py
227 @@ -0,0 +1,25 @@
228 +#-------------------------------------------------------------------------------
229 +# elftools tests
230 +#
231 +# Eli Bendersky (eliben@×××××.com)
232 +# This code is in the public domain
233 +#-------------------------------------------------------------------------------
234 +try:
235 + import unittest2 as unittest
236 +except ImportError:
237 + import unittest
238 +import os
239 +
240 +from utils import setup_syspath; setup_syspath()
241 +from elftools.common.exceptions import ELFError
242 +from elftools.elf.dynamic import DynamicTag
243 +
244 +
245 +class TestDynamicTag(unittest.TestCase):
246 + def test_requires_stringtable(self):
247 + with self.assertRaises(ELFError):
248 + dt = DynamicTag('', None)
249 +
250 +
251 +if __name__ == '__main__':
252 + unittest.main()
253 --
254 2.0.0