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 |