1#------------------------------------------------------------------------------
2# elftools tests
3#
4# Maxim Akhmedov (max42@yandex-team.ru)
5# This code is in the public domain
6#------------------------------------------------------------------------------
7import unittest
8import os
9
10from elftools.elf.elffile import ELFFile
11from elftools.elf.segments import NoteSegment
12
13
14class TestCoreNotes(unittest.TestCase):
15    """ This test makes sure than core dump specific
16        sections are properly analyzed.
17    """
18    @classmethod
19    def setUpClass(cls):
20        cls._core_file = open(os.path.join('test',
21                              'testfiles_for_unittests', 'core_linux64.elf'),
22                              'rb')
23
24    def test_core_prpsinfo(self):
25        elf = ELFFile(self._core_file)
26        for segment in elf.iter_segments():
27            if not isinstance(segment, NoteSegment):
28                continue
29            notes = list(segment.iter_notes())
30            for note in segment.iter_notes():
31                if note['n_type'] != 'NT_PRPSINFO':
32                    continue
33                desc = note['n_desc']
34                self.assertEqual(desc['pr_state'], 0)
35                self.assertEqual(desc['pr_sname'], b'R')
36                self.assertEqual(desc['pr_zomb'], 0)
37                self.assertEqual(desc['pr_nice'], 0)
38                self.assertEqual(desc['pr_flag'], 0x400600)
39                self.assertEqual(desc['pr_uid'], 1000)
40                self.assertEqual(desc['pr_gid'], 1000)
41                self.assertEqual(desc['pr_pid'], 23395)
42                self.assertEqual(desc['pr_ppid'], 23187)
43                self.assertEqual(desc['pr_pgrp'], 23395)
44                self.assertEqual(desc['pr_sid'], 23187)
45                self.assertEqual(
46                    desc['pr_fname'],
47                    b'coredump_self\x00\x00\x00')
48                self.assertEqual(
49                    desc['pr_psargs'],
50                    b'./coredump_self foo bar 42 ' + b'\x00' * (80 - 27))
51
52    def test_core_nt_file(self):
53        """
54        Test that the parsing of the NT_FILE note within a core file is
55        correct.
56        The assertions are made against the output of eu-readelf.
57
58        eu-readelf -n core_linux64.elf
59        ...
60        CORE                 621  FILE
61        10 files:
62        00400000-00401000 00000000 4096
63          /home/max42/pyelftools/test/coredump_self
64        00600000-00601000 00000000 4096
65          /home/max42/pyelftools/test/coredump_self
66        00601000-00602000 00001000 4096
67          /home/max42/pyelftools/test/coredump_self
68        7fa4593ae000-7fa45956d000 00000000 1830912
69          /lib/x86_64-linux-gnu/libc-2.23.so
70        7fa45956d000-7fa45976d000 001bf000 2097152
71          /lib/x86_64-linux-gnu/libc-2.23.so
72        7fa45976d000-7fa459771000 001bf000 16384
73          /lib/x86_64-linux-gnu/libc-2.23.so
74        7fa459771000-7fa459773000 001c3000 8192
75          /lib/x86_64-linux-gnu/libc-2.23.so
76        7fa459777000-7fa45979d000 00000000 155648
77          /lib/x86_64-linux-gnu/ld-2.23.so
78        7fa45999c000-7fa45999d000 00025000 4096
79          /lib/x86_64-linux-gnu/ld-2.23.so
80        7fa45999d000-7fa45999e000 00026000 4096
81          /lib/x86_64-linux-gnu/ld-2.23.so
82        ...
83        """
84        elf = ELFFile(self._core_file)
85        nt_file_found = False
86        for segment in elf.iter_segments():
87            if not isinstance(segment, NoteSegment):
88                continue
89            for note in segment.iter_notes():
90                if note['n_type'] != 'NT_FILE':
91                    continue
92                nt_file_found = True
93                desc = note['n_desc']
94                self.assertEqual(desc['num_map_entries'], 10)
95                self.assertEqual(desc['page_size'], 4096)
96                self.assertEqual(len(desc['Elf_Nt_File_Entry']), 10)
97                self.assertEqual(len(desc['filename']), 10)
98
99                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][0],
100                                            desc['page_size'],
101                                            0x00400000,
102                                            0x00401000,
103                                            0x00000000)
104                self.assertEqual(desc['filename'][0],
105                                 b"/home/max42/pyelftools/test/coredump_self")
106
107                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][1],
108                                            desc['page_size'],
109                                            0x00600000,
110                                            0x00601000,
111                                            0x00000000)
112                self.assertEqual(desc['filename'][1],
113                                 b"/home/max42/pyelftools/test/coredump_self")
114
115                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][2],
116                                            desc['page_size'],
117                                            0x00601000,
118                                            0x00602000,
119                                            0x00001000)
120                self.assertEqual(desc['filename'][2],
121                                 b"/home/max42/pyelftools/test/coredump_self")
122
123                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][3],
124                                            desc['page_size'],
125                                            0x7fa4593ae000,
126                                            0x7fa45956d000,
127                                            0x00000000)
128                self.assertEqual(desc['filename'][3],
129                                 b"/lib/x86_64-linux-gnu/libc-2.23.so")
130
131                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][4],
132                                            desc['page_size'],
133                                            0x7fa45956d000,
134                                            0x7fa45976d000,
135                                            0x001bf000)
136                self.assertEqual(desc['filename'][4],
137                                 b"/lib/x86_64-linux-gnu/libc-2.23.so")
138
139                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][5],
140                                            desc['page_size'],
141                                            0x7fa45976d000,
142                                            0x7fa459771000,
143                                            0x001bf000)
144                self.assertEqual(desc['filename'][5],
145                                 b"/lib/x86_64-linux-gnu/libc-2.23.so")
146
147                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][6],
148                                            desc['page_size'],
149                                            0x7fa459771000,
150                                            0x7fa459773000,
151                                            0x001c3000)
152                self.assertEqual(desc['filename'][6],
153                                 b"/lib/x86_64-linux-gnu/libc-2.23.so")
154
155                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][7],
156                                            desc['page_size'],
157                                            0x7fa459777000,
158                                            0x7fa45979d000,
159                                            0x00000000)
160                self.assertEqual(desc['filename'][7],
161                                 b"/lib/x86_64-linux-gnu/ld-2.23.so")
162
163                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][8],
164                                            desc['page_size'],
165                                            0x7fa45999c000,
166                                            0x7fa45999d000,
167                                            0x00025000)
168                self.assertEqual(desc['filename'][8],
169                                 b"/lib/x86_64-linux-gnu/ld-2.23.so")
170
171                self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][9],
172                                            desc['page_size'],
173                                            0x7fa45999d000,
174                                            0x7fa45999e000,
175                                            0x00026000)
176                self.assertEqual(desc['filename'][9],
177                                 b"/lib/x86_64-linux-gnu/ld-2.23.so")
178        self.assertTrue(nt_file_found)
179
180    def validate_nt_file_entry(self,
181                               entry,
182                               page_size,
183                               expected_vm_start,
184                               expected_vm_end,
185                               expected_page_offset):
186        self.assertEqual(entry.vm_start, expected_vm_start)
187        self.assertEqual(entry.vm_end, expected_vm_end)
188        self.assertEqual(entry.page_offset * page_size, expected_page_offset)
189
190    @classmethod
191    def tearDownClass(cls):
192        cls._core_file.close()
193