from .structs import ELFStructs
from .sections import (
Section, StringTableSection, SymbolTableSection,
- SUNWSyminfoTableSection, NullSection)
+ SUNWSyminfoTableSection, NullSection, NoteSection)
from .dynamic import DynamicSection, DynamicSegment
from .relocation import RelocationSection, RelocationHandler
from .gnuversions import (
section_header, name, self.stream, self)
elif sectype == 'SHT_DYNAMIC':
return DynamicSection(section_header, name, self.stream, self)
+ elif sectype == 'SHT_NOTE':
+ return NoteSection(section_header, name, self.stream, self)
else:
return Section(section_header, name, self.stream)
--- /dev/null
+#-------------------------------------------------------------------------------
+# elftools: elf/notes.py
+#
+# ELF notes
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from ..common.py3compat import bytes2str
+from ..common.utils import struct_parse, roundup
+from ..construct import CString
+
+
+def iter_notes(elffile, offset, size):
+ """ Yield all the notes in a section or segment.
+ """
+ end = offset + size
+ while offset < end:
+ note = struct_parse(
+ elffile.structs.Elf_Nhdr,
+ elffile.stream,
+ stream_pos=offset)
+ note['n_offset'] = offset
+ offset += elffile.structs.Elf_Nhdr.sizeof()
+ elffile.stream.seek(offset)
+ # n_namesz is 4-byte aligned.
+ disk_namesz = roundup(note['n_namesz'], 2)
+ note['n_name'] = bytes2str(
+ CString('').parse(elffile.stream.read(disk_namesz)))
+ offset += disk_namesz
+
+ desc_data = bytes2str(elffile.stream.read(note['n_descsz']))
+ if note['n_type'] == 'NT_GNU_ABI_TAG':
+ note['n_desc'] = struct_parse(elffile.structs.Elf_Nhdr_abi,
+ elffile.stream,
+ offset)
+ elif note['n_type'] == 'NT_GNU_BUILD_ID':
+ note['n_desc'] = ''.join('%.2x' % ord(b) for b in desc_data)
+ else:
+ note['n_desc'] = desc_data
+ offset += roundup(note['n_descsz'], 2)
+ note['n_size'] = offset - note['n_offset']
+ yield note
#-------------------------------------------------------------------------------
from ..common.utils import struct_parse, elf_assert, parse_cstring_from_stream
from collections import defaultdict
+from .notes import iter_notes
+
class Section(object):
""" Base class for ELF sections. Also used for all sections types that have
"""
for i in range(1, self.num_symbols() + 1):
yield self.get_symbol(i)
+
+
+class NoteSection(Section):
+ """ ELF NOTE section. Knows how to parse notes.
+ """
+ def __init__(self, header, name, stream, elffile):
+ super(NoteSection, self).__init__(header, name, stream)
+ self.elffile = elffile
+
+ def iter_notes(self):
+ """ Yield all the notes in the section. Each result is a dictionary-
+ like object with "n_name", "n_type", and "n_desc" fields, amongst
+ others.
+ """
+ return iter_notes(self.elffile, self['sh_offset'], self['sh_size'])
# This code is in the public domain
#-------------------------------------------------------------------------------
from ..construct import CString
-from ..common.utils import roundup, struct_parse
-from ..common.py3compat import bytes2str
+from ..common.utils import struct_parse
from .constants import SH_FLAGS
+from .notes import iter_notes
class Segment(object):
"""
def __init__(self, header, stream, elffile):
super(NoteSegment, self).__init__(header, stream)
- self._elfstructs = elffile.structs
+ self.elffile = elffile
def iter_notes(self):
- """ Iterates the list of notes in the segment.
+
+ """ Yield all the notes in the segment. Each result is a dictionary-
+ like object with "n_name", "n_type", and "n_desc" fields, amongst
+ others.
"""
- offset = self['p_offset']
- end = self['p_offset'] + self['p_filesz']
- while offset < end:
- note = struct_parse(
- self._elfstructs.Elf_Nhdr,
- self.stream,
- stream_pos=offset)
- note['n_offset'] = offset
- offset += self._elfstructs.Elf_Nhdr.sizeof()
- self.stream.seek(offset)
- # n_namesz is 4-byte aligned.
- disk_namesz = roundup(note['n_namesz'], 2)
- note['n_name'] = bytes2str(
- CString('').parse(self.stream.read(disk_namesz)))
- offset += disk_namesz
-
- desc_data = bytes2str(self.stream.read(note['n_descsz']))
- if note['n_type'] == 'NT_GNU_ABI_TAG':
- note['n_desc'] = struct_parse(self._elfstructs.Elf_Nhdr_abi,
- self.stream,
- offset)
- elif note['n_type'] == 'NT_GNU_BUILD_ID':
- note['n_desc'] = ''.join('%.2x' % ord(b) for b in desc_data)
- else:
- note['n_desc'] = desc_data
- offset += roundup(note['n_descsz'], 2)
- note['n_size'] = offset - note['n_offset']
- yield note
+ return iter_notes(self.elffile, self['p_offset'], self['p_filesz'])
--- /dev/null
+#-------------------------------------------------------------------------------
+# elftools example: elf_notes.py
+#
+# An example of obtaining note sections from an ELF file and examining
+# the notes it contains.
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from __future__ import print_function
+import sys
+
+# If pyelftools is not installed, the example can also run from the root or
+# examples/ dir of the source distribution.
+sys.path[0:0] = ['.', '..']
+
+from elftools.elf.elffile import ELFFile
+from elftools.elf.sections import NoteSection
+
+
+def process_file(filename):
+ print('Processing file:', filename)
+ with open(filename, 'rb') as f:
+ for sect in ELFFile(f).iter_sections():
+ if not isinstance(sect, NoteSection):
+ continue
+ print(' Note section "%s" at offset 0x%.8x with size %d' % (
+ sect.name, sect.header['sh_offset'], sect.header['sh_size']))
+ for note in sect.iter_notes():
+ print(' Name:', note['n_name'])
+ print(' Type:', note['n_type'])
+ desc = note['n_desc']
+ if note['n_type'] == 'NT_GNU_ABI_TAG':
+ print(' Desc: %s, ABI: %d.%d.%d' % (
+ desc['abi_os'],
+ desc['abi_major'],
+ desc['abi_minor'],
+ desc['abi_tiny']))
+ elif note['n_type'] == 'NT_GNU_BUILD_ID':
+ print(' Desc:', desc)
+ else:
+ print(' Desc:', ''.join('%.2x' % ord(b) for b in desc))
+
+
+if __name__ == '__main__':
+ if sys.argv[1] == '--test':
+ for filename in sys.argv[2:]:
+ process_file(filename)
--- /dev/null
+Processing file: ./examples/sample_exe64.elf
+ Note section ".note.ABI-tag" at offset 0x00000254 with size 32
+ Name: GNU
+ Type: NT_GNU_ABI_TAG
+ Desc: ELF_NOTE_OS_LINUX, ABI: 2.6.4
+ Note section ".note.SuSE" at offset 0x00000274 with size 24
+ Name: SuSE
+ Type: 1163097427
+ Desc: 01000a02
+ Note section ".note.gnu.build-id" at offset 0x0000028c with size 36
+ Name: GNU
+ Type: NT_GNU_BUILD_ID
+ Desc: 8e50cda8e25993499ac4aa2d8deaf58d0949d47d