From 78c3196d672cff38361ab4cd18fc6935e6e58f3f Mon Sep 17 00:00:00 2001 From: Romain Thomas Date: Thu, 9 Nov 2023 06:26:56 +0100 Subject: [PATCH] Refactor the ELF Note support --- api/python/CMakeLists.txt | 5 +- api/python/lief/ELF.pyi | 627 ++++++++------ api/python/lief/__init__.pyi | 12 + api/python/pyproject.toml | 2 +- api/python/src/ELF/enums.cpp | 44 - api/python/src/ELF/init.cpp | 41 +- api/python/src/ELF/objects/CMakeLists.txt | 54 +- .../ELF/objects/NoteDetails/CMakeLists.txt | 8 +- .../objects/NoteDetails/core/CMakeLists.txt | 17 +- .../objects/NoteDetails/core/pyCoreAuxv.cpp | 131 ++- .../objects/NoteDetails/core/pyCoreFile.cpp | 18 +- .../NoteDetails/core/pyCoreFileEntry.cpp | 45 - .../NoteDetails/core/pyCorePrPsInfo.cpp | 70 +- .../NoteDetails/core/pyCorePrStatus.cpp | 404 +++++---- .../NoteDetails/core/pyCoreSigInfo.cpp | 22 +- .../{pyAndroidNote.cpp => pyAndroidIdent.cpp} | 20 +- .../src/ELF/objects/NoteDetails/pyNoteAbi.cpp | 31 +- api/python/src/ELF/objects/pyBinary.cpp | 32 +- api/python/src/ELF/objects/pyNote.cpp | 160 +++- api/python/src/ELF/objects/pyNoteDetails.cpp | 34 - api/python/src/nanobind/utils.hpp | 24 + api/python/src/pyErr.cpp | 11 + api/python/src/pyErr.hpp | 39 +- doc/sphinx/api/cpp/elf.rst | 44 - doc/sphinx/api/python/elf.rst | 38 +- doc/sphinx/api/python/index.rst | 2 + doc/sphinx/changelog.rst | 1 + doc/sphinx/conf.py | 49 +- doc/sphinx/tutorials/12_elf_coredump.rst | 72 +- include/LIEF/ELF.hpp | 5 +- include/LIEF/ELF/Binary.hpp | 16 +- include/LIEF/ELF/Builder.hpp | 2 +- include/LIEF/ELF/EnumToString.hpp | 4 - include/LIEF/ELF/Note.hpp | 245 ++++-- include/LIEF/ELF/NoteDetails.hpp | 63 +- .../{AndroidNote.hpp => AndroidIdent.hpp} | 68 +- include/LIEF/ELF/NoteDetails/NoteAbi.hpp | 82 +- .../LIEF/ELF/NoteDetails/core/CoreAuxv.hpp | 127 +-- .../LIEF/ELF/NoteDetails/core/CoreFile.hpp | 105 +-- .../ELF/NoteDetails/core/CorePrPsInfo.hpp | 132 ++- .../ELF/NoteDetails/core/CorePrStatus.hpp | 304 ++++--- .../LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp | 74 +- include/LIEF/ELF/Parser.hpp | 4 +- include/LIEF/ELF/enums.hpp | 105 --- include/LIEF/ELF/hash.hpp | 3 +- include/LIEF/Visitor.hpp | 4 +- src/ELF/Binary.cpp | 21 +- src/ELF/Builder.cpp | 97 +-- src/ELF/Builder.tcc | 16 +- src/ELF/CMakeLists.txt | 2 - src/ELF/EnumToString.cpp | 217 ----- src/ELF/ExeLayout.hpp | 83 +- src/ELF/Layout.hpp | 12 +- src/ELF/Note.cpp | 796 ++++++++++++++---- src/ELF/NoteDetails/AndroidIdent.cpp | 86 ++ src/ELF/NoteDetails/AndroidNote.cpp | 149 ---- src/ELF/NoteDetails/CMakeLists.txt | 2 +- src/ELF/NoteDetails/NoteAbi.cpp | 111 ++- src/ELF/NoteDetails/core/CMakeLists.txt | 8 +- src/ELF/NoteDetails/core/CoreAuxv.cpp | 202 +++-- src/ELF/NoteDetails/core/CoreAuxv.tcc | 84 -- src/ELF/NoteDetails/core/CoreFile.cpp | 155 ++-- src/ELF/NoteDetails/core/CoreFile.tcc | 114 --- src/ELF/NoteDetails/core/CorePrPsInfo.cpp | 192 ++--- src/ELF/NoteDetails/core/CorePrPsInfo.tcc | 82 -- src/ELF/NoteDetails/core/CorePrStatus.cpp | 721 ++++++++++------ src/ELF/NoteDetails/core/CorePrStatus.tcc | 139 --- src/ELF/NoteDetails/core/CoreSigInfo.cpp | 100 +-- src/ELF/Parser.cpp | 147 ++-- src/ELF/Structures.hpp | 39 +- src/ELF/hash.cpp | 71 +- src/ELF/json.cpp | 153 ++-- src/ELF/json_internal.hpp | 4 +- src/ELF/note_utils.cpp | 40 - src/ELF/notes_utils.hpp | 30 - src/ELF/structures.inc | 35 - src/frozen.hpp | 18 +- src/internal_utils.hpp | 26 + tests/elf/test_core.py | 450 +++++----- tests/elf/test_elf.py | 12 +- tests/elf/test_notes.py | 41 +- tests/elf/test_parser.py | 6 + tests/elf/test_parser_simple.py | 8 +- tests/elf/test_str_hash.py | 5 +- 84 files changed, 3859 insertions(+), 4015 deletions(-) delete mode 100644 api/python/src/ELF/objects/NoteDetails/core/pyCoreFileEntry.cpp rename api/python/src/ELF/objects/NoteDetails/{pyAndroidNote.cpp => pyAndroidIdent.cpp} (62%) delete mode 100644 api/python/src/ELF/objects/pyNoteDetails.cpp create mode 100644 api/python/src/nanobind/utils.hpp rename include/LIEF/ELF/NoteDetails/{AndroidNote.hpp => AndroidIdent.hpp} (58%) create mode 100644 src/ELF/NoteDetails/AndroidIdent.cpp delete mode 100644 src/ELF/NoteDetails/AndroidNote.cpp delete mode 100644 src/ELF/NoteDetails/core/CoreAuxv.tcc delete mode 100644 src/ELF/NoteDetails/core/CoreFile.tcc delete mode 100644 src/ELF/NoteDetails/core/CorePrPsInfo.tcc delete mode 100644 src/ELF/NoteDetails/core/CorePrStatus.tcc delete mode 100644 src/ELF/note_utils.cpp delete mode 100644 src/ELF/notes_utils.hpp diff --git a/api/python/CMakeLists.txt b/api/python/CMakeLists.txt index 97286cac22..fc2eb093b3 100644 --- a/api/python/CMakeLists.txt +++ b/api/python/CMakeLists.txt @@ -39,11 +39,10 @@ message(STATUS "Python interpreter: ${Python_EXECUTABLE}") nanobind_add_module( pyLIEF NB_STATIC - - ${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.cpp - # Do not default to -Os NOMINSIZE + + ${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.cpp ) add_subdirectory(src) diff --git a/api/python/lief/ELF.pyi b/api/python/lief/ELF.pyi index 9abbb609b1..5be1b6f6dc 100644 --- a/api/python/lief/ELF.pyi +++ b/api/python/lief/ELF.pyi @@ -8,7 +8,11 @@ import lief.ELF.Binary # type: ignore import lief.ELF.Builder # type: ignore import lief.ELF.CoreAuxv # type: ignore import lief.ELF.CoreFile # type: ignore +import lief.ELF.CorePrPsInfo # type: ignore import lief.ELF.CorePrStatus # type: ignore +import lief.ELF.CorePrStatus.Registers # type: ignore +import lief.ELF.Note # type: ignore +import lief.ELF.NoteAbi # type: ignore import lief.ELF.Section # type: ignore import lief.ELF.Segment # type: ignore import lief.ELF.SymbolVersionDefinition # type: ignore @@ -231,7 +235,7 @@ class ARM_EFLAGS: @property def value(self) -> int: ... -class AndroidNote(NoteDetails): +class AndroidIdent(Note): ndk_build_number: str ndk_version: str sdk_version: int @@ -361,7 +365,7 @@ class Binary(lief.Binary): @overload def get(self, type: lief.ELF.SEGMENT_TYPES) -> lief.ELF.Segment: ... @overload - def get(self, type: lief.ELF.NOTE_TYPES) -> lief.ELF.Note: ... + def get(self, type: lief.ELF.Note.TYPE) -> lief.ELF.Note: ... @overload def get(self, type: lief.ELF.SECTION_TYPES) -> lief.ELF.Section: ... def get_dynamic_symbol(self, symbol_name: str) -> lief.ELF.Symbol: ... @@ -380,7 +384,7 @@ class Binary(lief.Binary): @overload def has(self, type: lief.ELF.SEGMENT_TYPES) -> bool: ... @overload - def has(self, type: lief.ELF.NOTE_TYPES) -> bool: ... + def has(self, type: lief.ELF.Note.TYPE) -> bool: ... @overload def has(self, type: lief.ELF.SECTION_TYPES) -> bool: ... def has_dynamic_symbol(self, symbol_name: str) -> bool: ... @@ -404,7 +408,7 @@ class Binary(lief.Binary): @overload def remove(self, note: lief.ELF.Note) -> None: ... @overload - def remove(self, type: lief.ELF.NOTE_TYPES) -> None: ... + def remove(self, type: lief.ELF.Note.TYPE) -> None: ... @overload def remove_dynamic_symbol(self, arg: lief.ELF.Symbol, /) -> None: ... @overload @@ -427,13 +431,13 @@ class Binary(lief.Binary): @overload def __contains__(self, arg: lief.ELF.DYNAMIC_TAGS, /) -> bool: ... @overload - def __contains__(self, arg: lief.ELF.NOTE_TYPES, /) -> bool: ... + def __contains__(self, arg: lief.ELF.Note.TYPE, /) -> bool: ... @overload def __contains__(self, arg: lief.ELF.SECTION_TYPES, /) -> bool: ... @overload def __getitem__(self, arg: lief.ELF.SEGMENT_TYPES, /) -> lief.ELF.Segment: ... @overload - def __getitem__(self, arg: lief.ELF.NOTE_TYPES, /) -> lief.ELF.Note: ... + def __getitem__(self, arg: lief.ELF.Note.TYPE, /) -> lief.ELF.Note: ... @overload def __getitem__(self, arg: lief.ELF.DYNAMIC_TAGS, /) -> lief.ELF.DynamicEntry: ... @overload @@ -453,7 +457,7 @@ class Binary(lief.Binary): @overload def __isub__(self, arg: lief.ELF.Note, /) -> lief.ELF.Binary: ... @overload - def __isub__(self, arg: lief.ELF.NOTE_TYPES, /) -> lief.ELF.Binary: ... + def __isub__(self, arg: lief.ELF.Note.TYPE, /) -> lief.ELF.Binary: ... @property def dtor_functions(self) -> list[lief.Function]: ... @property @@ -550,81 +554,91 @@ class Builder: def get_build(self) -> list[int]: ... def write(self, output: str) -> None: ... -class CoreAuxv(NoteDetails): - class TYPES: - BASE: ClassVar[CoreAuxv.TYPES] = ... - BASE_PLATFORM: ClassVar[CoreAuxv.TYPES] = ... - CKLTCK: ClassVar[CoreAuxv.TYPES] = ... - DCACHEBSIZE: ClassVar[CoreAuxv.TYPES] = ... - EGID: ClassVar[CoreAuxv.TYPES] = ... - ENTRY: ClassVar[CoreAuxv.TYPES] = ... - EUID: ClassVar[CoreAuxv.TYPES] = ... - EXECFD: ClassVar[CoreAuxv.TYPES] = ... - EXECFN: ClassVar[CoreAuxv.TYPES] = ... - FLAGS: ClassVar[CoreAuxv.TYPES] = ... - FPUCW: ClassVar[CoreAuxv.TYPES] = ... - GID: ClassVar[CoreAuxv.TYPES] = ... - HWCAP: ClassVar[CoreAuxv.TYPES] = ... - HWCAP2: ClassVar[CoreAuxv.TYPES] = ... - ICACHEBSIZE: ClassVar[CoreAuxv.TYPES] = ... - IGNORE: ClassVar[CoreAuxv.TYPES] = ... - IGNOREPPC: ClassVar[CoreAuxv.TYPES] = ... - L1D_CACHESHAPE: ClassVar[CoreAuxv.TYPES] = ... - L1I_CACHESHAPE: ClassVar[CoreAuxv.TYPES] = ... - NOTELF: ClassVar[CoreAuxv.TYPES] = ... - NULL: ClassVar[CoreAuxv.TYPES] = ... - PAGESZ: ClassVar[CoreAuxv.TYPES] = ... - PHDR: ClassVar[CoreAuxv.TYPES] = ... - PHENT: ClassVar[CoreAuxv.TYPES] = ... - PHNUM: ClassVar[CoreAuxv.TYPES] = ... - PLATFORM: ClassVar[CoreAuxv.TYPES] = ... - RANDOM: ClassVar[CoreAuxv.TYPES] = ... - SECURE: ClassVar[CoreAuxv.TYPES] = ... - SYSINFO: ClassVar[CoreAuxv.TYPES] = ... - SYSINFO_EHDR: ClassVar[CoreAuxv.TYPES] = ... - UCACHEBSIZE: ClassVar[CoreAuxv.TYPES] = ... - UID: ClassVar[CoreAuxv.TYPES] = ... +class CoreAuxv(Note): + class TYPE: + BASE: ClassVar[CoreAuxv.TYPE] = ... + BASE_PLATFORM: ClassVar[CoreAuxv.TYPE] = ... + CLKTCK: ClassVar[CoreAuxv.TYPE] = ... + DCACHEBSIZE: ClassVar[CoreAuxv.TYPE] = ... + EGID: ClassVar[CoreAuxv.TYPE] = ... + END: ClassVar[CoreAuxv.TYPE] = ... + ENTRY: ClassVar[CoreAuxv.TYPE] = ... + EUID: ClassVar[CoreAuxv.TYPE] = ... + EXECFD: ClassVar[CoreAuxv.TYPE] = ... + EXECFN: ClassVar[CoreAuxv.TYPE] = ... + FLAGS: ClassVar[CoreAuxv.TYPE] = ... + FPUCW: ClassVar[CoreAuxv.TYPE] = ... + GID: ClassVar[CoreAuxv.TYPE] = ... + HWCAP: ClassVar[CoreAuxv.TYPE] = ... + HWCAP2: ClassVar[CoreAuxv.TYPE] = ... + ICACHEBSIZE: ClassVar[CoreAuxv.TYPE] = ... + IGNORE: ClassVar[CoreAuxv.TYPE] = ... + IGNOREPPC: ClassVar[CoreAuxv.TYPE] = ... + NOTELF: ClassVar[CoreAuxv.TYPE] = ... + PAGESZ: ClassVar[CoreAuxv.TYPE] = ... + PHDR: ClassVar[CoreAuxv.TYPE] = ... + PHENT: ClassVar[CoreAuxv.TYPE] = ... + PHNUM: ClassVar[CoreAuxv.TYPE] = ... + RANDOM: ClassVar[CoreAuxv.TYPE] = ... + SECURE: ClassVar[CoreAuxv.TYPE] = ... + SYSINFO: ClassVar[CoreAuxv.TYPE] = ... + SYSINFO_EHDR: ClassVar[CoreAuxv.TYPE] = ... + TGT_PLATFORM: ClassVar[CoreAuxv.TYPE] = ... + UCACHEBSIZE: ClassVar[CoreAuxv.TYPE] = ... + UID: ClassVar[CoreAuxv.TYPE] = ... __name__: Any def __init__(self, *args, **kwargs) -> None: ... @staticmethod - def from_value(arg: int, /) -> lief.ELF.CoreAuxv.TYPES: ... + def from_value(arg: int, /) -> lief.ELF.CoreAuxv.TYPE: ... @property def value(self) -> int: ... - values: dict[lief.ELF.CoreAuxv.TYPES,int] def __init__(self, *args, **kwargs) -> None: ... - def get(self, type: lief.ELF.CoreAuxv.TYPES) -> object: ... - def has(self, type: lief.ELF.CoreAuxv.TYPES) -> bool: ... - def set(self, type: lief.ELF.CoreAuxv.TYPES, value: int) -> bool: ... - def __contains__(self, arg: lief.ELF.CoreAuxv.TYPES, /) -> bool: ... - def __getitem__(self, arg: lief.ELF.CoreAuxv.TYPES, /) -> int: ... - def __setitem__(self, arg0: lief.ELF.CoreAuxv.TYPES, arg1: int, /) -> None: ... - -class CoreFile(NoteDetails): + def get(self, type: lief.ELF.CoreAuxv.TYPE) -> Optional[int]: ... + @overload + def set(self, type: lief.ELF.CoreAuxv.TYPE, value: int) -> bool: ... + @overload + def set(self, arg: dict[lief.ELF.CoreAuxv.TYPE,int], /) -> bool: ... + def __getitem__(self, arg: lief.ELF.CoreAuxv.TYPE, /) -> Optional[int]: ... + @overload + def __setitem__(self, arg0: lief.ELF.CoreAuxv.TYPE, arg1: int, /) -> bool: ... + @overload + def __setitem__(self, arg: dict[lief.ELF.CoreAuxv.TYPE,int], /) -> bool: ... + @property + def values(self) -> dict[lief.ELF.CoreAuxv.TYPE,int]: ... + +class CoreFile(Note): + class entry_t: + end: int + file_ofs: int + path: str + start: int + def __init__(self, *args, **kwargs) -> None: ... + class files_t: @overload def __init__(self) -> None: ... @overload def __init__(self, arg: lief.ELF.CoreFile.files_t) -> None: ... @overload - def __init__(self, arg: Iterable[lief.ELF.CoreFileEntry], /) -> None: ... - def append(self, arg: lief.ELF.CoreFileEntry, /) -> None: ... + def __init__(self, arg: Iterable[lief.ELF.CoreFile.entry_t], /) -> None: ... + def append(self, arg: lief.ELF.CoreFile.entry_t, /) -> None: ... def clear(self) -> None: ... def extend(self, arg: lief.ELF.CoreFile.files_t, /) -> None: ... - def insert(self, arg0: int, arg1: lief.ELF.CoreFileEntry, /) -> None: ... - def pop(self, index: int = ...) -> lief.ELF.CoreFileEntry: ... + def insert(self, arg0: int, arg1: lief.ELF.CoreFile.entry_t, /) -> None: ... + def pop(self, index: int = ...) -> lief.ELF.CoreFile.entry_t: ... def __bool__(self) -> bool: ... @overload def __delitem__(self, arg: int, /) -> None: ... @overload def __delitem__(self, arg: slice, /) -> None: ... @overload - def __getitem__(self, arg: int, /) -> lief.ELF.CoreFileEntry: ... + def __getitem__(self, arg: int, /) -> lief.ELF.CoreFile.entry_t: ... @overload def __getitem__(self, arg: slice, /) -> lief.ELF.CoreFile.files_t: ... def __iter__(self) -> Iterator: ... def __len__(self) -> int: ... @overload - def __setitem__(self, arg0: int, arg1: lief.ELF.CoreFileEntry, /) -> None: ... + def __setitem__(self, arg0: int, arg1: lief.ELF.CoreFile.entry_t, /) -> None: ... @overload def __setitem__(self, arg0: slice, arg1: lief.ELF.CoreFile.files_t, /) -> None: ... files: lief.ELF.CoreFile.files_t @@ -632,122 +646,168 @@ class CoreFile(NoteDetails): def __iter__(self) -> Iterator: ... def __len__(self) -> int: ... -class CoreFileEntry: - end: int - file_ofs: int - path: str - start: int +class CorePrPsInfo(Note): + class info_t: + args: str + filename: str + flag: int + gid: int + nice: int + pgrp: int + pid: int + ppid: int + sid: int + sname: str + state: int + uid: int + zombie: bool + def __init__(self, *args, **kwargs) -> None: ... + @property + def args_stripped(self) -> str: ... + @property + def filename_stripped(self) -> str: ... + info: Optional[lief.ELF.CorePrPsInfo.info_t] def __init__(self, *args, **kwargs) -> None: ... -class CorePrPsInfo(NoteDetails): - file_name: str - flags: int - gid: int - pgrp: int - pid: int - ppid: int - sid: int - uid: int - def __init__(self, *args, **kwargs) -> None: ... +class CorePrStatus(Note): + class Registers: + class AARCH64: + PC: ClassVar[CorePrStatus.Registers.AARCH64] = ... + PSTATE: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X0: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X1: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X10: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X11: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X12: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X13: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X14: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X15: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X16: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X17: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X18: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X19: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X2: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X20: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X21: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X22: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X23: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X24: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X25: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X26: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X27: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X28: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X29: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X3: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X30: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X31: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X4: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X5: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X6: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X7: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X8: ClassVar[CorePrStatus.Registers.AARCH64] = ... + X9: ClassVar[CorePrStatus.Registers.AARCH64] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.CorePrStatus.Registers.AARCH64: ... + @property + def value(self) -> int: ... + + class ARM: + CPSR: ClassVar[CorePrStatus.Registers.ARM] = ... + R0: ClassVar[CorePrStatus.Registers.ARM] = ... + R1: ClassVar[CorePrStatus.Registers.ARM] = ... + R10: ClassVar[CorePrStatus.Registers.ARM] = ... + R11: ClassVar[CorePrStatus.Registers.ARM] = ... + R12: ClassVar[CorePrStatus.Registers.ARM] = ... + R13: ClassVar[CorePrStatus.Registers.ARM] = ... + R14: ClassVar[CorePrStatus.Registers.ARM] = ... + R15: ClassVar[CorePrStatus.Registers.ARM] = ... + R2: ClassVar[CorePrStatus.Registers.ARM] = ... + R3: ClassVar[CorePrStatus.Registers.ARM] = ... + R4: ClassVar[CorePrStatus.Registers.ARM] = ... + R5: ClassVar[CorePrStatus.Registers.ARM] = ... + R6: ClassVar[CorePrStatus.Registers.ARM] = ... + R7: ClassVar[CorePrStatus.Registers.ARM] = ... + R8: ClassVar[CorePrStatus.Registers.ARM] = ... + R9: ClassVar[CorePrStatus.Registers.ARM] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.CorePrStatus.Registers.ARM: ... + @property + def value(self) -> int: ... + + class X86: + CS: ClassVar[CorePrStatus.Registers.X86] = ... + DS: ClassVar[CorePrStatus.Registers.X86] = ... + EAX: ClassVar[CorePrStatus.Registers.X86] = ... + EBP: ClassVar[CorePrStatus.Registers.X86] = ... + EBX: ClassVar[CorePrStatus.Registers.X86] = ... + ECX: ClassVar[CorePrStatus.Registers.X86] = ... + EDI: ClassVar[CorePrStatus.Registers.X86] = ... + EDX: ClassVar[CorePrStatus.Registers.X86] = ... + EFLAGS: ClassVar[CorePrStatus.Registers.X86] = ... + EIP: ClassVar[CorePrStatus.Registers.X86] = ... + ES: ClassVar[CorePrStatus.Registers.X86] = ... + ESI: ClassVar[CorePrStatus.Registers.X86] = ... + ESP: ClassVar[CorePrStatus.Registers.X86] = ... + FS: ClassVar[CorePrStatus.Registers.X86] = ... + GS: ClassVar[CorePrStatus.Registers.X86] = ... + ORIG_EAX: ClassVar[CorePrStatus.Registers.X86] = ... + SS: ClassVar[CorePrStatus.Registers.X86] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.CorePrStatus.Registers.X86: ... + @property + def value(self) -> int: ... + + class X86_64: + CS: ClassVar[CorePrStatus.Registers.X86_64] = ... + EFLAGS: ClassVar[CorePrStatus.Registers.X86_64] = ... + ORIG_RAX: ClassVar[CorePrStatus.Registers.X86_64] = ... + R10: ClassVar[CorePrStatus.Registers.X86_64] = ... + R11: ClassVar[CorePrStatus.Registers.X86_64] = ... + R12: ClassVar[CorePrStatus.Registers.X86_64] = ... + R13: ClassVar[CorePrStatus.Registers.X86_64] = ... + R14: ClassVar[CorePrStatus.Registers.X86_64] = ... + R15: ClassVar[CorePrStatus.Registers.X86_64] = ... + R8: ClassVar[CorePrStatus.Registers.X86_64] = ... + R9: ClassVar[CorePrStatus.Registers.X86_64] = ... + RAX: ClassVar[CorePrStatus.Registers.X86_64] = ... + RBP: ClassVar[CorePrStatus.Registers.X86_64] = ... + RBX: ClassVar[CorePrStatus.Registers.X86_64] = ... + RCX: ClassVar[CorePrStatus.Registers.X86_64] = ... + RDI: ClassVar[CorePrStatus.Registers.X86_64] = ... + RDX: ClassVar[CorePrStatus.Registers.X86_64] = ... + RIP: ClassVar[CorePrStatus.Registers.X86_64] = ... + RSI: ClassVar[CorePrStatus.Registers.X86_64] = ... + RSP: ClassVar[CorePrStatus.Registers.X86_64] = ... + SS: ClassVar[CorePrStatus.Registers.X86_64] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.CorePrStatus.Registers.X86_64: ... + @property + def value(self) -> int: ... + def __init__(self, *args, **kwargs) -> None: ... -class CorePrStatus(NoteDetails): - class REGISTERS: - AARCH64_PC: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X0: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X1: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X10: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X11: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X12: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X13: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X14: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X15: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X16: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X17: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X18: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X19: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X2: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X20: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X21: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X22: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X23: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X24: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X25: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X26: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X27: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X28: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X29: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X3: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X30: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X31: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X4: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X5: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X6: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X7: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X8: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64_X9: ClassVar[CorePrStatus.REGISTERS] = ... - AARCH64__: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_CPSR: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R0: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R1: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R10: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R11: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R12: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R13: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R14: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R15: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R2: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R3: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R4: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R5: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R6: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R7: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R8: ClassVar[CorePrStatus.REGISTERS] = ... - ARM_R9: ClassVar[CorePrStatus.REGISTERS] = ... - UNKNOWN: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_CS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_EFLAGS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R10: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R11: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R12: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R13: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R14: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R15: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R8: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_R9: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RAX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RBP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RBX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RCX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RDI: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RDX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RIP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RSI: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_RSP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64_SS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_64__: ClassVar[CorePrStatus.REGISTERS] = ... - X86_CS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_DS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EAX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EBP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EBX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_ECX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EDI: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EDX: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EFLAGS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_EIP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_ES: ClassVar[CorePrStatus.REGISTERS] = ... - X86_ESI: ClassVar[CorePrStatus.REGISTERS] = ... - X86_ESP: ClassVar[CorePrStatus.REGISTERS] = ... - X86_FS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_GS: ClassVar[CorePrStatus.REGISTERS] = ... - X86_SS: ClassVar[CorePrStatus.REGISTERS] = ... - X86__: ClassVar[CorePrStatus.REGISTERS] = ... - __name__: Any + class pr_status_t: + cstime: lief.ELF.CorePrStatus.timeval_t # type: ignore + cursig: int + cutime: lief.ELF.CorePrStatus.timeval_t # type: ignore + info: lief.ELF.CorePrStatus.siginfo_t # type: ignore + pgrp: int + pid: int + ppid: int + reserved: int + sid: int + sighold: int + sigpend: int + stime: lief.ELF.CorePrStatus.timeval_t # type: ignore + utime: lief.ELF.CorePrStatus.timeval_t # type: ignore def __init__(self, *args, **kwargs) -> None: ... - @staticmethod - def from_value(arg: int, /) -> lief.ELF.CorePrStatus.REGISTERS: ... - @property - def value(self) -> int: ... class siginfo_t: errno: int @@ -755,35 +815,59 @@ class CorePrStatus(NoteDetails): signo: int def __init__(self, *args, **kwargs) -> None: ... - class timeval: + class timeval_t: sec: int usec: int def __init__(self, *args, **kwargs) -> None: ... - cstime: lief.ELF.CorePrStatus.timeval - current_sig: int - cutime: lief.ELF.CorePrStatus.timeval - pgrp: int - pid: int - ppid: int - register_context: dict[lief.ELF.CorePrStatus.REGISTERS,int] - sid: int - sighold: int - siginfo: lief.ELF.CorePrStatus.siginfo_t - sigpend: int - stime: lief.ELF.CorePrStatus.timeval - utime: lief.ELF.CorePrStatus.timeval + status: lief.ELF.CorePrStatus.pr_status_t def __init__(self, *args, **kwargs) -> None: ... - def get(self, register: lief.ELF.CorePrStatus.REGISTERS) -> object: ... - def has(self, register: lief.ELF.CorePrStatus.REGISTERS) -> bool: ... - def set(self, register: lief.ELF.CorePrStatus.REGISTERS, value: int) -> bool: ... - def __contains__(self, arg: lief.ELF.CorePrStatus.REGISTERS, /) -> bool: ... - def __getitem__(self, arg: lief.ELF.CorePrStatus.REGISTERS, /) -> int: ... - def __setitem__(self, arg0: lief.ELF.CorePrStatus.REGISTERS, arg1: int, /) -> None: ... - -class CoreSigInfo(NoteDetails): - sigcode: int - sigerrno: int - signo: int + @overload + def get(self, reg: lief.ELF.CorePrStatus.Registers.X86) -> Optional[int]: ... + @overload + def get(self, reg: lief.ELF.CorePrStatus.Registers.X86_64) -> Optional[int]: ... + @overload + def get(self, reg: lief.ELF.CorePrStatus.Registers.ARM) -> Optional[int]: ... + @overload + def get(self, reg: lief.ELF.CorePrStatus.Registers.AARCH64) -> Optional[int]: ... + @overload + def set(self, reg: lief.ELF.CorePrStatus.Registers.X86, value: int) -> lief.ok_error_t: ... + @overload + def set(self, reg: lief.ELF.CorePrStatus.Registers.X86_64, value: int) -> lief.ok_error_t: ... + @overload + def set(self, reg: lief.ELF.CorePrStatus.Registers.ARM, value: int) -> lief.ok_error_t: ... + @overload + def set(self, reg: lief.ELF.CorePrStatus.Registers.AARCH64, value: int) -> lief.ok_error_t: ... + @overload + def __getitem__(self, arg: lief.ELF.CorePrStatus.Registers.X86, /) -> Optional[int]: ... + @overload + def __getitem__(self, arg: lief.ELF.CorePrStatus.Registers.X86_64, /) -> Optional[int]: ... + @overload + def __getitem__(self, arg: lief.ELF.CorePrStatus.Registers.ARM, /) -> Optional[int]: ... + @overload + def __getitem__(self, arg: lief.ELF.CorePrStatus.Registers.AARCH64, /) -> Optional[int]: ... + @overload + def __setitem__(self, arg0: lief.ELF.CorePrStatus.Registers.X86, arg1: int, /) -> lief.ok_error_t: ... + @overload + def __setitem__(self, arg0: lief.ELF.CorePrStatus.Registers.X86_64, arg1: int, /) -> lief.ok_error_t: ... + @overload + def __setitem__(self, arg0: lief.ELF.CorePrStatus.Registers.ARM, arg1: int, /) -> lief.ok_error_t: ... + @overload + def __setitem__(self, arg0: lief.ELF.CorePrStatus.Registers.AARCH64, arg1: int, /) -> lief.ok_error_t: ... + @property + def architecture(self) -> lief.ELF.ARCH: ... + @property + def pc(self) -> Optional[int]: ... + @property + def register_values(self) -> list[int]: ... + @property + def return_value(self) -> Optional[int]: ... + @property + def sp(self) -> Optional[int]: ... + +class CoreSigInfo(Note): + sigcode: Optional[int] + sigerrno: Optional[int] + signo: Optional[int] def __init__(self, *args, **kwargs) -> None: ... class DYNAMIC_FLAGS: @@ -1313,90 +1397,97 @@ class MIPS_EFLAGS: @property def value(self) -> int: ... -class NOTE_ABIS: - FREEBSD: ClassVar[NOTE_ABIS] = ... - GNU: ClassVar[NOTE_ABIS] = ... - LINUX: ClassVar[NOTE_ABIS] = ... - NETBSD: ClassVar[NOTE_ABIS] = ... - SOLARIS2: ClassVar[NOTE_ABIS] = ... - SYLLABLE: ClassVar[NOTE_ABIS] = ... - UNKNOWN: ClassVar[NOTE_ABIS] = ... - __name__: Any - def __init__(self, *args, **kwargs) -> None: ... - @staticmethod - def from_value(arg: int, /) -> lief.ELF.NOTE_ABIS: ... - @property - def value(self) -> int: ... - -class NOTE_TYPES: - ABI_TAG: ClassVar[NOTE_TYPES] = ... - BUILD_ID: ClassVar[NOTE_TYPES] = ... - CRASHPAD: ClassVar[NOTE_TYPES] = ... - GNU_BUILD_ATTRIBUTE_FUNC: ClassVar[NOTE_TYPES] = ... - GNU_BUILD_ATTRIBUTE_OPEN: ClassVar[NOTE_TYPES] = ... - GOLD_VERSION: ClassVar[NOTE_TYPES] = ... - HWCAP: ClassVar[NOTE_TYPES] = ... - PROPERTY_TYPE_0: ClassVar[NOTE_TYPES] = ... - UNKNOWN: ClassVar[NOTE_TYPES] = ... - __name__: Any - def __init__(self, *args, **kwargs) -> None: ... - @staticmethod - def from_value(arg: int, /) -> lief.ELF.NOTE_TYPES: ... - @property - def value(self) -> int: ... - -class NOTE_TYPES_CORE: - ARM_HW_BREAK: ClassVar[NOTE_TYPES_CORE] = ... - ARM_HW_WATCH: ClassVar[NOTE_TYPES_CORE] = ... - ARM_SVE: ClassVar[NOTE_TYPES_CORE] = ... - ARM_SYSTEM_CALL: ClassVar[NOTE_TYPES_CORE] = ... - ARM_TLS: ClassVar[NOTE_TYPES_CORE] = ... - ARM_VFP: ClassVar[NOTE_TYPES_CORE] = ... - AUXV: ClassVar[NOTE_TYPES_CORE] = ... - FILE: ClassVar[NOTE_TYPES_CORE] = ... - I386_IOPERM: ClassVar[NOTE_TYPES_CORE] = ... - I386_TLS: ClassVar[NOTE_TYPES_CORE] = ... - I386_XSTATE: ClassVar[NOTE_TYPES_CORE] = ... - PRFPREG: ClassVar[NOTE_TYPES_CORE] = ... - PRPSINFO: ClassVar[NOTE_TYPES_CORE] = ... - PRSTATUS: ClassVar[NOTE_TYPES_CORE] = ... - SIGINFO: ClassVar[NOTE_TYPES_CORE] = ... - TASKSTRUCT: ClassVar[NOTE_TYPES_CORE] = ... - UNKNOWN: ClassVar[NOTE_TYPES_CORE] = ... - __name__: Any - def __init__(self, *args, **kwargs) -> None: ... - @staticmethod - def from_value(arg: int, /) -> lief.ELF.NOTE_TYPES_CORE: ... - @property - def value(self) -> int: ... - class Note(lief.Object): - description: list[int] + class TYPE: + ANDROID_IDENT: ClassVar[Note.TYPE] = ... + ANDROID_KUSER: ClassVar[Note.TYPE] = ... + ANDROID_MEMTAG: ClassVar[Note.TYPE] = ... + CORE_ARM_HW_BREAK: ClassVar[Note.TYPE] = ... + CORE_ARM_HW_WATCH: ClassVar[Note.TYPE] = ... + CORE_ARM_PACA_KEYS: ClassVar[Note.TYPE] = ... + CORE_ARM_PACG_KEYS: ClassVar[Note.TYPE] = ... + CORE_ARM_PAC_MASK: ClassVar[Note.TYPE] = ... + CORE_ARM_SVE: ClassVar[Note.TYPE] = ... + CORE_ARM_SYSTEM_CALL: ClassVar[Note.TYPE] = ... + CORE_ARM_TLS: ClassVar[Note.TYPE] = ... + CORE_ARM_VFP: ClassVar[Note.TYPE] = ... + CORE_AUXV: ClassVar[Note.TYPE] = ... + CORE_FILE: ClassVar[Note.TYPE] = ... + CORE_FPREGS: ClassVar[Note.TYPE] = ... + CORE_FPREGSET: ClassVar[Note.TYPE] = ... + CORE_LWPSINFO: ClassVar[Note.TYPE] = ... + CORE_LWPSTATUS: ClassVar[Note.TYPE] = ... + CORE_PAC_ENABLED_KEYS: ClassVar[Note.TYPE] = ... + CORE_PRPSINFO: ClassVar[Note.TYPE] = ... + CORE_PRSTATUS: ClassVar[Note.TYPE] = ... + CORE_PRXFPREG: ClassVar[Note.TYPE] = ... + CORE_PSINFO: ClassVar[Note.TYPE] = ... + CORE_PSTATUS: ClassVar[Note.TYPE] = ... + CORE_SIGINFO: ClassVar[Note.TYPE] = ... + CORE_TAGGED_ADDR_CTRL: ClassVar[Note.TYPE] = ... + CORE_TASKSTRUCT: ClassVar[Note.TYPE] = ... + CORE_WIN32PSTATUS: ClassVar[Note.TYPE] = ... + CORE_X86_CET: ClassVar[Note.TYPE] = ... + CORE_X86_IOPERM: ClassVar[Note.TYPE] = ... + CORE_X86_TLS: ClassVar[Note.TYPE] = ... + CORE_X86_XSTATE: ClassVar[Note.TYPE] = ... + CRASHPAD: ClassVar[Note.TYPE] = ... + GNU_ABI_TAG: ClassVar[Note.TYPE] = ... + GNU_BUILD_ATTRIBUTE_FUNC: ClassVar[Note.TYPE] = ... + GNU_BUILD_ATTRIBUTE_OPEN: ClassVar[Note.TYPE] = ... + GNU_BUILD_ID: ClassVar[Note.TYPE] = ... + GNU_GOLD_VERSION: ClassVar[Note.TYPE] = ... + GNU_HWCAP: ClassVar[Note.TYPE] = ... + GNU_PROPERTY_TYPE_0: ClassVar[Note.TYPE] = ... + GO_BUILDID: ClassVar[Note.TYPE] = ... + STAPSDT: ClassVar[Note.TYPE] = ... + UNKNOWN: ClassVar[Note.TYPE] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.Note.TYPE: ... + @property + def value(self) -> int: ... + description: memoryview name: str - type: lief.ELF.NOTE_TYPES - type_core: lief.ELF.NOTE_TYPES_CORE + def __init__(self, *args, **kwargs) -> None: ... + def copy(self) -> Optional[lief.ELF.Note]: ... @overload - def __init__(self) -> None: ... + @staticmethod + def create(name: str, original_type: int, description: list[int], file_type: lief.ELF.E_TYPE = ..., arch: lief.ELF.ARCH = ..., cls: lief.ELF.ELF_CLASS = ...) -> Optional[lief.ELF.Note]: ... @overload - def __init__(self, name: str, type: lief.ELF.NOTE_TYPES, description: list[int]) -> None: ... - @property - def details(self) -> lief.ELF.NoteDetails: ... - @property - def is_android(self) -> bool: ... + @staticmethod + def create(raw: bytes, file_type: lief.ELF.E_TYPE = ..., arch: lief.ELF.ARCH = ..., cls: lief.ELF.ELF_CLASS = ...) -> Optional[lief.ELF.Note]: ... + @overload + @staticmethod + def create(name: str, type: lief.ELF.Note.TYPE, description: list[int], arch: lief.ELF.ARCH = ..., cls: lief.ELF.ELF_CLASS = ...) -> Optional[lief.ELF.Note]: ... @property - def is_core(self) -> bool: ... + def original_type(self) -> int: ... @property def size(self) -> int: ... - -class NoteAbi(NoteDetails): + @property + def type(self) -> lief.ELF.Note.TYPE: ... + +class NoteAbi(Note): + class ABI: + FREEBSD: ClassVar[NoteAbi.ABI] = ... + GNU: ClassVar[NoteAbi.ABI] = ... + LINUX: ClassVar[NoteAbi.ABI] = ... + NACL: ClassVar[NoteAbi.ABI] = ... + NETBSD: ClassVar[NoteAbi.ABI] = ... + SOLARIS2: ClassVar[NoteAbi.ABI] = ... + SYLLABLE: ClassVar[NoteAbi.ABI] = ... + __name__: Any + def __init__(self, *args, **kwargs) -> None: ... + @staticmethod + def from_value(arg: int, /) -> lief.ELF.NoteAbi.ABI: ... + @property + def value(self) -> int: ... def __init__(self, *args, **kwargs) -> None: ... @property - def abi(self) -> lief.ELF.NOTE_ABIS: ... + def abi(self) -> Optional[lief.ELF.NoteAbi.ABI]: ... @property - def version(self) -> list[int]: ... - -class NoteDetails(lief.Object): - def __init__(self, *args, **kwargs) -> None: ... + def version(self) -> Optional[list[int]]: ... class OS_ABI: AIX: ClassVar[OS_ABI] = ... diff --git a/api/python/lief/__init__.pyi b/api/python/lief/__init__.pyi index 3c33001b74..53ae988a42 100644 --- a/api/python/lief/__init__.pyi +++ b/api/python/lief/__init__.pyi @@ -261,6 +261,18 @@ class lief_errors: __name__: Any def __init__(self, *args, **kwargs) -> None: ... +class ok_error_t: + def __init__(self, *args, **kwargs) -> None: ... + def __bool__(self) -> bool: ... + @property + def error(self) -> lief_errors: ... + @property + def is_error(self) -> bool: ... + @property + def is_value(self) -> bool: ... + @property + def value(self) -> lief.ok_t: ... + class ok_t: def __init__(self, *args, **kwargs) -> None: ... def __bool__(self) -> bool: ... diff --git a/api/python/pyproject.toml b/api/python/pyproject.toml index 4292dc3e4a..3028fa2740 100644 --- a/api/python/pyproject.toml +++ b/api/python/pyproject.toml @@ -30,5 +30,5 @@ homepage = "https://lief-project.github.io/" documentation = "https://lief-project.github.io/doc/latest/" repository = "https://github.com/lief-project/LIEF" changelog = "https://lief-project.github.io/doc/latest/changelog.html" -Funding = "https://lief-project.github.io/about" +Funding = "https://github.com/sponsors/lief-project" Tracker = "https://github.com/lief-project/LIEF/issues" diff --git a/api/python/src/ELF/enums.cpp b/api/python/src/ELF/enums.cpp index edbccdd875..c9a953dc54 100644 --- a/api/python/src/ELF/enums.cpp +++ b/api/python/src/ELF/enums.cpp @@ -1177,50 +1177,6 @@ void init_enums(nb::module_& m) { .value(PY_ENUM(DYNSYM_COUNT_METHODS::COUNT_RELOCATIONS)); - enum_(m, "NOTE_TYPES") - .value(PY_ENUM(NOTE_TYPES::NT_UNKNOWN)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_ABI_TAG)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_HWCAP)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_BUILD_ID)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_GOLD_VERSION)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_PROPERTY_TYPE_0)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_OPEN)) - .value(PY_ENUM(NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_FUNC)) - .value(PY_ENUM(NOTE_TYPES::NT_CRASHPAD)); - - - enum_(m, "NOTE_TYPES_CORE") - .value(PY_ENUM(NOTE_TYPES_CORE::NT_CORE_UNKNOWN)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_PRSTATUS)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_PRFPREG)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_PRPSINFO)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_TASKSTRUCT)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_AUXV)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_SIGINFO)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_FILE)) - - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_VFP)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_TLS)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_HW_BREAK)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_HW_WATCH)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_SYSTEM_CALL)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_ARM_SVE)) - - .value(PY_ENUM(NOTE_TYPES_CORE::NT_386_TLS)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_386_IOPERM)) - .value(PY_ENUM(NOTE_TYPES_CORE::NT_386_XSTATE)); - - - enum_(m, "NOTE_ABIS") - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_UNKNOWN)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_LINUX)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_GNU)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_SOLARIS2)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_FREEBSD)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_NETBSD)) - .value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_SYLLABLE)); - - enum_(m, "RELOCATION_PURPOSES") .value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_NONE)) .value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT)) diff --git a/api/python/src/ELF/init.cpp b/api/python/src/ELF/init.cpp index 40f8cc041e..f4f7ec7f68 100644 --- a/api/python/src/ELF/init.cpp +++ b/api/python/src/ELF/init.cpp @@ -30,15 +30,6 @@ #include "LIEF/ELF/DynamicSharedObject.hpp" #include "LIEF/ELF/GnuHash.hpp" #include "LIEF/ELF/Header.hpp" -#include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails.hpp" -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" -#include "LIEF/ELF/NoteDetails/NoteAbi.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" -#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" -#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp" #include "LIEF/ELF/Parser.hpp" #include "LIEF/ELF/Relocation.hpp" #include "LIEF/ELF/Section.hpp" @@ -51,10 +42,30 @@ #include "LIEF/ELF/SysvHash.hpp" #include "LIEF/ELF/utils.hpp" +#include "LIEF/ELF/Note.hpp" +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" +#include "LIEF/ELF/NoteDetails/NoteAbi.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" +#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp" +#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" + #define CREATE(X,Y) create(Y) namespace LIEF::ELF::py { +void init_notes(nb::module_& m) { + CREATE(Note, m); + CREATE(AndroidIdent, m); + CREATE(NoteAbi, m); + CREATE(CoreAuxv, m); + CREATE(CoreFile, m); + CREATE(CorePrPsInfo, m); + CREATE(CoreSigInfo, m); + CREATE(CorePrStatus, m); +} + void init_objects(nb::module_& m) { CREATE(ParserConfig, m); CREATE(Parser, m); @@ -79,16 +90,8 @@ void init_objects(nb::module_& m) { CREATE(GnuHash, m); CREATE(SysvHash, m); CREATE(Builder, m); - CREATE(Note, m); - CREATE(NoteDetails, m); - CREATE(AndroidNote, m); - CREATE(NoteAbi, m); - CREATE(CorePrPsInfo, m); - CREATE(CoreFile, m); - CREATE(CoreFileEntry, m); - CREATE(CorePrStatus, m); - CREATE(CoreAuxv, m); - CREATE(CoreSigInfo, m); + + init_notes(m); } inline void init_utils(nb::module_&) { diff --git a/api/python/src/ELF/objects/CMakeLists.txt b/api/python/src/ELF/objects/CMakeLists.txt index 616be71079..032af23055 100644 --- a/api/python/src/ELF/objects/CMakeLists.txt +++ b/api/python/src/ELF/objects/CMakeLists.txt @@ -1,32 +1,28 @@ -set(LIEF_PYTHON_ELF_OBJECT_SRC - "${CMAKE_CURRENT_SOURCE_DIR}/pyParser.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyBinary.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyBuilder.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntry.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryArray.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryFlags.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryLibrary.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryRpath.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryRunPath.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicSharedObject.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyGnuHash.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyHeader.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyParserConfig.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyNote.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyNoteDetails.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyRelocation.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySection.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySegment.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbol.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersion.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionAux.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionAuxRequirement.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionRequirement.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionDefinition.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pySysvHash.cpp" +target_sources(pyLIEF PRIVATE + pyParser.cpp + pyBinary.cpp + pyBuilder.cpp + pyDynamicEntry.cpp + pyDynamicEntryArray.cpp + pyDynamicEntryFlags.cpp + pyDynamicEntryLibrary.cpp + pyDynamicEntryRpath.cpp + pyDynamicEntryRunPath.cpp + pyDynamicSharedObject.cpp + pyGnuHash.cpp + pyHeader.cpp + pyParserConfig.cpp + pyNote.cpp + pyRelocation.cpp + pySection.cpp + pySegment.cpp + pySymbol.cpp + pySymbolVersion.cpp + pySymbolVersionAux.cpp + pySymbolVersionAuxRequirement.cpp + pySymbolVersionRequirement.cpp + pySymbolVersionDefinition.cpp + pySysvHash.cpp ) -target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_ELF_OBJECT_SRC}) - add_subdirectory(NoteDetails) - diff --git a/api/python/src/ELF/objects/NoteDetails/CMakeLists.txt b/api/python/src/ELF/objects/NoteDetails/CMakeLists.txt index b86d00ac79..46ef27c73d 100644 --- a/api/python/src/ELF/objects/NoteDetails/CMakeLists.txt +++ b/api/python/src/ELF/objects/NoteDetails/CMakeLists.txt @@ -1,9 +1,7 @@ -set(LIEF_PYTHON_ELF_NOTE_DETAILS_SRC - "${CMAKE_CURRENT_SOURCE_DIR}/pyAndroidNote.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyNoteAbi.cpp" +target_sources(pyLIEF PRIVATE + pyAndroidIdent.cpp + pyNoteAbi.cpp ) -target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ELF_NOTE_DETAILS_SRC}") - add_subdirectory(core) diff --git a/api/python/src/ELF/objects/NoteDetails/core/CMakeLists.txt b/api/python/src/ELF/objects/NoteDetails/core/CMakeLists.txt index b4e16fbfff..628848bead 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/CMakeLists.txt +++ b/api/python/src/ELF/objects/NoteDetails/core/CMakeLists.txt @@ -1,12 +1,7 @@ -set(LIEF_PYTHON_ELF_NOTE_DETAILS_CORE - "${CMAKE_CURRENT_SOURCE_DIR}/pyCorePrPsInfo.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyCoreFile.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyCoreFileEntry.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyCorePrStatus.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyCoreAuxv.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/pyCoreSigInfo.cpp" +target_sources(pyLIEF PRIVATE + pyCorePrPsInfo.cpp + pyCoreFile.cpp + pyCorePrStatus.cpp + pyCoreAuxv.cpp + pyCoreSigInfo.cpp ) -target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ELF_NOTE_DETAILS_CORE}") - - - diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCoreAuxv.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCoreAuxv.cpp index 17ac476ae5..e708c8badf 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCoreAuxv.cpp +++ b/api/python/src/ELF/objects/NoteDetails/core/pyCoreAuxv.cpp @@ -21,90 +21,87 @@ #include "ELF/pyELF.hpp" #include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" -#include "LIEF/ELF/EnumToString.hpp" +#include "pyErr.hpp" #include "enums_wrapper.hpp" -#define PY_ENUM(x) LIEF::ELF::to_string(x), x namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - nb::class_ cls(m, "CoreAuxv"); - LIEF::enum_(cls, "TYPES") - .value(PY_ENUM(AUX_TYPE::AT_NULL)) - .value(PY_ENUM(AUX_TYPE::AT_IGNORE)) - .value(PY_ENUM(AUX_TYPE::AT_EXECFD)) - .value(PY_ENUM(AUX_TYPE::AT_PHDR)) - .value(PY_ENUM(AUX_TYPE::AT_PHENT)) - .value(PY_ENUM(AUX_TYPE::AT_PHNUM)) - .value(PY_ENUM(AUX_TYPE::AT_PAGESZ)) - .value(PY_ENUM(AUX_TYPE::AT_BASE)) - .value(PY_ENUM(AUX_TYPE::AT_FLAGS)) - .value(PY_ENUM(AUX_TYPE::AT_ENTRY)) - .value(PY_ENUM(AUX_TYPE::AT_NOTELF)) - .value(PY_ENUM(AUX_TYPE::AT_UID)) - .value(PY_ENUM(AUX_TYPE::AT_EUID)) - .value(PY_ENUM(AUX_TYPE::AT_GID)) - .value(PY_ENUM(AUX_TYPE::AT_EGID)) - .value(PY_ENUM(AUX_TYPE::AT_CLKTCK)) - .value(PY_ENUM(AUX_TYPE::AT_PLATFORM)) - .value(PY_ENUM(AUX_TYPE::AT_HWCAP)) - .value(PY_ENUM(AUX_TYPE::AT_HWCAP2)) - .value(PY_ENUM(AUX_TYPE::AT_FPUCW)) - .value(PY_ENUM(AUX_TYPE::AT_DCACHEBSIZE)) - .value(PY_ENUM(AUX_TYPE::AT_ICACHEBSIZE)) - .value(PY_ENUM(AUX_TYPE::AT_UCACHEBSIZE)) - .value(PY_ENUM(AUX_TYPE::AT_IGNOREPPC)) - .value(PY_ENUM(AUX_TYPE::AT_SECURE)) - .value(PY_ENUM(AUX_TYPE::AT_BASE_PLATFORM)) - .value(PY_ENUM(AUX_TYPE::AT_RANDOM)) - .value(PY_ENUM(AUX_TYPE::AT_EXECFN)) - .value(PY_ENUM(AUX_TYPE::AT_SYSINFO)) - .value(PY_ENUM(AUX_TYPE::AT_SYSINFO_EHDR)) - .value(PY_ENUM(AUX_TYPE::AT_L1I_CACHESHAPE)) - .value(PY_ENUM(AUX_TYPE::AT_L1D_CACHESHAPE)); + nb::class_ cls(m, "CoreAuxv"); + #define PY_ENUM(X) .value(LIEF::ELF::to_string(CoreAuxv::TYPE::X), CoreAuxv::TYPE::X) + LIEF::enum_(cls, "TYPE") + PY_ENUM(END) + PY_ENUM(IGNORE) + PY_ENUM(EXECFD) + PY_ENUM(PHDR) + PY_ENUM(PHENT) + PY_ENUM(PHNUM) + PY_ENUM(PAGESZ) + PY_ENUM(BASE) + PY_ENUM(FLAGS) + PY_ENUM(ENTRY) + PY_ENUM(NOTELF) + PY_ENUM(UID) + PY_ENUM(EUID) + PY_ENUM(GID) + PY_ENUM(EGID) + PY_ENUM(TGT_PLATFORM) + PY_ENUM(HWCAP) + PY_ENUM(CLKTCK) + PY_ENUM(FPUCW) + PY_ENUM(DCACHEBSIZE) + PY_ENUM(ICACHEBSIZE) + PY_ENUM(UCACHEBSIZE) + PY_ENUM(IGNOREPPC) + PY_ENUM(SECURE) + PY_ENUM(BASE_PLATFORM) + PY_ENUM(RANDOM) + PY_ENUM(HWCAP2) + PY_ENUM(EXECFN) + PY_ENUM(SYSINFO) + PY_ENUM(SYSINFO_EHDR) + ; + #undef PY_ENUM cls - .def_prop_rw("values", - nb::overload_cast<>(&CoreAuxv::values, nb::const_), - nb::overload_cast(&CoreAuxv::values), - "Current values as a dictionary for which keys are AUXV types"_doc) + .def_prop_ro("values", &CoreAuxv::values, + R"doc( + Return the auxiliary vector as a dictionary of :class:`.TYPE` / `int` + )doc" + ) .def("get", - [] (const CoreAuxv& status, AUX_TYPE atype) -> nb::object { - bool error; - const uint64_t val = status.get(atype, &error); - if (error) { - return nb::none(); - } - return nb::int_(val); - }, - "Return the type value"_doc, - "type"_a) - - .def("set", - &CoreAuxv::set, - "Set type value"_doc, - "type"_a, "value"_a) - - .def("has", - &CoreAuxv::has, - "Check if a value is associated with the given type"_doc, - "type"_a) + [] (const CoreAuxv& self, CoreAuxv::TYPE type) { + return LIEF::py::value_or_none(&CoreAuxv::get, self, type); + }, "type"_a, + R"doc( + Get the auxv value from the provided type. Return `None` if + it is not present. + )doc"_doc + ) .def("__getitem__", - &CoreAuxv::operator[], - nb::rv_policy::copy) + [] (const CoreAuxv& self, CoreAuxv::TYPE type) { + return LIEF::py::value_or_none(&CoreAuxv::get, self, type); + } + ) - .def("__setitem__", - [] (CoreAuxv& status, AUX_TYPE atype, uint64_t val) { - status.set(atype, val); - }) + .def("set", nb::overload_cast(&CoreAuxv::set), + "type"_a, "value"_a, + R"doc( + Change the value for the given type. + )doc") + .def("set", nb::overload_cast>(&CoreAuxv::set), + R"doc( + Replace **all** the values by the given dictionary. + )doc") - .def("__contains__", &CoreAuxv::has) + .def("__setitem__", nb::overload_cast(&CoreAuxv::set)) + .def("__setitem__", nb::overload_cast>(&CoreAuxv::set)) LIEF_DEFAULT_STR(CoreAuxv); } diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCoreFile.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCoreFile.cpp index 31e2fcccaa..af2ff2ed2e 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCoreFile.cpp +++ b/api/python/src/ELF/objects/NoteDetails/core/pyCoreFile.cpp @@ -28,10 +28,24 @@ namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - - nb::class_ cls(m, "CoreFile"); + nb::class_ cls(m, "CoreFile"); nb::bind_vector(cls, "files_t"); + nb::class_(cls, "entry_t") + .def_rw("start", &CoreFile::entry_t::start, + "Start address of mapped file"_doc) + + .def_rw("end", &CoreFile::entry_t::end, + "End address of mapped file"_doc) + + .def_rw("file_ofs", &CoreFile::entry_t::file_ofs, + "Offset (in core) of mapped file"_doc) + + .def_rw("path", &CoreFile::entry_t::path, + "Path of mapped file"_doc) + + LIEF_DEFAULT_STR(CoreFile::entry_t); + cls .def_prop_rw("files", nb::overload_cast<>(&CoreFile::files, nb::const_), diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCoreFileEntry.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCoreFileEntry.cpp deleted file mode 100644 index 4f355f4939..0000000000 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCoreFileEntry.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include - -#include "ELF/pyELF.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" - -namespace LIEF::ELF::py { - -template<> -void create(nb::module_& m) { - - nb::class_(m, "CoreFileEntry") - - .def_rw("start", &CoreFileEntry::start, - "Start address of mapped file"_doc) - - .def_rw("end", &CoreFileEntry::end, - "End address of mapped file"_doc) - - .def_rw("file_ofs", &CoreFileEntry::file_ofs, - "Offset (in core) of mapped file"_doc) - - .def_rw("path", &CoreFileEntry::path, - "Path of mapped file"_doc) - - LIEF_DEFAULT_STR(CoreFileEntry); -} - -} diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCorePrPsInfo.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCorePrPsInfo.cpp index eaf682f1e8..dadf0b0f92 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCorePrPsInfo.cpp +++ b/api/python/src/ELF/objects/NoteDetails/core/pyCorePrPsInfo.cpp @@ -15,8 +15,10 @@ */ #include #include + #include +#include "pyErr.hpp" #include "ELF/pyELF.hpp" #include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" @@ -25,49 +27,31 @@ namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - - nb::class_(m, "CorePrPsInfo") - - .def_prop_rw("file_name", - nb::overload_cast<>(&CorePrPsInfo::file_name, nb::const_), - nb::overload_cast(&CorePrPsInfo::file_name), - "Process file name"_doc) - - .def_prop_rw("flags", - nb::overload_cast<>(&CorePrPsInfo::flags, nb::const_), - nb::overload_cast(&CorePrPsInfo::flags), - "Process flags"_doc) - - .def_prop_rw("uid", - nb::overload_cast<>(&CorePrPsInfo::uid, nb::const_), - nb::overload_cast(&CorePrPsInfo::uid), - "Process User ID"_doc) - - .def_prop_rw("gid", - nb::overload_cast<>(&CorePrPsInfo::gid, nb::const_), - nb::overload_cast(&CorePrPsInfo::gid), - "Process Group ID"_doc) - - .def_prop_rw("pid", - nb::overload_cast<>(&CorePrPsInfo::pid, nb::const_), - nb::overload_cast(&CorePrPsInfo::pid), - "Process ID"_doc) - - .def_prop_rw("ppid", - nb::overload_cast<>(&CorePrPsInfo::ppid, nb::const_), - nb::overload_cast(&CorePrPsInfo::ppid), - "Process parent ID"_doc) - - .def_prop_rw("pgrp", - nb::overload_cast<>(&CorePrPsInfo::pgrp, nb::const_), - nb::overload_cast(&CorePrPsInfo::pgrp), - "Process session group ID"_doc) - - .def_prop_rw("sid", - nb::overload_cast<>(&CorePrPsInfo::sid, nb::const_), - nb::overload_cast(&CorePrPsInfo::sid), - "Process session ID"_doc) - + nb::class_ cls(m, "CorePrPsInfo"); + nb::class_(cls, "info_t") + .def_rw("state", &CorePrPsInfo::info_t::state) + .def_rw("sname", &CorePrPsInfo::info_t::sname) + .def_rw("zombie", &CorePrPsInfo::info_t::zombie) + .def_rw("nice", &CorePrPsInfo::info_t::nice) + .def_rw("flag", &CorePrPsInfo::info_t::flag) + .def_rw("uid", &CorePrPsInfo::info_t::uid) + .def_rw("gid", &CorePrPsInfo::info_t::gid) + .def_rw("pid", &CorePrPsInfo::info_t::pid) + .def_rw("ppid", &CorePrPsInfo::info_t::ppid) + .def_rw("pgrp", &CorePrPsInfo::info_t::pgrp) + .def_rw("sid", &CorePrPsInfo::info_t::sid) + .def_rw("filename", &CorePrPsInfo::info_t::filename) + .def_rw("args", &CorePrPsInfo::info_t::args) + .def_prop_ro("filename_stripped", &CorePrPsInfo::info_t::filename_stripped) + .def_prop_ro("args_stripped", &CorePrPsInfo::info_t::args_stripped); + + cls + .def_prop_rw("info", + [] (const CorePrPsInfo& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&CorePrPsInfo::info, nb::const_), self); + }, + nb::overload_cast(&CorePrPsInfo::info) + ) LIEF_DEFAULT_STR(CorePrPsInfo); } diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCorePrStatus.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCorePrStatus.cpp index 7b2bc0b5a6..da5db779bf 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCorePrStatus.cpp +++ b/api/python/src/ELF/objects/NoteDetails/core/pyCorePrStatus.cpp @@ -17,235 +17,231 @@ #include #include #include +#include +#include "pyErr.hpp" #include "ELF/pyELF.hpp" - #include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" -#include "LIEF/ELF/EnumToString.hpp" #include "enums_wrapper.hpp" -#define PY_ENUM(x) LIEF::ELF::to_string(x), x +#define GET_SET_REGISTER(ARCH) \ + .def("get", [] (const CorePrStatus& self, CorePrStatus::Registers::ARCH reg) { \ + return LIEF::py::value_or_none(nb::overload_cast(&CorePrStatus::get, nb::const_), self, reg); \ + }, "Get the register value or non if it is not present", "reg"_a) \ + .def("__getitem__", [] (const CorePrStatus& self, CorePrStatus::Registers::ARCH reg) { \ + return LIEF::py::value_or_none(nb::overload_cast(&CorePrStatus::get, nb::const_), self, reg); \ + }) \ + .def("set", nb::overload_cast(&CorePrStatus::set), \ + "Change the register value", "reg"_a, "value"_a) \ + .def("__setitem__", nb::overload_cast(&CorePrStatus::set)) namespace LIEF::ELF::py { template<> void create(nb::module_& m) { + nb::class_ cls(m, "CorePrStatus"); - nb::class_ cls(m, "CorePrStatus"); - - nb::class_(cls, "timeval") + nb::class_(cls, "timeval_t") .def_rw("sec", &CorePrStatus::timeval_t::sec) .def_rw("usec", &CorePrStatus::timeval_t::usec); nb::class_(cls, "siginfo_t") - .def_rw("sicode", &CorePrStatus::siginfo_t::si_code) - .def_rw("errno", &CorePrStatus::siginfo_t::si_errno) - .def_rw("signo", &CorePrStatus::siginfo_t::si_signo); - + .def_rw("sicode", &CorePrStatus::siginfo_t::code) + .def_rw("errno", &CorePrStatus::siginfo_t::err) + .def_rw("signo", &CorePrStatus::siginfo_t::signo); + + nb::class_(cls, "pr_status_t") + .def_rw("info", &CorePrStatus::pr_status_t::info) + .def_rw("cursig", &CorePrStatus::pr_status_t::cursig) + .def_rw("reserved", &CorePrStatus::pr_status_t::reserved) + .def_rw("sigpend", &CorePrStatus::pr_status_t::sigpend) + .def_rw("sighold", &CorePrStatus::pr_status_t::sighold) + .def_rw("pid", &CorePrStatus::pr_status_t::pid) + .def_rw("ppid", &CorePrStatus::pr_status_t::ppid) + .def_rw("pgrp", &CorePrStatus::pr_status_t::pgrp) + .def_rw("sid", &CorePrStatus::pr_status_t::sid) + .def_rw("utime", &CorePrStatus::pr_status_t::utime) + .def_rw("stime", &CorePrStatus::pr_status_t::stime) + .def_rw("cutime", &CorePrStatus::pr_status_t::cutime) + .def_rw("cstime", &CorePrStatus::pr_status_t::cstime); + + nb::class_ Registers(cls, "Registers"); cls - .def_prop_rw("siginfo", - nb::overload_cast<>(&CorePrStatus::siginfo, nb::const_), - nb::overload_cast(&CorePrStatus::siginfo), + .def_prop_rw("status", + nb::overload_cast<>(&CorePrStatus::status, nb::const_), + nb::overload_cast(&CorePrStatus::status), "Info associated with the signal"_doc) - .def_prop_rw("current_sig", - nb::overload_cast<>(&CorePrStatus::current_sig, nb::const_), - nb::overload_cast(&CorePrStatus::current_sig), - "Current Signal"_doc) - - .def_prop_rw("sigpend", - nb::overload_cast<>(&CorePrStatus::sigpend, nb::const_), - nb::overload_cast(&CorePrStatus::sigpend), - "Set of pending signals"_doc) - - .def_prop_rw("sighold", - nb::overload_cast<>(&CorePrStatus::sighold, nb::const_), - nb::overload_cast(&CorePrStatus::sighold), - "Set of held signals"_doc) - - .def_prop_rw("pid", - nb::overload_cast<>(&CorePrStatus::pid, nb::const_), - nb::overload_cast(&CorePrStatus::pid), - "Process ID"_doc) - - .def_prop_rw("ppid", - nb::overload_cast<>(&CorePrStatus::ppid, nb::const_), - nb::overload_cast(&CorePrStatus::ppid), - "Process parent ID"_doc) - - .def_prop_rw("pgrp", - nb::overload_cast<>(&CorePrStatus::pgrp, nb::const_), - nb::overload_cast(&CorePrStatus::pgrp), - "Process group ID"_doc) - - .def_prop_rw("sid", - nb::overload_cast<>(&CorePrStatus::sid, nb::const_), - nb::overload_cast(&CorePrStatus::sid), - "Process session ID"_doc) - - .def_prop_rw("utime", - nb::overload_cast<>(&CorePrStatus::utime, nb::const_), - nb::overload_cast(&CorePrStatus::utime), - "User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc) - - .def_prop_rw("utime", - nb::overload_cast<>(&CorePrStatus::utime, nb::const_), - nb::overload_cast(&CorePrStatus::utime), - "User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc) - - .def_prop_rw("stime", - nb::overload_cast<>(&CorePrStatus::stime, nb::const_), - nb::overload_cast(&CorePrStatus::stime), - "System time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc) - - .def_prop_rw("cutime", - nb::overload_cast<>(&CorePrStatus::cutime, nb::const_), - nb::overload_cast(&CorePrStatus::cutime), - "Cumulative user time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc) - - .def_prop_rw("cstime", - nb::overload_cast<>(&CorePrStatus::cstime, nb::const_), - nb::overload_cast(&CorePrStatus::cstime), - "Cumulative system time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc) - - .def_prop_rw("register_context", - nb::overload_cast<>(&CorePrStatus::reg_context, nb::const_), - nb::overload_cast(&CorePrStatus::reg_context), - "Current registers state as a dictionary where the keys are " - RST_CLASS_REF(lief.ELF.CorePrStatus.REGISTERS) " and the values the register's value"_doc) - - .def("get", - [] (const CorePrStatus& status, CorePrStatus::REGISTERS reg) -> nb::object { - bool error; - const uint64_t val = status.get(reg, &error); - if (error) { - return nb::none(); - } - return nb::int_(val); - }, - "Return the register value"_doc, - "register"_a) - - .def("set", - &CorePrStatus::set, - "Set register value"_doc, - "register"_a, "value"_a) + .def_prop_ro("architecture", &CorePrStatus::architecture, + R"doc(Original target architecture.)doc"_doc) - .def("has", - &CorePrStatus::has, - "Check if a value is associated with the given register"_doc, - "register"_a) + .def_prop_ro("pc", [] (const CorePrStatus& self) { + return LIEF::py::value_or_none(&CorePrStatus::pc, self); + }, + R"doc( + Return the program counter value (`rip`, `pc`, `eip` etc) + )doc"_doc) - .def("__getitem__", - &CorePrStatus::operator[], - nb::rv_policy::copy) + .def_prop_ro("sp", [] (const CorePrStatus& self) { + return LIEF::py::value_or_none(&CorePrStatus::sp, self); + }, + R"doc( + Return the stack pointer value + )doc"_doc) - .def("__setitem__", - [] (CorePrStatus& status, CorePrStatus::REGISTERS reg, uint64_t val) { - status.set(reg, val); - }) + .def_prop_ro("return_value", [] (const CorePrStatus& self) { + return LIEF::py::value_or_none(&CorePrStatus::return_value, self); + }, + R"doc( + The value of the register that holds the return value according to + the calling convention. + )doc"_doc) + + .def_prop_ro("register_values", &CorePrStatus::register_values, + R"doc( + List of the register values. + This list is **guarantee** to be as long as the number of registers defined + in the :class:`~.Registers` or empty if it can't be resolved. + + Thus, one can access a specific register through: + + .. code-block:: python + + reg_vals: list[int] = note.register_values() + x20 = reg_vals[CorePrStatus.Registesr.AARCH64.X20.value] + )doc"_doc + ) + + GET_SET_REGISTER(X86) + GET_SET_REGISTER(X86_64) + GET_SET_REGISTER(ARM) + GET_SET_REGISTER(AARCH64) + LIEF_DEFAULT_STR(CorePrStatus); - .def("__contains__", - &CorePrStatus::has) - LIEF_DEFAULT_STR(CorePrStatus); + #define ENTRY(X) .value(to_string(CorePrStatus::Registers::X86::X), CorePrStatus::Registers::X86::X) + enum_(Registers, "X86", + R"doc( + Registers for the x86 architecture (:attr:`~.ARCH.i386`) + )doc"_doc) + ENTRY(EBX) + ENTRY(ECX) + ENTRY(EDX) + ENTRY(ESI) + ENTRY(EDI) + ENTRY(EBP) + ENTRY(EAX) + ENTRY(DS) + ENTRY(ES) + ENTRY(FS) + ENTRY(GS) + ENTRY(ORIG_EAX) + ENTRY(EIP) + ENTRY(CS) + ENTRY(EFLAGS) + ENTRY(ESP) + ENTRY(SS) + ; + #undef ENTRY + + #define ENTRY(X) .value(to_string(CorePrStatus::Registers::X86_64::X), CorePrStatus::Registers::X86_64::X) + enum_(Registers, "X86_64", + R"doc( + Registers for the x86-64 architecture (:attr:`~.ARCH.x86_64`) + )doc"_doc) + ENTRY(R15) + ENTRY(R14) + ENTRY(R13) + ENTRY(R12) + ENTRY(RBP) + ENTRY(RBX) + ENTRY(R11) + ENTRY(R10) + ENTRY(R9) + ENTRY(R8) + ENTRY(RAX) + ENTRY(RCX) + ENTRY(RDX) + ENTRY(RSI) + ENTRY(RDI) + ENTRY(ORIG_RAX) + ENTRY(RIP) + ENTRY(CS) + ENTRY(EFLAGS) + ENTRY(RSP) + ENTRY(SS) + ; + #undef ENTRY + + #define ENTRY(X) .value(to_string(CorePrStatus::Registers::ARM::X), CorePrStatus::Registers::ARM::X) + enum_(Registers, "ARM", + R"doc( + Registers for the ARM architecture (:attr:`~.ARCH.ARM`) + )doc"_doc) + ENTRY(R0) + ENTRY(R1) + ENTRY(R2) + ENTRY(R3) + ENTRY(R4) + ENTRY(R5) + ENTRY(R6) + ENTRY(R7) + ENTRY(R8) + ENTRY(R9) + ENTRY(R10) + ENTRY(R11) + ENTRY(R12) + ENTRY(R13) + ENTRY(R14) + ENTRY(R15) + ENTRY(CPSR) + ; + #undef ENTRY + + #define ENTRY(X) .value(to_string(CorePrStatus::Registers::AARCH64::X), CorePrStatus::Registers::AARCH64::X) + enum_(Registers, "AARCH64", + R"doc( + Registers for the AARCH64 architecture (:attr:`~.ARCH.AARCH64`) + )doc"_doc) + ENTRY(X0) + ENTRY(X1) + ENTRY(X2) + ENTRY(X3) + ENTRY(X4) + ENTRY(X5) + ENTRY(X6) + ENTRY(X7) + ENTRY(X8) + ENTRY(X9) + ENTRY(X10) + ENTRY(X11) + ENTRY(X12) + ENTRY(X13) + ENTRY(X14) + ENTRY(X15) + ENTRY(X15) + ENTRY(X16) + ENTRY(X17) + ENTRY(X18) + ENTRY(X19) + ENTRY(X20) + ENTRY(X21) + ENTRY(X22) + ENTRY(X23) + ENTRY(X24) + ENTRY(X25) + ENTRY(X26) + ENTRY(X27) + ENTRY(X28) + ENTRY(X29) + ENTRY(X30) + ENTRY(X31) + ENTRY(PC) + ENTRY(PSTATE) + ; + #undef ENTRY - LIEF::enum_(cls, "REGISTERS") - .value(PY_ENUM(CorePrStatus::REGISTERS::UNKNOWN)) - - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EBX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_ECX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EDX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_ESI)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EDI)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EBP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EAX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_DS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_ES)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_FS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_GS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86__)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EIP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_CS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_EFLAGS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_ESP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_SS)) - - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R15)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R14)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R13)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R12)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RBP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RBX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R11)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R10)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R9)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_R8)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RAX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RCX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RDX)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RSI)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RDI)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64__)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RIP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_CS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_EFLAGS)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_RSP)) - .value(PY_ENUM(CorePrStatus::REGISTERS::X86_64_SS)) - - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R0)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R1)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R2)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R3)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R4)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R5)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R6)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R7)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R8)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R9)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R10)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R11)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R12)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R13)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R14)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_R15)) - .value(PY_ENUM(CorePrStatus::REGISTERS::ARM_CPSR)) - - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X0)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X1)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X2)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X3)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X4)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X5)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X6)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X7)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X8)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X9)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X10)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X11)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X12)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X13)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X14)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X15)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X16)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X17)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X18)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X19)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X20)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X21)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X22)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X23)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X24)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X25)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X26)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X27)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X28)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X29)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X30)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X31)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_PC)) - .value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64__)); } } diff --git a/api/python/src/ELF/objects/NoteDetails/core/pyCoreSigInfo.cpp b/api/python/src/ELF/objects/NoteDetails/core/pyCoreSigInfo.cpp index 7099214432..c2a451cbb2 100644 --- a/api/python/src/ELF/objects/NoteDetails/core/pyCoreSigInfo.cpp +++ b/api/python/src/ELF/objects/NoteDetails/core/pyCoreSigInfo.cpp @@ -17,6 +17,7 @@ #include #include +#include "pyErr.hpp" #include "ELF/pyELF.hpp" #include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp" @@ -26,21 +27,26 @@ namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - nb::class_(m, "CoreSigInfo") - + nb::class_(m, "CoreSigInfo") .def_prop_rw("signo", - nb::overload_cast<>(&CoreSigInfo::signo, nb::const_), - nb::overload_cast(&CoreSigInfo::signo), + [] (const CoreSigInfo& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&CoreSigInfo::signo, nb::const_), self); + }, + nb::overload_cast(&CoreSigInfo::signo), "Signal number"_doc) .def_prop_rw("sigcode", - nb::overload_cast<>(&CoreSigInfo::sigcode, nb::const_), - nb::overload_cast(&CoreSigInfo::sigcode), + [] (const CoreSigInfo& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&CoreSigInfo::sigcode, nb::const_), self); + }, + nb::overload_cast(&CoreSigInfo::sigcode), "Signal code"_doc) .def_prop_rw("sigerrno", - nb::overload_cast<>(&CoreSigInfo::sigerrno, nb::const_), - nb::overload_cast(&CoreSigInfo::sigerrno), + [] (const CoreSigInfo& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&CoreSigInfo::sigerrno, nb::const_), self); + }, + nb::overload_cast(&CoreSigInfo::sigerrno), "If non-zero, an errno value associated with this signal"_doc) LIEF_DEFAULT_STR(CoreSigInfo); diff --git a/api/python/src/ELF/objects/NoteDetails/pyAndroidNote.cpp b/api/python/src/ELF/objects/NoteDetails/pyAndroidIdent.cpp similarity index 62% rename from api/python/src/ELF/objects/NoteDetails/pyAndroidNote.cpp rename to api/python/src/ELF/objects/NoteDetails/pyAndroidIdent.cpp index de6f82c34c..d536112f05 100644 --- a/api/python/src/ELF/objects/NoteDetails/pyAndroidNote.cpp +++ b/api/python/src/ELF/objects/NoteDetails/pyAndroidIdent.cpp @@ -19,29 +19,29 @@ #include "ELF/pyELF.hpp" -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" namespace LIEF::ELF::py { template<> -void create(nb::module_& m) { - nb::class_(m, "AndroidNote") +void create(nb::module_& m) { + nb::class_(m, "AndroidIdent") .def_prop_rw("sdk_version", - nb::overload_cast<>(&AndroidNote::sdk_version, nb::const_), - nb::overload_cast(&AndroidNote::sdk_version), + nb::overload_cast<>(&AndroidIdent::sdk_version, nb::const_), + nb::overload_cast(&AndroidIdent::sdk_version), "Target SDK platform"_doc) .def_prop_rw("ndk_version", - nb::overload_cast<>(&AndroidNote::ndk_version, nb::const_), - nb::overload_cast(&AndroidNote::ndk_version), + nb::overload_cast<>(&AndroidIdent::ndk_version, nb::const_), + nb::overload_cast(&AndroidIdent::ndk_version), "Android NDK version used to build the current binary"_doc) .def_prop_rw("ndk_build_number", - nb::overload_cast<>(&AndroidNote::ndk_build_number, nb::const_), - nb::overload_cast(&AndroidNote::ndk_build_number), + nb::overload_cast<>(&AndroidIdent::ndk_build_number, nb::const_), + nb::overload_cast(&AndroidIdent::ndk_build_number), "Android NDK build number"_doc) - LIEF_DEFAULT_STR(AndroidNote); + LIEF_DEFAULT_STR(AndroidIdent); } } diff --git a/api/python/src/ELF/objects/NoteDetails/pyNoteAbi.cpp b/api/python/src/ELF/objects/NoteDetails/pyNoteAbi.cpp index cc0106f6ca..5d0e85b2f8 100644 --- a/api/python/src/ELF/objects/NoteDetails/pyNoteAbi.cpp +++ b/api/python/src/ELF/objects/NoteDetails/pyNoteAbi.cpp @@ -21,19 +21,42 @@ #include "ELF/pyELF.hpp" #include "LIEF/ELF/NoteDetails/NoteAbi.hpp" +#include "enums_wrapper.hpp" +#include "pyErr.hpp" namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - nb::class_(m, "NoteAbi") + nb::class_ nabi(m, "NoteAbi", + R"doc( + Class that wraps the `NT_GNU_ABI_TAG` note + )doc"_doc + ); + #define ENTRY(X) .value(to_string(NoteAbi::ABI::X), NoteAbi::ABI::X) + enum_(nabi, "ABI", "ABI recognized by this note"_doc) + ENTRY(LINUX) + ENTRY(GNU) + ENTRY(SOLARIS2) + ENTRY(FREEBSD) + ENTRY(NETBSD) + ENTRY(SYLLABLE) + ENTRY(NACL) + ; + #undef ENTRY + + nabi .def_prop_ro("abi", - nb::overload_cast<>(&NoteAbi::abi, nb::const_), - "Return the target " RST_CLASS_REF(lief.ELF.NOTE_ABIS) ""_doc) + [] (const NoteAbi& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&NoteAbi::abi, nb::const_), self); + }, + R"doc(Return the target :class:`~.ABI`)doc"_doc) .def_prop_ro("version", - nb::overload_cast<>(&NoteAbi::version, nb::const_), + [] (const NoteAbi& self) { + return LIEF::py::value_or_none(nb::overload_cast<>(&NoteAbi::version, nb::const_), self); + }, "Return the target version as ``(Major, Minor, Patch)``"_doc) LIEF_DEFAULT_STR(NoteAbi); diff --git a/api/python/src/ELF/objects/pyBinary.cpp b/api/python/src/ELF/objects/pyBinary.cpp index 515ce380d3..a33018d990 100644 --- a/api/python/src/ELF/objects/pyBinary.cpp +++ b/api/python/src/ELF/objects/pyBinary.cpp @@ -344,10 +344,10 @@ void create(nb::module_& m) { nb::rv_policy::reference_internal) .def("get", - nb::overload_cast(&Binary::get), + nb::overload_cast(&Binary::get), R"delim( Return the first binary's :class:`~lief.ELF.Note` from the given - :class:`~lief.ELF.NOTE_TYPES`. + :class:`~lief.ELF.Note.TYPE`. It returns None if the note can't be found. )delim"_doc, @@ -379,8 +379,8 @@ void create(nb::module_& m) { "type"_a) .def("has", - nb::overload_cast(&Binary::has, nb::const_), - "Check if a " RST_CLASS_REF(lief.ELF.Note) " of *type* (" RST_CLASS_REF(lief.ELF.NOTE_TYPES) ") exists"_doc, + nb::overload_cast(&Binary::has, nb::const_), + "Check if a " RST_CLASS_REF(lief.ELF.Note) " of *type* (" RST_CLASS_REF(lief.ELF.Note.TYPE) ") exists"_doc, "type"_a) .def("has", @@ -516,8 +516,8 @@ void create(nb::module_& m) { "note"_a) .def("remove", - nb::overload_cast(&Binary::remove), - "Remove **all** the " RST_CLASS_REF(lief.ELF.Note) " with the given " RST_CLASS_REF(lief.ELF.NOTE_TYPES) ""_doc, + nb::overload_cast(&Binary::remove), + "Remove **all** the " RST_CLASS_REF(lief.ELF.Note) " with the given " RST_CLASS_REF(lief.ELF.Note.TYPE) ""_doc, "type"_a) .def_prop_ro("has_notes", @@ -728,20 +728,24 @@ void create(nb::module_& m) { .def(nb::self += Segment(), nb::rv_policy::reference_internal) .def(nb::self += Section(), nb::rv_policy::reference_internal) .def(nb::self += DynamicEntry(), nb::rv_policy::reference_internal) - .def(nb::self += Note(), nb::rv_policy::reference_internal) - + .def("__iadd__", [] (Binary& self, const Note& note) { + self += note; + return &self; + }, nb::rv_policy::reference_internal) .def(nb::self -= DynamicEntry(), nb::rv_policy::reference_internal) .def(nb::self -= DYNAMIC_TAGS(), nb::rv_policy::reference_internal) - - .def(nb::self -= Note(), nb::rv_policy::reference_internal) - .def(nb::self -= NOTE_TYPES(), nb::rv_policy::reference_internal) + .def("__isub__", [] (Binary& self, const Note& note) { + self -= note; + return &self; + }, nb::rv_policy::reference_internal) + .def(nb::self -= Note::TYPE(), nb::rv_policy::reference_internal) .def("__getitem__", nb::overload_cast(&Binary::operator[]), nb::rv_policy::reference_internal) .def("__getitem__", - nb::overload_cast(&Binary::operator[]), + nb::overload_cast(&Binary::operator[]), nb::rv_policy::reference_internal) .def("__getitem__", @@ -761,8 +765,8 @@ void create(nb::module_& m) { "Check if the " RST_CLASS_REF(lief.ELF.DynamicEntry) " associated with the given " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " exists"_doc) .def("__contains__", - nb::overload_cast(&Binary::has, nb::const_), - "Check if the " RST_CLASS_REF(lief.ELF.Note) " associated with the given " RST_CLASS_REF(lief.ELF.NOTE_TYPES) " exists"_doc) + nb::overload_cast(&Binary::has, nb::const_), + "Check if the " RST_CLASS_REF(lief.ELF.Note) " associated with the given " RST_CLASS_REF(lief.ELF.Note.TYPE) " exists"_doc) .def("__contains__", nb::overload_cast(&Binary::has, nb::const_), diff --git a/api/python/src/ELF/objects/pyNote.cpp b/api/python/src/ELF/objects/pyNote.cpp index e9a4907ce7..d83ca0e3e8 100644 --- a/api/python/src/ELF/objects/pyNote.cpp +++ b/api/python/src/ELF/objects/pyNote.cpp @@ -17,68 +17,148 @@ #include #include #include +#include +#include "nanobind/extra/memoryview.hpp" +#include "nanobind/utils.hpp" #include "ELF/pyELF.hpp" #include "LIEF/ELF/Note.hpp" #include "LIEF/ELF/NoteDetails.hpp" +#include "enums_wrapper.hpp" + namespace LIEF::ELF::py { template<> void create(nb::module_& m) { - nb::class_(m, "Note", + nb::class_ note(m, "Note", R"delim( Class which represents an ELF note. - )delim"_doc) - - .def(nb::init<>(), - "Default constructor") - - .def(nb::init&>(), - "Constructor from a ``name``, ``type`` and ``description``"_doc, - "name"_a, "type"_a, "description"_a) - - .def_prop_ro("details", - nb::overload_cast<>(&Note::details), - "Parse the given note description and return a " RST_CLASS_REF(lief.ELF.NoteDetails) " object"_doc, - nb::rv_policy::reference_internal) + )delim"_doc); + + #define ENTRY(X) .value(to_string(Note::TYPE::X), Note::TYPE::X) + enum_(note, "TYPE", "LIEF representation of the ELF `NT_` values.") + ENTRY(UNKNOWN) + ENTRY(GNU_ABI_TAG) + ENTRY(GNU_HWCAP) + ENTRY(GNU_ABI_TAG) + ENTRY(GNU_HWCAP) + ENTRY(GNU_BUILD_ID) + ENTRY(GNU_GOLD_VERSION) + ENTRY(GNU_PROPERTY_TYPE_0) + ENTRY(GNU_BUILD_ATTRIBUTE_OPEN) + ENTRY(GNU_BUILD_ATTRIBUTE_FUNC) + ENTRY(CRASHPAD) + ENTRY(CORE_PRSTATUS) + ENTRY(CORE_FPREGSET) + ENTRY(CORE_PRPSINFO) + ENTRY(CORE_TASKSTRUCT) + ENTRY(CORE_AUXV) + ENTRY(CORE_PSTATUS) + ENTRY(CORE_FPREGS) + ENTRY(CORE_PSINFO) + ENTRY(CORE_LWPSTATUS) + ENTRY(CORE_LWPSINFO) + ENTRY(CORE_WIN32PSTATUS) + ENTRY(CORE_FILE) + ENTRY(CORE_PRXFPREG) + ENTRY(CORE_SIGINFO) + ENTRY(CORE_ARM_VFP) + ENTRY(CORE_ARM_TLS) + ENTRY(CORE_ARM_HW_BREAK) + ENTRY(CORE_ARM_HW_WATCH) + ENTRY(CORE_ARM_SYSTEM_CALL) + ENTRY(CORE_ARM_SVE) + ENTRY(CORE_ARM_PAC_MASK) + ENTRY(CORE_ARM_PACA_KEYS) + ENTRY(CORE_ARM_PACG_KEYS) + ENTRY(CORE_TAGGED_ADDR_CTRL) + ENTRY(CORE_PAC_ENABLED_KEYS) + ENTRY(CORE_X86_TLS) + ENTRY(CORE_X86_IOPERM) + ENTRY(CORE_X86_XSTATE) + ENTRY(CORE_X86_CET) + ENTRY(ANDROID_MEMTAG) + ENTRY(ANDROID_KUSER) + ENTRY(ANDROID_IDENT) + ENTRY(STAPSDT) + ENTRY(GO_BUILDID) + ; + #undef ENTRY + + const auto create_overload_0 = nb::overload_cast(&Note::create); + const auto create_overload_1 = nb::overload_cast(&Note::create); + note + .def_static("create", create_overload_0, + R"doc( + Create a note from the owner name, the original type (`NT_xxx` value) + and the description. + + Depending on the note, the filetype, the architecture and the ELF class might be needed. + )doc"_doc, + "name"_a, "original_type"_a, "description"_a, + "file_type"_a = E_TYPE::ET_NONE, "arch"_a = ARCH::EM_NONE, "cls"_a = ELF_CLASS::ELFCLASSNONE) + + .def_static("create", + [] (nb::bytes bytes, E_TYPE ftype, ARCH arch, ELF_CLASS cls) -> std::unique_ptr { + std::unique_ptr stream = to_stream(bytes); + if (!stream) { + return nullptr; + } + return Note::create(*stream, ftype, arch, cls); + }, + R"doc( + Create a note from the given `bytes` buffer. + + Depending on the note, the filetype, the architecture and the ELF class might + be needed. + )doc"_doc, + "raw"_a, + "file_type"_a = E_TYPE::ET_NONE, "arch"_a = ARCH::EM_NONE, + "cls"_a = ELF_CLASS::ELFCLASSNONE) + + .def_static("create", create_overload_1, + R"doc( + Create the owner name, the type and the description + + Depending on the note, the filetype, the architecture and the ELF class might + be needed. + )doc"_doc, + "name"_a, "type"_a, "description"_a, + "arch"_a = ARCH::EM_NONE, "cls"_a = ELF_CLASS::ELFCLASSNONE) .def_prop_rw("name", nb::overload_cast<>(&Note::name, nb::const_), - nb::overload_cast(&Note::name), - "Return the *name* of the note (Usually the owner)."_doc) + nb::overload_cast(&Note::name), + "Return the *name* of the note also known as the owner."_doc) - .def_prop_rw("type", - nb::overload_cast<>(&Note::type, nb::const_), - nb::overload_cast(&Note::type), - "Return the type of the note. It can be one of the " RST_CLASS_REF(lief.ELF.NOTE_TYPES) " values"_doc) + .def_prop_ro("original_type", + nb::overload_cast<>(&Note::original_type, nb::const_), + R"doc( + Return the original `NT_` value of the note. - .def_prop_rw("type_core", - nb::overload_cast<>(&Note::type_core, nb::const_), - nb::overload_cast(&Note::type_core), - "Return the type of the note for ELF Core (ET_CORE). It Can be one of the " RST_CLASS_REF(lief.ELF.NOTE_TYPES_CORE) " values"_doc) + This value should be interpreted according the the :attr:`~.name` of the + note. + )doc"_doc) + + .def_prop_ro("type", + nb::overload_cast<>(&Note::type, nb::const_), + R"doc( + Return the LIEF type representation of the note. + )doc"_doc) .def_prop_rw("description", - nb::overload_cast<>(&Note::description, nb::const_), - nb::overload_cast(&Note::description), + [] (const Note& self) { + const std::vector& content = self.description(); + return nb::memoryview::from_memory(content.data(), content.size()); + }, + nb::overload_cast(&Note::description), "Return the description associated with the note"_doc) - .def_prop_ro("is_core", - &Note::is_core, - "True if the note is associated with a coredump"_doc) - - .def_prop_ro("is_android", - &Note::is_android, - R"delim( - True if the current note is specific to Android. - - If true, :attr:`lief.Note.details` returns a reference to the :class:`~lief.ELF.AndroidNote` object - )delim"_doc) - - .def_prop_ro("size", &Note::size, - "Size of the **raw** note"_doc) + .def_prop_ro("size", &Note::size, "Size of the **raw** note"_doc) + LIEF_CLONABLE(Note) LIEF_DEFAULT_STR(Note); } diff --git a/api/python/src/ELF/objects/pyNoteDetails.cpp b/api/python/src/ELF/objects/pyNoteDetails.cpp deleted file mode 100644 index 4553e65437..0000000000 --- a/api/python/src/ELF/objects/pyNoteDetails.cpp +++ /dev/null @@ -1,34 +0,0 @@ - -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include - -#include "ELF/pyELF.hpp" - -#include "LIEF/ELF/NoteDetails.hpp" - -namespace LIEF::ELF::py { - -template<> -void create(nb::module_& m) { - nb::class_(m, "NoteDetails") - LIEF_DEFAULT_STR(NoteDetails); -} - -} - diff --git a/api/python/src/nanobind/utils.hpp b/api/python/src/nanobind/utils.hpp new file mode 100644 index 0000000000..6e32a5d0c9 --- /dev/null +++ b/api/python/src/nanobind/utils.hpp @@ -0,0 +1,24 @@ +#ifndef PY_LIEF_NB_UTILS_H +#define PY_LIEF_NB_UTILS_H + +#include +#include +#include +#include + +NAMESPACE_BEGIN(NB_NAMESPACE) + +inline std::vector to_vector(nanobind::bytes bytes) { + const auto* ptr = reinterpret_cast(bytes.c_str()); + return {ptr, ptr + bytes.size()}; +} + + +inline std::unique_ptr to_stream(nanobind::bytes bytes) { + const auto* ptr = reinterpret_cast(bytes.c_str()); + return std::make_unique(ptr, bytes.size()); +} + +NAMESPACE_END(NB_NAMESPACE) + +#endif diff --git a/api/python/src/pyErr.cpp b/api/python/src/pyErr.cpp index 86377f57c2..7f363e9dbb 100644 --- a/api/python/src/pyErr.cpp +++ b/api/python/src/pyErr.cpp @@ -10,6 +10,17 @@ void init_errors(nb::module_& m) { )delim") .def("__bool__", [] (const ok_t&) { return true; }); + nb::class_(m, "ok_error_t", + R"delim( + Return either: :class:`~.ok_t` (success) or :class:`~.lief_errors` (error) + )delim") + .def_prop_ro("is_error", [] (const ok_error_t& val) { return !val.has_value(); }) + .def_prop_ro("is_value", [] (const ok_error_t& val) { return val.has_value(); }) + .def_prop_ro("error", [] (const ok_error_t& val) { return val.error(); }) + .def_prop_ro("value", [] (const ok_error_t& val) { return val.value(); }) + .def("__bool__", [] (const ok_error_t& val) { return val.has_value(); }); + + nb::enum_(m, "lief_errors", R"delim( Enum class which represents an error generated by LIEF's functions )delim") diff --git a/api/python/src/pyErr.hpp b/api/python/src/pyErr.hpp index a8f9df528b..e3fe045e18 100644 --- a/api/python/src/pyErr.hpp +++ b/api/python/src/pyErr.hpp @@ -22,7 +22,6 @@ #include "typing.hpp" namespace LIEF::py { - template struct typing_error : public nanobind::object { using value_type = typename RetTy::value_type; @@ -41,9 +40,23 @@ struct typing_error : public nanobind::object { return true; } }; -} -namespace LIEF::py { +template +struct value_or_none_t : public nanobind::object { + LIEF_PY_DEFAULT_CTOR(value_or_none_t, nanobind::object); + using value_type = typename RetTy::value_type; + + static constexpr auto Name = nanobind::detail::const_name("Optional[") + + nanobind::detail::make_caster::Name + + nanobind::detail::const_name("]"); + + NB_OBJECT_DEFAULT_NONAME(value_or_none_t, object, check) + static bool check(handle h) { + return true; + } +}; + + template , std::enable_if_t>{}, int> = 0> @@ -68,6 +81,26 @@ typing_error error_or(Func f, Ts&&... args) { return nb::cast(ret.value()); } + +template > +value_or_none_t value_or_none(Func f, Ts&&... args) { + namespace nb = nanobind; + if constexpr (std::is_member_pointer_v>) { + auto&& ret = std::mem_fn(f)(std::forward(args)...); + if (!ret) { + return nb::none(); + } + return nb::cast(*ret); + } else { + auto&& ret = f(std::forward(args)...); + if (!ret) { + return nb::none(); + } + return nb::cast(*ret); + } +} + void init_errors(nanobind::module_&); } diff --git a/doc/sphinx/api/cpp/elf.rst b/doc/sphinx/api/cpp/elf.rst index 9b97f0484f..e3873c97c4 100644 --- a/doc/sphinx/api/cpp/elf.rst +++ b/doc/sphinx/api/cpp/elf.rst @@ -182,14 +182,6 @@ Note ---------- -Note Details -************ - -.. doxygenclass:: LIEF::ELF::NoteDetails - :project: lief - ----------- - Core PrPsInfo ************* @@ -207,15 +199,6 @@ Core File ---------- - -Core File Entry -*************** - -.. doxygenstruct:: LIEF::ELF::CoreFileEntry - :project: lief - ----------- - Core PrStatus ************* @@ -434,33 +417,6 @@ Dynamic symbols counting ---------- -Note types -~~~~~~~~~~ - -.. doxygenenum:: LIEF::ELF::NOTE_TYPES - :project: lief - ----------- - -Note Core types -~~~~~~~~~~~~~~~ - -.. doxygenenum:: LIEF::ELF::NOTE_TYPES_CORE - :project: lief - ----------- - - -Note ABIs -~~~~~~~~~ - -.. doxygenenum:: LIEF::ELF::NOTE_ABIS - :project: lief - - ----------- - - Relocation purpose ~~~~~~~~~~~~~~~~~~ diff --git a/doc/sphinx/api/python/elf.rst b/doc/sphinx/api/python/elf.rst index 0114495fce..8693de404a 100644 --- a/doc/sphinx/api/python/elf.rst +++ b/doc/sphinx/api/python/elf.rst @@ -158,13 +158,6 @@ Note ---------- -Note Details -************ - -.. autoclass:: lief.ELF.NoteDetails - ----------- - Core PrPsInfo ************* @@ -184,12 +177,6 @@ Core File .. autoclass:: lief.ELF.CoreFile ----------- - -Core File Entry -*************** - -.. autoclass:: lief.ELF.CoreFileEntry ---------- @@ -208,10 +195,10 @@ Core Auxiliary Vector ---------- -Android Note +Android Ident ************* -.. autoclass:: lief.ELF.AndroidNote +.. autoclass:: lief.ELF.AndroidIdent ---------- @@ -429,27 +416,6 @@ Relocation purpose ---------- -Note types -~~~~~~~~~~ - -.. autoclass:: lief.ELF.NOTE_TYPES - ----------- - -Note ABIs -~~~~~~~~~ - -.. autoclass:: lief.ELF.NOTE_ABIS - ----------- - - -Note Core types -~~~~~~~~~~~~~~~ - -.. autoclass:: lief.ELF.NOTE_TYPES_CORE - ----------- ARM Processor flags ~~~~~~~~~~~~~~~~~~~ diff --git a/doc/sphinx/api/python/index.rst b/doc/sphinx/api/python/index.rst index 9b8c46a6bf..3205257287 100644 --- a/doc/sphinx/api/python/index.rst +++ b/doc/sphinx/api/python/index.rst @@ -55,6 +55,8 @@ Error Handling .. autoclass:: lief.ok_t +.. autoclass:: lief.ok_error_t + See also the section :ref:`err_handling` Exceptions diff --git a/doc/sphinx/changelog.rst b/doc/sphinx/changelog.rst index faa67be317..fdb80b2215 100644 --- a/doc/sphinx/changelog.rst +++ b/doc/sphinx/changelog.rst @@ -6,6 +6,7 @@ Changelog :ELF: + * Refactoring of the ELF note processing * Fix relocation issue when using `-Wl,--emit-relocs` (c.f. :issue:`897` / :pr:`898` by :github_user:`adamjseitz`) * Improve the computation of the dynamic symbols thanks to :github_user:`adamjseitz` (c.f. :issue:`922`) * Add support for the LoongArch architecture thanks to :github_user:`loongson-zn` (c.f. :pr:`921`) diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 8ddf09428b..cfb263f940 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -1,13 +1,22 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import re +import inspect import lief import os import pathlib -import inspect -from pathlib import Path +import re +import sphinx +import sys +from datetime import date from docutils import nodes +from docutils.nodes import Node +from pathlib import Path +from sphinx.ext.inheritance_diagram import InheritanceDiagram +from sphinx.util import logging +from sphinx.util.typing import OptionSpec +from typing import Any + from sphinx.util import logging from sphinx.util.inspect import ( getdoc, @@ -51,6 +60,7 @@ extensions = [ 'sphinx.ext.mathjax', 'sphinx.ext.autodoc', + 'sphinx.ext.inheritance_diagram', ] @@ -293,6 +303,38 @@ def _autodoc_process_docstring(app, what, name, obj, options, lines: list[str]): lines[:] = [] return + +class LIEFInheritanceDiagram(InheritanceDiagram): + option_spec: OptionSpec = { + **InheritanceDiagram.option_spec, + 'depth': int + } + def _check_module(self, module, obj, depth: int): + if not module.__name__.startswith("lief"): + return [] + + classes = [] + for name, member in inspect.getmembers(module): + if inspect.isclass(member) and issubclass(member, obj): + mro = inspect.getmro(member) + if (0 < depth and mro.index(obj) <= depth) or depth == 0: + classes.append(f"{module.__name__}.{name}") + if inspect.ismodule(member) and member != module: + classes.extend(self._check_module(member, obj, depth)) + return list(set(classes)) + + def run(self) -> list[Node]: + cls = None + classes = [] + depth = self.options.get('depth', 0) + if self.arguments[0].startswith("lief._lief"): + elements = self.arguments[0].split(".")[2:] + cls = lief._lief + for element in elements: + cls = getattr(cls, element) + self.arguments[0] = " ".join(self._check_module(lief, cls, depth)) + return super().run() + def setup(app): app.add_css_file('css/custom.css') # may also be an URL @@ -300,6 +342,7 @@ def setup(app): app.add_role('pr', pr_role) app.add_role('issue', issue_role) app.add_role('github_user', github_user) + app.add_directive('lief-inheritance', LIEFInheritanceDiagram) app.connect('autodoc-process-signature', _on_process_signature) app.connect('autodoc-process-docstring', _autodoc_process_docstring) diff --git a/doc/sphinx/tutorials/12_elf_coredump.rst b/doc/sphinx/tutorials/12_elf_coredump.rst index 4c10212343..34389d75d7 100644 --- a/doc/sphinx/tutorials/12_elf_coredump.rst +++ b/doc/sphinx/tutorials/12_elf_coredump.rst @@ -15,7 +15,7 @@ has been generated. The memory state embeds a *snapshot* of all segments mapped in the memory space of the program. The CPU state contains register values when the core dump has been generated. -Coredump files use a subset of the ELF structures to register these information. **Segments** are used for +Coredump files use a subset of the ELF structures to store this information. **Segments** are used for the memory state of the process while ELF notes (:class:`lief.ELF.Note`) are used for process metadata (pid, signal, ...) Especially, the CPU state is stored in a note with a special type. @@ -31,7 +31,7 @@ For more details about coredump internal structure, one can look at the followin Coredump Analysis ~~~~~~~~~~~~~~~~~ -As corefiles are effectively ELF, we can open these files using the :func:`lief.parse` function: +As core files are effectively ELF, we can open these files using the :func:`lief.parse` function: .. code-block:: python @@ -53,34 +53,38 @@ To resolve the relationship between libraries and segments, we can look at the s .. code-block:: python - note_file = [n for n in core.notes if n.type_core == lief.ELF.NOTE_TYPES_CORE.FILE] - assert len(note_file) == 1 + nt_core_file = core.get(lief.ELF.Note.TYPE.CORE.FILE) - note_file = note_file.pop() +ELF notes are represented through the main :class:`lief.ELF.Note` interface. Some notes +like (:class:`lief.ELF.CoreFile`) can expose additional API by extending the +original :class:`lief.ELF.Note`. -.. warning:: +.. lief-inheritance:: lief._lief.ELF.Note + :top-classes: lief._lief.ELF.Note + :depth: 1 + :parts: 1 - Due to enum conflict between :class:`lief.ELF.NOTE_TYPES` and :class:`lief.ELF.NOTE_TYPES_CORE`, - scripts must use :attr:`lief.ELF.Note.type_core` on ELF corefile instead of :attr:`lief.ELF.Note.type` +.. note:: -The ``note_file`` variable is basically an object :class:`lief.ELF.Note` on which the attribute -:attr:`lief.ELF.Note.details` can be access to have the underlying specialization of the note. -In the case of a note type :attr:`lief.ELF.NOTE_TYPES_CORE.FILE`, the attribute :attr:`~lief.ELF.Note.details` returns an -instance of :class:`lief.ELF.CoreFile`. + All note details inherit from the base class :class:`lief.ELF.Note` (or :cpp:class:`LIEF::ELF::Note`) -.. note:: + Especially, in C++ we must downcast according to the `classof` function: - All note details inherit from the base class :class:`lief.ELF.NoteDetails` (or :cpp:class:`LIEF::ELF::NoteDetails`) + .. code-block:: cpp - Especially, in C++ we must downcast the reference returned by :cpp:func:`LIEF::ELF::Note::details`: + for (const Note& note : binary->notes()) { + if (CoreFile::classof(¬e)) { + const auto& nt_core_file = static_cast(note.details()); + .. code-block:: python + for note in binary.notes: + if isinstance(note, lief.ELF.CoreFile): + print("This is a CoreFile note") We can eventually use the attribute :attr:`lief.ELF.CoreFile.files` or directly iterate on @@ -119,20 +123,18 @@ the :class:`lief.ELF.CoreFile` object. Both give access to the :class:`lief.ELF. From this output, we can see that the :class:`~lief.ELF.Segment` of the main executable (``/data/local/tmp/hello-exe``), are mapped from address ``0x5580b86000`` to address ``0x5580b99000``. -One can also access to the registers state by using the note for which the :attr:`~lief.ELF.Note.type_core` -is :class:`lief.ELF.CorePrStatus`. +One can also access to the registers state by looking for the note: :class:`lief.ELF.CorePrStatus`. .. code-block:: python for note in core.notes: - if note.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS: - details = note.details - print(details) + if not isinstance(note, lief.ELF.CorePrStatus): + continue - # Print instruction pointer - print(hex(details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_PC])) - # or - print(hex(details.get(lief.ELF.CorePrStatus.REGISTERS.AARCH64_PC))) + # Both are equivalent + print(note.pc) + reg_values = note.register_values + print(reg_values[lief.ELF.CorePrStatus.Registers.AARCH64.PC.value]) .. code-block:: text @@ -148,8 +150,8 @@ we can update the register values as follows: .. code-block:: python - note_prstatus = [n for n in core.notes if n.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS][0] - note_prstatus.details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_PC] = 0xDEADC0DE + prstatus = elf_core.get(lief.ELF.Note.TYPE.CORE_PRSTATUS) + prstatus.set(lief.ELF.CorePrStatus.Registers.AARCH64.PC, 0xDEADC0DE) core.write("/tmp/new.core") @@ -166,8 +168,8 @@ is that **relocations** and **dependencies** are resolved inside the coredump. This API could be used in association with other tools. For instance, we could use `Triton `_ API: -- `AArch64Cpu::setConcreteRegisterValue() `_ -- `AArch64Cpu::setConcreteMemoryAreaValue() `_ +- `AArch64Cpu::setConcreteRegisterValue() `_ +- `AArch64Cpu::setConcreteMemoryAreaValue() `_ to map the coredump in Triton and then use its engines: Taint analysis, symbolic execution. @@ -176,12 +178,10 @@ to map the coredump in Triton and then use its engines: Taint analysis, symbolic .. [1] https://www.gabriel.urdhr.fr/2015/05/29/core-file/ - - .. rubric:: API * :func:`lief.parse` -* :attr:`lief.ELF.Note.details` +* :class:`lief.ELF.Note` * :class:`lief.ELF.CorePrPsInfo` * :class:`lief.ELF.CorePrStatus` diff --git a/include/LIEF/ELF.hpp b/include/LIEF/ELF.hpp index 8c7040c42f..4ce17af132 100644 --- a/include/LIEF/ELF.hpp +++ b/include/LIEF/ELF.hpp @@ -47,11 +47,8 @@ #include "LIEF/ELF/SymbolVersionDefinition.hpp" #include "LIEF/ELF/SymbolVersionRequirement.hpp" #include "LIEF/ELF/SysvHash.hpp" - -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" -#include "LIEF/ELF/NoteDetails/NoteAbi.hpp" -#include "LIEF/ELF/NoteDetails/Core.hpp" #include "LIEF/ELF/NoteDetails.hpp" + #endif #endif diff --git a/include/LIEF/ELF/Binary.hpp b/include/LIEF/ELF/Binary.hpp index 8578518257..49d5ef9913 100644 --- a/include/LIEF/ELF/Binary.hpp +++ b/include/LIEF/ELF/Binary.hpp @@ -25,6 +25,7 @@ #include "LIEF/Abstract/Binary.hpp" +#include "LIEF/ELF/Note.hpp" #include "LIEF/ELF/Header.hpp" #include "LIEF/ELF/Builder.hpp" @@ -39,7 +40,6 @@ class DynamicEntry; class ExeLayout; class GnuHash; class Layout; -class Note; class ObjectFileLayout; class Parser; class Relocation; @@ -281,7 +281,7 @@ class LIEF_API Binary : public LIEF::Binary { void remove(const Note& note); //! Remove **all** notes with the given type - void remove(NOTE_TYPES type); + void remove(Note::TYPE type); //! Remove the given segment void remove(const Segment& seg); @@ -692,8 +692,8 @@ class LIEF_API Binary : public LIEF::Binary { //! Return the **first** ELF::Note associated with the given type //! If a note can't be found, it returns a nullptr. - const Note* get(NOTE_TYPES type) const; - Note* get(NOTE_TYPES type); + const Note* get(Note::TYPE type) const; + Note* get(Note::TYPE type); //! Return the **first** ELF::Section associated with the given type //! If a section can't be found, it returns a nullptr. @@ -707,7 +707,7 @@ class LIEF_API Binary : public LIEF::Binary { bool has(SEGMENT_TYPES type) const; //! Check if a ELF::Note associated with the given type exists. - bool has(NOTE_TYPES type) const; + bool has(Note::TYPE type) const; //! Check if a ELF::Section associated with the given type exists. bool has(ELF_SECTION_TYPES type) const; @@ -783,7 +783,7 @@ class LIEF_API Binary : public LIEF::Binary { Binary& operator-=(DYNAMIC_TAGS tag); Binary& operator-=(const Note& note); - Binary& operator-=(NOTE_TYPES type); + Binary& operator-=(Note::TYPE type); Segment* operator[](SEGMENT_TYPES type); const Segment* operator[](SEGMENT_TYPES type) const; @@ -791,8 +791,8 @@ class LIEF_API Binary : public LIEF::Binary { DynamicEntry* operator[](DYNAMIC_TAGS tag); const DynamicEntry* operator[](DYNAMIC_TAGS tag) const; - Note* operator[](NOTE_TYPES type); - const Note* operator[](NOTE_TYPES type) const; + Note* operator[](Note::TYPE type); + const Note* operator[](Note::TYPE type) const; Section* operator[](ELF_SECTION_TYPES type); const Section* operator[](ELF_SECTION_TYPES type) const; diff --git a/include/LIEF/ELF/Builder.hpp b/include/LIEF/ELF/Builder.hpp index 7cd66f6a3f..32195a2d1d 100644 --- a/include/LIEF/ELF/Builder.hpp +++ b/include/LIEF/ELF/Builder.hpp @@ -171,7 +171,7 @@ class LIEF_API Builder { template ok_error_t build_notes(); - ok_error_t build(const Note& note, std::set& sections); + ok_error_t update_note_section(const Note& note, std::set& notes); template ok_error_t build_overlay(); diff --git a/include/LIEF/ELF/EnumToString.hpp b/include/LIEF/ELF/EnumToString.hpp index a4cb859f7a..6c30fc0fc4 100644 --- a/include/LIEF/ELF/EnumToString.hpp +++ b/include/LIEF/ELF/EnumToString.hpp @@ -40,9 +40,6 @@ LIEF_API const char* to_string(ELF_CLASS e); LIEF_API const char* to_string(ELF_DATA e); LIEF_API const char* to_string(OS_ABI e); LIEF_API const char* to_string(DYNSYM_COUNT_METHODS e); -LIEF_API const char* to_string(NOTE_TYPES e); -LIEF_API const char* to_string(NOTE_TYPES_CORE e); -LIEF_API const char* to_string(NOTE_ABIS e); LIEF_API const char* to_string(RELOCATION_PURPOSES e); LIEF_API const char* to_string(IDENTITY e); LIEF_API const char* to_string(SYMBOL_SECTION_INDEX e); @@ -50,7 +47,6 @@ LIEF_API const char* to_string(DYNAMIC_FLAGS e); LIEF_API const char* to_string(DYNAMIC_FLAGS_1 e); LIEF_API const char* to_string(ELF_SEGMENT_FLAGS e); LIEF_API const char* to_string(ELF_SYMBOL_VISIBILITY e); -LIEF_API const char* to_string(AUX_TYPE e); LIEF_API const char* to_string(PPC64_EFLAGS e); LIEF_API const char* to_string(ARM_EFLAGS e); diff --git a/include/LIEF/ELF/Note.hpp b/include/LIEF/ELF/Note.hpp index 99fe25b3e9..aa20512a94 100644 --- a/include/LIEF/ELF/Note.hpp +++ b/include/LIEF/ELF/Note.hpp @@ -22,96 +22,229 @@ #include "LIEF/Object.hpp" #include "LIEF/visibility.h" +#include "LIEF/errors.hpp" #include "LIEF/ELF/enums.hpp" namespace LIEF { +class BinaryStream; namespace ELF { -class Parser; -class Builder; -class Binary; -class NoteDetails; - -//! Class which represents an ELF note +/// Class which represents an ELF note. This class can be instantiated using +/// the static Note::create functions. class LIEF_API Note : public Object { - friend class Parser; friend class Builder; friend class Binary; - friend class NoteDetails; public: //! Container used to handle the description data using description_t = std::vector; - public: - Note(); - Note(std::string name, uint32_t type, description_t description, Binary* binary=nullptr); - Note(const std::string& name, NOTE_TYPES type, const description_t& description, Binary* binary=nullptr); - Note(const std::string& name, NOTE_TYPES_CORE type, const description_t& description, Binary* binary=nullptr); - - Note& operator=(Note copy); - Note(const Note& copy); - - ~Note() override; + /// LIEF representation of the ELF `NT_` values. + enum class TYPE { + UNKNOWN = 0, + /// Match `NT_GNU_ABI_TAG`: Operating system (OS) ABI information + /// + /// See: NoteAbi + GNU_ABI_TAG, + /// Match `NT_HWCAP`: Synthetic hardware capabilities information + GNU_HWCAP, + /// Match `NT_GNU_BUILD_ID`: Unique build ID as generated by the GNU ld + GNU_BUILD_ID, + /// Match `NT_GNU_GOLD_VERSION`: The version of gold used to link + GNU_GOLD_VERSION, + /// Match `NT_GNU_PROPERTY_TYPE_0`: Program property note, as described in + /// "Linux Extensions to the gABI". + GNU_PROPERTY_TYPE_0, + + GNU_BUILD_ATTRIBUTE_OPEN, + GNU_BUILD_ATTRIBUTE_FUNC, + + /// Crashpad note used by the Chromium project + CRASHPAD, + + /// Coredump that wraps the `elf_prstatus` structure + CORE_PRSTATUS, + CORE_FPREGSET, + /// Coredump that wraps the `elf_prpsinfo` structure + /// + /// See: CorePrPsInfo + CORE_PRPSINFO, + CORE_TASKSTRUCT, + /// Coredump that contains a copy of all the auxiliary vectors (auxv) + /// + /// See: CoreAuxv + CORE_AUXV, + CORE_PSTATUS, + /// Coredump that wraps the `fpregset` structure + CORE_FPREGS, + /// Coredump that wraps the `psinfo` structure + CORE_PSINFO, + CORE_LWPSTATUS, + CORE_LWPSINFO, + CORE_WIN32PSTATUS, + CORE_FILE, + CORE_PRXFPREG, + CORE_SIGINFO, + + CORE_ARM_VFP, + CORE_ARM_TLS, + CORE_ARM_HW_BREAK, + CORE_ARM_HW_WATCH, + CORE_ARM_SYSTEM_CALL, + CORE_ARM_SVE, + CORE_ARM_PAC_MASK, + CORE_ARM_PACA_KEYS, + CORE_ARM_PACG_KEYS, + CORE_TAGGED_ADDR_CTRL, + CORE_PAC_ENABLED_KEYS, + + CORE_X86_TLS, + CORE_X86_IOPERM, + CORE_X86_XSTATE, + CORE_X86_CET, + + /// Note that is specific to Android and that describes information such as + /// the NDK version or the SDK build number. + /// + /// See AndroidIdent + ANDROID_IDENT, + ANDROID_MEMTAG, + ANDROID_KUSER, + + /// Note specific to Go binaries + GO_BUILDID, + /// Note for SystemTap probes + STAPSDT, + }; - //! Return the *name* of the note - const std::string& name() const; - - //! Return the type of the note. It could be one of the NOTE_TYPES values - NOTE_TYPES type() const; - - //! Return the type of the note for core ELF (ET_CORE). - //! It could be one of the NOTE_TYPES_CORE values - NOTE_TYPES_CORE type_core() const; + public: + /// Convert the raw integer note type into a TYPE according to the owner + static result convert_type(E_TYPE ftype, uint32_t type, + const std::string& name); + + /// Try to determine the ELF section name associated with the TYPE + /// provided in parameter + static result type_to_section(TYPE type); + + static result note_to_section(const Note& note) { + return type_to_section(note.type()); + } + + /// Try to determine the owner's name of the TYPE provided in parameter + static result type_owner(TYPE type); + + /// Create a new note from the given parameters. Additional information + /// such as the architecture or the ELF class could be required for + /// creating notes like Coredump notes. + static std::unique_ptr create( + const std::string& name, uint32_t type, description_t description, + E_TYPE ftype = E_TYPE::ET_NONE, ARCH arch = ARCH::EM_NONE, + ELF_CLASS cls = ELF_CLASS::ELFCLASSNONE); + + /// Create a new note from the given parameters. Additional information + /// such as the architecture or the ELF class could be required for + /// creating notes like Coredump notes. + static std::unique_ptr create( + const std::string& name, TYPE type, description_t description, + ARCH arch = ARCH::EM_NONE, ELF_CLASS cls = ELF_CLASS::ELFCLASSNONE); + + /// Create a new note from the given stream. Additional information + /// such as the architecture or the ELF class could be required for + /// creating notes like Coredump notes. + static std::unique_ptr create(BinaryStream& stream, + E_TYPE ftype = E_TYPE::ET_NONE, ARCH arch = ARCH::EM_NONE, + ELF_CLASS cls = ELF_CLASS::ELFCLASSNONE); + + Note& operator=(const Note& copy) = default; + Note(const Note& copy) = default; + + ~Note() override = default; + + /// Clone the current note and keep its polymorphic type + virtual std::unique_ptr clone() const { + return std::unique_ptr(new Note(*this)); + } + + /// Return the *name* of the note (also known as 'owner' ) + const std::string& name() const { + return name_; + } + + /// Return the type of the note. This type does not match the `NT_` type + /// value. For accessing the original `NT_` value, check original_type() + TYPE type() const { + return type_; + } + + /// The original `NT_xxx` integer value. The meaning of this value likely + /// depends on the owner of the note. + uint32_t original_type() const { + return original_type_; + } //! Return the description associated with the note - const description_t& description() const; - - description_t& description(); - - //! True if the current note is associated with a core dump - bool is_core() const; + const description_t& description() const { + return description_; + } - //! True if the current note is specific to Android. - //! - //! If true, ``details()`` returns a reference to the LIEF::ELF::AndroidNote object - bool is_android() const; + description_t& description() { + return description_; + } - const NoteDetails& details() const; - NoteDetails& details(); + void name(std::string name) { + name_ = std::move(name); + } - void name(const std::string& name); - void type(NOTE_TYPES type); - void type_core(NOTE_TYPES_CORE type); - void description(const description_t& description); + /// Change the description of the note + void description(description_t description) { + description_ = std::move(description); + } - //! Size of the **raw** note + /// Size of the **raw** note which includes padding uint64_t size() const; virtual void dump(std::ostream& os) const; - - void swap(Note& other); - void accept(Visitor& visitor) const override; - LIEF_API friend std::ostream& operator<<(std::ostream& os, const Note& note); + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const Note& note) { + note.dump(os); + return os; + } protected: - Binary* binary_{nullptr}; - std::string name_; - NOTE_TYPES type_; - description_t description_; + Note() = default; + Note(std::string name, TYPE type, uint32_t original_type, + description_t description) : + name_(std::move(name)), + type_(type), + original_type_(original_type), + description_(std::move(description)) + {} + + template + LIEF_LOCAL result read_at(size_t offset) const; + + template + LIEF_LOCAL ok_error_t write_at(size_t offset, const T& value); - private: - bool is_core_{false}; - std::pair> details_; + LIEF_LOCAL ok_error_t write_string_at(size_t offset, const std::string& value); + + LIEF_LOCAL result + read_string_at(size_t offset, size_t maxsize = 0) const; + + std::string name_; + TYPE type_ = TYPE::UNKNOWN; + uint32_t original_type_ = 0; + description_t description_; }; +LIEF_API const char* to_string(Note::TYPE type); + } // namepsace ELF } // namespace LIEF - #endif diff --git a/include/LIEF/ELF/NoteDetails.hpp b/include/LIEF/ELF/NoteDetails.hpp index 53ccc0b5d1..1010160b1d 100644 --- a/include/LIEF/ELF/NoteDetails.hpp +++ b/include/LIEF/ELF/NoteDetails.hpp @@ -15,64 +15,7 @@ */ #ifndef LIEF_ELF_NOTE_DETAILS_H #define LIEF_ELF_NOTE_DETAILS_H - -#include -#include -#include - -#include "LIEF/Object.hpp" -#include "LIEF/visibility.h" - -namespace LIEF { -namespace ELF { - -class Parser; -class Builder; -class Binary; -class Note; - -class LIEF_API NoteDetails : public Object { - - friend class Parser; - friend class Builder; - friend class Binary; - - public: - using description_t = std::vector; - NoteDetails(); - - protected: - NoteDetails(Note& note); - - public: - ~NoteDetails() override; - - virtual NoteDetails* clone() const; - - const description_t& description() const; - - virtual void dump(std::ostream& os) const; - - - void accept(Visitor& visitor) const override; - - LIEF_API friend std::ostream& operator<<(std::ostream& os, const NoteDetails& note); - - protected: - virtual void parse(); - virtual void build(); - - description_t& description(); - Binary* binary(); - const Binary* binary() const; - - private: - Note* note_{nullptr}; - description_t empty_; -}; - - -} // namepsace ELF -} // namespace LIEF - +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" +#include "LIEF/ELF/NoteDetails/NoteAbi.hpp" +#include "LIEF/ELF/NoteDetails/Core.hpp" #endif diff --git a/include/LIEF/ELF/NoteDetails/AndroidNote.hpp b/include/LIEF/ELF/NoteDetails/AndroidIdent.hpp similarity index 58% rename from include/LIEF/ELF/NoteDetails/AndroidNote.hpp rename to include/LIEF/ELF/NoteDetails/AndroidIdent.hpp index 8e5d54e1aa..d69d9c3d87 100644 --- a/include/LIEF/ELF/NoteDetails/AndroidNote.hpp +++ b/include/LIEF/ELF/NoteDetails/AndroidIdent.hpp @@ -13,85 +13,67 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LIEF_ELF_ANDROID_NOTE_H -#define LIEF_ELF_ANDROID_NOTE_H +#ifndef LIEF_ELF_ANDROID_IDENT_H +#define LIEF_ELF_ANDROID_IDENT_H #include #include +#include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/Note.hpp" namespace LIEF { namespace ELF { -class Parser; -class Builder; -class Binary; -class Note; - //! Class representing the ".note.android.ident" section //! //! @see: https://android.googlesource.com/platform/ndk/+/ndk-release-r16/sources/crt/crtbrand.S#39 -class LIEF_API AndroidNote : public NoteDetails { - - friend class Parser; - friend class Builder; - friend class Binary; - +class LIEF_API AndroidIdent : public Note { public: - static constexpr const char NAME[] = "Android"; - - static constexpr size_t sdk_version_offset = 0; static constexpr size_t sdk_version_size = sizeof(uint32_t); - - static constexpr size_t ndk_version_offset = sdk_version_offset + sdk_version_size; static constexpr size_t ndk_version_size = 64 * sizeof(char); - - static constexpr size_t ndk_build_number_offset = ndk_version_offset + ndk_version_size; static constexpr size_t ndk_build_number_size = 64 * sizeof(char); - static AndroidNote make(Note& note); - public: - using NoteDetails::NoteDetails; - using description_t = std::vector; - - AndroidNote* clone() const override; + std::unique_ptr clone() const override { + return std::unique_ptr(new AndroidIdent(*this)); + } - //! Target SDK version + //! Target SDK version (or 0 if it can't be resolved) uint32_t sdk_version() const; - //! NDK version used + //! NDK version used (or an empty string if it can't be parsed) std::string ndk_version() const; - //! NDK build number + //! NDK build number (or an empty string if it can't be parsed) std::string ndk_build_number() const; void sdk_version(uint32_t version); void ndk_version(const std::string& ndk_version); void ndk_build_number(const std::string& ndk_build_number); - void dump(std::ostream& os) const override; void accept(Visitor& visitor) const override; - ~AndroidNote() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::ANDROID_IDENT; + } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const AndroidNote& note); + ~AndroidIdent() override = default; - protected: - void parse() override; - void build() override; - - private: - AndroidNote(Note& note); + static constexpr size_t description_size() { + return sdk_version_size + ndk_version_size + ndk_build_number_size; + } - uint32_t sdk_version_ = 0; - std::string ndk_version_; - std::string ndk_build_number_; + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const AndroidIdent& note) { + note.dump(os); + return os; + } + protected: + using Note::Note; }; diff --git a/include/LIEF/ELF/NoteDetails/NoteAbi.hpp b/include/LIEF/ELF/NoteDetails/NoteAbi.hpp index c0f39941ef..9609cd74e4 100644 --- a/include/LIEF/ELF/NoteDetails/NoteAbi.hpp +++ b/include/LIEF/ELF/NoteDetails/NoteAbi.hpp @@ -13,79 +13,81 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LIEF_ELF_NOTE_DETAILS_ABI_H -#define LIEF_ELF_NOTE_DETAILS_ABI_H +#ifndef LIEF_ELF_NOTE_ABI_H +#define LIEF_ELF_NOTE_ABI_H #include #include #include +#include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" #include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails.hpp" namespace LIEF { namespace ELF { -class Parser; -class Builder; -class Binary; - -//! Class representing the ``.note.android.ident`` section -//! -//! @see: https://android.googlesource.com/platform/ndk/+/ndk-release-r16/sources/crt/crtbrand.S#39 -class LIEF_API NoteAbi : public NoteDetails { - - friend class Parser; - friend class Builder; - friend class Binary; - +/// Class that wraps the `NT_GNU_ABI_TAG` note +class LIEF_API NoteAbi : public Note { public: - - //! Version type: (Major, Minor, Patch) + /// ABI recognized by this note + enum class ABI { + LINUX = 0, + GNU, + SOLARIS2, + FREEBSD, + NETBSD, + SYLLABLE, + NACL + }; + /// Version type: (Major, Minor, Patch) using version_t = std::array; static constexpr size_t abi_offset = 0; static constexpr size_t abi_size = sizeof(uint32_t); - static constexpr size_t version_offset = abi_offset + abi_size; + static constexpr size_t version_offset = abi_size; static constexpr size_t version_size = 3 * sizeof(uint32_t); - static NoteAbi make(Note& note); - - NoteAbi* clone() const override; - public: - using NoteDetails::NoteDetails; - using description_t = typename Note::description_t; + using Note::Note; + + std::unique_ptr clone() const override { + return std::unique_ptr(new NoteAbi(*this)); + } - //! @brief Return the target version as ````. - version_t version() const; + /// Return the version or an error if it can't be parsed + result version() const; - //! @brief Return the target ABI. Require a NT_GNU_ABI_TAG type - NOTE_ABIS abi() const; + /// Return the ABI or an error if it can't be parsed + result abi() const; + void version(const version_t& version); + void version(ABI abi); void dump(std::ostream& os) const override; void accept(Visitor& visitor) const override; - ~NoteAbi() override; - - LIEF_API friend std::ostream& operator<<(std::ostream& os, const NoteAbi& note); - - protected: - void parse() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::GNU_ABI_TAG; + } - private: - NoteAbi(Note& note); + //// Size of the description content + static constexpr uint8_t description_size() { + return /* abi */ sizeof(uint32_t) + /* version */ 3 * sizeof(uint32_t); + } - version_t version_; - NOTE_ABIS abi_; + ~NoteAbi() override = default; + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const NoteAbi& note) { + note.dump(os); + return os; + } }; +LIEF_API const char* to_string(NoteAbi::ABI abi); } // namepsace ELF } // namespace LIEF diff --git a/include/LIEF/ELF/NoteDetails/core/CoreAuxv.hpp b/include/LIEF/ELF/NoteDetails/core/CoreAuxv.hpp index 41c6eaa3d3..015b898583 100644 --- a/include/LIEF/ELF/NoteDetails/core/CoreAuxv.hpp +++ b/include/LIEF/ELF/NoteDetails/core/CoreAuxv.hpp @@ -21,74 +21,99 @@ #include #include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" #include "LIEF/ELF/enums.hpp" -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/Note.hpp" namespace LIEF { namespace ELF { -class Parser; -class Builder; -class Binary; -class Note; - -//! Class representing core Auxv object -class LIEF_API CoreAuxv : public NoteDetails { - - public: - using NoteDetails::NoteDetails; - - using val_context_t = std::map; - +//! Class representing core auxv object +class LIEF_API CoreAuxv : public Note { public: - static CoreAuxv make(Note& note); - - CoreAuxv* clone() const override; - - //! Auxiliary values - const val_context_t& values() const; - - //! Get an auxiliary value. If ``error`` is set, - //! this function and the value exists, the function set the boolean value to ``false`` - //! Otherwise it set the value to ``true`` - uint64_t get(AUX_TYPE atype, bool* error = nullptr) const; - - //! Check if the given register is present in the info - bool has(AUX_TYPE reg) const; - - void values(const val_context_t& ctx); - - bool set(AUX_TYPE atype, uint64_t value); - - - uint64_t& operator[](AUX_TYPE atype); + enum class TYPE { + END = 0, /**< End of vector */ + IGNORE, /**< Entry should be ignored */ + EXECFD, /**< File descriptor of program */ + PHDR, /**< Program headers for program */ + PHENT, /**< Size of program header entry */ + PHNUM, /**< Number of program headers */ + PAGESZ, /**< System page size */ + BASE, /**< Base address of interpreter */ + FLAGS, /**< Flags */ + ENTRY, /**< Entry point of program */ + NOTELF, /**< Program is not ELF */ + UID, /**< Real uid */ + EUID, /**< Effective uid */ + GID, /**< Real gid */ + EGID, /**< Effective gid */ + TGT_PLATFORM, /**< String identifying platform. */ + HWCAP, /**< Machine dependent hints about processor capabilities. */ + CLKTCK, /**< Frequency of times() */ + FPUCW, /**< Used FPU control word. */ + DCACHEBSIZE, /**< Data cache block size. */ + ICACHEBSIZE, /**< Instruction cache block size. */ + UCACHEBSIZE, /**< Instruction cache block size. */ + IGNOREPPC, /**< Entry should be ignored. */ + SECURE, /**< Boolean, was exec setuid-like?. */ + BASE_PLATFORM, /**< String identifying real platform */ + RANDOM, /**< Address of 16 random bytes */ + HWCAP2, /**< Extension of AT_HWCAP */ + //ENTRY27, + //ENTRY28, + //ENTRY29, + //ENTRY30, + EXECFN = 31, /**< Filename of executable */ + SYSINFO, /**< Filename of executable */ + SYSINFO_EHDR, /**< Pointer to ELF header of system-supplied DSO. */ + }; + + CoreAuxv(ARCH arch, ELF_CLASS cls, std::string name, + uint32_t type, description_t description) : + Note(std::move(name), Note::TYPE::CORE_AUXV, type, std::move(description)), + arch_(arch), class_(cls) + {} + + std::unique_ptr clone() const override { + return std::unique_ptr(new CoreAuxv(*this)); + } + + /// A map of CoreAuxv::TYPE and the value + std::map values() const; + + /// Return the value associated with the provided TYPE or + /// a lief_errors::not_found if the type is not present. + result get(TYPE type) const; + + result operator[](TYPE type) const { + return get(type); + } + + bool set(TYPE type, uint64_t value); + bool set(std::map values); void dump(std::ostream& os) const override; void accept(Visitor& visitor) const override; - ~CoreAuxv() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::CORE_AUXV; + } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CoreAuxv& note); + ~CoreAuxv() override = default; - protected: - template - LIEF_LOCAL void parse_(); + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const CoreAuxv& note) { + note.dump(os); + return os; + } - template - LIEF_LOCAL void build_(); - - void parse() override; - void build() override; - - private: - CoreAuxv(Note& note); - - val_context_t ctx_; + protected: + ARCH arch_ = ARCH::EM_NONE; + ELF_CLASS class_ = ELF_CLASS::ELFCLASSNONE; }; +LIEF_API const char* to_string(CoreAuxv::TYPE type); } // namepsace ELF } // namespace LIEF diff --git a/include/LIEF/ELF/NoteDetails/core/CoreFile.hpp b/include/LIEF/ELF/NoteDetails/core/CoreFile.hpp index 00f6591dee..4a7891da32 100644 --- a/include/LIEF/ELF/NoteDetails/core/CoreFile.hpp +++ b/include/LIEF/ELF/NoteDetails/core/CoreFile.hpp @@ -19,83 +19,94 @@ #include #include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/Note.hpp" namespace LIEF { namespace ELF { -class Parser; -class Builder; -class Binary; -class Note; - -//! Core file entry -struct CoreFileEntry { - uint64_t start; ///< Start address of mapped file - uint64_t end; ///< End address of mapped file - uint64_t file_ofs; ///< Offset (in core) of mapped file - std::string path; ///< Path of mapped file - - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CoreFileEntry& entry); -}; - -//! Class representing core PrPsInfo object -class LIEF_API CoreFile : public NoteDetails { - +/// Class representing a core `NT_FILE` which describes the mapped files +/// of the process +class LIEF_API CoreFile : public Note { public: - using NoteDetails::NoteDetails; - - using files_t = std::vector; + //! Core file entry + struct entry_t { + uint64_t start = 0; /// Start address of mapped file + uint64_t end = 0; ///< End address of mapped file + uint64_t file_ofs = 0; ///< Offset (in core) of mapped file + std::string path; ///< Path of mapped file + + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const entry_t& entry); + }; + + using files_t = std::vector; using iterator = files_t::iterator; using const_iterator = files_t::const_iterator; public: - static CoreFile make(Note& note); + CoreFile(ARCH arch, ELF_CLASS cls, std::string name, + uint32_t type, Note::description_t description); - CoreFile* clone() const override; + std::unique_ptr clone() const override { + return std::unique_ptr(new CoreFile(*this)); + } //! Number of coredump file entries - uint64_t count() const; + uint64_t count() const { + return files_.size(); + } //! Coredump file entries - const files_t& files() const; + const files_t& files() const { + return files_; + } - iterator begin(); - iterator end(); + iterator begin() { + return files_.begin(); + } - const_iterator begin() const; - const_iterator end() const; + iterator end() { + return files_.end(); + } - void files(const files_t&); + const_iterator begin() const { + return files_.begin(); + } + const_iterator end() const { + return files_.end(); + } - void dump(std::ostream& os) const override; + void files(const files_t& file); + void dump(std::ostream& os) const override; void accept(Visitor& visitor) const override; - ~CoreFile() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::CORE_FILE; + } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CoreFile& note); + ~CoreFile() override = default; - protected: - template - LIEF_LOCAL void parse_(); + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const CoreFile& note) { + note.dump(os); + return os; + } - template - LIEF_LOCAL void build_(); - - void parse() override; - void build() override; + protected: + template + LIEF_LOCAL void read_files(); - private: - CoreFile(Note& note); + template + LIEF_LOCAL void write_files(); - private: files_t files_; - uint64_t page_size_; + uint64_t page_size_ = 0; + ARCH arch_ = ARCH::EM_NONE; + ELF_CLASS class_ = ELF_CLASS::ELFCLASSNONE; }; } // namepsace ELF diff --git a/include/LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp b/include/LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp index aedb9dba30..e4e14038f6 100644 --- a/include/LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp +++ b/include/LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp @@ -13,100 +13,80 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LIEF_ELF_CORE_PSINFO_H -#define LIEF_ELF_CORE_PSINFO_H +#ifndef LIEF_ELF_CORE_PRPSINFO_H +#define LIEF_ELF_CORE_PRPSINFO_H #include #include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" - -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/enums.hpp" +#include "LIEF/ELF/Note.hpp" namespace LIEF { namespace ELF { -class Note; -class Parser; -class Builder; -class Binary; - -//! Class representing core PrPsInfo object -class LIEF_API CorePrPsInfo : public NoteDetails { - +/// Class representing the NT_PRPSINFO core note. +/// This kind of note represents general information about the process +class LIEF_API CorePrPsInfo : public Note { public: - using NoteDetails::NoteDetails; - - public: - static CorePrPsInfo make(Note& note); - - CorePrPsInfo* clone() const override; - - //! Process file name - std::string file_name() const; - - //! Process flag - uint64_t flags() const; - - //! Process user id - uint32_t uid() const; - - //! Process group id - uint32_t gid() const; - - //! Process ID - int32_t pid() const; - - //! Process parent ID - int32_t ppid() const; - - //! Process session group ID - int32_t pgrp() const; - - //! Process session ID - int32_t sid() const; - - void file_name(const std::string& file_name); - void flags(uint64_t); - void uid(uint32_t); - void gid(uint32_t); - void pid(int32_t); - void ppid(int32_t); - void pgrp(int32_t); - void sid(int32_t); - + struct info_t { + uint8_t state = 0; /// Numeric process state + char sname = ' '; /// printable character representing state + bool zombie = false; /// Whether the process is a zombie + uint8_t nice = 0; /// Nice value + uint64_t flag = 0; /// Process flag + uint32_t uid = 0; /// Process user ID + uint32_t gid = 0; /// Process group ID + uint32_t pid = 0; /// Process ID + uint32_t ppid = 0; /// Process parent ID + uint32_t pgrp = 0; /// Process group + uint32_t sid = 0; /// Process session id + std::string filename; /// Filename of the executable + std::string args; /// Initial part of the arguments + + /// Return the filename without the ending '\x00' + std::string filename_stripped() const { + return filename.c_str(); + } + + /// Return the args without the ending '\x00' + std::string args_stripped() const { + return args.c_str(); + } + }; + CorePrPsInfo(ARCH arch, ELF_CLASS cls, std::string name, + uint32_t type, description_t description) : + Note(std::move(name), TYPE::CORE_PRPSINFO, type, std::move(description)), + arch_(arch), class_(cls) + {} + + std::unique_ptr clone() const override { + return std::unique_ptr(new CorePrPsInfo(*this)); + } + + /// Return a `elf_prpsinfo`-like structure or an error if it can't be parsed. + result info() const; + void info(const info_t& info); void dump(std::ostream& os) const override; void accept(Visitor& visitor) const override; - ~CorePrPsInfo() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::CORE_PRPSINFO; + } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CorePrPsInfo& note); - - protected: - template - LIEF_LOCAL void parse_(); - - template - LIEF_LOCAL void build_(); - - void parse() override; - void build() override; - - private: - CorePrPsInfo(Note& note); + ~CorePrPsInfo() override = default; + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const CorePrPsInfo& note) { + note.dump(os); + return os; + } private: - std::string file_name_; - uint64_t flags_; - uint32_t uid_; - uint32_t gid_; - int32_t pid_; - int32_t ppid_; - int32_t pgrp_; - int32_t sid_; + ARCH arch_ = ARCH::EM_NONE; + ELF_CLASS class_ = ELF_CLASS::ELFCLASSNONE; }; } // namepsace ELF diff --git a/include/LIEF/ELF/NoteDetails/core/CorePrStatus.hpp b/include/LIEF/ELF/NoteDetails/core/CorePrStatus.hpp index c1bfe462a1..f779253bdc 100644 --- a/include/LIEF/ELF/NoteDetails/core/CorePrStatus.hpp +++ b/include/LIEF/ELF/NoteDetails/core/CorePrStatus.hpp @@ -18,13 +18,11 @@ #include #include -#include #include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" - -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/enums.hpp" +#include "LIEF/ELF/Note.hpp" namespace LIEF { namespace ELF { @@ -34,188 +32,168 @@ class Builder; class Binary; //! Class representing core PrPsInfo object -class LIEF_API CorePrStatus : public NoteDetails { - +class LIEF_API CorePrStatus : public Note { public: - using NoteDetails::NoteDetails; struct siginfo_t { - int32_t si_signo; - int32_t si_code; - int32_t si_errno; + int32_t signo = 0; + int32_t code = 0; + int32_t err = 0; }; struct timeval_t { - uint64_t sec; - uint64_t usec; - }; - - - enum class REGISTERS { - UNKNOWN, - - // x86 - // === - X86_START, - X86_EBX, X86_ECX, X86_EDX, X86_ESI, X86_EDI, X86_EBP, X86_EAX, - X86_DS, X86_ES, X86_FS, X86_GS, X86__, X86_EIP, X86_CS, X86_EFLAGS, X86_ESP, X86_SS, - X86_END, - - // x86-64 - // ====== - X86_64_START, - X86_64_R15, X86_64_R14, X86_64_R13, X86_64_R12, X86_64_RBP, X86_64_RBX, X86_64_R11, X86_64_R10, - X86_64_R9, X86_64_R8, X86_64_RAX, X86_64_RCX, X86_64_RDX, X86_64_RSI, X86_64_RDI, X86_64__, - X86_64_RIP, X86_64_CS, X86_64_EFLAGS, X86_64_RSP, X86_64_SS, - X86_64_END, - - // ARM - // === - ARM_START, - ARM_R0, ARM_R1, ARM_R2, ARM_R3, ARM_R4, ARM_R5, ARM_R6, ARM_R7, - ARM_R8, ARM_R9, ARM_R10, ARM_R11, ARM_R12, ARM_R13, ARM_R14, ARM_R15, - ARM_CPSR, - ARM_END, - - // AArch64 - // ======= - AARCH64_START, - AARCH64_X0, AARCH64_X1, AARCH64_X2, AARCH64_X3, AARCH64_X4, AARCH64_X5, AARCH64_X6, AARCH64_X7, - AARCH64_X8, AARCH64_X9, AARCH64_X10, AARCH64_X11, AARCH64_X12, AARCH64_X13, AARCH64_X14, AARCH64_X15, - AARCH64_X16, AARCH64_X17, AARCH64_X18, AARCH64_X19, AARCH64_X20, AARCH64_X21, AARCH64_X22, AARCH64_X23, - AARCH64_X24, AARCH64_X25, AARCH64_X26, AARCH64_X27, AARCH64_X28, AARCH64_X29, AARCH64_X30, AARCH64_X31, - AARCH64_PC, AARCH64__, - AARCH64_END, + uint64_t sec = 0; + uint64_t usec = 0; }; - using reg_context_t = std::map; - - public: - static CorePrStatus make(Note& note); - - CorePrStatus* clone() const override; - - //! Info associated with the signal - const siginfo_t& siginfo() const; - - //! Current Signal - uint16_t current_sig() const; - - //! Set of pending signals - uint64_t sigpend() const; - - //! Set of held signals - uint64_t sighold() const; - - //! Process ID - int32_t pid() const; - - //! Process parent ID - int32_t ppid() const; - - //! Process group ID - int32_t pgrp() const; - - //! Process session ID - int32_t sid() const; - - //! User time - timeval_t utime() const; - - //! System time - timeval_t stime() const; - - //! Cumulative user time - timeval_t cutime() const; - - //! Cumulative system time - timeval_t cstime() const; - //! GP registers state - const reg_context_t& reg_context() const; + struct pr_status_t { + siginfo_t info; - //! Return the program counter - uint64_t pc() const; + uint16_t cursig = 0; + uint16_t reserved = 0; - //! Return the stack pointer - uint64_t sp() const; + uint64_t sigpend = 0; + uint64_t sighold = 0; - //! Get register value. If ``error`` is set, - //! this function and the register exists, the function set the boolean value to ``false`` - //! Otherwise it set the value to ``true`` - uint64_t get(REGISTERS reg, bool* error = nullptr) const; + int32_t pid = 0; + int32_t ppid = 0; + int32_t pgrp = 0; + int32_t sid = 0; - //! Check if the given register is present in the info - bool has(REGISTERS reg) const; - - void siginfo(const siginfo_t& siginfo); - void current_sig(uint16_t current_sig); - - void sigpend(uint64_t sigpend); - void sighold(uint64_t sighold); - - void pid(int32_t pid); - void ppid(int32_t ppid); - void pgrp(int32_t pgrp); - void sid(int32_t sid); - - void utime(timeval_t utime); - void stime(timeval_t stime); - void cutime(timeval_t cutime); - void cstime(timeval_t cstime); - - void reg_context(const reg_context_t& ctx); - - bool set(REGISTERS reg, uint64_t value); + timeval_t utime; + timeval_t stime; + timeval_t cutime; + timeval_t cstime; + }; + struct Registers { + /// Register for the x86 architecture (ARCH::EM_386). + enum class X86 { + EBX = 0, ECX, EDX, ESI, EDI, EBP, EAX, + DS, ES, FS, GS, ORIG_EAX, EIP, CS, EFLAGS, ESP, SS, + _COUNT + }; + + /// Register for the x86-64 architecture (ARCH::EM_X86_64). + enum class X86_64 { + R15 = 0, R14, R13, R12, RBP, RBX, R11, R10, + R9, R8, RAX, RCX, RDX, RSI, RDI, ORIG_RAX, + RIP, CS, EFLAGS, RSP, SS, + _COUNT + }; + + /// Register for the ARM architecture (ARCH::EM_ARM). + enum class ARM { + R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, + CPSR, + _COUNT + }; + + /// Register for the AARCH64 architecture (ARCH::AARCH64). + enum class AARCH64 { + X0 = 0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, + X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, + X31, PC, PSTATE, + _COUNT + }; + }; - uint64_t& operator[](REGISTERS reg); + public: + CorePrStatus(ARCH arch, ELF_CLASS cls, std::string name, + uint32_t type, description_t description) : + Note(std::move(name), TYPE::CORE_PRSTATUS, type, std::move(description)), + arch_(arch), class_(cls) + {} + + std::unique_ptr clone() const override { + return std::unique_ptr(new CorePrStatus(*this)); + } + + /// Return the pr_status_t structure + pr_status_t status() const; + void status(const pr_status_t& status); + + ARCH architecture() const { + return arch_; + } + + /// The program counter or an error if not found + result pc() const; + + /// The stack pointer or an error if not found + result sp() const; + + /// The value of the register that holds the return value according to + /// the calling convention. + result return_value() const; + + /// Get the value for the given X86 register or return an error + result get(Registers::X86 reg) const; + /// Get the value for the given X86_64 register or return an error + result get(Registers::X86_64 reg) const; + /// Get the value for the given ARM register or return an error + result get(Registers::ARM reg) const; + /// Get the value for the given AARCH64 register or return an error + result get(Registers::AARCH64 reg) const; + + ok_error_t set(Registers::X86 reg, uint64_t value); + ok_error_t set(Registers::X86_64 reg, uint64_t value); + ok_error_t set(Registers::ARM reg, uint64_t value); + ok_error_t set(Registers::AARCH64 reg, uint64_t value); + + /// A list of the register values. + /// This list is **guarantee** to be as long as the Registers::ARM::_COUNT or + /// empty if it can't be resolved. Thus, one can access a specific register + /// with: + /// ```cpp + /// if (architecture() == ARCH::EM_AARCH64) { + /// auto reg_vals = register_values() + /// if (!reg_vals.empty()) { + /// auto x20 = reg_vals[static_cast(Register::AARCH64::X20)] + /// } + /// } + /// ``` + std::vector register_values() const; + + result operator[](Registers::X86 reg) const { + return get(reg); + } + + result operator[](Registers::X86_64 reg) const { + return get(reg); + } + + result operator[](Registers::ARM reg) const { + return get(reg); + } + + result operator[](Registers::AARCH64 reg) const { + return get(reg); + } void dump(std::ostream& os) const override; - static std::ostream& dump(std::ostream& os, const timeval_t& time); - static std::ostream& dump(std::ostream& os, const siginfo_t& siginfo); - static std::ostream& dump(std::ostream& os, const reg_context_t& ctx); - void accept(Visitor& visitor) const override; - ~CorePrStatus() override; + static bool classof(const Note* note) { + return note->type() == Note::TYPE::CORE_PRSTATUS; + } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CorePrStatus& note); + ~CorePrStatus() override = default; - protected: - template - LIEF_LOCAL void parse_(); - - template - LIEF_LOCAL void build_(); - - void parse() override; - void build() override; + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const CorePrStatus& note) { + note.dump(os); + return os; + } private: - CorePrStatus(Note& note); - - std::pair reg_enum_range() const; - - siginfo_t siginfo_; - uint16_t cursig_; - - uint64_t sigpend_; - uint64_t sighold_; - - int32_t pid_; - int32_t ppid_; - int32_t pgrp_; - int32_t sid_; - - timeval_t utime_; - timeval_t stime_; - timeval_t cutime_; - timeval_t cstime_; - - reg_context_t ctx_; + ARCH arch_ = ARCH::EM_NONE; + ELF_CLASS class_ = ELF_CLASS::ELFCLASSNONE; }; - -LIEF_API const char* to_string(CorePrStatus::REGISTERS e); +LIEF_API const char* to_string(CorePrStatus::Registers::X86 e); +LIEF_API const char* to_string(CorePrStatus::Registers::X86_64 e); +LIEF_API const char* to_string(CorePrStatus::Registers::ARM e); +LIEF_API const char* to_string(CorePrStatus::Registers::AARCH64 e); } // namepsace ELF } // namespace LIEF diff --git a/include/LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp b/include/LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp index dba93185ee..8a1f883daa 100644 --- a/include/LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp +++ b/include/LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp @@ -18,71 +18,51 @@ #include #include -#include -#include +#include -#include "LIEF/Object.hpp" #include "LIEF/visibility.h" - -#include "LIEF/ELF/NoteDetails.hpp" +#include "LIEF/ELF/Note.hpp" +#include "LIEF/errors.hpp" namespace LIEF { namespace ELF { -class Note; -class Parser; -class Builder; -class Binary; - -//! Class representing core siginfo object -class LIEF_API CoreSigInfo : public NoteDetails { - +//! Class representing a core siginfo object +class LIEF_API CoreSigInfo : public Note { public: - using NoteDetails::NoteDetails; - - public: - static CoreSigInfo make(Note& note); - - CoreSigInfo* clone() const override; - - //! Signal number. - int32_t signo() const; + std::unique_ptr clone() const override { + return std::unique_ptr(new CoreSigInfo(*this)); + } - //! Signal code. - int32_t sigcode() const; + /// Signal number of an error if it can't be resolved + result signo() const; + /// Signal code of an error if it can't be resolved + result sigcode() const; - //! If non-zero, an errno value associated with this signal. - int32_t sigerrno() const; - - void signo(int32_t signo); - void sigcode(int32_t sigcode); - void sigerrno(int32_t sigerrno); + /// Signal error number of an error if it can't be resolved + result sigerrno() const; + void signo(uint32_t value); + void sigcode(uint32_t value); + void sigerrno(uint32_t value); void dump(std::ostream& os) const override; - void accept(Visitor& visitor) const override; - ~CoreSigInfo() override; + ~CoreSigInfo() override = default; - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CoreSigInfo& note); + static bool classof(const Note* note) { + return note->type() == Note::TYPE::CORE_SIGINFO; + } + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const CoreSigInfo& note) { + note.dump(os); + return os; + } protected: - void parse() override; - void build() override; - - private: - CoreSigInfo(Note& note); - struct siginfo_t { - int32_t si_signo; - int32_t si_code; - int32_t si_errno; - }; - - siginfo_t siginfo_; + using Note::Note; }; - - } // namepsace ELF } // namespace LIEF diff --git a/include/LIEF/ELF/Parser.hpp b/include/LIEF/ELF/Parser.hpp index bd2525e90c..f4f4bddf55 100644 --- a/include/LIEF/ELF/Parser.hpp +++ b/include/LIEF/ELF/Parser.hpp @@ -38,6 +38,7 @@ class Section; class Binary; class Segment; class Symbol; +class Note; //! Class which parses and transforms an ELF file into a ELF::Binary object class LIEF_API Parser : public LIEF::Parser { @@ -51,7 +52,6 @@ class LIEF_API Parser : public LIEF::Parser { static constexpr uint32_t NB_MAX_RELOCATIONS = 3000000; static constexpr uint32_t NB_MAX_DYNAMIC_ENTRIES = 1000; static constexpr uint32_t NB_MAX_MASKWORD = 512; - static constexpr uint32_t MAX_NOTE_DESCRIPTION = 1_MB; static constexpr uint32_t MAX_SECTION_SIZE = 2_GB; static constexpr uint32_t MAX_SEGMENT_SIZE = 3_GB; @@ -224,6 +224,8 @@ class LIEF_API Parser : public LIEF::Parser { //! Parse Note (.gnu.note) ok_error_t parse_notes(uint64_t offset, uint64_t size); + std::unique_ptr get_note(uint32_t type, std::string name, std::vector desc_bytes); + //! Parse Symbols's SYSV hash ok_error_t parse_symbol_sysv_hash(uint64_t offset); diff --git a/include/LIEF/ELF/enums.hpp b/include/LIEF/ELF/enums.hpp index 204567a0f9..a291b7ddb8 100644 --- a/include/LIEF/ELF/enums.hpp +++ b/include/LIEF/ELF/enums.hpp @@ -885,64 +885,6 @@ enum { VER_NEED_CURRENT = 1 }; - -enum class AUX_TYPE: size_t { - - AT_NULL = 0, /**< End of vector */ - AT_IGNORE = 1, /**< Entry should be ignored */ - AT_EXECFD = 2, /**< File descriptor of program */ - AT_PHDR = 3, /**< Program headers for program */ - AT_PHENT = 4, /**< Size of program header entry */ - AT_PHNUM = 5, /**< Number of program headers */ - AT_PAGESZ = 6, /**< System page size */ - AT_BASE = 7, /**< Base address of interpreter */ - AT_FLAGS = 8, /**< Flags */ - AT_ENTRY = 9, /**< Entry point of program */ - AT_NOTELF = 10, /**< Program is not ELF */ - AT_UID = 11, /**< Real uid */ - AT_EUID = 12, /**< Effective uid */ - AT_GID = 13, /**< Real gid */ - AT_EGID = 14, /**< Effective gid */ - AT_CLKTCK = 17, /**< Frequency of times() */ - - /* Some more special a_type values describing the hardware. */ - - AT_PLATFORM = 15, /**< String identifying platform. */ - AT_HWCAP = 16, /**< Machine dependent hints about processor capabilities. */ - - /* This entry gives some information about the FPU initialization - performed by the kernel. */ - - AT_FPUCW = 18, /**< Used FPU control word. */ - - /* Cache block sizes. */ - AT_DCACHEBSIZE = 19, /**< Data cache block size. */ - AT_ICACHEBSIZE = 20, /**< Instruction cache block size. */ - AT_UCACHEBSIZE = 21, /**< Unified cache block size. */ - - /* A special ignored value for PPC, used by the kernel to control the - interpretation of the AUXV. Must be > 16. */ - - AT_IGNOREPPC = 22, /**< Entry should be ignored. */ - AT_SECURE = 23, /**< Boolean, was exec setuid-like? */ - AT_BASE_PLATFORM = 24, /**< String identifying real platforms.*/ - AT_RANDOM = 25, /**< Address of 16 random bytes. */ - AT_HWCAP2 = 26, /**< Extension of AT_HWCAP. */ - AT_EXECFN = 31, /**< Filename of executable. */ - - /* Pointer to the global system page used for system calls and other - nice things. */ - AT_SYSINFO = 32, - AT_SYSINFO_EHDR = 33, - - /* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains - log2 of line size; mask those to get cache size. */ - AT_L1I_CACHESHAPE = 34, - AT_L1D_CACHESHAPE = 35, - AT_L2_CACHESHAPE = 36, - AT_L3_CACHESHAPE = 37 -}; - /** Methods that can be used by the LIEF::ELF::Parser to count the number of dynamic symbols */ enum class DYNSYM_COUNT_METHODS: size_t { @@ -952,53 +894,6 @@ enum class DYNSYM_COUNT_METHODS: size_t { COUNT_RELOCATIONS = 3, /**< Count based on PLT/GOT relocations (very reliable but not accurate) */ }; -enum class NOTE_TYPES: size_t { - NT_UNKNOWN = 0, - NT_GNU_ABI_TAG = 1, - NT_GNU_HWCAP = 2, - NT_GNU_BUILD_ID = 3, - NT_GNU_GOLD_VERSION = 4, - NT_GNU_PROPERTY_TYPE_0 = 5, - NT_GNU_BUILD_ATTRIBUTE_OPEN = 0x100, - NT_GNU_BUILD_ATTRIBUTE_FUNC = 0x101, - NT_CRASHPAD = 0x4f464e49, -}; - -enum class NOTE_TYPES_CORE: size_t { - NT_CORE_UNKNOWN = 0, - NT_PRSTATUS = 1, - NT_PRFPREG = 2, - NT_PRPSINFO = 3, - NT_TASKSTRUCT = 4, - NT_AUXV = 6, - NT_SIGINFO = 0x53494749, - NT_FILE = 0x46494c45, - NT_PRXFPREG = 0x46e62b7f, - - NT_ARM_VFP = 0x400, - NT_ARM_TLS = 0x401, - NT_ARM_HW_BREAK = 0x402, - NT_ARM_HW_WATCH = 0x403, - NT_ARM_SYSTEM_CALL = 0x404, - NT_ARM_SVE = 0x405, - - NT_386_TLS = 0x200, - NT_386_IOPERM = 0x201, - NT_386_XSTATE = 0x202, - -}; - - -enum class NOTE_ABIS: size_t { - ELF_NOTE_UNKNOWN = ~(unsigned int)(0), - ELF_NOTE_OS_LINUX = 0, - ELF_NOTE_OS_GNU = 1, - ELF_NOTE_OS_SOLARIS2 = 2, - ELF_NOTE_OS_FREEBSD = 3, - ELF_NOTE_OS_NETBSD = 4, - ELF_NOTE_OS_SYLLABLE = 5, -}; - enum class RELOCATION_PURPOSES: size_t { RELOC_PURPOSE_NONE = 0, RELOC_PURPOSE_PLTGOT = 1, diff --git a/include/LIEF/ELF/hash.hpp b/include/LIEF/ELF/hash.hpp index 5a24393e46..de74afd209 100644 --- a/include/LIEF/ELF/hash.hpp +++ b/include/LIEF/ELF/hash.hpp @@ -82,8 +82,7 @@ class LIEF_API Hash : public LIEF::Hash { void visit(const SymbolVersionRequirement& svr) override; void visit(const SymbolVersionDefinition& svd) override; void visit(const Note& note) override; - void visit(const NoteDetails& details) override; - void visit(const AndroidNote& note) override; + void visit(const AndroidIdent& note) override; void visit(const NoteAbi& note) override; void visit(const CorePrPsInfo& pinfo) override; void visit(const CorePrStatus& pstatus) override; diff --git a/include/LIEF/Visitor.hpp b/include/LIEF/Visitor.hpp index 4dadb6bc25..613f15d1e8 100644 --- a/include/LIEF/Visitor.hpp +++ b/include/LIEF/Visitor.hpp @@ -131,7 +131,7 @@ LIEF_ELF_FORWARD(SymbolVersionAux) LIEF_ELF_FORWARD(SymbolVersionAuxRequirement) LIEF_ELF_FORWARD(Note) LIEF_ELF_FORWARD(NoteDetails) -LIEF_ELF_FORWARD(AndroidNote) +LIEF_ELF_FORWARD(AndroidIdent) LIEF_ELF_FORWARD(NoteAbi) LIEF_ELF_FORWARD(CorePrPsInfo) LIEF_ELF_FORWARD(CorePrStatus) @@ -269,7 +269,7 @@ class LIEF_API Visitor { LIEF_ELF_VISITABLE(SymbolVersionAuxRequirement) LIEF_ELF_VISITABLE(Note) LIEF_ELF_VISITABLE(NoteDetails) - LIEF_ELF_VISITABLE(AndroidNote) + LIEF_ELF_VISITABLE(AndroidIdent) LIEF_ELF_VISITABLE(NoteAbi) LIEF_ELF_VISITABLE(CorePrPsInfo) LIEF_ELF_VISITABLE(CorePrStatus) diff --git a/src/ELF/Binary.cpp b/src/ELF/Binary.cpp index dc96643d02..ab976c4705 100644 --- a/src/ELF/Binary.cpp +++ b/src/ELF/Binary.cpp @@ -309,16 +309,16 @@ void Binary::remove(const Note& note) { if (it_note == std::end(notes_)) { LIEF_WARN("Can't find the note with the type {}. It can't be removed!", - to_string(static_cast(note.type()))); + to_string(static_cast(note.type()))); return; } notes_.erase(it_note); } -void Binary::remove(NOTE_TYPES type) { +void Binary::remove(Note::TYPE type) { for (auto it = std::begin(notes_); it != std::end(notes_);) { std::unique_ptr& n = *it; - if (static_cast(n->type()) == type) { + if (n->type() == type) { n.reset(nullptr); it = notes_.erase(it); } else { @@ -1864,10 +1864,10 @@ Segment* Binary::get(SEGMENT_TYPES type) { return const_cast(static_cast(this)->get(type)); } -const Note* Binary::get(NOTE_TYPES type) const { +const Note* Binary::get(Note::TYPE type) const { const auto it_note = std::find_if(std::begin(notes_), std::end(notes_), [type] (const std::unique_ptr& note) { - return static_cast(note->type()) == type; + return note->type() == type; }); if (it_note == std::end(notes_)) { return nullptr; @@ -1877,7 +1877,7 @@ const Note* Binary::get(NOTE_TYPES type) const { } -Note* Binary::get(NOTE_TYPES type) { +Note* Binary::get(Note::TYPE type) { return const_cast(static_cast(this)->get(type)); } @@ -1902,7 +1902,7 @@ bool Binary::has(SEGMENT_TYPES type) const { return get(type) != nullptr; } -bool Binary::has(NOTE_TYPES type) const { +bool Binary::has(Note::TYPE type) const { return get(type) != nullptr; } @@ -1969,7 +1969,6 @@ Binary::it_notes Binary::notes() { return notes_; } - void Binary::accept(LIEF::Visitor& visitor) const { visitor.visit(*this); } @@ -3347,7 +3346,7 @@ Binary& Binary::operator-=(const Note& note) { return *this; } -Binary& Binary::operator-=(NOTE_TYPES type) { +Binary& Binary::operator-=(Note::TYPE type) { remove(type); return *this; } @@ -3370,11 +3369,11 @@ const DynamicEntry* Binary::operator[](DYNAMIC_TAGS tag) const { return get(tag); } -Note* Binary::operator[](NOTE_TYPES type) { +Note* Binary::operator[](Note::TYPE type) { return get(type); } -const Note* Binary::operator[](NOTE_TYPES type) const { +const Note* Binary::operator[](Note::TYPE type) const { return get(type); } diff --git a/src/ELF/Builder.cpp b/src/ELF/Builder.cpp index 4e0856e92f..70a5fa611b 100644 --- a/src/ELF/Builder.cpp +++ b/src/ELF/Builder.cpp @@ -26,7 +26,6 @@ #include "LIEF/ELF/Symbol.hpp" #include "LIEF/ELF/Note.hpp" -#include "notes_utils.hpp" #include "Builder.tcc" @@ -186,76 +185,54 @@ ok_error_t Builder::build_empty_symbol_gnuhash() { return ok(); } - - -ok_error_t Builder::build(const Note& note, std::set& sections) { - using value_t = typename note_to_section_map_t::value_type; - +ok_error_t Builder::update_note_section(const Note& note, + std::set& notes) +{ Segment* segment_note = binary_->get(SEGMENT_TYPES::PT_NOTE); if (segment_note == nullptr) { LIEF_ERR("Can't find the PT_NOTE segment"); return make_error_code(lief_errors::not_found); } - const auto& note_to_section_map = get_note_to_section(); - auto range_secname = note_to_section_map.equal_range(note.type()); - const bool known_section = (range_secname.first != range_secname.second); - - const auto it_section_name = std::find_if( - range_secname.first, range_secname.second, - [this] (value_t p) { - return binary_->has_section(p.second); - }); + auto res_secname = Note::type_to_section(note.type()); + if (!res_secname) { + LIEF_ERR("LIEF doesn't know the section name for note: '{}'", + to_string(note.type())); + return make_error_code(lief_errors::not_supported); + } - bool has_section = (it_section_name != range_secname.second); + Section* note_sec = binary_->get_section(*res_secname); + if (!note_sec) { + LIEF_ERR("Section {} not present", *res_secname); + return make_error_code(lief_errors::not_found); + } - std::string section_name; - if (has_section) { - section_name = it_section_name->second; - } else if (known_section) { - section_name = range_secname.first->second; - } else { - section_name = fmt::format(".note.{:x}", static_cast(note.type())); + const auto& offset_map = static_cast(layout_.get())->note_off_map(); + auto it_offset = offset_map.find(¬e); + if (it_offset == offset_map.end()) { + LIEF_ERR("Can't find offset for note '{}'", to_string(note.type())); + return make_error_code(lief_errors::not_found); } - const std::unordered_map& offset_map = reinterpret_cast(layout_.get())->note_off_map(); - const auto& it_offset = offset_map.find(¬e); + if (!notes.insert(¬e).second) { + LIEF_DEBUG("Note '{}' has already been processed", to_string(note.type())); + note_sec->virtual_address(0); + note_sec->size(note_sec->size() + note.size()); + return ok_t(); + } - // Link section and notes - if (binary_->has(note.type()) && has_section) { - if (it_offset == std::end(offset_map)) { - LIEF_ERR("Can't find {}", to_string(note.type())); - return make_error_code(lief_errors::not_found); - } - const size_t note_offset = it_offset->second; - Section* section = binary_->get_section(section_name); - if (section == nullptr) { - LIEF_ERR("Can't find section {}", section_name); - return make_error_code(lief_errors::not_found); - } - if (sections.insert(section).second) { - section->offset(segment_note->file_offset() + note_offset); - section->size(note.size()); - section->virtual_address(segment_note->virtual_address() + note_offset); - // Special process for GNU_PROPERTY: - // This kind of note has a dedicated segment while others don't - // Therefore, when relocating this note, we need - // to update the segment as well. - if (note.type() == NOTE_TYPES::NT_GNU_PROPERTY_TYPE_0 && - binary_->has(SEGMENT_TYPES::PT_GNU_PROPERTY)) - { - Segment* seg = binary_->get(SEGMENT_TYPES::PT_GNU_PROPERTY); - if (seg == nullptr) return ok(); // Should not append as it is checked by has(...) - - seg->file_offset(section->offset()); - seg->physical_size(section->size()); - seg->virtual_address(section->virtual_address()); - seg->physical_address(section->virtual_address()); - seg->virtual_size(section->size()); - } - } else /* We already handled this kind of note */ { - section->virtual_address(0); - section->size(section->size() + note.size()); + const uint64_t note_offset = it_offset->second; + note_sec->offset(segment_note->file_offset() + note_offset); + note_sec->size(note.size()); + note_sec->virtual_address(segment_note->virtual_address() + note_offset); + + if (note.type() == Note::TYPE::GNU_PROPERTY_TYPE_0) { + if (Segment* seg = binary_->get(SEGMENT_TYPES::PT_GNU_PROPERTY)) { + seg->file_offset(note_sec->offset()); + seg->physical_size(note_sec->size()); + seg->virtual_address(note_sec->virtual_address()); + seg->physical_address(note_sec->virtual_address()); + seg->virtual_size(note_sec->size()); } } return ok(); diff --git a/src/ELF/Builder.tcc b/src/ELF/Builder.tcc index d223408dd2..0db631873c 100644 --- a/src/ELF/Builder.tcc +++ b/src/ELF/Builder.tcc @@ -1720,22 +1720,16 @@ ok_error_t Builder::build_notes() { } // Clear the original content of the segment note_segment->content(std::vector(note_segment->physical_size(), 0)); - + // Write the cached note note_segment->content(static_cast(layout_.get())->raw_notes()); - //TODO: .note.netbds etc if (binary_->header().file_type() == E_TYPE::ET_CORE) { - LIEF_WARN("Building note for coredump is not supported yet"); - return make_error_code(lief_errors::not_supported); + return ok_t(); } - // Track the list of the sections we wrote - // NOTE(romain): it is only used by the function build() itself but - // to avoid creating an instance field, we create this - // variable in the scode of this function - std::set sections; - for (Note& note: binary_->notes()) { - build(note, sections); + std::set notes; + for (const Note& note: binary_->notes()) { + update_note_section(note, notes); } return ok(); } diff --git a/src/ELF/CMakeLists.txt b/src/ELF/CMakeLists.txt index 0e925729b3..7c75e91dc2 100644 --- a/src/ELF/CMakeLists.txt +++ b/src/ELF/CMakeLists.txt @@ -18,7 +18,6 @@ target_sources(LIB_LIEF PRIVATE Header.cpp Layout.cpp Note.cpp - NoteDetails.cpp Parser.cpp Parser.tcc Relocation.cpp @@ -33,7 +32,6 @@ target_sources(LIB_LIEF PRIVATE SymbolVersionRequirement.cpp SysvHash.cpp hash.cpp - note_utils.cpp utils.cpp json_api.cpp) diff --git a/src/ELF/EnumToString.cpp b/src/ELF/EnumToString.cpp index ea4ae69203..1fc9fea9b2 100644 --- a/src/ELF/EnumToString.cpp +++ b/src/ELF/EnumToString.cpp @@ -1293,68 +1293,6 @@ const char* to_string(DYNSYM_COUNT_METHODS e) { return it == enumStrings.end() ? "UNDEFINED" : it->second; } - -const char* to_string(NOTE_TYPES e) { - CONST_MAP(NOTE_TYPES, const char*, 9) enumStrings { - { NOTE_TYPES::NT_UNKNOWN, "UNKNOWN"}, - { NOTE_TYPES::NT_GNU_ABI_TAG, "ABI_TAG"}, - { NOTE_TYPES::NT_GNU_HWCAP, "HWCAP"}, - { NOTE_TYPES::NT_GNU_BUILD_ID, "BUILD_ID"}, - { NOTE_TYPES::NT_GNU_GOLD_VERSION, "GOLD_VERSION"}, - { NOTE_TYPES::NT_GNU_PROPERTY_TYPE_0, "PROPERTY_TYPE_0"}, - { NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_OPEN, "GNU_BUILD_ATTRIBUTE_OPEN"}, - { NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_FUNC, "GNU_BUILD_ATTRIBUTE_FUNC"}, - { NOTE_TYPES::NT_CRASHPAD, "CRASHPAD"}, - }; - - const auto it = enumStrings.find(e); - return it == enumStrings.end() ? "UNDEFINED" : it->second; -} - - -const char* to_string(NOTE_TYPES_CORE e) { - CONST_MAP(NOTE_TYPES_CORE, const char*, 17) enumStrings { - { NOTE_TYPES_CORE::NT_CORE_UNKNOWN, "UNKNOWN"}, - { NOTE_TYPES_CORE::NT_PRSTATUS, "PRSTATUS"}, - { NOTE_TYPES_CORE::NT_PRFPREG, "PRFPREG"}, - { NOTE_TYPES_CORE::NT_PRPSINFO, "PRPSINFO"}, - { NOTE_TYPES_CORE::NT_TASKSTRUCT, "TASKSTRUCT"}, - { NOTE_TYPES_CORE::NT_AUXV, "AUXV"}, - { NOTE_TYPES_CORE::NT_SIGINFO, "SIGINFO"}, - { NOTE_TYPES_CORE::NT_FILE, "FILE"}, - - { NOTE_TYPES_CORE::NT_ARM_VFP, "ARM_VFP"}, - { NOTE_TYPES_CORE::NT_ARM_TLS, "ARM_TLS"}, - { NOTE_TYPES_CORE::NT_ARM_HW_BREAK, "ARM_HW_BREAK"}, - { NOTE_TYPES_CORE::NT_ARM_HW_WATCH, "ARM_HW_WATCH"}, - { NOTE_TYPES_CORE::NT_ARM_SYSTEM_CALL, "ARM_SYSTEM_CALL"}, - { NOTE_TYPES_CORE::NT_ARM_SVE, "ARM_SVE"}, - - { NOTE_TYPES_CORE::NT_386_TLS, "I386_TLS"}, - { NOTE_TYPES_CORE::NT_386_IOPERM, "I386_IOPERM"}, - { NOTE_TYPES_CORE::NT_386_XSTATE, "I386_XSTATE"}, - }; - - const auto it = enumStrings.find(e); - return it == enumStrings.end() ? "UNKNOWN" : it->second; -} - - -const char* to_string(NOTE_ABIS e) { - CONST_MAP(NOTE_ABIS, const char*, 7) enumStrings { - { NOTE_ABIS::ELF_NOTE_UNKNOWN, "UNKNOWN"}, - { NOTE_ABIS::ELF_NOTE_OS_LINUX, "LINUX"}, - { NOTE_ABIS::ELF_NOTE_OS_GNU, "GNU"}, - { NOTE_ABIS::ELF_NOTE_OS_SOLARIS2, "SOLARIS2"}, - { NOTE_ABIS::ELF_NOTE_OS_FREEBSD, "FREEBSD"}, - { NOTE_ABIS::ELF_NOTE_OS_NETBSD, "NETBSD"}, - { NOTE_ABIS::ELF_NOTE_OS_SYLLABLE, "SYLLABLE"}, - }; - - const auto it = enumStrings.find(e); - return it == enumStrings.end() ? "UNDEFINED" : it->second; -} - const char* to_string(RELOCATION_PURPOSES e) { CONST_MAP(RELOCATION_PURPOSES, const char*, 4) enumStrings { { RELOCATION_PURPOSES::RELOC_PURPOSE_NONE, "NONE"}, @@ -1579,47 +1517,6 @@ const char* to_string(ELF_SEGMENT_FLAGS e) { } -const char* to_string(AUX_TYPE e) { - CONST_MAP(AUX_TYPE, const char*, 32) enum_strings { - { AUX_TYPE::AT_NULL, "NULL" }, - { AUX_TYPE::AT_IGNORE, "IGNORE" }, - { AUX_TYPE::AT_EXECFD, "EXECFD" }, - { AUX_TYPE::AT_PHDR, "PHDR" }, - { AUX_TYPE::AT_PHENT, "PHENT" }, - { AUX_TYPE::AT_PHNUM, "PHNUM" }, - { AUX_TYPE::AT_PAGESZ, "PAGESZ" }, - { AUX_TYPE::AT_BASE, "BASE" }, - { AUX_TYPE::AT_FLAGS, "FLAGS" }, - { AUX_TYPE::AT_ENTRY, "ENTRY" }, - { AUX_TYPE::AT_NOTELF, "NOTELF" }, - { AUX_TYPE::AT_UID, "UID" }, - { AUX_TYPE::AT_EUID, "EUID" }, - { AUX_TYPE::AT_GID, "GID" }, - { AUX_TYPE::AT_EGID, "EGID" }, - { AUX_TYPE::AT_CLKTCK, "CKLTCK" }, - { AUX_TYPE::AT_PLATFORM, "PLATFORM" }, - { AUX_TYPE::AT_HWCAP, "HWCAP" }, - { AUX_TYPE::AT_HWCAP2, "HWCAP2" }, - { AUX_TYPE::AT_FPUCW, "FPUCW" }, - { AUX_TYPE::AT_DCACHEBSIZE, "DCACHEBSIZE" }, - { AUX_TYPE::AT_ICACHEBSIZE, "ICACHEBSIZE" }, - { AUX_TYPE::AT_UCACHEBSIZE, "UCACHEBSIZE" }, - { AUX_TYPE::AT_IGNOREPPC, "IGNOREPPC" }, - { AUX_TYPE::AT_SECURE, "SECURE" }, - { AUX_TYPE::AT_BASE_PLATFORM, "BASE_PLATFORM" }, - { AUX_TYPE::AT_RANDOM, "RANDOM" }, - { AUX_TYPE::AT_EXECFN, "EXECFN" }, - { AUX_TYPE::AT_SYSINFO, "SYSINFO" }, - { AUX_TYPE::AT_SYSINFO_EHDR, "SYSINFO_EHDR" }, - { AUX_TYPE::AT_L1I_CACHESHAPE, "L1I_CACHESHAPE" }, - { AUX_TYPE::AT_L1D_CACHESHAPE, "L1D_CACHESHAPE" }, - }; - - const auto it = enum_strings.find(e); - return it == enum_strings.end() ? "UNDEFINED" : it->second; -} - - const char* to_string(ELF_SYMBOL_VISIBILITY e) { CONST_MAP(ELF_SYMBOL_VISIBILITY, const char*, 4) enum_strings { { ELF_SYMBOL_VISIBILITY::STV_DEFAULT, "DEFAULT" }, @@ -1632,119 +1529,5 @@ const char* to_string(ELF_SYMBOL_VISIBILITY e) { return it == enum_strings.end() ? "UNDEFINED" : it->second; } - -const char* to_string(CorePrStatus::REGISTERS e) { - CONST_MAP(CorePrStatus::REGISTERS, const char*, 90) enum_strings { - { CorePrStatus::REGISTERS::UNKNOWN, "UNKNOWN" }, - - // X86 - // === - { CorePrStatus::REGISTERS::X86_EBX, "X86_EBX" }, - { CorePrStatus::REGISTERS::X86_ECX, "X86_ECX" }, - { CorePrStatus::REGISTERS::X86_EDX, "X86_EDX" }, - { CorePrStatus::REGISTERS::X86_ESI, "X86_ESI" }, - { CorePrStatus::REGISTERS::X86_EDI, "X86_EDI" }, - { CorePrStatus::REGISTERS::X86_EBP, "X86_EBP" }, - { CorePrStatus::REGISTERS::X86_EAX, "X86_EAX" }, - { CorePrStatus::REGISTERS::X86_DS, "X86_DS" }, - { CorePrStatus::REGISTERS::X86_ES, "X86_ES" }, - { CorePrStatus::REGISTERS::X86_FS, "X86_FS" }, - { CorePrStatus::REGISTERS::X86_GS, "X86_GS" }, - { CorePrStatus::REGISTERS::X86__, "X86__" }, - { CorePrStatus::REGISTERS::X86_EIP, "X86_EIP" }, - { CorePrStatus::REGISTERS::X86_CS, "X86_CS" }, - { CorePrStatus::REGISTERS::X86_EFLAGS, "X86_EFLAGS" }, - { CorePrStatus::REGISTERS::X86_ESP, "X86_ESP" }, - { CorePrStatus::REGISTERS::X86_SS, "X86_SS" }, - - - { CorePrStatus::REGISTERS::X86_64_R15, "X86_64_R15" }, - { CorePrStatus::REGISTERS::X86_64_R14, "X86_64_R14" }, - { CorePrStatus::REGISTERS::X86_64_R13, "X86_64_R13" }, - { CorePrStatus::REGISTERS::X86_64_R12, "X86_64_R12" }, - { CorePrStatus::REGISTERS::X86_64_RBP, "X86_64_RBP" }, - { CorePrStatus::REGISTERS::X86_64_RBX, "X86_64_RBX" }, - { CorePrStatus::REGISTERS::X86_64_R11, "X86_64_R11" }, - { CorePrStatus::REGISTERS::X86_64_R10, "X86_64_R10" }, - { CorePrStatus::REGISTERS::X86_64_R9, "X86_64_R9" }, - { CorePrStatus::REGISTERS::X86_64_R8, "X86_64_R8" }, - { CorePrStatus::REGISTERS::X86_64_RAX, "X86_64_RAX" }, - { CorePrStatus::REGISTERS::X86_64_RCX, "X86_64_RCX" }, - { CorePrStatus::REGISTERS::X86_64_RDX, "X86_64_RDX" }, - { CorePrStatus::REGISTERS::X86_64_RSI, "X86_64_RSI" }, - { CorePrStatus::REGISTERS::X86_64_RDI, "X86_64_RDI" }, - { CorePrStatus::REGISTERS::X86_64__, "X86_64__" }, - { CorePrStatus::REGISTERS::X86_64_RIP, "X86_64_RIP" }, - { CorePrStatus::REGISTERS::X86_64_CS, "X86_64_CS" }, - { CorePrStatus::REGISTERS::X86_64_EFLAGS, "X86_64_EFLAGS" }, - { CorePrStatus::REGISTERS::X86_64_RSP, "X86_64_RSP" }, - { CorePrStatus::REGISTERS::X86_64_SS, "X86_64_SS" }, - - { CorePrStatus::REGISTERS::ARM_R0, "ARM_R0" }, - { CorePrStatus::REGISTERS::ARM_R1, "ARM_R1" }, - { CorePrStatus::REGISTERS::ARM_R2, "ARM_R2" }, - { CorePrStatus::REGISTERS::ARM_R3, "ARM_R3" }, - { CorePrStatus::REGISTERS::ARM_R4, "ARM_R4" }, - { CorePrStatus::REGISTERS::ARM_R5, "ARM_R5" }, - { CorePrStatus::REGISTERS::ARM_R6, "ARM_R6" }, - { CorePrStatus::REGISTERS::ARM_R7, "ARM_R7" }, - { CorePrStatus::REGISTERS::ARM_R8, "ARM_R8" }, - { CorePrStatus::REGISTERS::ARM_R9, "ARM_R9" }, - { CorePrStatus::REGISTERS::ARM_R10, "ARM_R10" }, - { CorePrStatus::REGISTERS::ARM_R11, "ARM_R11" }, - { CorePrStatus::REGISTERS::ARM_R12, "ARM_R12" }, - { CorePrStatus::REGISTERS::ARM_R13, "ARM_R13" }, - { CorePrStatus::REGISTERS::ARM_R14, "ARM_R14" }, - { CorePrStatus::REGISTERS::ARM_R15, "ARM_R15" }, - { CorePrStatus::REGISTERS::ARM_CPSR, "ARM_CPSR" }, - - { CorePrStatus::REGISTERS::AARCH64_X0, "AARCH64_X0" }, - { CorePrStatus::REGISTERS::AARCH64_X1, "AARCH64_X1" }, - { CorePrStatus::REGISTERS::AARCH64_X2, "AARCH64_X2" }, - { CorePrStatus::REGISTERS::AARCH64_X3, "AARCH64_X3" }, - { CorePrStatus::REGISTERS::AARCH64_X4, "AARCH64_X4" }, - { CorePrStatus::REGISTERS::AARCH64_X5, "AARCH64_X5" }, - { CorePrStatus::REGISTERS::AARCH64_X6, "AARCH64_X6" }, - { CorePrStatus::REGISTERS::AARCH64_X7, "AARCH64_X7" }, - { CorePrStatus::REGISTERS::AARCH64_X8, "AARCH64_X8" }, - { CorePrStatus::REGISTERS::AARCH64_X9, "AARCH64_X9" }, - { CorePrStatus::REGISTERS::AARCH64_X10, "AARCH64_X10" }, - { CorePrStatus::REGISTERS::AARCH64_X11, "AARCH64_X11" }, - { CorePrStatus::REGISTERS::AARCH64_X12, "AARCH64_X12" }, - { CorePrStatus::REGISTERS::AARCH64_X13, "AARCH64_X13" }, - { CorePrStatus::REGISTERS::AARCH64_X14, "AARCH64_X14" }, - { CorePrStatus::REGISTERS::AARCH64_X15, "AARCH64_X15" }, - { CorePrStatus::REGISTERS::AARCH64_X16, "AARCH64_X16" }, - { CorePrStatus::REGISTERS::AARCH64_X17, "AARCH64_X17" }, - { CorePrStatus::REGISTERS::AARCH64_X18, "AARCH64_X18" }, - { CorePrStatus::REGISTERS::AARCH64_X19, "AARCH64_X19" }, - { CorePrStatus::REGISTERS::AARCH64_X20, "AARCH64_X20" }, - { CorePrStatus::REGISTERS::AARCH64_X21, "AARCH64_X21" }, - { CorePrStatus::REGISTERS::AARCH64_X22, "AARCH64_X22" }, - { CorePrStatus::REGISTERS::AARCH64_X23, "AARCH64_X23" }, - { CorePrStatus::REGISTERS::AARCH64_X24, "AARCH64_X24" }, - { CorePrStatus::REGISTERS::AARCH64_X25, "AARCH64_X25" }, - { CorePrStatus::REGISTERS::AARCH64_X26, "AARCH64_X26" }, - { CorePrStatus::REGISTERS::AARCH64_X27, "AARCH64_X27" }, - { CorePrStatus::REGISTERS::AARCH64_X28, "AARCH64_X28" }, - { CorePrStatus::REGISTERS::AARCH64_X29, "AARCH64_X29" }, - { CorePrStatus::REGISTERS::AARCH64_X30, "AARCH64_X30" }, - { CorePrStatus::REGISTERS::AARCH64_X31, "AARCH64_X31" }, - { CorePrStatus::REGISTERS::AARCH64_PC, "AARCH64_PC" }, - { CorePrStatus::REGISTERS::AARCH64__, "AARCH64__" }, - - }; - - const auto it = enum_strings.find(e); - return it == enum_strings.end() ? "UNKNOWN" : it->second; -} - - - - - } // namespace ELF } // namespace LIEF - - - diff --git a/src/ELF/ExeLayout.hpp b/src/ELF/ExeLayout.hpp index 0015fdacad..8c390107e5 100644 --- a/src/ELF/ExeLayout.hpp +++ b/src/ELF/ExeLayout.hpp @@ -43,15 +43,12 @@ #include "ELF/Structures.hpp" #include "internal_utils.hpp" -#include "notes_utils.hpp" #include "logging.hpp" #include "Layout.hpp" namespace LIEF { namespace ELF { -class Note; - //! Compute the size and the offset of the elements //! needed to rebuild the ELF file. class LIEF_LOCAL ExeLayout : public Layout { @@ -215,8 +212,8 @@ class LIEF_LOCAL ExeLayout : public Layout { raw_notes.write_conv(descsz); // Then the note's type - const NOTE_TYPES type = note.type(); - raw_notes.write_conv(static_cast(type)); + const uint32_t type = note.original_type(); + raw_notes.write_conv(type); // Then we write the note's name const std::string& name = note.name(); @@ -1278,65 +1275,45 @@ class LIEF_LOCAL ExeLayout : public Layout { } // Process note sections - const Segment* segment_note = binary_->get(SEGMENT_TYPES::PT_NOTE); - if (segment_note != nullptr) { - using value_t = typename note_to_section_map_t::value_type; - const note_to_section_map_t& note_to_section_map = get_note_to_section(); + if (const Segment* segment_note = binary_->get(SEGMENT_TYPES::PT_NOTE)) { + //using value_t = typename note_to_section_map_t::value_type; + //const note_to_section_map_t& note_to_section_map = get_note_to_section(); for (const Note& note : binary_->notes()) { - auto range_secname = note_to_section_map.equal_range(note.type()); - const bool known_section = (range_secname.first != range_secname.second); - - const NOTE_TYPES type = note.type(); - - const auto it_section_name = std::find_if( - range_secname.first, range_secname.second, - [this] (value_t p) { - return binary_->has_section(p.second); - }); - - bool has_section = (it_section_name != range_secname.second); - + auto section_res = Note::note_to_section(note); const auto& it_offset = notes_off_map_.find(¬e); - std::string section_name; - if (has_section) { - section_name = it_section_name->second; - } else if (known_section) { - section_name = range_secname.first->second; - } else { - section_name = fmt::format(".note.{:x}", static_cast(type)); + if (!section_res) { + LIEF_ERR("Note type: {} ('{}') is not supported", + to_string(note.type()), note.name()); + continue; } - // If the binary does not have the note "type" - // but still have the section, then remove the section - if (!binary_->has(note.type()) && has_section) { - binary_->remove_section(section_name, true); - } + const char* sec_name = *section_res; // If the binary has the note type but does not have // the section (likly because the user added the note manually) // then, create the section - if (binary_->has(type) && !has_section) { + if (const Section* nsec = binary_->get_section(*section_res); + nsec == nullptr) + { if (it_offset == std::end(notes_off_map_)) { - LIEF_ERR("Can't find {}", to_string(type)); - } else { - const size_t note_offset = it_offset->second; - - const Note& note = *binary_->get(type); - - Section section{section_name, ELF_SECTION_TYPES::SHT_NOTE}; - section += ELF_SECTION_FLAGS::SHF_ALLOC; - - Section* section_added = binary_->add(section, /*loaded */ false); - if (section_added == nullptr) { - LIEF_ERR("Can't add SHT_NOTE section"); - return make_error_code(lief_errors::build_error); - } - section_added->offset(segment_note->file_offset() + note_offset); - section_added->size(note.size()); - section.virtual_address(segment_note->virtual_address() + note_offset); - section_added->alignment(4); + LIEF_ERR("Can't find raw data for note: '{}'", to_string(note.type())); + continue; + } + const size_t note_offset = it_offset->second; + + Section section{sec_name, ELF_SECTION_TYPES::SHT_NOTE}; + section += ELF_SECTION_FLAGS::SHF_ALLOC; + + Section* section_added = binary_->add(section, /*loaded */ false); + if (section_added == nullptr) { + LIEF_ERR("Can't add SHT_NOTE section"); + return make_error_code(lief_errors::build_error); } + section_added->offset(segment_note->file_offset() + note_offset); + section_added->size(note.size()); + section.virtual_address(segment_note->virtual_address() + note_offset); + section_added->alignment(4); } } } diff --git a/src/ELF/Layout.hpp b/src/ELF/Layout.hpp index fe51f574cb..bdab9c1bda 100644 --- a/src/ELF/Layout.hpp +++ b/src/ELF/Layout.hpp @@ -28,27 +28,27 @@ class Layout { public: Layout(Binary& bin); - inline virtual const std::unordered_map& shstr_map() const { + virtual const std::unordered_map& shstr_map() const { return shstr_name_map_; } - inline virtual const std::unordered_map& strtab_map() const { + virtual const std::unordered_map& strtab_map() const { return strtab_name_map_; } - inline virtual const std::vector& raw_shstr() const { + virtual const std::vector& raw_shstr() const { return raw_shstrtab_; } - inline virtual const std::vector& raw_strtab() const { + virtual const std::vector& raw_strtab() const { return raw_strtab_; } - inline void set_strtab_section(Section& section) { + void set_strtab_section(Section& section) { strtab_section_ = §ion; } - inline void set_dyn_sym_idx(int32_t val) { + void set_dyn_sym_idx(int32_t val) { new_symndx_ = val; } diff --git a/src/ELF/Note.cpp b/src/ELF/Note.cpp index 0ea74a0281..33f7ed9f72 100644 --- a/src/ELF/Note.cpp +++ b/src/ELF/Note.cpp @@ -20,204 +20,554 @@ #include #include - #include "LIEF/utils.hpp" - #include "LIEF/ELF/hash.hpp" - #include "LIEF/ELF/EnumToString.hpp" - #include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails.hpp" -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" #include "LIEF/ELF/NoteDetails/NoteAbi.hpp" -#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" -#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" #include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" +#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" +#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" #include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp" +#include "LIEF/iostream.hpp" +#include "LIEF/BinaryStream/BinaryStream.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" + +#include "frozen.hpp" +#include "logging.hpp" +#include "internal_utils.hpp" + +#define IMPL_READ_AT(T) \ + template result Note::read_at(size_t) const; + +#define IMPL_WRITE_AT(T) \ + template ok_error_t Note::write_at(size_t offset, const T& value); namespace LIEF { namespace ELF { -Note::~Note() = default; +static constexpr auto NT_CORE_NAME = "CORE"; +static constexpr auto NT_GNU_NAME = "GNU"; +static constexpr auto NT_ANDROID_NAME = "Android"; +static constexpr auto NT_LINUX_NAME = "LINUX"; +static constexpr auto NT_GO_NAME = "Go"; +static constexpr auto NT_STAPSDT_NAME = "stapsdt"; +static constexpr auto NT_CRASHPAD_NAME = "Crashpad"; + +CONST_MAP_ALT GNU_TYPES { + std::pair(1, Note::TYPE::GNU_ABI_TAG), + std::pair(2, Note::TYPE::GNU_HWCAP), + std::pair(3, Note::TYPE::GNU_BUILD_ID), + std::pair(4, Note::TYPE::GNU_GOLD_VERSION), + std::pair(5, Note::TYPE::GNU_PROPERTY_TYPE_0), +}; + +CONST_MAP_ALT GENERIC_TYPES { + std::pair(0x100, Note::TYPE::GNU_BUILD_ATTRIBUTE_OPEN), + std::pair(0x101, Note::TYPE::GNU_BUILD_ATTRIBUTE_FUNC), +}; + +/* Core note types. */ +CONST_MAP_ALT CORE_TYPES { + std::pair(1, Note::TYPE::CORE_PRSTATUS), + std::pair(2, Note::TYPE::CORE_FPREGSET), + std::pair(3, Note::TYPE::CORE_PRPSINFO), + std::pair(4, Note::TYPE::CORE_TASKSTRUCT), + std::pair(6, Note::TYPE::CORE_AUXV), + std::pair(10, Note::TYPE::CORE_PSTATUS), + std::pair(12, Note::TYPE::CORE_FPREGS), + std::pair(13, Note::TYPE::CORE_PSINFO), + std::pair(16, Note::TYPE::CORE_LWPSTATUS), + std::pair(17, Note::TYPE::CORE_LWPSINFO), + std::pair(18, Note::TYPE::CORE_WIN32PSTATUS), + std::pair(0x53494749, Note::TYPE::CORE_SIGINFO), + std::pair(0x46e62b7f, Note::TYPE::CORE_PRXFPREG), + std::pair(0x46494c45, Note::TYPE::CORE_FILE), +}; + +CONST_MAP_ALT CORE_ARM_YPES { + std::pair(0x400, Note::TYPE::CORE_ARM_VFP), + std::pair(0x401, Note::TYPE::CORE_ARM_TLS), + std::pair(0x402, Note::TYPE::CORE_ARM_HW_BREAK), + std::pair(0x403, Note::TYPE::CORE_ARM_HW_WATCH), + std::pair(0x404, Note::TYPE::CORE_ARM_SYSTEM_CALL), + std::pair(0x405, Note::TYPE::CORE_ARM_SVE), + std::pair(0x406, Note::TYPE::CORE_ARM_PAC_MASK), + std::pair(0x407, Note::TYPE::CORE_ARM_PACA_KEYS), + std::pair(0x408, Note::TYPE::CORE_ARM_PACG_KEYS), + std::pair(0x409, Note::TYPE::CORE_TAGGED_ADDR_CTRL), + std::pair(0x40a, Note::TYPE::CORE_PAC_ENABLED_KEYS), +}; + +CONST_MAP_ALT CORE_X86_TYPES { + std::pair(0x200, Note::TYPE::CORE_X86_TLS), + std::pair(0x201, Note::TYPE::CORE_X86_IOPERM), + std::pair(0x202, Note::TYPE::CORE_X86_XSTATE), + std::pair(0x203, Note::TYPE::CORE_X86_CET), +}; + + +/* Android notes */ +CONST_MAP_ALT ANDROID_TYPES { + std::pair(1, Note::TYPE::ANDROID_IDENT), + std::pair(3, Note::TYPE::ANDROID_KUSER), + std::pair(4, Note::TYPE::ANDROID_MEMTAG), +}; + +/* Go types. */ +CONST_MAP_ALT GO_TYPES { + std::pair(4, Note::TYPE::GO_BUILDID), +}; + +/* Stapsdt types. */ +CONST_MAP_ALT STAPSDT_TYPES { + std::pair(3, Note::TYPE::STAPSDT), +}; + +/* Crashpad types. */ +CONST_MAP_ALT CRASHPAD_TYPES { + std::pair(0x4f464e49, Note::TYPE::CRASHPAD), +}; + +static inline std::string strip_zero(const std::string& name) { + return name.c_str(); +} -Note& Note::operator=(Note other) { - swap(other); - return *this; +result Note::type_to_section(TYPE type) { + CONST_MAP_ALT TYPE2SECTION { + std::pair(TYPE::GNU_ABI_TAG, ".note.ABI-tag"), + std::pair(TYPE::GNU_HWCAP, ".note.gnu.hwcap"), + std::pair(TYPE::GNU_BUILD_ID, ".note.gnu.build-id"), + std::pair(TYPE::GNU_GOLD_VERSION, ".note.gnu.gold-version"), + std::pair(TYPE::GNU_PROPERTY_TYPE_0, ".note.gnu.property"), + std::pair(TYPE::GNU_BUILD_ATTRIBUTE_OPEN, ".gnu.build.attributes"), + std::pair(TYPE::GNU_BUILD_ATTRIBUTE_FUNC, ".gnu.build.attributes"), + + std::pair(TYPE::STAPSDT, ".note.stapsdt"), + std::pair(TYPE::CRASHPAD, ".note.crashpad.info"), + std::pair(TYPE::ANDROID_IDENT, ".note.android.ident"), + std::pair(TYPE::GO_BUILDID, ".note.go.buildid"), + }; + + if (auto it = TYPE2SECTION.find(type); it != TYPE2SECTION.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); } -Note::Note(const Note& other): - Object(other), - binary_(other.binary_), - name_(other.name_), - type_(other.type_), - description_(other.description_) -{ - const auto& details = other.details_; - details_ = std::make_pair(details.first, std::unique_ptr{details.second->clone()}); +inline result raw_type(const std::string& name, Note::TYPE type) { + std::string norm_name = strip_zero(name); + + if (norm_name == NT_CORE_NAME) { + for (const auto& [nt, ntype] : CORE_TYPES) { + if (ntype == type) { + return nt; + } + } + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_LINUX_NAME) { + for (const auto& [nt, ntype] : CORE_ARM_YPES) { + if (ntype == type) { + return nt; + } + } + for (const auto& [nt, ntype] : CORE_X86_TYPES) { + if (ntype == type) { + return nt; + } + } + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_ANDROID_NAME) { + for (const auto& [nt, ntype] : ANDROID_TYPES) { + if (ntype == type) { + return nt; + } + } + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_GNU_NAME) { + for (const auto& [nt, ntype] : GNU_TYPES) { + if (ntype == type) { + return nt; + } + } + + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_GO_NAME) { + for (const auto& [nt, ntype] : GO_TYPES) { + if (ntype == type) { + return nt; + } + } + + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_STAPSDT_NAME) { + for (const auto& [nt, ntype] : STAPSDT_TYPES) { + if (ntype == type) { + return nt; + } + } + return make_error_code(lief_errors::not_found); + } + + if (norm_name == NT_CRASHPAD_NAME) { + for (const auto& [nt, ntype] : CRASHPAD_TYPES) { + if (ntype == type) { + return nt; + } + } + + return make_error_code(lief_errors::not_found); + } + + for (const auto& [nt, ntype] : GENERIC_TYPES) { + if (ntype == type) { + return nt; + } + } + + return make_error_code(lief_errors::not_found); } -void Note::swap(Note& other) { - std::swap(binary_, other.binary_); - std::swap(name_, other.name_); - std::swap(type_, other.type_); - std::swap(description_, other.description_); - std::swap(details_, other.details_); + + +result Note::type_owner(Note::TYPE type) { + CONST_MAP_ALT TYPE2OWNER { + std::pair(TYPE::GNU_ABI_TAG ,NT_GNU_NAME), + std::pair(TYPE::GNU_HWCAP ,NT_GNU_NAME), + std::pair(TYPE::GNU_BUILD_ID ,NT_GNU_NAME), + std::pair(TYPE::GNU_GOLD_VERSION ,NT_GNU_NAME), + std::pair(TYPE::GNU_PROPERTY_TYPE_0 ,NT_GNU_NAME), + std::pair(TYPE::CORE_PRSTATUS ,NT_CORE_NAME), + std::pair(TYPE::CORE_FPREGSET ,NT_CORE_NAME), + std::pair(TYPE::CORE_PRPSINFO ,NT_CORE_NAME), + std::pair(TYPE::CORE_TASKSTRUCT ,NT_CORE_NAME), + std::pair(TYPE::CORE_AUXV ,NT_CORE_NAME), + std::pair(TYPE::CORE_PSTATUS ,NT_CORE_NAME), + std::pair(TYPE::CORE_FPREGS ,NT_CORE_NAME), + std::pair(TYPE::CORE_PSINFO ,NT_CORE_NAME), + std::pair(TYPE::CORE_LWPSTATUS ,NT_CORE_NAME), + std::pair(TYPE::CORE_LWPSINFO ,NT_CORE_NAME), + std::pair(TYPE::CORE_WIN32PSTATUS ,NT_CORE_NAME), + std::pair(TYPE::CORE_FILE ,NT_CORE_NAME), + std::pair(TYPE::CORE_PRXFPREG ,NT_CORE_NAME), + std::pair(TYPE::CORE_SIGINFO ,NT_CORE_NAME), + std::pair(TYPE::CORE_ARM_VFP ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_TLS ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_HW_BREAK ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_HW_WATCH ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_SYSTEM_CALL ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_SVE ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_PAC_MASK ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_PACA_KEYS ,NT_LINUX_NAME), + std::pair(TYPE::CORE_ARM_PACG_KEYS ,NT_LINUX_NAME), + std::pair(TYPE::CORE_TAGGED_ADDR_CTRL ,NT_LINUX_NAME), + std::pair(TYPE::CORE_PAC_ENABLED_KEYS ,NT_LINUX_NAME), + std::pair(TYPE::CORE_X86_TLS ,NT_LINUX_NAME), + std::pair(TYPE::CORE_X86_IOPERM ,NT_LINUX_NAME), + std::pair(TYPE::CORE_X86_XSTATE ,NT_LINUX_NAME), + std::pair(TYPE::CORE_X86_CET ,NT_LINUX_NAME), + std::pair(TYPE::ANDROID_MEMTAG ,NT_ANDROID_NAME), + std::pair(TYPE::ANDROID_KUSER ,NT_ANDROID_NAME), + std::pair(TYPE::ANDROID_IDENT ,NT_ANDROID_NAME), + std::pair(TYPE::GO_BUILDID ,NT_GO_NAME), + std::pair(TYPE::STAPSDT ,NT_STAPSDT_NAME), + std::pair(TYPE::CRASHPAD ,NT_CRASHPAD_NAME), + }; + + if (auto it = TYPE2OWNER.find(type); it != TYPE2OWNER.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); } -Note::Note() : - type_{NOTE_TYPES::NT_UNKNOWN}, - details_{std::make_pair(NOTE_TYPES::NT_UNKNOWN, std::make_unique())} -{} - -Note::Note(std::string name, uint32_t type, description_t description, Binary* binary): - binary_{binary}, - name_{std::move(name)}, - type_{static_cast(type)}, - description_{std::move(description)}, - details_{std::make_pair(NOTE_TYPES::NT_UNKNOWN, std::make_unique())} -{} - -Note::Note(const std::string& name, NOTE_TYPES type, const description_t& description, Binary* binary): - Note::Note{name, static_cast(type), description, binary} -{} - -Note::Note(const std::string& name, NOTE_TYPES_CORE type, const description_t& description, Binary* binary): - Note::Note{name, static_cast(type), description, binary} + +result Note::convert_type(E_TYPE ftype, uint32_t type, + const std::string& name) { - is_core_ = true; - details(); -} + std::string norm_name = strip_zero(name); + + if (ftype == E_TYPE::ET_CORE) { + if (norm_name == NT_CORE_NAME) { + if (auto it = CORE_TYPES.find(type); it != CORE_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } + if (norm_name == NT_LINUX_NAME) { + if (auto it = CORE_ARM_YPES.find(type); it != CORE_ARM_YPES.end()) { + return it->second; + } + if (auto it = CORE_X86_TYPES.find(type); it != CORE_X86_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } + return make_error_code(lief_errors::not_found); + } -const std::string& Note::name() const { - return name_; -} + if (norm_name == NT_ANDROID_NAME) { + if (auto it = ANDROID_TYPES.find(type); it != ANDROID_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } -NOTE_TYPES Note::type() const { - return type_; -} + if (norm_name == NT_GNU_NAME) { + if (auto it = GNU_TYPES.find(type); it != GNU_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } -NOTE_TYPES_CORE Note::type_core() const { - return static_cast(type_); -} + if (norm_name == NT_GO_NAME) { + if (auto it = GO_TYPES.find(type); it != GO_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } -const Note::description_t& Note::description() const { - return description_; -} + if (norm_name == NT_STAPSDT_NAME) { + if (auto it = STAPSDT_TYPES.find(type); it != STAPSDT_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } -Note::description_t& Note::description() { - return description_; -} + if (norm_name == NT_CRASHPAD_NAME) { + if (auto it = CRASHPAD_TYPES.find(type); it != CRASHPAD_TYPES.end()) { + return it->second; + } + return make_error_code(lief_errors::not_found); + } -bool Note::is_core() const { - return is_core_; + // Generic types + if (auto it = GENERIC_TYPES.find(type); it != GENERIC_TYPES.end()) { + return it->second; + } + + return make_error_code(lief_errors::not_found); } +std::unique_ptr +Note::create(BinaryStream& stream, E_TYPE ftype, ARCH arch, ELF_CLASS cls) { + static constexpr uint32_t MAX_NOTE_DESCRIPTION = 1_MB; + const size_t pos = stream.pos(); + auto res_namesz = stream.read_conv(); + if (!res_namesz) { + return nullptr; + } -bool Note::is_android() const { - return name() == AndroidNote::NAME; -} + const auto namesz = *res_namesz; + LIEF_DEBUG("[0x{:06x}] Name size: 0x{:x}", pos, namesz); -const NoteDetails& Note::details() const { - return *(details_.second); -} + auto res_descz = stream.read_conv(); + if (!res_descz) { + return nullptr; + } + + uint32_t descsz = std::min(*res_descz, MAX_NOTE_DESCRIPTION); + LIEF_DEBUG("Description size: 0x{:x}", descsz); -NoteDetails& Note::details() { - NOTE_TYPES type = this->type(); - auto& dcache = details_; + auto res_type = stream.read_conv(); + if (!res_type) { + return nullptr; + } + + uint32_t type = *res_type; + LIEF_DEBUG("Type: 0x{:x}", type); - // already in cache - if (dcache.first == type) { - return *(dcache.second); + if (namesz == 0) { // System reserves + return nullptr; } + std::vector name_buffer(namesz, 0); + if (!stream.read_data(name_buffer, namesz)) { + LIEF_ERR("Can't read note name"); + return nullptr; + } + + std::string name(reinterpret_cast(name_buffer.data()), name_buffer.size()); + LIEF_DEBUG("Name: {}", name); - std::unique_ptr details = nullptr; + stream.align(sizeof(uint32_t)); - if (is_android()) { - details = std::make_unique(AndroidNote::make(*this)); + std::vector description; + if (descsz > 0) { + const size_t nb_chunks = (descsz - 1) / sizeof(uint32_t) + 1; + description.reserve(nb_chunks); + for (size_t i = 0; i < nb_chunks; ++i) { + if (const auto chunk = stream.read_conv()) { + description.push_back(*chunk); + } else { + break; + } + } + stream.align(sizeof(uint32_t)); + } + std::vector desc_bytes; + if (!description.empty()) { + const auto* start_ptr = reinterpret_cast(description.data()); + desc_bytes = {start_ptr, + start_ptr + description.size() * sizeof(uint32_t)}; } - if (is_core()) { - auto type_core = static_cast(type); + return create(name, type, std::move(desc_bytes), ftype, arch, cls); +} - switch(type_core) { - case NOTE_TYPES_CORE::NT_PRPSINFO: - { - details = std::make_unique(CorePrPsInfo::make(*this)); - break; - } +std::unique_ptr +Note::create(const std::string& name, Note::TYPE ntype, Note::description_t description, + ARCH arch, ELF_CLASS cls) +{ + std::string owner; + auto res_owner = type_owner(ntype); + if (res_owner) { + if (!name.empty() && strip_zero(name) != *res_owner) { + LIEF_WARN("The note owner of '{}' should be '{}' while '{}' is provided", + to_string(ntype), *res_owner, name); + } + owner = std::move(*res_owner); + } else { + if (!name.empty()) { + owner = name; + } else { + LIEF_ERR("Note owner name can't be resolved!"); + return nullptr; + } + } - case NOTE_TYPES_CORE::NT_FILE: - { - details = std::make_unique(CoreFile::make(*this)); - break; - } + auto int_type = raw_type(owner, ntype); + if (!int_type) { + LIEF_ERR("Can't determine the raw type of note '{}' for the owner '{}'", + to_string(ntype), owner); + return nullptr; + } + std::string norm_name = owner; - case NOTE_TYPES_CORE::NT_PRSTATUS: - { - details = std::make_unique(CorePrStatus::make(*this)); - break; + // The name of these types have a special meaning + if (ntype != Note::TYPE::GNU_BUILD_ATTRIBUTE_FUNC && + ntype != Note::TYPE::GNU_BUILD_ATTRIBUTE_OPEN) + { + norm_name = strip_zero(owner); + } + switch (ntype) { + case Note::TYPE::CORE_PRSTATUS: + { + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("CORE_PRSTATUS requires a valid ELF class"); + return nullptr; } - case NOTE_TYPES_CORE::NT_AUXV: - { - details = std::make_unique(CoreAuxv::make(*this)); - break; + if (arch == ARCH::EM_NONE) { + LIEF_WARN("CORE_PRSTATUS requires a valid architecture"); + return nullptr; + } + return std::unique_ptr(new CorePrStatus( + arch, cls, std::move(norm_name), *int_type, std::move(description) + )); + } + case Note::TYPE::CORE_PRPSINFO: + { + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("CORE_PRPSINFO requires a valid ELF class"); + return nullptr; } - case NOTE_TYPES_CORE::NT_SIGINFO: - { - details = std::make_unique(CoreSigInfo::make(*this)); - break; + if (arch == ARCH::EM_NONE) { + LIEF_WARN("CORE_PRPSINFO requires a valid architecture"); + return nullptr; + } + return std::unique_ptr(new CorePrPsInfo( + arch, cls, std::move(norm_name), *int_type, std::move(description) + )); + } + case Note::TYPE::CORE_FILE: + { + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("CORE_FILE requires a valid ELF class"); + return nullptr; } - default: - break; - } - } + if (arch == ARCH::EM_NONE) { + LIEF_WARN("CORE_FILE requires a valid architecture"); + return nullptr; + } + return std::unique_ptr(new CoreFile( + arch, cls, std::move(norm_name), *int_type, std::move(description) + )); + } + case Note::TYPE::CORE_AUXV: + { + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("CORE_AUXV requires a valid ELF class"); + return nullptr; + } - if (!details) { - switch (type) { - case NOTE_TYPES::NT_GNU_ABI_TAG: - { - details = std::make_unique(NoteAbi::make(*this)); - break; + if (arch == ARCH::EM_NONE) { + LIEF_WARN("CORE_AUXV requires a valid architecture"); + return nullptr; + } + return std::unique_ptr(new CoreAuxv( + arch, cls, std::move(norm_name), *int_type, std::move(description) + )); + } + case Note::TYPE::CORE_SIGINFO: + { + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("CORE_SIGINFO requires a valid ELF class"); + return nullptr; } - default: - { - details = std::make_unique(); - break; + if (arch == ARCH::EM_NONE) { + LIEF_WARN("CORE_SIGINFO requires a valid architecture"); + return nullptr; } - } + return std::unique_ptr(new CoreSigInfo( + std::move(norm_name), ntype, *int_type, std::move(description) + )); + } + case Note::TYPE::ANDROID_IDENT: + return std::unique_ptr(new AndroidIdent( + std::move(norm_name), ntype, *int_type, std::move(description) + )); + case Note::TYPE::GNU_ABI_TAG: + return std::unique_ptr(new NoteAbi( + std::move(norm_name), ntype, *int_type, std::move(description) + )); + + default: + return std::unique_ptr(new Note( + std::move(norm_name), ntype, *int_type, std::move(description) + )); } - - // update cache - dcache.first = type; - dcache.second.swap(details); - return *dcache.second; + return nullptr; } -void Note::name(const std::string& name) { - name_ = name; -} -void Note::type(NOTE_TYPES type) { - type_ = type; - is_core_ = false; -} - -void Note::type_core(NOTE_TYPES_CORE type) { - type_ = static_cast(type); - is_core_ = true; - details(); +std::unique_ptr +Note::create(const std::string& name, uint32_t type, Note::description_t description, + E_TYPE ftype, ARCH arch, ELF_CLASS cls) +{ + auto conv = Note::convert_type(ftype, type, name); + if (!conv) { + LIEF_WARN("Note type: 0x{:x} is not supported for owner: '{}'", type, name); + return std::unique_ptr(new Note(std::move(name), Note::TYPE::UNKNOWN, type, + std::move(description))); + } + return create(name, *conv, std::move(description), arch, cls); } -void Note::description(const description_t& description) { - description_ = description; -} uint64_t Note::size() const { uint64_t size = 0; @@ -233,63 +583,137 @@ void Note::accept(Visitor& visitor) const { visitor.visit(*this); } +void Note::dump(std::ostream& os) const { + os << fmt::format("{}(0x{:04x}) '{}' [{}]", + to_string(type()), original_type(), name(), + to_hex(description(), 10)); +} +const char* to_string(Note::TYPE type) { + #define ENTRY(X) std::pair(Note::TYPE::X, #X) + STRING_MAP enums2str { + ENTRY(UNKNOWN), + ENTRY(GNU_ABI_TAG), + ENTRY(GNU_HWCAP), + ENTRY(GNU_ABI_TAG), + ENTRY(GNU_HWCAP), + ENTRY(GNU_BUILD_ID), + ENTRY(GNU_GOLD_VERSION), + ENTRY(GNU_PROPERTY_TYPE_0), + ENTRY(GNU_BUILD_ATTRIBUTE_OPEN), + ENTRY(GNU_BUILD_ATTRIBUTE_FUNC), + ENTRY(CRASHPAD), + ENTRY(CORE_PRSTATUS), + ENTRY(CORE_FPREGSET), + ENTRY(CORE_PRPSINFO), + ENTRY(CORE_TASKSTRUCT), + ENTRY(CORE_AUXV), + ENTRY(CORE_PSTATUS), + ENTRY(CORE_FPREGS), + ENTRY(CORE_PSINFO), + ENTRY(CORE_LWPSTATUS), + ENTRY(CORE_LWPSINFO), + ENTRY(CORE_WIN32PSTATUS), + ENTRY(CORE_FILE), + ENTRY(CORE_PRXFPREG), + ENTRY(CORE_SIGINFO), + + ENTRY(CORE_ARM_VFP), + ENTRY(CORE_ARM_TLS), + ENTRY(CORE_ARM_HW_BREAK), + ENTRY(CORE_ARM_HW_WATCH), + ENTRY(CORE_ARM_SYSTEM_CALL), + ENTRY(CORE_ARM_SVE), + ENTRY(CORE_ARM_PAC_MASK), + ENTRY(CORE_ARM_PACA_KEYS), + ENTRY(CORE_ARM_PACG_KEYS), + ENTRY(CORE_TAGGED_ADDR_CTRL), + ENTRY(CORE_PAC_ENABLED_KEYS), + ENTRY(CORE_X86_TLS), + ENTRY(CORE_X86_IOPERM), + ENTRY(CORE_X86_XSTATE), + ENTRY(CORE_X86_CET), + + ENTRY(ANDROID_MEMTAG), + ENTRY(ANDROID_KUSER), + ENTRY(ANDROID_IDENT), + ENTRY(STAPSDT), + ENTRY(GO_BUILDID), + }; + #undef ENTRY + + if (auto it = enums2str.find(type); it != enums2str.end()) { + return it->second; + } + return "UNKNOWN"; +} -void Note::dump(std::ostream& os) const { - const description_t& desc = description(); - - std::string description_str = std::accumulate( - std::begin(desc), - std::begin(desc) + std::min(16, desc.size()), std::string{}, - [] (const std::string& a, uint8_t v) { - std::ostringstream hex_v; - hex_v << std::setw(2) << std::setfill('0') << std::hex; - hex_v << static_cast(v); - - return a.empty() ? "[" + hex_v.str() : a + " " + hex_v.str(); - }); - if (desc.size() > 16) { - description_str += " ..."; - } - description_str += "]"; - os << std::hex << std::left; - os << std::setw(33) << std::setfill(' ') << "Name:" << name() << std::endl; - const std::string type_str = is_core() ? to_string(type_core()) : to_string(type()); - os << std::setw(33) << std::setfill(' ') << "Type:" << type_str << std::endl; - os << std::setw(33) << std::setfill(' ') << "Description:" << description_str << std::endl; - - if (!is_core()) { - // GOLD VERSION - if (type() == NOTE_TYPES::NT_GNU_GOLD_VERSION) { - std::string version_str{reinterpret_cast(desc.data()), desc.size()}; - os << std::setw(33) << std::setfill(' ') << "Version:" << version_str << std::endl; - } - // BUILD ID - if (type() == NOTE_TYPES::NT_GNU_BUILD_ID) { - std::string hash = std::accumulate(std::begin(desc), std::end(desc), std::string{}, - [] (const std::string& a, uint8_t v) { - std::ostringstream hex_v; - hex_v << std::setw(2) << std::setfill('0') << std::hex; - hex_v << static_cast(v); +template +result Note::read_at(size_t offset) const { + auto stream = SpanStream::from_vector(description_); + if (!stream) { + return make_error_code(get_error(stream)); + } + return stream->peek(offset); +} - return a + hex_v.str(); - }); - os << std::setw(33) << std::setfill(' ') << "ID Hash:" << hash << std::endl; - } +result Note::read_string_at(size_t offset, size_t max_size) const { + auto stream = SpanStream::from_vector(description_); + if (!stream) { + return make_error_code(get_error(stream)); + } + if (max_size > 0) { + return stream->peek_string_at(offset, max_size); } - details().dump(os); + return stream->peek_string_at(offset); } -std::ostream& operator<<(std::ostream& os, const Note& note) { - note.dump(os); - return os; +template +ok_error_t Note::write_at(size_t offset, const T& value) { + Note::description_t original = description_; + vector_iostream ios; + ios.write(original); + ios.seekp(offset); + ios.write(value); + ios.move(description_); + return ok(); +} + +ok_error_t Note::write_string_at(size_t offset, const std::string& value) { + Note::description_t original = description_; + const auto* data = reinterpret_cast(value.data()); + vector_iostream ios; + ios.write(original); + ios.seekp(offset); + ios.write(data, value.size()); + ios.move(description_); + return ok(); } +IMPL_READ_AT(uint8_t); +IMPL_READ_AT(int8_t); +IMPL_READ_AT(uint16_t); +IMPL_READ_AT(int16_t); +IMPL_READ_AT(uint32_t); +IMPL_READ_AT(int32_t); +IMPL_READ_AT(uint64_t); +IMPL_READ_AT(int64_t); + +IMPL_WRITE_AT(uint8_t); +IMPL_WRITE_AT(int8_t); +IMPL_WRITE_AT(uint16_t); +IMPL_WRITE_AT(int16_t); +IMPL_WRITE_AT(uint32_t); +IMPL_WRITE_AT(int32_t); +IMPL_WRITE_AT(uint64_t); +IMPL_WRITE_AT(int64_t); +IMPL_WRITE_AT(std::string); + } // namespace ELF } // namespace LIEF diff --git a/src/ELF/NoteDetails/AndroidIdent.cpp b/src/ELF/NoteDetails/AndroidIdent.cpp new file mode 100644 index 0000000000..260ce125d7 --- /dev/null +++ b/src/ELF/NoteDetails/AndroidIdent.cpp @@ -0,0 +1,86 @@ +/* Copyright 2017 - 2023 R. Thomas + * Copyright 2017 - 2023 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "logging.hpp" + +#include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" +#include "LIEF/ELF/hash.hpp" +#include "LIEF/iostream.hpp" + +namespace LIEF { +namespace ELF { + +static constexpr auto sdk_version_offset = 0; +static constexpr auto ndk_version_offset = sizeof(uint32_t); +static constexpr auto ndk_build_number_offset = ndk_version_offset + AndroidIdent::ndk_version_size; + +uint32_t AndroidIdent::sdk_version() const { + auto val = read_at(sdk_version_offset); + if (!val) { + return 0; + } + return *val; +} + +std::string AndroidIdent::ndk_version() const { + auto val = read_string_at(ndk_version_offset); + if (!val) { + return ""; + } + return *val; +} + +std::string AndroidIdent::ndk_build_number() const { + auto val = read_string_at(ndk_build_number_offset); + if (!val) { + return ""; + } + return *val; +} + +void AndroidIdent::sdk_version(uint32_t version) { + write_at(sdk_version_offset, version); +} + +void AndroidIdent::ndk_version(const std::string& ndk_version) { + std::string sized_nersion = ndk_version; + sized_nersion.resize(ndk_version_size, 0); + write_string_at(ndk_version_offset, sized_nersion); +} + +void AndroidIdent::ndk_build_number(const std::string& ndk_build_number) { + std::string sized_nersion = ndk_build_number; + sized_nersion.resize(ndk_build_number_size); + write_string_at(ndk_build_number_offset, sized_nersion); +} + +void AndroidIdent::accept(Visitor& visitor) const { + visitor.visit(*this); +} + +void AndroidIdent::dump(std::ostream& os) const { + Note::dump(os); + os << '\n'; + os << fmt::format("SDK: {} NDK: {} NDK Build: {}", + sdk_version(), ndk_version(), ndk_build_number() + ); +} + +} // namespace ELF +} // namespace LIEF diff --git a/src/ELF/NoteDetails/AndroidNote.cpp b/src/ELF/NoteDetails/AndroidNote.cpp deleted file mode 100644 index 6d58b2915b..0000000000 --- a/src/ELF/NoteDetails/AndroidNote.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include - -#include "LIEF/ELF/hash.hpp" - -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" - -namespace LIEF { -namespace ELF { - -AndroidNote AndroidNote::make(Note& note) { - AndroidNote android_note = note; - android_note.parse(); - return android_note; -} - -AndroidNote::AndroidNote(Note& note) : - NoteDetails::NoteDetails{note} -{} - -AndroidNote* AndroidNote::clone() const { - return new AndroidNote(*this); -} - -uint32_t AndroidNote::sdk_version() const { - return sdk_version_; -} - -std::string AndroidNote::ndk_version() const { - return ndk_version_; -} - -std::string AndroidNote::ndk_build_number() const { - return ndk_build_number_; -} - -void AndroidNote::sdk_version(uint32_t version) { - sdk_version_ = version; - build(); -} - -void AndroidNote::ndk_version(const std::string& ndk_version) { - ndk_version_ = ndk_version; - build(); -} - -void AndroidNote::ndk_build_number(const std::string& ndk_build_number) { - ndk_build_number_ = ndk_build_number; - build(); -} - - -void AndroidNote::parse() { - const description_t& desc = description(); - - // Parse SDK Version - if (desc.size() < (sdk_version_offset + sdk_version_size)) { - return; - } - sdk_version_ = *reinterpret_cast(desc.data() + sdk_version_offset); - - // Parse NDK Version - if (desc.size() < (ndk_version_offset + ndk_version_size)) { - return ; - } - ndk_version_ = std::string{reinterpret_cast(desc.data()) + ndk_version_offset, ndk_version_size}; - - // Parse NDK Build Number - if (desc.size() < (ndk_build_number_offset + ndk_build_number_size)) { - return ; - } - ndk_build_number_ = std::string{reinterpret_cast(desc.data()) + ndk_build_number_offset, ndk_build_number_size}; -} - -void AndroidNote::build() { - description_t& desc = description(); - - // Build SDK Version - // ================= - if (desc.size() < (sdk_version_offset + sdk_version_size)) { - desc.resize(sdk_version_offset + sdk_version_size); - } - - std::copy( - reinterpret_cast(&sdk_version_), - reinterpret_cast(&sdk_version_) + sdk_version_size, - desc.data() + sdk_version_offset); - - // Build NDK Version - // ================= - if (desc.size() < (ndk_version_offset + ndk_version_size)) { - desc.resize(ndk_version_offset + ndk_version_size); - } - - std::copy( - reinterpret_cast(ndk_version_.data()), - reinterpret_cast(ndk_version_.data()) + ndk_version_.size(), - desc.data() + ndk_version_offset); - - // Build NDK Build Number - // ====================== - if (desc.size() < (ndk_build_number_offset + ndk_build_number_size)) { - desc.resize(ndk_build_number_offset + ndk_build_number_size); - } - - std::copy( - reinterpret_cast(ndk_build_number_.data()), - reinterpret_cast(ndk_build_number_.data()) + ndk_build_number_.size(), - desc.data() + ndk_build_number_offset); -} - -void AndroidNote::accept(Visitor& visitor) const { - visitor.visit(*this); -} - - - - -void AndroidNote::dump(std::ostream& os) const { - os << std::setw(33) << std::setfill(' ') << "SDK Version: " << std::dec << sdk_version() << std::endl; - os << std::setw(33) << std::setfill(' ') << "NDK Version: " << ndk_version() << std::endl; - os << std::setw(33) << std::setfill(' ') << "NDK Builder Number: " << ndk_build_number() << std::endl; -} - -std::ostream& operator<<(std::ostream& os, const AndroidNote& note) { - note.dump(os); - return os; -} - -AndroidNote::~AndroidNote() = default; - -} // namespace ELF -} // namespace LIEF diff --git a/src/ELF/NoteDetails/CMakeLists.txt b/src/ELF/NoteDetails/CMakeLists.txt index 55cf9ffa2b..e54dcf9390 100644 --- a/src/ELF/NoteDetails/CMakeLists.txt +++ b/src/ELF/NoteDetails/CMakeLists.txt @@ -1,6 +1,6 @@ target_sources(LIB_LIEF PRIVATE - AndroidNote.cpp NoteAbi.cpp + AndroidIdent.cpp ) add_subdirectory(core) diff --git a/src/ELF/NoteDetails/NoteAbi.cpp b/src/ELF/NoteDetails/NoteAbi.cpp index ae46077d59..c2b1514f78 100644 --- a/src/ELF/NoteDetails/NoteAbi.cpp +++ b/src/ELF/NoteDetails/NoteAbi.cpp @@ -16,89 +16,86 @@ #include #include +#include "frozen.hpp" +#include "internal_utils.hpp" + #include "LIEF/ELF/hash.hpp" #include "LIEF/ELF/EnumToString.hpp" - +#include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/iostream.hpp" #include "LIEF/ELF/NoteDetails/NoteAbi.hpp" +#include "spdlog/fmt/fmt.h" + namespace LIEF { namespace ELF { -NoteAbi NoteAbi::make(Note& note) { - NoteAbi abi = note; - abi.parse(); - return abi; +result NoteAbi::version() const { + NoteAbi::version_t version; + for (size_t i = 0; i < version.size(); ++i) { + auto res = read_at(version_offset + i * sizeof(uint32_t)); + if (!res) { + return make_error_code(lief_errors::read_error); + } + version[i] = *res; + } + return version; } -NoteAbi* NoteAbi::clone() const { - return new NoteAbi(*this); +result NoteAbi::abi() const { + auto value = read_at(abi_offset); + if (!value) { + return make_error_code(get_error(value)); + } + return static_cast(*value); } -NoteAbi::NoteAbi(Note& note) : - NoteDetails::NoteDetails{note}, - version_{{0, 0, 0}}, - abi_{NOTE_ABIS::ELF_NOTE_UNKNOWN} -{} - -NoteAbi::version_t NoteAbi::version() const { - return version_; +void NoteAbi::version(const version_t& version) { + write_at(version_offset + 0 * sizeof(uint32_t), version[0]); + write_at(version_offset + 1 * sizeof(uint32_t), version[1]); + write_at(version_offset + 2 * sizeof(uint32_t), version[2]); } -NOTE_ABIS NoteAbi::abi() const { - return abi_; +void NoteAbi::version(ABI abi) { + write_at(abi_offset, static_cast(abi)); } -void NoteAbi::parse() { - const description_t& desc = description(); - - // Parse ABI - if (desc.size() < (abi_offset + abi_size)) { - return; - } - abi_ = static_cast(*reinterpret_cast(desc.data())); - - // Parse Version - if (desc.size() < (version_offset + version_size)) { - return; - } - - const auto* version = reinterpret_cast(desc.data() + version_offset); - version_ = {{version[0], version[1], version[2]}}; -} - - void NoteAbi::accept(Visitor& visitor) const { visitor.visit(*this); } - - - void NoteAbi::dump(std::ostream& os) const { - version_t version = this->version(); - std::string version_str; - // Major - version_str += std::to_string(std::get<0>(version)); - version_str += "."; + Note::dump(os); + os << '\n'; + auto version_res = version().value_or(version_t({0, 0, 0})); + auto abi_res = to_string_or(abi(), "???"); + os << fmt::format(" {}.{}.{} '{}'", + version_res[0], version_res[1], version_res[2], abi_res + ); +} - // Minor - version_str += std::to_string(std::get<1>(version)); - version_str += "."; - // Patch - version_str += std::to_string(std::get<2>(version)); +const char* to_string(NoteAbi::ABI abi) { + #define ENTRY(X) std::pair(NoteAbi::ABI::X, #X) + STRING_MAP enums2str { + ENTRY(LINUX), + ENTRY(GNU), + ENTRY(SOLARIS2), + ENTRY(FREEBSD), + ENTRY(NETBSD), + ENTRY(SYLLABLE), + ENTRY(NACL), + }; + #undef ENTRY + + if (auto it = enums2str.find(abi); it != enums2str.end()) { + return it->second; + } - os << std::setw(33) << std::setfill(' ') << "ABI:" << to_string(abi()) << std::endl; - os << std::setw(33) << std::setfill(' ') << "Version:" << version_str << std::endl; -} + return "UNKNOWN"; -std::ostream& operator<<(std::ostream& os, const NoteAbi& note) { - note.dump(os); - return os; } -NoteAbi::~NoteAbi() = default; - } // namespace ELF } // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CMakeLists.txt b/src/ELF/NoteDetails/core/CMakeLists.txt index 51064374c0..54d255133c 100644 --- a/src/ELF/NoteDetails/core/CMakeLists.txt +++ b/src/ELF/NoteDetails/core/CMakeLists.txt @@ -1,12 +1,8 @@ target_sources(LIB_LIEF PRIVATE - CorePrPsInfo.cpp - CorePrPsInfo.tcc + CoreAuxv.cpp CoreFile.cpp - CoreFile.tcc + CorePrPsInfo.cpp CorePrStatus.cpp - CorePrStatus.tcc - CoreAuxv.cpp - CoreAuxv.tcc CoreSigInfo.cpp ) diff --git a/src/ELF/NoteDetails/core/CoreAuxv.cpp b/src/ELF/NoteDetails/core/CoreAuxv.cpp index f8a6bf7894..163deeeeac 100644 --- a/src/ELF/NoteDetails/core/CoreAuxv.cpp +++ b/src/ELF/NoteDetails/core/CoreAuxv.cpp @@ -19,111 +19,177 @@ #include "LIEF/ELF/hash.hpp" #include "LIEF/ELF/EnumToString.hpp" -#include "LIEF/ELF/Binary.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" +#include "LIEF/Visitor.hpp" +#include "LIEF/iostream.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" +#include "frozen.hpp" +#include "spdlog/fmt/fmt.h" #include "ELF/Structures.hpp" -#include "CoreAuxv.tcc" - namespace LIEF { namespace ELF { -CoreAuxv::CoreAuxv(Note& note): - NoteDetails::NoteDetails{note} -{} - -CoreAuxv CoreAuxv::make(Note& note) { - CoreAuxv pinfo(note); - pinfo.parse(); - return pinfo; +template inline result +get_impl(CoreAuxv::TYPE type, const Note::description_t& desc) { + using Elf_Auxv = typename ELF_T::Elf_Auxv; + auto stream = SpanStream::from_vector(desc); + if (!stream) { + return make_error_code(get_error(stream)); + } + while (*stream) { + auto auxv = stream->read(); + if (!auxv) { + return make_error_code(lief_errors::not_found); + } + const auto atype = static_cast(auxv->a_type); + auto value = auxv->a_un.a_val; + if (atype == CoreAuxv::TYPE::END) { + return make_error_code(lief_errors::not_found); + } + if (atype == type) { + return static_cast(value); + } + } + return make_error_code(lief_errors::not_found); } -CoreAuxv* CoreAuxv::clone() const { - return new CoreAuxv(*this); -} +template inline std::map +get_values_impl(const Note::description_t& desc) { + using Elf_Auxv = typename ELF_T::Elf_Auxv; + auto stream = SpanStream::from_vector(desc); + if (!stream) { + return {}; + } + std::map values; + while (*stream) { + auto auxv = stream->read(); + if (!auxv) { + return values; + } + const auto atype = static_cast(auxv->a_type); + auto value = auxv->a_un.a_val; + if (atype == CoreAuxv::TYPE::END) { + return values; + } -const CoreAuxv::val_context_t& CoreAuxv::values() const { - return ctx_; + values[atype] = static_cast(value); + } + return values; } - -uint64_t CoreAuxv::get(LIEF::ELF::AUX_TYPE atype, bool* error) const { - if (!has(atype)) { - if (error != nullptr) { - *error = true; +template +inline bool write_impl(Note::description_t& description, + std::map values) +{ + using Elf_Auxv = typename ELF_T::Elf_Auxv; + using ptr_t = typename ELF_T::uint; + vector_iostream io; + io.reserve(values.size() * sizeof(Elf_Auxv)); + + for (const auto& [type, value] : values) { + // This will be added at the end + if (type == CoreAuxv::TYPE::END) { + continue; } - return 0; - } - - if (error != nullptr) { - *error = false; + io.write(static_cast(type)) + .write(static_cast(value)); } - return ctx_.at(atype); -} + io.write(static_cast(CoreAuxv::TYPE::END)) + .write(static_cast(0)); -bool CoreAuxv::has(LIEF::ELF::AUX_TYPE reg) const { - return ctx_.find(reg) != std::end(ctx_); + io.move(description); + return true; } -void CoreAuxv::values(const val_context_t& ctx) { - ctx_ = ctx; - build(); -} - -bool CoreAuxv::set(LIEF::ELF::AUX_TYPE atype, uint64_t value) { - ctx_[atype] = value; - build(); - return true; +result CoreAuxv::get(TYPE type) const { + return class_ == ELF_CLASS::ELFCLASS32 ? + get_impl(type, description_) : + get_impl(type, description_); } -void CoreAuxv::accept(Visitor& visitor) const { - visitor.visit(*this); +std::map CoreAuxv::values() const { + return class_ == ELF_CLASS::ELFCLASS32 ? + get_values_impl(description_) : + get_values_impl(description_); } +bool CoreAuxv::set(TYPE type, uint64_t value) { + std::map vals = values(); + vals[type] = value; + return set(vals); +} -uint64_t& CoreAuxv::operator[](LIEF::ELF::AUX_TYPE atype) { - return ctx_[atype]; +bool CoreAuxv::set(std::map values) { + return class_ == ELF_CLASS::ELFCLASS32 ? + write_impl(description_, values) : + write_impl(description_, values); } void CoreAuxv::dump(std::ostream& os) const { - static constexpr size_t WIDTH = 16; - os << std::left; + Note::dump(os); - os << std::setw(WIDTH) << std::setfill(' ') << "Auxiliary values: "<< std::dec << std::endl; - for (const auto& val : ctx_) { - os << std::setw(14) << std::setfill(' ') << to_string(val.first) << ": " << std::hex << std::showbase << val.second << std::endl; + const auto& aux_vals = values(); + if (aux_vals.empty()) { + return; } - os << std::endl; -} - -void CoreAuxv::parse() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - parse_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - parse_(); + os << '\n'; + for (const auto& [type, val] : aux_vals) { + os << fmt::format(" {}: 0x{:08x}\n", to_string(type), val); } } -void CoreAuxv::build() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - build_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - build_(); - } +void CoreAuxv::accept(Visitor& visitor) const { + visitor.visit(*this); } +const char* to_string(CoreAuxv::TYPE type) { + #define ENTRY(X) std::pair(CoreAuxv::TYPE::X, #X) + STRING_MAP enums2str { + ENTRY(END), + ENTRY(IGNORE), + ENTRY(EXECFD), + ENTRY(PHDR), + ENTRY(PHENT), + ENTRY(PHNUM), + ENTRY(PAGESZ), + ENTRY(BASE), + ENTRY(FLAGS), + ENTRY(ENTRY), + ENTRY(NOTELF), + ENTRY(UID), + ENTRY(EUID), + ENTRY(GID), + ENTRY(EGID), + ENTRY(TGT_PLATFORM), + ENTRY(HWCAP), + ENTRY(CLKTCK), + ENTRY(FPUCW), + ENTRY(DCACHEBSIZE), + ENTRY(ICACHEBSIZE), + ENTRY(UCACHEBSIZE), + ENTRY(IGNOREPPC), + ENTRY(SECURE), + ENTRY(BASE_PLATFORM), + ENTRY(RANDOM), + ENTRY(HWCAP2), + ENTRY(EXECFN), + ENTRY(SYSINFO), + ENTRY(SYSINFO_EHDR), + }; + #undef ENTRY + + if (auto it = enums2str.find(type); it != enums2str.end()) { + return it->second; + } -std::ostream& operator<<(std::ostream& os, const CoreAuxv& note) { - note.dump(os); - return os; + return "UNKNOWN"; } - -CoreAuxv::~CoreAuxv() = default; - } // namespace ELF } // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CoreAuxv.tcc b/src/ELF/NoteDetails/core/CoreAuxv.tcc deleted file mode 100644 index 84aecb67fc..0000000000 --- a/src/ELF/NoteDetails/core/CoreAuxv.tcc +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - - -#include "LIEF/utils.hpp" -#include "LIEF/BinaryStream/VectorStream.hpp" -#include "LIEF/iostream.hpp" - -#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" -#include "LIEF/ELF/Note.hpp" - -namespace LIEF { -namespace ELF { - -template -void CoreAuxv::parse_() { - using Elf_Auxv = typename ELF_T::Elf_Auxv; - using uint__ = typename ELF_T::uint; - - const Note::description_t& desc = description(); - if (desc.size() < sizeof(Elf_Auxv)) { - return; - } - - VectorStream stream(desc); - while (stream.can_read()) { - auto res_auxv = stream.read(); - if (!res_auxv) { - break; - } - auto auxv = *res_auxv; - auto type = static_cast(auxv.a_type); - if (type == AUX_TYPE::AT_NULL) { - break; - } - ctx_[type] = static_cast(auxv.a_un.a_val); - } - -} - -template -void CoreAuxv::build_() { - using Elf_Auxv = typename ELF_T::Elf_Auxv; - using uint__ = typename ELF_T::uint; - - Note::description_t& desc = description(); - - vector_iostream raw_output; - raw_output.reserve(ctx_.size() * sizeof(Elf_Auxv)); - - for (const auto& val : ctx_) { - AUX_TYPE type = val.first; - // skip for now, will be added at the end - if (type == AUX_TYPE::AT_NULL) { - continue; - } - const Elf_Auxv aux = { static_cast(val.first), {static_cast(val.second)} }; - raw_output.write_conv(aux); - } - // AT_NULL - const Elf_Auxv terminator = {0, {0}}; - raw_output.write_conv(terminator); - - std::vector raw = raw_output.raw(); - std::copy(std::begin(raw), std::end(raw), - std::begin(desc)); -} - -} // namespace ELF -} // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CoreFile.cpp b/src/ELF/NoteDetails/core/CoreFile.cpp index 58811acb94..ef4d5b604f 100644 --- a/src/ELF/NoteDetails/core/CoreFile.cpp +++ b/src/ELF/NoteDetails/core/CoreFile.cpp @@ -17,111 +17,122 @@ #include #include +#include "logging.hpp" #include "LIEF/ELF/hash.hpp" - -#include "LIEF/ELF/Binary.hpp" +#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" #include "ELF/Structures.hpp" - -#include "CoreFile.tcc" +#include "LIEF/iostream.hpp" namespace LIEF { namespace ELF { -class Note; -CoreFile::CoreFile(Note& note): - NoteDetails::NoteDetails{note} -{} +template +void CoreFile::read_files() { + static constexpr auto MAX_ENTRIES = 6000; + using Elf_Addr = typename ELF_T::Elf_Addr; + using Elf_FileEntry = typename ELF_T::Elf_FileEntry; -CoreFile CoreFile::make(Note& note) { - CoreFile file(note); - file.parse(); - return file; -} + auto stream = SpanStream::from_vector(description_); + if (!stream) { + return; + } -CoreFile* CoreFile::clone() const { - return new CoreFile(*this); -} + auto count = stream->read(); + if (!count) { + return; + } + if (*count > MAX_ENTRIES) { + LIEF_ERR("Too many entries ({} while limited at {})", *count, MAX_ENTRIES); + return; + } -uint64_t CoreFile::count() const { - return files_.size(); -} + auto page_size = stream->read(); + if (!page_size) { + return; + } + + page_size_ = *page_size; + files_.resize(*count); + for (size_t i = 0; i < files_.size(); ++i) { + auto entry = stream->read(); + if (!entry) { + break; + } + files_[i] = {entry->start, entry->end, entry->file_ofs, ""}; + } -const CoreFile::files_t& CoreFile::files() const { - return files_; + for (size_t i = 0; i < files_.size(); ++i) { + auto path = stream->read_string(); + if (!path) { + break; + } + files_[i].path = std::move(*path); + } } +template +void CoreFile::write_files() { + using Elf_Addr = typename ELF_T::Elf_Addr; + using Elf_FileEntry = typename ELF_T::Elf_FileEntry; + + vector_iostream ios; + ios.write(static_cast(files_.size())); + ios.write(static_cast(page_size_)); + for (const entry_t& entry : files_) { + Elf_FileEntry raw_entry; + std::memset(&raw_entry, 0, sizeof(Elf_FileEntry)); + + raw_entry.start = static_cast(entry.start); + raw_entry.end = static_cast(entry.end); + raw_entry.file_ofs = static_cast(entry.file_ofs); + ios.write(raw_entry); + } -CoreFile::iterator CoreFile::begin() { - return std::begin(files_); + for (const entry_t& entry : files_) { + ios.write(entry.path); + } + ios.move(description_); } -CoreFile::iterator CoreFile::end() { - return std::end(files_); -} +CoreFile::CoreFile(ARCH arch, ELF_CLASS cls, std::string name, + uint32_t type, Note::description_t description) : + Note(std::move(name), Note::TYPE::CORE_FILE, type, std::move(description)), + arch_(arch), class_(cls) +{ -CoreFile::const_iterator CoreFile::begin() const { - return std::begin(files_); + class_ == ELF_CLASS::ELFCLASS32 ? read_files() : + read_files(); } -CoreFile::const_iterator CoreFile::end() const { - return std::end(files_); -} void CoreFile::files(const CoreFile::files_t& files) { files_ = files; - build(); -} + class_ == ELF_CLASS::ELFCLASS32 ? write_files() : + write_files(); +} void CoreFile::accept(Visitor& visitor) const { visitor.visit(*this); } - - void CoreFile::dump(std::ostream& os) const { - static constexpr size_t WIDTH = 16; - os << std::left; - - os << std::setw(WIDTH) << std::setfill(' ') << "Files: "<< std::dec << std::endl; - for (const CoreFileEntry& file : files()) { - os << " - "; - os << file.path << " "; - os << "[" << std::hex << std::showbase << file.start << ", " << file.end << "] "; - os << file.file_ofs; - os << std::endl; + Note::dump(os); + const files_t& files = this->files(); + if (files.empty()) { + return; } - os << std::endl; -} - -void CoreFile::parse() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - parse_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - parse_(); + os << '\n'; + for (const entry_t& entry : files) { + os << " " << entry << '\n'; } } -void CoreFile::build() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - build_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - build_(); - } -} - -std::ostream& operator<<(std::ostream& os, const CoreFile& note) { - note.dump(os); - return os; -} - -CoreFile::~CoreFile() = default; - - -std::ostream& operator<<(std::ostream& os, const CoreFileEntry& entry) { - os << std::hex << std::showbase; - os << entry.path << ": [" << entry.start << ", " << entry.end << "]@" << entry.file_ofs; +std::ostream& operator<<(std::ostream& os, const CoreFile::entry_t& entry) { + os << fmt::format("{}: [0x{:04x}, 0x{:04x}]@0x{:x}", + entry.path, entry.start, entry.end, entry.file_ofs); return os; } diff --git a/src/ELF/NoteDetails/core/CoreFile.tcc b/src/ELF/NoteDetails/core/CoreFile.tcc deleted file mode 100644 index 0e0c2f96ba..0000000000 --- a/src/ELF/NoteDetails/core/CoreFile.tcc +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "logging.hpp" - -#include "LIEF/utils.hpp" -#include "LIEF/BinaryStream/VectorStream.hpp" -#include "LIEF/iostream.hpp" - -#include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" - - -namespace LIEF { -namespace ELF { - -template -void CoreFile::parse_() { - static constexpr auto MAX_ENTRIES = 6000; - using Elf_Addr = typename ELF_T::Elf_Addr; - using Elf_FileEntry = typename ELF_T::Elf_FileEntry; - - VectorStream stream{description()}; - - auto res_count = stream.read_conv(); - if (!res_count) { - return; - } - - const auto count = *res_count; - const auto res_page_size = stream.read_conv(); - - if (!res_page_size) { - LIEF_ERR("Can't read CoreFile.page_size"); - return; - } - - if (count > MAX_ENTRIES) { - LIEF_ERR("Too many entries ({} while limited at {})", count, MAX_ENTRIES); - return; - } - - page_size_ = *res_page_size; - files_.resize(count); - - for (uint32_t idx = 0; idx < count; idx++) { - auto res_entry = stream.read_conv(); - if (!res_entry) { - break; - } - const auto entry = *res_entry; - files_[idx] = {entry.start, entry.end, entry.file_ofs, {}}; - } - - for (uint32_t idx = 0; idx < count; idx++) { - auto res_path = stream.read_string(); - if (!res_path) { - break; - } - std::string path = std::move(*res_path); - if (!path.empty()) { - files_[idx].path = std::move(path); - } - } -} - -template -void CoreFile::build_() { - using Elf_Addr = typename ELF_T::Elf_Addr; - using Elf_FileEntry = typename ELF_T::Elf_FileEntry; - - Note::description_t& desc = description(); - - auto cnt = static_cast(count()); - auto page_size = static_cast(page_size_); - - vector_iostream raw_output; - size_t desc_part_size = sizeof(Elf_Addr) * 2 + cnt * sizeof(Elf_FileEntry); - raw_output.reserve(desc_part_size); - - raw_output.write_conv(cnt); - raw_output.write_conv(page_size); - for (const CoreFileEntry& entry: files_) { - const Elf_FileEntry raw_entry = { - static_cast(entry.start), - static_cast(entry.end), - static_cast(entry.file_ofs) - }; - raw_output.write_conv(raw_entry); - } - for (const CoreFileEntry& entry: files_) { - raw_output.write(entry.path); - } - desc = std::move(raw_output.raw()); -} - -} // namespace ELF -} // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CorePrPsInfo.cpp b/src/ELF/NoteDetails/core/CorePrPsInfo.cpp index b2b585229b..62499133a9 100644 --- a/src/ELF/NoteDetails/core/CorePrPsInfo.cpp +++ b/src/ELF/NoteDetails/core/CorePrPsInfo.cpp @@ -18,146 +18,120 @@ #include #include "LIEF/ELF/hash.hpp" - #include "ELF/Structures.hpp" -#include "CorePrPsInfo.tcc" +#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/iostream.hpp" + +#include "spdlog/fmt/fmt.h" namespace LIEF { namespace ELF { -CorePrPsInfo::CorePrPsInfo(Note& note): - NoteDetails::NoteDetails{note}, - flags_(0), - uid_(0), - gid_(0), - pid_(0), - ppid_(0), - pgrp_(0), - sid_(0) -{} - -CorePrPsInfo CorePrPsInfo::make(Note& note) { - CorePrPsInfo pinfo(note); - pinfo.parse(); - return pinfo; -} - -CorePrPsInfo* CorePrPsInfo::clone() const { - return new CorePrPsInfo(*this); -} - -std::string CorePrPsInfo::file_name() const { - return file_name_; -} - -uint64_t CorePrPsInfo::flags() const { - return flags_; -} - -uint32_t CorePrPsInfo::uid() const { - return uid_; -} +template +inline result +get_info_impl(const Note::description_t& description) { + using Elf_Prpsinfo = typename ELF_T::Elf_Prpsinfo; + CorePrPsInfo::info_t info; + auto stream = SpanStream::from_vector(description); + if (!stream) { + return make_error_code(get_error(stream)); + } + auto raw = stream->read(); + if (!raw) { + return make_error_code(get_error(raw)); + } -uint32_t CorePrPsInfo::gid() const { - return gid_; -} + info.state = raw->pr_state; + info.sname = raw->pr_sname; + info.zombie = static_cast(raw->pr_zomb); + info.nice = raw->pr_nice; + info.flag = raw->pr_flag; + info.uid = raw->pr_uid; + info.gid = raw->pr_gid; + info.pid = raw->pr_pid; + info.ppid = raw->pr_ppid; + info.pgrp = raw->pr_pgrp; + info.sid = raw->pr_sid; + info.filename = std::string(raw->pr_fname, sizeof(Elf_Prpsinfo::pr_fname)); + info.args = std::string(raw->pr_psargs, sizeof(Elf_Prpsinfo::pr_psargs)); -int32_t CorePrPsInfo::pid() const { - return pid_; + return info; } -int32_t CorePrPsInfo::ppid() const { - return ppid_; -} +template inline ok_error_t +write_info_impl(Note::description_t& description, + const CorePrPsInfo::info_t& info) +{ + using Elf_Prpsinfo = typename ELF_T::Elf_Prpsinfo; + Elf_Prpsinfo raw; + std::memset(reinterpret_cast(&raw), 0, sizeof(Elf_Prpsinfo)); -int32_t CorePrPsInfo::pgrp() const { - return pgrp_; -} -int32_t CorePrPsInfo::sid() const { - return sid_; -} + raw.pr_state = info.state; + raw.pr_sname = info.sname; + raw.pr_zomb = static_cast(info.zombie); + raw.pr_nice = info.nice; + raw.pr_flag = info.flag; + raw.pr_uid = info.uid; + raw.pr_gid = info.gid; + raw.pr_pid = info.pid; + raw.pr_ppid = info.ppid; + raw.pr_pgrp = info.pgrp; + raw.pr_sid = info.sid; -void CorePrPsInfo::file_name(const std::string& file_name) { - file_name_ = file_name; - build(); -} + std::string filename = info.filename; + filename.resize(sizeof(Elf_Prpsinfo::pr_fname)); -void CorePrPsInfo::flags(uint64_t flags) { - flags_ = flags; - build(); -} + std::string args = info.args; + args.resize(sizeof(Elf_Prpsinfo::pr_psargs)); -void CorePrPsInfo::uid(uint32_t uid) { - uid_ = uid; - build(); -} + std::move(filename.begin(), filename.end(), raw.pr_fname); + std::move(args.begin(), args.end(), raw.pr_psargs); -void CorePrPsInfo::gid(uint32_t gid) { - gid_ = gid; - build(); + vector_iostream ios; + ios.write(raw); + ios.move(description); + return ok_t(); } -void CorePrPsInfo::pid(int32_t pid) { - pid_ = pid; - build(); -} -void CorePrPsInfo::ppid(int32_t ppid) { - ppid_ = ppid; - build(); +result CorePrPsInfo::info() const { + return class_ == ELF_CLASS::ELFCLASS32 ? + get_info_impl(description_) : + get_info_impl(description_); } -void CorePrPsInfo::pgrp(int32_t pgrp) { - pgrp_ = pgrp; - build(); -} -void CorePrPsInfo::sid(int32_t sid) { - sid_ = sid; - build(); +void CorePrPsInfo::info(const info_t& info) { + class_ == ELF_CLASS::ELFCLASS32 ? + write_info_impl(description_, info) : + write_info_impl(description_, info); } void CorePrPsInfo::accept(Visitor& visitor) const { visitor.visit(*this); } - - void CorePrPsInfo::dump(std::ostream& os) const { - os << std::left; - os << std::setw(12) << std::setfill(' ') << "File name: " << std::dec << file_name() << std::endl; - os << std::setw(12) << std::setfill(' ') << "UID: " << std::dec << uid() << std::endl; - os << std::setw(12) << std::setfill(' ') << "GID: " << std::dec << gid() << std::endl; - os << std::setw(12) << std::setfill(' ') << "PID: " << std::dec << pid() << std::endl; - os << std::setw(12) << std::setfill(' ') << "PPID: " << std::dec << ppid() << std::endl; - os << std::setw(12) << std::setfill(' ') << "PGRP: " << std::dec << pgrp() << std::endl; - os << std::setw(12) << std::setfill(' ') << "SID: " << std::dec << sid() << std::endl; -} - -void CorePrPsInfo::parse() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - parse_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - parse_(); - } -} - -void CorePrPsInfo::build() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - build_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - build_(); + Note::dump(os); + auto info_res = info(); + if (!info_res) { + return; } + os << '\n'; + os << fmt::format(" Path: {} (args: {})\n", + info_res->filename_stripped(), info_res->args_stripped()) + << fmt::format(" UID: {:04d} GID: {:04d} PID: {:04d}\n", + info_res->uid, info_res->gid, info_res->pid) + << fmt::format(" PPID: {:04d} PGRP: {:04d} SID: {:04d}\n", + info_res->ppid, info_res->pgrp, info_res->sid) + << fmt::format(" Flag: 0x{:04x} Nice: {} Zombie: {}\n", + info_res->flag, info_res->nice, info_res->zombie) + << fmt::format(" State: 0x{:x} State Name: {}\n", + info_res->state, info_res->sname); } -std::ostream& operator<<(std::ostream& os, const CorePrPsInfo& note) { - note.dump(os); - return os; -} - -CorePrPsInfo::~CorePrPsInfo() = default; - } // namespace ELF } // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CorePrPsInfo.tcc b/src/ELF/NoteDetails/core/CorePrPsInfo.tcc deleted file mode 100644 index 569b31a07b..0000000000 --- a/src/ELF/NoteDetails/core/CorePrPsInfo.tcc +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - - -#include "LIEF/utils.hpp" - -#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp" -#include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/Binary.hpp" - -namespace LIEF { -namespace ELF { - -template -void CorePrPsInfo::parse_() { - using Elf_Prpsinfo = typename ELF_T::Elf_Prpsinfo; - - const Note::description_t& desc = description(); - - if (desc.size() < sizeof(Elf_Prpsinfo)) { - return; - } - - const auto* info = reinterpret_cast(desc.data()); - - // parse info structure - file_name_ = std::string(info->pr_fname, sizeof(info->pr_fname)).c_str(); - flags_ = info->pr_flag; - uid_ = info->pr_uid; - gid_ = info->pr_gid; - pid_ = info->pr_pid; - ppid_ = info->pr_ppid; - pgrp_ = info->pr_pgrp; - sid_ = info->pr_sid; -} - -template -void CorePrPsInfo::build_() { - using Elf_Prpsinfo = typename ELF_T::Elf_Prpsinfo; - Note::description_t& desc = description(); - constexpr size_t desc_size = sizeof(Elf_Prpsinfo); - if (desc.size() < desc_size) { - desc.resize(desc_size); - } - - auto* info = reinterpret_cast(desc.data()); - // update info structure - const size_t fname_size = sizeof(info->pr_fname) - 1; - - std::string fname = file_name_; - fname.resize(fname_size, 0); - - std::move( - std::begin(file_name_), - std::end(file_name_), - info->pr_fname); - - info->pr_flag = flags_; - info->pr_uid = uid_; - info->pr_gid = gid_; - info->pr_pid = pid_; - info->pr_ppid = ppid_; - info->pr_pgrp = pgrp_; - info->pr_sid = sid_; -} - -} // namespace ELF -} // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CorePrStatus.cpp b/src/ELF/NoteDetails/core/CorePrStatus.cpp index f6454ee5d6..e6aaca7cfd 100644 --- a/src/ELF/NoteDetails/core/CorePrStatus.cpp +++ b/src/ELF/NoteDetails/core/CorePrStatus.cpp @@ -18,358 +18,557 @@ #include #include "logging.hpp" +#include "frozen.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/iostream.hpp" #include "LIEF/ELF/hash.hpp" #include "LIEF/ELF/EnumToString.hpp" -#include "LIEF/ELF/Binary.hpp" +#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" #include "ELF/Structures.hpp" -#include "CorePrStatus.tcc" - namespace LIEF { namespace ELF { -class Note; -CorePrStatus::CorePrStatus(Note& note): - NoteDetails::NoteDetails{note} -{} +template +inline CorePrStatus::pr_status_t +get_status_impl(const Note::description_t& description) { + using Elf_Prstatus = typename ELF_T::Elf_Prstatus; + CorePrStatus::pr_status_t status; -CorePrStatus CorePrStatus::make(Note& note) { - CorePrStatus pinfo(note); - pinfo.parse(); - return pinfo; -} + auto stream = SpanStream::from_vector(description); + if (!stream) { + return {}; + } -CorePrStatus* CorePrStatus::clone() const { - return new CorePrStatus(*this); -} + auto raw_pr_status = stream->read(); + if (!raw_pr_status) { + return {}; + } -const CorePrStatus::reg_context_t& CorePrStatus::reg_context() const { - return ctx_; -} + status.info.signo = raw_pr_status->pr_info.si_signo; + status.info.code = raw_pr_status->pr_info.si_code; + status.info.err = raw_pr_status->pr_info.si_errno; + status.cursig = raw_pr_status->pr_cursig; + status.reserved = raw_pr_status->reserved; + status.sigpend = raw_pr_status->pr_sigpend; + status.sighold = raw_pr_status->pr_sighold; -const CorePrStatus::siginfo_t& CorePrStatus::siginfo() const { - return siginfo_; -} + status.pid = raw_pr_status->pr_pid; + status.ppid = raw_pr_status->pr_ppid; + status.pgrp = raw_pr_status->pr_pgrp; + status.sid = raw_pr_status->pr_sid; -uint16_t CorePrStatus::current_sig() const { - return cursig_; -} + status.utime.sec = raw_pr_status->pr_utime.tv_sec; + status.utime.usec = raw_pr_status->pr_utime.tv_usec; -uint64_t CorePrStatus::sigpend() const { - return sigpend_; -} + status.stime.sec = raw_pr_status->pr_stime.tv_sec; + status.stime.usec = raw_pr_status->pr_stime.tv_usec; -uint64_t CorePrStatus::sighold() const { - return sighold_; -} + status.cutime.sec = raw_pr_status->pr_cutime.tv_sec; + status.cutime.usec = raw_pr_status->pr_cutime.tv_usec; -int32_t CorePrStatus::pid() const { - return pid_; -} + status.cstime.sec = raw_pr_status->pr_cstime.tv_sec; + status.cstime.usec = raw_pr_status->pr_cstime.tv_usec; -int32_t CorePrStatus::ppid() const { - return ppid_; + return status; } -int32_t CorePrStatus::pgrp() const { - return pgrp_; -} +template +inline Note::description_t write_status_impl(const CorePrStatus::pr_status_t& status) { + using Elf_Prstatus = typename ELF_T::Elf_Prstatus; + Elf_Prstatus raw_pr_status; -int32_t CorePrStatus::sid() const { - return sid_; -} + raw_pr_status.pr_info.si_signo = status.info.signo; + raw_pr_status.pr_info.si_code = status.info.code; + raw_pr_status.pr_info.si_errno = status.info.err; -CorePrStatus::timeval_t CorePrStatus::utime() const { - return utime_; -} + raw_pr_status.pr_cursig = status.cursig; + raw_pr_status.reserved = status.reserved; + raw_pr_status.pr_sigpend = static_cast(status.sigpend); + raw_pr_status.pr_sighold = static_cast(status.sighold); -CorePrStatus::timeval_t CorePrStatus::stime() const { - return stime_; -} + raw_pr_status.pr_pid = status.pid; + raw_pr_status.pr_ppid = status.ppid; + raw_pr_status.pr_pgrp = status.pgrp; + raw_pr_status.pr_sid = status.sid; -CorePrStatus::timeval_t CorePrStatus::cutime() const { - return cutime_; -} + raw_pr_status.pr_utime.tv_sec = status.utime.sec; + raw_pr_status.pr_utime.tv_usec = status.utime.usec; -CorePrStatus::timeval_t CorePrStatus::cstime() const { - return cstime_; -} + raw_pr_status.pr_cutime.tv_sec = status.cutime.sec; + raw_pr_status.pr_cutime.tv_usec = status.cutime.usec; + + raw_pr_status.pr_stime.tv_sec = status.stime.sec; + raw_pr_status.pr_stime.tv_usec = status.stime.usec; + raw_pr_status.pr_cstime.tv_sec = status.cstime.sec; + raw_pr_status.pr_cstime.tv_usec = status.cstime.usec; + + vector_iostream ios; + ios.write(raw_pr_status); + return ios.raw(); +} -uint64_t CorePrStatus::get(CorePrStatus::REGISTERS reg, bool* error) const { - if (!has(reg)) { - if (error != nullptr) { - *error = true; +template +inline result +get_reg_impl(REG_T reg, const Note::description_t& description, + ELF_CLASS cls, ARCH arch) +{ + if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_386) { + return make_error_code(lief_errors::not_found); } - return 0; } - - if (error != nullptr) { - *error = false; + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_X86_64) { + return make_error_code(lief_errors::not_found); + } + } + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_ARM) { + return make_error_code(lief_errors::not_found); + } + } + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_AARCH64) { + return make_error_code(lief_errors::not_found); + } + } + else { + LIEF_WARN("Architecture not supported"); + return make_error_code(lief_errors::not_found); } - return ctx_.at(reg); -} -bool CorePrStatus::has(CorePrStatus::REGISTERS reg) const { - return ctx_.find(reg) != std::end(ctx_); -} + auto pos = static_cast(reg); + if (pos < 0 || pos >= static_cast(REG_T::_COUNT)) { + return make_error_code(lief_errors::not_found); + } + auto stream = SpanStream::from_vector(description); + if (!stream) { + return make_error_code(lief_errors::not_found); + } -uint64_t CorePrStatus::pc() const { - const ARCH arch = binary()->header().machine_type(); - switch (arch) { - case ARCH::EM_386: return get(REGISTERS::X86_EIP); - case ARCH::EM_X86_64: return get(REGISTERS::X86_64_RIP); - case ARCH::EM_ARM: return get(REGISTERS::ARM_R15); - case ARCH::EM_AARCH64: return get(REGISTERS::AARCH64_PC); - default: - { - LIEF_WARN("{} not supported", to_string(arch)); - return 0; - } + if (cls == ELF_CLASS::ELFCLASS32) { + stream->increment_pos(sizeof(details::ELF32::Elf_Prstatus)); + stream->increment_pos(pos * sizeof(uint32_t)); + auto value = stream->read(); + if (!value) { + return make_error_code(lief_errors::corrupted); + } + return *value; } -} -uint64_t CorePrStatus::sp() const { - const ARCH arch = binary()->header().machine_type(); - switch (arch) { - case ARCH::EM_386: return get(REGISTERS::X86_ESP); - case ARCH::EM_X86_64: return get(REGISTERS::X86_64_RSP); - case ARCH::EM_ARM: return get(REGISTERS::ARM_R13); - case ARCH::EM_AARCH64: return get(REGISTERS::AARCH64_X31); - default: - { - LIEF_WARN("{} not supported", to_string(arch)); - return 0; - } + if (cls == ELF_CLASS::ELFCLASS64) { + stream->increment_pos(sizeof(details::ELF64::Elf_Prstatus)); + stream->increment_pos(pos * sizeof(uint64_t)); + auto value = stream->read(); + if (!value) { + return make_error_code(lief_errors::corrupted); + } + return *value; } + return make_error_code(lief_errors::not_found); } +template +inline ok_error_t +set_reg_impl(REG_T reg, uint64_t value, Note::description_t& description, + ELF_CLASS cls, ARCH arch) +{ + if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_386) { + return make_error_code(lief_errors::not_found); + } + } + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_X86_64) { + return make_error_code(lief_errors::not_found); + } + } + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_ARM) { + return make_error_code(lief_errors::not_found); + } + } + else if constexpr (std::is_same_v) + { + if (arch != ARCH::EM_AARCH64) { + return make_error_code(lief_errors::not_found); + } + } + else { + LIEF_WARN("Architecture not supported"); + return make_error_code(lief_errors::not_found); + } -void CorePrStatus::siginfo(const CorePrStatus::siginfo_t& siginfo) { - siginfo_ = siginfo; - build(); -} + auto pos = static_cast(reg); + if (pos < 0 || pos >= static_cast(REG_T::_COUNT)) { + return make_error_code(lief_errors::not_found); + } -void CorePrStatus::current_sig(uint16_t current_sig) { - cursig_ = current_sig; - build(); -} + size_t offset = 0; + vector_iostream os; + os.write(description); -void CorePrStatus::sigpend(uint64_t sigpend) { - sigpend_ = sigpend; - build(); -} + if (cls == ELF_CLASS::ELFCLASS32) { + offset += sizeof(details::ELF32::Elf_Prstatus) + pos * sizeof(uint32_t); + os.seekp(offset); + os.write(value); + return ok(); + } -void CorePrStatus::sighold(uint64_t sighold) { - sighold_ = sighold; - build(); -} + if (cls == ELF_CLASS::ELFCLASS64) { + offset += sizeof(details::ELF64::Elf_Prstatus) + pos * sizeof(uint64_t); + os.seekp(offset); + os.write(value); + os.move(description); + return ok(); + } -void CorePrStatus::pid(int32_t pid) { - pid_ = pid; - build(); + return make_error_code(lief_errors::not_found); } -void CorePrStatus::ppid(int32_t ppid) { - ppid_ = ppid; - build(); +std::vector CorePrStatus::register_values() const { + std::vector values; + switch (arch_) { + case ARCH::EM_X86_64: + { + using Reg = Registers::X86_64; + const auto count = static_cast(Reg::_COUNT); + values.reserve(count); + for (size_t i = 0; i < count; ++i) { + if (auto val = get(Reg(i))) { + values.push_back(std::move(*val)); + } else { + return {}; + } + } + return values; + } + case ARCH::EM_386: + { + using Reg = Registers::X86; + const auto count = static_cast(Reg::_COUNT); + values.reserve(count); + for (size_t i = 0; i < count; ++i) { + if (auto val = get(Reg(i))) { + values.push_back(std::move(*val)); + } else { + return {}; + } + } + return values; + } + case ARCH::EM_ARM: + { + using Reg = Registers::ARM; + const auto count = static_cast(Reg::_COUNT); + values.reserve(count); + for (size_t i = 0; i < count; ++i) { + if (auto val = get(Reg(i))) { + values.push_back(std::move(*val)); + } else { + return {}; + } + } + return values; + } + case ARCH::EM_AARCH64: + { + using Reg = Registers::AARCH64; + const auto count = static_cast(Reg::_COUNT); + values.reserve(count); + for (size_t i = 0; i < count; ++i) { + if (auto val = get(Reg(i))) { + values.push_back(std::move(*val)); + } else { + return {}; + } + } + return values; + } + default: return {}; + } } -void CorePrStatus::pgrp(int32_t pgrp) { - pgrp_ = pgrp; - build(); +CorePrStatus::pr_status_t CorePrStatus::status() const { + if (class_ == ELF_CLASS::ELFCLASS32) { + return get_status_impl(description_); + } + return get_status_impl(description_); } -void CorePrStatus::sid(int32_t sid) { - sid_ = sid; - build(); -} +void CorePrStatus::status(const pr_status_t& status) { + Note::description_t description = class_ == ELF_CLASS::ELFCLASS32 ? + write_status_impl(status) : + write_status_impl(status); -void CorePrStatus::utime(CorePrStatus::timeval_t utime) { - utime_ = utime; - build(); -} + if (description.empty()) { + return; + } -void CorePrStatus::stime(CorePrStatus::timeval_t stime) { - stime_ = stime; - build(); -} + if (description_.size() < description.size()) { + description_.resize(description.size()); + } -void CorePrStatus::cutime(CorePrStatus::timeval_t cutime) { - cutime_ = cutime; - build(); + std::move(description.begin(), description.end(), description_.begin()); } -void CorePrStatus::cstime(CorePrStatus::timeval_t cstime) { - cstime_ = cstime; - build(); +result CorePrStatus::get(Registers::X86 reg) const { + return get_reg_impl(reg, description_, class_, arch_); } -void CorePrStatus::reg_context(const reg_context_t& ctx) { - ctx_ = ctx; - build(); +result CorePrStatus::get(Registers::X86_64 reg) const { + return get_reg_impl(reg, description_, class_, arch_); } -bool CorePrStatus::set(REGISTERS reg, uint64_t value) { - ctx_[reg] = value; - build(); - return true; +result CorePrStatus::get(Registers::ARM reg) const { + return get_reg_impl(reg, description_, class_, arch_); } -void CorePrStatus::accept(Visitor& visitor) const { - visitor.visit(*this); +result CorePrStatus::get(Registers::AARCH64 reg) const { + return get_reg_impl(reg, description_, class_, arch_); } - - -uint64_t& CorePrStatus::operator[](REGISTERS reg) { - return ctx_[reg]; +ok_error_t CorePrStatus::set(Registers::X86 reg, uint64_t value) { + return set_reg_impl(reg, value, description_, class_, arch_); } -void CorePrStatus::dump(std::ostream& os) const { - static constexpr size_t WIDTH = 16; - os << std::left; - - os << std::setw(WIDTH) << std::setfill(' ') << "Siginfo: "<< std::dec; - dump(os, siginfo()); - os << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Current Signal: "<< std::dec - << current_sig() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Pending signal: "<< std::dec - << sigpend() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Signal held: "<< std::dec - << sighold() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "PID: "<< std::dec - << pid() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "PPID: "<< std::dec - << ppid() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "PGRP: "<< std::dec - << pgrp() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "SID: "<< std::dec - << sid() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "utime: "<< std::dec; - dump(os, utime()); - os << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "stime: "<< std::dec; - dump(os, stime()); - os << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "cutime: "<< std::dec; - dump(os, cutime()); - os << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "cstime: "<< std::dec; - dump(os, cstime()); - os << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Registers: "<< std::dec << std::endl; - dump(os, reg_context()); - os << std::endl; - +ok_error_t CorePrStatus::set(Registers::X86_64 reg, uint64_t value) { + return set_reg_impl(reg, value, description_, class_, arch_); } -std::ostream& CorePrStatus::dump(std::ostream& os, const CorePrStatus::timeval_t& time) { - os << std::dec; - os << time.sec << ":" << time.usec; - return os; +ok_error_t CorePrStatus::set(Registers::ARM reg, uint64_t value) { + return set_reg_impl(reg, value, description_, class_, arch_); } -std::ostream& CorePrStatus::dump(std::ostream& os, const CorePrStatus::siginfo_t& siginfo) { - os << std::dec; - os << siginfo.si_signo << " - " << siginfo.si_code << " - " << siginfo.si_errno; - return os; +ok_error_t CorePrStatus::set(Registers::AARCH64 reg, uint64_t value) { + return set_reg_impl(reg, value, description_, class_, arch_); } -std::ostream& CorePrStatus::dump(std::ostream& os, const reg_context_t& ctx) { - for (const auto& reg_val : ctx) { - os << std::setw(14) << std::setfill(' ') << to_string(reg_val.first) << ": " << std::hex << std::showbase << reg_val.second << std::endl; +result CorePrStatus::pc() const { + switch (arch_) { + case ARCH::EM_AARCH64: return get(Registers::AARCH64::PC); + case ARCH::EM_ARM: return get(Registers::ARM::R15); + case ARCH::EM_386: return get(Registers::X86::EIP); + case ARCH::EM_X86_64: return get(Registers::X86_64::RIP); + default: return make_error_code(lief_errors::not_supported); } - return os; } - -void CorePrStatus::parse() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - parse_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - parse_(); +result CorePrStatus::sp() const { + switch (arch_) { + case ARCH::EM_AARCH64: return get(Registers::AARCH64::X31); + case ARCH::EM_ARM: return get(Registers::ARM::R13); + case ARCH::EM_386: return get(Registers::X86::ESP); + case ARCH::EM_X86_64: return get(Registers::X86_64::RSP); + default: return make_error_code(lief_errors::not_supported); } } -void CorePrStatus::build() { - if (binary()->type() == ELF_CLASS::ELFCLASS64) { - build_(); - } else if (binary()->type() == ELF_CLASS::ELFCLASS32) { - build_(); +result CorePrStatus::return_value() const { + switch (arch_) { + case ARCH::EM_AARCH64: return get(Registers::AARCH64::X0); + case ARCH::EM_ARM: return get(Registers::ARM::R0); + case ARCH::EM_386: return get(Registers::X86::EAX); + case ARCH::EM_X86_64: return get(Registers::X86_64::RAX); + default: return make_error_code(lief_errors::not_supported); } } +template +void dump_impl(std::ostream& os, const std::vector& reg_vals) { + for (size_t i = 0; i < reg_vals.size(); ++i) { + if constexpr (std::is_void_v) { + os << fmt::format(" 0x{:08x}\n", reg_vals[i]); + } else { + os << fmt::format(" {}: 0x{:08x}\n", to_string(REG(i)), reg_vals[i]); + } + } +} -std::pair CorePrStatus::reg_enum_range() const { - const ARCH arch = binary()->header().machine_type(); - - size_t enum_start = 0; - size_t enum_end = 0; - - switch (arch) { - case ARCH::EM_386: - { - enum_start = static_cast(REGISTERS::X86_START) + 1; - enum_end = static_cast(REGISTERS::X86_END); - break; - } - - case ARCH::EM_X86_64: - { - enum_start = static_cast(REGISTERS::X86_64_START) + 1; - enum_end = static_cast(REGISTERS::X86_64_END); - break; - } - +void CorePrStatus::dump(std::ostream& os) const { + Note::dump(os); + const CorePrStatus::pr_status_t& status = this->status(); + os << '\n' + << fmt::format(" PID: {:04d} PPID: {:04d} PGRP: {:04d}\n", + status.pid, status.ppid, status.pgrp) + << fmt::format(" SID: {:04d} SIGNO: {:04d} SIGCODE: {:04d}\n", + status.sid, status.info.signo, status.info.code) + << fmt::format(" SIGERR: {:04d} SIGPEND: {:04d} SIGHOLD: {:04d}\n", + status.info.err, status.sigpend, status.sighold) + << fmt::format(" CURRSIG: 0x{:04d} reserved: {}\n", + status.cursig, status.reserved); + const std::vector& reg_vals = register_values(); + switch (architecture()) { case ARCH::EM_ARM: - { - enum_start = static_cast(REGISTERS::ARM_START) + 1; - enum_end = static_cast(REGISTERS::ARM_END); - break; - } - + dump_impl(os, reg_vals); break; case ARCH::EM_AARCH64: - { - enum_start = static_cast(REGISTERS::AARCH64_START) + 1; - enum_end = static_cast(REGISTERS::AARCH64_END); - break; - } - + dump_impl(os, reg_vals); break; + case ARCH::EM_386: + dump_impl(os, reg_vals); break; + case ARCH::EM_X86_64: + dump_impl(os, reg_vals); break; default: - { - LIEF_WARN("{} not supported", to_string(arch)); - } + dump_impl(os, reg_vals); break; + } - return {enum_start, enum_end}; } -std::ostream& operator<<(std::ostream& os, const CorePrStatus& note) { - note.dump(os); - return os; +void CorePrStatus::accept(Visitor& visitor) const { + visitor.visit(*this); } +const char* to_string(CorePrStatus::Registers::X86 e) { + #define ENTRY(X) std::pair(CorePrStatus::Registers::X86::X, #X) + STRING_MAP enum_strings { + ENTRY(EBX), + ENTRY(ECX), + ENTRY(EDX), + ENTRY(ESI), + ENTRY(EDI), + ENTRY(EBP), + ENTRY(EAX), + ENTRY(DS), + ENTRY(ES), + ENTRY(FS), + ENTRY(GS), + ENTRY(ORIG_EAX), + ENTRY(EIP), + ENTRY(CS), + ENTRY(EFLAGS), + ENTRY(ESP), + ENTRY(SS), + }; + #undef ENTRY + + if (auto it = enum_strings.find(e); it != enum_strings.end()) { + return it->second; + } + return "UNKNOWN"; +} + +const char* to_string(CorePrStatus::Registers::X86_64 e) { + #define ENTRY(X) std::pair(CorePrStatus::Registers::X86_64::X, #X) + STRING_MAP enums2str { + ENTRY(R15), + ENTRY(R14), + ENTRY(R13), + ENTRY(R12), + ENTRY(RBP), + ENTRY(RBX), + ENTRY(R11), + ENTRY(R10), + ENTRY(R9), + ENTRY(R8), + ENTRY(RAX), + ENTRY(RCX), + ENTRY(RDX), + ENTRY(RSI), + ENTRY(RDI), + ENTRY(ORIG_RAX), + ENTRY(RIP), + ENTRY(CS), + ENTRY(EFLAGS), + ENTRY(RSP), + ENTRY(SS), + }; + #undef ENTRY + + if (auto it = enums2str.find(e); it != enums2str.end()) { + return it->second; + } + return "UNKNOWN"; +} + +const char* to_string(CorePrStatus::Registers::ARM e) { + #define ENTRY(X) std::pair(CorePrStatus::Registers::ARM::X, #X) + STRING_MAP enums2str { + ENTRY(R0), + ENTRY(R1), + ENTRY(R2), + ENTRY(R3), + ENTRY(R4), + ENTRY(R5), + ENTRY(R6), + ENTRY(R7), + ENTRY(R8), + ENTRY(R9), + ENTRY(R10), + ENTRY(R11), + ENTRY(R12), + ENTRY(R13), + ENTRY(R14), + ENTRY(R15), + ENTRY(CPSR), + }; + #undef ENTRY + + if (auto it = enums2str.find(e); it != enums2str.end()) { + return it->second; + } - -CorePrStatus::~CorePrStatus() = default; + return "UNKNOWN"; +} + +const char* to_string(CorePrStatus::Registers::AARCH64 e) { + #define ENTRY(X) std::pair(CorePrStatus::Registers::AARCH64::X, #X) + STRING_MAP enum_strings { + ENTRY(X0), + ENTRY(X1), + ENTRY(X2), + ENTRY(X3), + ENTRY(X4), + ENTRY(X5), + ENTRY(X6), + ENTRY(X7), + ENTRY(X8), + ENTRY(X9), + ENTRY(X10), + ENTRY(X11), + ENTRY(X12), + ENTRY(X13), + ENTRY(X14), + ENTRY(X15), + ENTRY(X15), + ENTRY(X16), + ENTRY(X17), + ENTRY(X18), + ENTRY(X19), + ENTRY(X20), + ENTRY(X21), + ENTRY(X22), + ENTRY(X23), + ENTRY(X24), + ENTRY(X25), + ENTRY(X26), + ENTRY(X27), + ENTRY(X28), + ENTRY(X29), + ENTRY(X30), + ENTRY(X31), + ENTRY(PC), + ENTRY(PSTATE), + }; + #undef ENTRY + + if (auto it = enum_strings.find(e); it != enum_strings.end()) { + return it->second; + } + return "UNKNOWN"; +} } // namespace ELF } // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CorePrStatus.tcc b/src/ELF/NoteDetails/core/CorePrStatus.tcc deleted file mode 100644 index ee9bd756df..0000000000 --- a/src/ELF/NoteDetails/core/CorePrStatus.tcc +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - - -#include "LIEF/utils.hpp" -#include "LIEF/BinaryStream/VectorStream.hpp" -#include "LIEF/iostream.hpp" - -#include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp" - -namespace LIEF { -namespace ELF { - -template -void CorePrStatus::parse_() { - using Elf_Prstatus = typename ELF_T::Elf_Prstatus; - using uint__ = typename ELF_T::uint; - - const Note::description_t& desc = description(); - if (desc.size() < sizeof(Elf_Prstatus)) { - return; - } - const auto* status = reinterpret_cast(desc.data()); - - siginfo_.si_signo = status->pr_info.si_signo; - siginfo_.si_errno = status->pr_info.si_errno; - siginfo_.si_code = status->pr_info.si_code; - - cursig_ = status->pr_cursig; - - sigpend_ = status->pr_sigpend; - sighold_ = status->pr_sighold; - - pid_ = status->pr_pid; - ppid_ = status->pr_ppid; - pgrp_ = status->pr_pgrp; - sid_ = status->pr_sid; - - utime_.sec = status->pr_utime.tv_sec; - utime_.usec = status->pr_utime.tv_usec; - - stime_.sec = status->pr_stime.tv_sec; - stime_.usec = status->pr_stime.tv_usec; - - cutime_.sec = status->pr_cutime.tv_sec; - cutime_.usec = status->pr_cutime.tv_usec; - - cstime_.sec = status->pr_cstime.tv_sec; - cstime_.usec = status->pr_cstime.tv_usec; - - size_t enum_start = 0; - size_t enum_end = 0; - std::tie(enum_start, enum_end) = reg_enum_range(); - - VectorStream stream(std::move(desc)); - stream.setpos(sizeof(Elf_Prstatus)); - - for (size_t i = enum_start; i < enum_end; ++i) { - auto val = stream.read(); - if (!val) { - break; - } - ctx_[static_cast(i)] = *val; - } -} - -template -void CorePrStatus::build_() { - using Elf_Prstatus = typename ELF_T::Elf_Prstatus; - using uint__ = typename ELF_T::uint; - - Note::description_t& desc = description(); - Elf_Prstatus status; - - status.pr_info.si_signo = static_cast(siginfo_.si_signo); - status.pr_info.si_code = static_cast(siginfo_.si_code); - status.pr_info.si_errno = static_cast(siginfo_.si_errno); - - status.pr_cursig = static_cast(cursig_); - status.reserved = static_cast(0xFE19); - - status.pr_sigpend = static_cast(sigpend_); - status.pr_sighold = static_cast(sighold_); - - status.pr_pid = static_cast(pid_); - status.pr_ppid = static_cast(ppid_); - status.pr_pgrp = static_cast(pgrp_); - status.pr_sid = static_cast(sid_); - - status.pr_utime.tv_sec = static_cast(utime_.sec); - status.pr_utime.tv_usec = static_cast(utime_.usec); - - status.pr_stime.tv_sec = static_cast(stime_.sec); - status.pr_stime.tv_usec = static_cast(stime_.usec); - - status.pr_cutime.tv_sec = static_cast(cutime_.sec); - status.pr_cutime.tv_usec = static_cast(cutime_.usec); - - status.pr_cstime.tv_sec = static_cast(cstime_.sec); - status.pr_cstime.tv_usec = static_cast(cstime_.usec); - - vector_iostream raw_output; - size_t desc_part_size = sizeof(Elf_Prstatus); - raw_output.reserve(desc_part_size); - raw_output.write(reinterpret_cast(&status), sizeof(Elf_Prstatus)); - - size_t enum_start = 0; - size_t enum_end = 0; - std::tie(enum_start, enum_end) = reg_enum_range(); - - for (size_t i = enum_start; i < enum_end; ++i) { - auto reg = static_cast(i); - auto val = static_cast(get(reg)); - raw_output.write_conv(val); - } - - std::vector raw = raw_output.raw(); - std::copy(std::begin(raw), std::end(raw), - std::begin(desc)); - -} - -} // namespace ELF -} // namespace LIEF diff --git a/src/ELF/NoteDetails/core/CoreSigInfo.cpp b/src/ELF/NoteDetails/core/CoreSigInfo.cpp index 4c0e5faea8..6165140afb 100644 --- a/src/ELF/NoteDetails/core/CoreSigInfo.cpp +++ b/src/ELF/NoteDetails/core/CoreSigInfo.cpp @@ -17,108 +17,56 @@ #include #include +#include "LIEF/BinaryStream/SpanStream.hpp" #include "LIEF/ELF/hash.hpp" - -#include "LIEF/ELF/Note.hpp" #include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp" #include "ELF/Structures.hpp" +#include "spdlog/fmt/fmt.h" + namespace LIEF { namespace ELF { -CoreSigInfo::CoreSigInfo(Note& note): - NoteDetails::NoteDetails{note} -{} - -CoreSigInfo CoreSigInfo::make(Note& note) { - CoreSigInfo pinfo(note); - pinfo.parse(); - return pinfo; -} - -CoreSigInfo* CoreSigInfo::clone() const { - return new CoreSigInfo(*this); -} +static constexpr auto signo_offset = offsetof(details::Elf_siginfo, si_signo); +static constexpr auto sigcode_offset = offsetof(details::Elf_siginfo, si_code); +static constexpr auto si_errno_offset = offsetof(details::Elf_siginfo, si_errno); -int32_t CoreSigInfo::signo() const { - return siginfo_.si_signo; +result CoreSigInfo::signo() const { + return read_at(signo_offset); } -int32_t CoreSigInfo::sigcode() const { - return siginfo_.si_code; +result CoreSigInfo::sigcode() const { + return read_at(sigcode_offset); } -int32_t CoreSigInfo::sigerrno() const { - return siginfo_.si_errno; +result CoreSigInfo::sigerrno() const { + return read_at(si_errno_offset); } -void CoreSigInfo::signo(int32_t signo) { - siginfo_.si_signo = signo; - build(); +void CoreSigInfo::signo(uint32_t value) { + write_at(signo_offset, value); } -void CoreSigInfo::sigcode(int32_t sigcode) { - siginfo_.si_code = sigcode; - build(); +void CoreSigInfo::sigcode(uint32_t value) { + write_at(sigcode_offset, value); } -void CoreSigInfo::sigerrno(int32_t sigerrno) { - siginfo_.si_errno = sigerrno; - build(); +void CoreSigInfo::sigerrno(uint32_t value) { + write_at(si_errno_offset, value); } void CoreSigInfo::accept(Visitor& visitor) const { visitor.visit(*this); } - - void CoreSigInfo::dump(std::ostream& os) const { - static constexpr size_t WIDTH = 16; - os << std::left; - - os << std::setw(WIDTH) << std::setfill(' ') << "Signo: "<< std::dec - << signo() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Code: "<< std::dec - << sigcode() << std::endl; - - os << std::setw(WIDTH) << std::setfill(' ') << "Errno: "<< std::dec - << sigerrno() << std::endl; + Note::dump(os); + os << '\n' + << fmt::format(" signo: {} code: {} errno: {}\n", + signo().value_or(-1), + sigcode().value_or(-1), + sigerrno().value_or(-1)); } - -void CoreSigInfo::parse() { - const Note::description_t& desc = description(); - if (desc.size() < sizeof(details::Elf_siginfo)) { - return; - } - const auto* siginfo = reinterpret_cast(desc.data()); - siginfo_.si_signo = siginfo->si_signo; - siginfo_.si_code = siginfo->si_code; - siginfo_.si_errno = siginfo->si_errno; -} - - -void CoreSigInfo::build() { - Note::description_t& desc = description(); - if (desc.size() < sizeof(details::Elf_siginfo)) { - desc.resize(sizeof(details::Elf_siginfo)); - } - std::copy( - reinterpret_cast(&siginfo_), - reinterpret_cast(&siginfo_) + sizeof(details::Elf_siginfo), - std::begin(desc)); -} - - -std::ostream& operator<<(std::ostream& os, const CoreSigInfo& note) { - note.dump(os); - return os; -} - - -CoreSigInfo::~CoreSigInfo() = default; - } // namespace ELF } // namespace LIEF diff --git a/src/ELF/Parser.cpp b/src/ELF/Parser.cpp index 17749e2d7f..7f1c87ec1c 100644 --- a/src/ELF/Parser.cpp +++ b/src/ELF/Parser.cpp @@ -30,7 +30,6 @@ #include "LIEF/ELF/Symbol.hpp" #include "LIEF/ELF/Note.hpp" #include "LIEF/ELF/SysvHash.hpp" -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" #include "ELF/DataHandler/Handler.hpp" @@ -502,92 +501,88 @@ ok_error_t Parser::parse_symbol_sysv_hash(uint64_t offset) { return ok(); } -ok_error_t Parser::parse_notes(uint64_t offset, uint64_t size) { - LIEF_DEBUG("== Parsing note segment =="); +#if 0 +std::unique_ptr Parser::get_note(uint32_t type, std::string name, + std::vector desc_bytes) +{ + const E_TYPE ftype = binary_->header().file_type(); - stream_->setpos(offset); - uint64_t last_offset = offset + size; + auto conv = Note::convert_type(ftype, type, name); + if (!conv) { + LIEF_WARN("Note type: 0x{:x} is not supported for owner: '{}'", type, name); + return std::make_unique(std::move(name), Note::TYPE::UNKNOWN, type, + std::move(desc_bytes)); + } - while(stream_->pos() < last_offset) { - const size_t pos = stream_->pos(); - auto res_namesz = stream_->read_conv(); - if (!res_namesz) { - break; - } + Note::TYPE ntype = *conv; - const auto namesz = *res_namesz; - LIEF_DEBUG("[0x{:06x}] Name size: 0x{:x}", pos, namesz); + if (ntype != Note::TYPE::GNU_BUILD_ATTRIBUTE_FUNC && + ntype != Note::TYPE::GNU_BUILD_ATTRIBUTE_OPEN) + { + name = name.c_str(); + } - auto res_descz = stream_->read_conv(); - if (!res_descz) { - break; - } + const ARCH arch = binary_->header().machine_type(); + const ELF_CLASS cls = binary_->header().identity_class(); - uint32_t descsz = std::min(*res_descz, Parser::MAX_NOTE_DESCRIPTION); - LIEF_DEBUG("Description size: 0x{:x}", descsz); + if (cls != ELF_CLASS::ELFCLASS32 && cls != ELF_CLASS::ELFCLASS64) { + LIEF_WARN("Invalid ELFCLASS"); + return nullptr; + } - auto res_type = stream_->read_conv(); - if (!res_type) { - break; - } + switch (ntype) { + case Note::TYPE::CORE_PRSTATUS: + return std::make_unique(arch, cls, std::move(name), type, + std::move(desc_bytes)); + case Note::TYPE::CORE_PRPSINFO: + return std::make_unique(arch, cls, std::move(name), type, + std::move(desc_bytes)); + case Note::TYPE::CORE_FILE: + return std::make_unique(arch, cls, std::move(name), type, + std::move(desc_bytes)); + case Note::TYPE::CORE_AUXV: + return std::make_unique(arch, cls, std::move(name), type, + std::move(desc_bytes)); + case Note::TYPE::CORE_SIGINFO: + return std::make_unique(std::move(name), ntype, type, + std::move(desc_bytes)); + case Note::TYPE::ANDROID_IDENT: + return std::make_unique(std::move(name), ntype, type, + std::move(desc_bytes)); + case Note::TYPE::GNU_ABI_TAG: + return std::make_unique(std::move(name), ntype, type, + std::move(desc_bytes)); - auto type = static_cast(*res_type); - LIEF_DEBUG("Type: 0x{:x}", static_cast(type)); + default: + return std::make_unique(std::move(name), ntype, type, + std::move(desc_bytes)); + } +} +#endif - if (namesz == 0) { // System reserves - break; - } - std::vector name_buffer(namesz, 0); - if (!stream_->read_data(name_buffer, namesz)) { - LIEF_ERR("Can't read note name"); - break; - } +ok_error_t Parser::parse_notes(uint64_t offset, uint64_t size) { + LIEF_DEBUG("== Parsing note segment =="); - std::string name(reinterpret_cast(name_buffer.data()), name_buffer.size()); - if (type != NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_FUNC && - type != NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_OPEN) - { - name = name.c_str(); - } - LIEF_DEBUG("Name: {}", name); - - stream_->align(sizeof(uint32_t)); - - std::vector description; - if (descsz > 0) { - const size_t nb_chunks = (descsz - 1) / sizeof(uint32_t) + 1; - description.reserve(nb_chunks); - for (size_t i = 0; i < nb_chunks; ++i) { - if (const auto chunk = stream_->read_conv()) { - description.push_back(*chunk); - } else { - break; - } - } - stream_->align(sizeof(uint32_t)); - } - std::unique_ptr note; - std::vector desc_bytes; - if (!description.empty()) { - desc_bytes = { - reinterpret_cast(description.data()), - reinterpret_cast(description.data()) + description.size() * sizeof(uint32_t) - }; - } + stream_->setpos(offset); + uint64_t last_offset = offset + size; - if (binary_->header().file_type() == E_TYPE::ET_CORE) { - note = std::make_unique(name, static_cast(type), - std::move(desc_bytes), binary_.get()); + while(stream_->pos() < last_offset) { + std::unique_ptr note = Note::create( + *stream_, + binary_->header().file_type(), binary_->header().machine_type(), + binary_->header().identity_class() + ); + + if (note != nullptr) { + const auto it_note = std::find_if( + std::begin(binary_->notes_), std::end(binary_->notes_), + [¬e] (const std::unique_ptr& n) { return *n == *note; }); + + if (it_note == std::end(binary_->notes_)) { // Not already present + binary_->notes_.push_back(std::move(note)); + } } else { - note = std::make_unique(name, type, std::move(desc_bytes), binary_.get()); - } - - const auto it_note = std::find_if( - std::begin(binary_->notes_), std::end(binary_->notes_), - [¬e] (const std::unique_ptr& n) { return *n == *note; }); - - if (it_note == std::end(binary_->notes_)) { // Not already present - binary_->notes_.push_back(std::move(note)); + LIEF_WARN("Note not parsed!"); } } return ok(); diff --git a/src/ELF/Structures.hpp b/src/ELF/Structures.hpp index 5236305fee..ff73ba6539 100644 --- a/src/ELF/Structures.hpp +++ b/src/ELF/Structures.hpp @@ -12,9 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* From llvm/Support/ELF.h */ -#ifndef LIEF_ELF_STRUCTURES_H_ -#define LIEF_ELF_STRUCTURES_H_ +#ifndef LIEF_ELF_STRUCTURES_H +#define LIEF_ELF_STRUCTURES_H #include @@ -22,7 +21,6 @@ #include "LIEF/ELF/enums.hpp" namespace LIEF { -//! @brief Namespace related to the LIEF's ELF module namespace ELF { namespace details { @@ -159,7 +157,40 @@ static const DYNAMIC_FLAGS_1 dynamic_flags_1_array[] = { DYNAMIC_FLAGS_1::DF_1_PIE, }; +struct Elf64_Prpsinfo +{ + char pr_state; + char pr_sname; + char pr_zomb; + char pr_nice; + uint32_t pr_pad; + uint64_t pr_flag; + uint32_t pr_uid; + uint32_t pr_gid; + int32_t pr_pid; + int32_t pr_ppid; + int32_t pr_pgrp; + int32_t pr_sid; + char pr_fname[16]; + char pr_psargs[80]; +}; +struct Elf32_Prpsinfo +{ + char pr_state; + char pr_sname; + char pr_zomb; + char pr_nice; + uint32_t pr_flag; + uint16_t pr_uid; + uint16_t pr_gid; + int32_t pr_pid; + int32_t pr_ppid; + int32_t pr_pgrp; + int32_t pr_sid; + char pr_fname[16]; + char pr_psargs[80]; +}; class ELF32 { public: diff --git a/src/ELF/hash.cpp b/src/ELF/hash.cpp index f5d97da19e..e66b1426a3 100644 --- a/src/ELF/hash.cpp +++ b/src/ELF/hash.cpp @@ -26,8 +26,7 @@ #include "LIEF/ELF/GnuHash.hpp" #include "LIEF/ELF/Header.hpp" #include "LIEF/ELF/Note.hpp" -#include "LIEF/ELF/NoteDetails.hpp" -#include "LIEF/ELF/NoteDetails/AndroidNote.hpp" +#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp" #include "LIEF/ELF/NoteDetails/NoteAbi.hpp" #include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp" #include "LIEF/ELF/NoteDetails/core/CoreFile.hpp" @@ -233,84 +232,36 @@ void Hash::visit(const SymbolVersionAuxRequirement& svar) { void Hash::visit(const Note& note) { process(note.name()); process(note.type()); + process(note.original_type()); process(note.description()); } -void Hash::visit(const NoteDetails& details) { - process(details.description()); +void Hash::visit(const AndroidIdent& note) { + visit(static_cast(note)); } - -void Hash::visit(const AndroidNote& note) { - visit(static_cast(note)); -} - +// void Hash::visit(const NoteAbi& note) { - visit(static_cast(note)); + visit(static_cast(note)); } void Hash::visit(const CorePrPsInfo& pinfo) { - process(pinfo.file_name()); - process(pinfo.flags()); - process(pinfo.uid()); - process(pinfo.gid()); - process(pinfo.pid()); - process(pinfo.ppid()); - process(pinfo.pgrp()); - process(pinfo.sid()); + visit(static_cast(pinfo)); } void Hash::visit(const CorePrStatus& pstatus) { - process(pstatus.siginfo().si_code); - process(pstatus.siginfo().si_errno); - process(pstatus.siginfo().si_signo); - - process(pstatus.current_sig()); - process(pstatus.sigpend()); - process(pstatus.sighold()); - process(pstatus.pid()); - process(pstatus.ppid()); - process(pstatus.pgrp()); - process(pstatus.sid()); - - process(pstatus.utime().sec); - process(pstatus.utime().usec); - - process(pstatus.stime().sec); - process(pstatus.stime().usec); - - process(pstatus.cutime().sec); - process(pstatus.cutime().usec); - - process(pstatus.cstime().sec); - process(pstatus.cstime().usec); - - for (const CorePrStatus::reg_context_t::value_type& val : pstatus.reg_context()) { - process(val.first); // Register - process(val.second); // Value - } + visit(static_cast(pstatus)); } void Hash::visit(const CoreAuxv& auxv) { - for (const CoreAuxv::val_context_t::value_type& val : auxv.values()) { - process(val.first); // Type - process(val.second); // Value - } + visit(static_cast(auxv)); } void Hash::visit(const CoreSigInfo& siginfo) { - process(siginfo.signo()); - process(siginfo.sigcode()); - process(siginfo.sigerrno()); + visit(static_cast(siginfo)); } void Hash::visit(const CoreFile& file) { - process(file.count()); - for (const CoreFileEntry& entry : file.files()) { - process(entry.start); - process(entry.end); - process(entry.file_ofs); - process(entry.path); - } + visit(static_cast(file)); } void Hash::visit(const GnuHash& gnuhash) { diff --git a/src/ELF/json.cpp b/src/ELF/json.cpp index d2e00aa83d..863b275958 100644 --- a/src/ELF/json.cpp +++ b/src/ELF/json.cpp @@ -378,84 +378,135 @@ void JsonVisitor::visit(const SymbolVersionAuxRequirement& svar) { } void JsonVisitor::visit(const Note& note) { - node_["name"] = note.name(); - const std::string type_str = note.is_core() ? to_string(note.type_core()) : to_string(note.type()); - node_["type"] = type_str; - JsonVisitor visitor; - const NoteDetails& d = note.details(); - d.accept(visitor); - node_["details"] = visitor.get(); -} - -void JsonVisitor::visit(const NoteDetails&) { - node_ = json::object(); + node_["name"] = note.name(); + node_["type"] = to_string(note.type()); + node_["original_type"] = note.original_type(); } void JsonVisitor::visit(const NoteAbi& note_abi) { - node_["abi"] = to_string(note_abi.abi()); - node_["version"] = note_abi.version(); + visit(static_cast(note_abi)); + if (auto abi = note_abi.abi()) { + node_["abi"] = to_string(*abi); + } + if (auto version = note_abi.version()) { + node_["version"] = *version; + } } void JsonVisitor::visit(const CorePrPsInfo& pinfo) { - node_["file_name"] = pinfo.file_name(); - node_["flags"] = pinfo.flags(); - node_["uid"] = pinfo.uid(); - node_["gid"] = pinfo.gid(); - node_["pid"] = pinfo.pid(); - node_["ppid"] = pinfo.ppid(); - node_["pgrp"] = pinfo.pgrp(); - node_["sid"] = pinfo.sid(); + visit(static_cast(pinfo)); + auto info = pinfo.info(); + if (!info) { + return; + } + node_["state"] = info->state; + node_["sname"] = info->sname; + node_["zombie"] = info->zombie; + node_["flag"] = info->flag; + node_["uid"] = info->uid; + node_["gid"] = info->gid; + node_["pid"] = info->pid; + node_["ppid"] = info->ppid; + node_["pgrp"] = info->pgrp; + node_["sid"] = info->sid; + node_["filename"] = info->filename_stripped(); + node_["args"] = info->args_stripped(); } - void JsonVisitor::visit(const CorePrStatus& pstatus) { - node_["current_sig"] = pstatus.current_sig(); - node_["sigpend"] = pstatus.sigpend(); - node_["sighold"] = pstatus.sighold(); - node_["pid"] = pstatus.pid(); - node_["ppid"] = pstatus.ppid(); - node_["pgrp"] = pstatus.pgrp(); - node_["sid"] = pstatus.sid(); - node_["sigpend"] = pstatus.sigpend(); + visit(static_cast(pstatus)); + const CorePrStatus::pr_status_t& status = pstatus.status(); + node_["current_sig"] = status.cursig; + node_["sigpend"] = status.sigpend; + node_["sighold"] = status.sighold; + node_["pid"] = status.pid; + node_["ppid"] = status.ppid; + node_["pgrp"] = status.pgrp; + node_["sid"] = status.sid; + node_["sigpend"] = status.sigpend; node_["utime"] = { - {"tv_sec", pstatus.utime().sec}, - {"tv_usec", pstatus.utime().usec} + {"tv_sec", status.utime.sec}, + {"tv_usec", status.utime.usec} }; node_["stime"] = { - {"tv_sec", pstatus.stime().sec}, - {"tv_usec", pstatus.stime().sec} + {"tv_sec", status.stime.sec}, + {"tv_usec", status.stime.sec} }; node_["stime"] = { - {"tv_sec", pstatus.stime().sec}, - {"tv_usec", pstatus.stime().usec} + {"tv_sec", status.stime.sec}, + {"tv_usec", status.stime.usec} }; - json regs; - for (const CorePrStatus::reg_context_t::value_type& val : pstatus.reg_context()) { - regs[to_string(val.first)] = val.second; - }; - node_["regs"] = regs; + std::vector reg_vals = pstatus.register_values(); + if (!reg_vals.empty()) { + json regs; + switch (pstatus.architecture()) { + case ARCH::EM_386: + { + for (size_t i = 0; i < reg_vals.size(); ++i) { + regs[to_string(CorePrStatus::Registers::X86(i))] = reg_vals[i]; + } + break; + } + case ARCH::EM_X86_64: + { + for (size_t i = 0; i < reg_vals.size(); ++i) { + regs[to_string(CorePrStatus::Registers::X86_64(i))] = reg_vals[i]; + } + break; + } + case ARCH::EM_ARM: + { + for (size_t i = 0; i < reg_vals.size(); ++i) { + regs[to_string(CorePrStatus::Registers::ARM(i))] = reg_vals[i]; + } + break; + } + case ARCH::EM_AARCH64: + { + for (size_t i = 0; i < reg_vals.size(); ++i) { + regs[to_string(CorePrStatus::Registers::AARCH64(i))] = reg_vals[i]; + } + break; + } + default: + { + regs = reg_vals; + } + } + node_["regs"] = regs; + } } void JsonVisitor::visit(const CoreAuxv& auxv) { + visit(static_cast(auxv)); std::vector values; - for (const CoreAuxv::val_context_t::value_type& val : auxv.values()) { - node_[to_string(val.first)] = val.second; + const std::map aux_values = auxv.values(); + for (const auto& [k, v] : aux_values) { + node_[to_string(k)] = v; } } void JsonVisitor::visit(const CoreSigInfo& siginfo) { - node_["signo"] = siginfo.signo(); - node_["sigcode"] = siginfo.sigcode(); - node_["sigerrno"] = siginfo.sigerrno(); + visit(static_cast(siginfo)); + if (auto signo = siginfo.signo()) { + node_["signo"] = *signo; + } + if (auto sigcode = siginfo.sigcode()) { + node_["sigcode"] = *sigcode; + } + if (auto sigerrno = siginfo.sigerrno()) { + node_["sigerrno"] = *sigerrno; + } } void JsonVisitor::visit(const CoreFile& file) { + visit(static_cast(file)); std::vector files; - for (const CoreFileEntry& entry : file.files()) { + for (const CoreFile::entry_t& entry : file.files()) { const json file = { {"start", entry.start}, {"end", entry.end}, @@ -468,6 +519,14 @@ void JsonVisitor::visit(const CoreFile& file) { node_["count"] = file.count(); } +void JsonVisitor::visit(const AndroidIdent& ident) { + visit(static_cast(ident)); + node_["ndk_version"] = ident.ndk_version(); + node_["sdk_verison"] = ident.sdk_version(); + node_["ndk_build_number"] = ident.ndk_build_number(); +} + + void JsonVisitor::visit(const GnuHash& gnuhash) { node_["nb_buckets"] = gnuhash.nb_buckets(); node_["symbol_index"] = gnuhash.symbol_index(); diff --git a/src/ELF/json_internal.hpp b/src/ELF/json_internal.hpp index 37c563ade0..f15dec2ae5 100644 --- a/src/ELF/json_internal.hpp +++ b/src/ELF/json_internal.hpp @@ -23,7 +23,7 @@ namespace LIEF { namespace ELF { -class AndroidNote; +class AndroidIdent; class Binary; class CoreAuxv; class CoreFile; @@ -80,7 +80,7 @@ class JsonVisitor : public LIEF::JsonVisitor { void visit(const SymbolVersionDefinition& svd) override; void visit(const Note& note) override; void visit(const NoteAbi& note) override; - void visit(const NoteDetails& details) override; + void visit(const AndroidIdent& note) override; void visit(const CorePrPsInfo& pinfo) override; void visit(const CorePrStatus& pstatus) override; void visit(const CoreAuxv& auxv) override; diff --git a/src/ELF/note_utils.cpp b/src/ELF/note_utils.cpp deleted file mode 100644 index a104cca19f..0000000000 --- a/src/ELF/note_utils.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "notes_utils.hpp" - -namespace LIEF { -namespace ELF { -const note_to_section_map_t& get_note_to_section() { - static const note_to_section_map_t note_to_section_map = { - { NOTE_TYPES::NT_GNU_ABI_TAG, ".note.ABI-tag" }, - { NOTE_TYPES::NT_GNU_ABI_TAG, ".note.android.ident" }, - - { NOTE_TYPES::NT_GNU_HWCAP, ".note.gnu.hwcap" }, - { NOTE_TYPES::NT_GNU_BUILD_ID, ".note.gnu.build-id" }, - { NOTE_TYPES::NT_GNU_BUILD_ID, ".note.stapsdt" }, // Alternative name - { NOTE_TYPES::NT_GNU_GOLD_VERSION, ".note.gnu.gold-version" }, - { NOTE_TYPES::NT_GNU_GOLD_VERSION, ".note.go.buildid" }, - { NOTE_TYPES::NT_GNU_PROPERTY_TYPE_0, ".note.gnu.property" }, - { NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_OPEN, ".gnu.build.attributes" }, - { NOTE_TYPES::NT_GNU_BUILD_ATTRIBUTE_FUNC, ".gnu.build.attributes" }, - { NOTE_TYPES::NT_CRASHPAD, ".note.crashpad.info" }, - - { NOTE_TYPES::NT_UNKNOWN, ".note" }, - }; - return note_to_section_map; -} -} -} diff --git a/src/ELF/notes_utils.hpp b/src/ELF/notes_utils.hpp deleted file mode 100644 index a0dedc17b2..0000000000 --- a/src/ELF/notes_utils.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2017 - 2023 R. Thomas - * Copyright 2017 - 2023 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef LIEF_ELF_NOTES_UTILS_H -#define LIEF_ELF_NOTES_UTILS_H -#include "LIEF/ELF/enums.hpp" - -#include - -namespace LIEF { -namespace ELF { -using note_to_section_map_t = std::multimap; - -const note_to_section_map_t& get_note_to_section(); - -} -} -#endif diff --git a/src/ELF/structures.inc b/src/ELF/structures.inc index 6343208bd7..5c9e503b1c 100644 --- a/src/ELF/structures.inc +++ b/src/ELF/structures.inc @@ -268,41 +268,6 @@ struct Elf32_Verdaux Elf32_Word vda_next; /**< Offset in bytes to next verdaux entry */ }; -/** Structure for note type NT_PRPSINFO */ -struct Elf64_Prpsinfo -{ - char pr_state; /**< Numeric process state */ - char pr_sname; /**< Char for pr_state */ - char pr_zomb; /**< Process is a zombie */ - char pr_nice; /**< Nice value */ - uint32_t pr_pad; - uint64_t pr_flag; /**< Process flags */ - uint32_t pr_uid; /**< Process user ID */ - uint32_t pr_gid; /**< Process group ID */ - int32_t pr_pid; /**< Process ID */ - int32_t pr_ppid; /**< Process parent ID */ - int32_t pr_pgrp; /**< Process group */ - int32_t pr_sid; /**< Process session ID */ - char pr_fname[16]; /**< Filename of executable */ - char pr_psargs[80]; /**< Initial part of arg list */ -}; - -struct Elf32_Prpsinfo -{ - char pr_state; /**< Numeric process state */ - char pr_sname; /**< Char for pr_state */ - char pr_zomb; /**< Process is a zombie */ - char pr_nice; /**< Nice value */ - uint32_t pr_flag; /**< Process flags */ - uint16_t pr_uid; /**< Process user ID */ - uint16_t pr_gid; /**< Process group ID */ - int32_t pr_pid; /**< Process ID */ - int32_t pr_ppid; /**< Process parent ID */ - int32_t pr_pgrp; /**< Process group */ - int32_t pr_sid; /**< Process session ID */ - char pr_fname[16]; /**< Filename of executable */ - char pr_psargs[80]; /**< Initial part of arg list */ -}; struct Elf_siginfo { int32_t si_signo; diff --git a/src/frozen.hpp b/src/frozen.hpp index 9dd66596c5..d62053a65a 100644 --- a/src/frozen.hpp +++ b/src/frozen.hpp @@ -19,11 +19,19 @@ #include "compiler_support.h" #ifdef LIEF_FROZEN_ENABLED -#include -#define CONST_MAP(KEY, VAL, NUM) constexpr frozen::map -#else -#include -#define CONST_MAP(KEY, VAL, NUM) static const std::unordered_map +# include +# define CONST_MAP(KEY, VAL, NUM) constexpr frozen::map +# define STRING_MAP constexpr frozen::map +# define CONST_MAP_ALT constexpr frozen::map +namespace frozen { +template +map(std::pair, Args...) -> map; +} +#else // !LIEF_FROZEN_ENABLED +# include +# define CONST_MAP(KEY, VAL, NUM) static const std::unordered_map +# define STRING_MAP static const std::unordered_map +# define CONST_MAP_ALT static const std::unordered_map #endif #endif diff --git a/src/internal_utils.hpp b/src/internal_utils.hpp index e11eec17e7..aefa660c23 100644 --- a/src/internal_utils.hpp +++ b/src/internal_utils.hpp @@ -20,8 +20,10 @@ #include #include #include +#include "spdlog/fmt/fmt.h" #include "LIEF/span.hpp" +#include "LIEF/errors.hpp" namespace LIEF { @@ -37,6 +39,30 @@ inline std::vector as_vector(span s) { return std::vector(s.begin(), s.end()); } +template +inline const char* to_string_or(result res, const char* defval = "???") { + return res ? to_string(*res) : defval; +} + +template +inline std::string to_hex(const T& container, size_t maxsize = 0) { + size_t count = maxsize; + if (count == 0 || count > container.size()) { + count = container.size(); + } + std::string out; + out.reserve(count * 2); + for (size_t i = 0; i < count; ++i) { + out += fmt::format("{:02x} ", container[i]); + } + if (count < container.size()) { + out += "..."; + } else{ + out.pop_back(); // remove trailing ' ' + } + return out; +} + template std::vector optimize(const HANDLER& container, std::string(* getter)(const typename HANDLER::value_type&), diff --git a/tests/elf/test_core.py b/tests/elf/test_core.py index 4499c66338..2560fdf0a5 100644 --- a/tests/elf/test_core.py +++ b/tests/elf/test_core.py @@ -7,138 +7,127 @@ lief.logging.set_level(lief.logging.LOGGING_LEVEL.INFO) def test_core_arm(): - core = lief.parse(get_sample('ELF/ELF32_ARM_core_hello.core')) + core: lief.ELF.Binary = lief.parse(get_sample('ELF/ELF32_ARM_core_hello.core')) notes = core.notes assert len(notes) == 6 + assert all(len(str(n).strip()) > 0 for n in notes), "\n".join(str(n) for n in notes) # Check NT_PRPSINFO # ================= - prpsinfo = notes[0] + prpsinfo: lief.ELF.CorePrPsInfo = notes[0] + assert isinstance(prpsinfo, lief.ELF.CorePrPsInfo) - assert prpsinfo.is_core - assert prpsinfo.type_core == lief.ELF.NOTE_TYPES_CORE.PRPSINFO + assert prpsinfo.type == lief.ELF.Note.TYPE.CORE_PRPSINFO - # Check details - details = prpsinfo.details - assert isinstance(details, lief.ELF.CorePrPsInfo) + info = prpsinfo.info - assert details.file_name == "hello-exe" - assert details.uid == 2000 - assert details.gid == 2000 - assert details.pid == 8166 - assert details.ppid == 8163 - assert details.pgrp == 8166 - assert details.sid == 7997 + # Check details + assert info.filename_stripped == "hello-exe" + assert info.args_stripped == "./hello-exe " + assert info.uid == 2000 + assert info.gid == 2000 + assert info.pid == 8166 + assert info.ppid == 8163 + assert info.pgrp == 8166 + assert info.sid == 7997 # Check NT_PRSTATUS # ================= - prstatus = notes[1] + prstatus: lief.ELF.CorePrStatus = notes[1] - assert prstatus.is_core - assert prstatus.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS + assert prstatus.type == lief.ELF.Note.TYPE.CORE_PRSTATUS # Check details - details = prstatus.details - - assert details.current_sig == 7 - assert details.sigpend == 0 - assert details.sighold == 0 - assert details.pid == 8166 - assert details.ppid == 0 - assert details.pgrp == 0 - assert details.sid == 0 - - assert details.utime.sec == 0 - assert details.utime.usec == 0 - - assert details.stime.sec == 0 - assert details.stime.usec == 0 - - assert details.cutime.sec == 0 - assert details.cutime.usec == 0 - - assert details.cstime.sec == 0 - assert details.cstime.usec == 0 - - reg_ctx = details.register_context - assert len(reg_ctx) == 17 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R0] == 0xaad75074 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R1] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R2] == 0xb - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R3] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R4] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R5] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R6] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R7] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R8] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R9] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R10] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R11] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R12] == 0xA - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R13] == 1 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R14] == 0xf7728841 - assert details[lief.ELF.CorePrStatus.REGISTERS.ARM_R15] == 0xaad7507c - assert details.get(lief.ELF.CorePrStatus.REGISTERS.ARM_CPSR) == 0x60010010 + + status = prstatus.status + assert status.cursig == 7 + assert status.sigpend == 0 + assert status.sighold == 0 + assert status.pid == 8166 + assert status.ppid == 0 + assert status.pgrp == 0 + assert status.sid == 0 + + assert status.utime.sec == 0 + assert status.utime.usec == 0 + + assert status.stime.sec == 0 + assert status.stime.usec == 0 + + assert status.cutime.sec == 0 + assert status.cutime.usec == 0 + + assert status.cstime.sec == 0 + assert status.cstime.usec == 0 + + reg_values = prstatus.register_values + assert len(reg_values) == 17 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R0.value] == 0xaad75074 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R1.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R2.value] == 0xb + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R3.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R4.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R5.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R6.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R7.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R8.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R9.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R10.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R11.value] == 0 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R12.value] == 0xA + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R13.value] == 1 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R14.value] == 0xf7728841 + assert reg_values[lief.ELF.CorePrStatus.Registers.ARM.R15.value] == 0xaad7507c + assert prstatus.get(lief.ELF.CorePrStatus.Registers.ARM.CPSR) == 0x60010010 arm_vfp = notes[2] - # Check NT_NOTE - # ================= - siginfo = notes[3] - assert siginfo.is_core - assert siginfo.type_core == lief.ELF.NOTE_TYPES_CORE.SIGINFO + siginfo: lief.ELF.CoreSigInfo = notes[3] + assert siginfo.type == lief.ELF.Note.TYPE.CORE_SIGINFO - # Check details - details = siginfo.details - assert details.signo == 7 - assert details.sigcode == 0 - assert details.sigerrno == 1 + assert siginfo.signo == 7 + assert siginfo.sigcode == 0 + assert siginfo.sigerrno == 1 # Check NT_AUXV # ================= - auxv = notes[4] - - assert auxv.is_core - assert auxv.type_core == lief.ELF.NOTE_TYPES_CORE.AUXV - - # Check details - details = auxv.details - - assert len(details.values) == 18 - assert details[lief.ELF.CoreAuxv.TYPES.PHDR] == 0xaad74034 - assert details[lief.ELF.CoreAuxv.TYPES.PHENT] == 0x20 - assert details[lief.ELF.CoreAuxv.TYPES.PHNUM] == 0x9 - assert details[lief.ELF.CoreAuxv.TYPES.PAGESZ] == 4096 - assert details[lief.ELF.CoreAuxv.TYPES.BASE] == 0xf7716000 - assert details[lief.ELF.CoreAuxv.TYPES.FLAGS] == 0 - assert details[lief.ELF.CoreAuxv.TYPES.ENTRY] == 0xaad75074 - assert details[lief.ELF.CoreAuxv.TYPES.UID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.EUID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.GID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.EGID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.PLATFORM] == 0xfffefb5c - assert details[lief.ELF.CoreAuxv.TYPES.HWCAP] == 0x27b0d6 - assert details[lief.ELF.CoreAuxv.TYPES.CKLTCK] == 0x64 - assert details[lief.ELF.CoreAuxv.TYPES.SECURE] == 0 - assert details[lief.ELF.CoreAuxv.TYPES.RANDOM] == 0xfffefb4c - assert details[lief.ELF.CoreAuxv.TYPES.HWCAP2] == 0x1f - assert details[lief.ELF.CoreAuxv.TYPES.EXECFN] == 0xfffeffec + auxv: lief.ELF.CoreAuxv = notes[4] + + assert auxv.type == lief.ELF.Note.TYPE.CORE_AUXV + + assert len(auxv.values) == 18 + assert auxv[lief.ELF.CoreAuxv.TYPE.PHDR] == 0xaad74034 + assert auxv[lief.ELF.CoreAuxv.TYPE.PHENT] == 0x20 + assert auxv[lief.ELF.CoreAuxv.TYPE.PHNUM] == 0x9 + assert auxv[lief.ELF.CoreAuxv.TYPE.PAGESZ] == 4096 + assert auxv[lief.ELF.CoreAuxv.TYPE.BASE] == 0xf7716000 + assert auxv[lief.ELF.CoreAuxv.TYPE.FLAGS] == 0 + assert auxv[lief.ELF.CoreAuxv.TYPE.ENTRY] == 0xaad75074 + assert auxv[lief.ELF.CoreAuxv.TYPE.UID] == 2000 + assert auxv[lief.ELF.CoreAuxv.TYPE.EUID] == 2000 + assert auxv[lief.ELF.CoreAuxv.TYPE.GID] == 2000 + assert auxv[lief.ELF.CoreAuxv.TYPE.EGID] == 2000 + assert auxv[lief.ELF.CoreAuxv.TYPE.TGT_PLATFORM] == 0xfffefb5c + assert auxv[lief.ELF.CoreAuxv.TYPE.HWCAP] == 0x27b0d6 + assert auxv[lief.ELF.CoreAuxv.TYPE.CLKTCK] == 0x64 + assert auxv[lief.ELF.CoreAuxv.TYPE.SECURE] == 0 + assert auxv[lief.ELF.CoreAuxv.TYPE.RANDOM] == 0xfffefb4c + assert auxv[lief.ELF.CoreAuxv.TYPE.HWCAP2] == 0x1f + assert auxv[lief.ELF.CoreAuxv.TYPE.EXECFN] == 0xfffeffec # Check NT_FILE # ================= - note = notes[5] + note: lief.ELF.CoreFile = notes[5] - assert note.is_core - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.FILE + assert note.type == lief.ELF.Note.TYPE.CORE_FILE # Check details - details = note.details - files = details.files + files = note.files - assert len(files) == len(details) - assert 21 == len(details) + assert len(files) == len(note) + assert 21 == len(note) assert files[0].start == 0xaad74000 assert files[0].end == 0xaad78000 @@ -152,7 +141,7 @@ def test_core_arm(): assert last.file_ofs == 0x8a000 assert last.path == "/system/bin/linker" - assert all(len(c.path) > 0 for c in details) + assert all(len(c.path) > 0 for c in note) def test_core_arm64(): @@ -162,149 +151,141 @@ def test_core_arm64(): assert len(notes) == 6 + assert all(len(str(n).strip()) > 0 for n in notes) + # Check NT_PRPSINFO # ================= - prpsinfo = notes[0] + prpsinfo: lief.ELF.CorePrPsInfo = notes[0] - assert prpsinfo.is_core - assert prpsinfo.type_core == lief.ELF.NOTE_TYPES_CORE.PRPSINFO + assert prpsinfo.type == lief.ELF.Note.TYPE.CORE_PRPSINFO # Check details - details = prpsinfo.details - assert isinstance(details, lief.ELF.CorePrPsInfo) - assert details.file_name == "hello-exe" - assert details.uid == 2000 - assert details.gid == 2000 - assert details.pid == 8104 - assert details.ppid == 8101 - assert details.pgrp == 8104 - assert details.sid == 7997 + assert isinstance(prpsinfo, lief.ELF.CorePrPsInfo) + info = prpsinfo.info + assert info.filename_stripped == "hello-exe" + assert info.args_stripped == "./hello-exe " + assert info.uid == 2000 + assert info.gid == 2000 + assert info.pid == 8104 + assert info.ppid == 8101 + assert info.pgrp == 8104 + assert info.sid == 7997 # Check NT_PRSTATUS # ================= - prstatus = notes[1] + prstatus: lief.ELF.CorePrStatus = notes[1] - assert prstatus.is_core - assert prstatus.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS + assert prstatus.type == lief.ELF.Note.TYPE.CORE_PRSTATUS # Check details - details = prstatus.details - - assert details.current_sig == 5 - assert details.sigpend == 0 - assert details.sighold == 0 - assert details.pid == 8104 - assert details.ppid == 0 - assert details.pgrp == 0 - assert details.sid == 0 - - assert details.utime.sec == 0 - assert details.utime.usec == 0 - - assert details.stime.sec == 0 - assert details.stime.usec == 0 - - assert details.cutime.sec == 0 - assert details.cutime.usec == 0 - - assert details.cstime.sec == 0 - assert details.cstime.usec == 0 - - - reg_ctx = details.register_context - assert len(reg_ctx) == 34 - - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X0] == 0x5580b86f50 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X1] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X2] == 0x1 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X3] == 0x7fb7e2e160 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X4] == 0x7fb7e83030 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X5] == 0x4 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X6] == 0x6f6c2f617461642f - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X7] == 0x2f706d742f6c6163 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X8] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X9] == 0xa - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X10] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X11] == 0xA - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X12] == 0x0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X13] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X14] == 0x878ca62ae01a9a5 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X15] == 0x7fb7e7a000 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X16] == 0x7fb7c132c8 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X17] == 0x7fb7bb0adc - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X18] == 0x7fb7c1e000 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X19] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X20] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X21] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X22] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X23] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X24] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X25] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X26] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X27] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X28] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X29] == 0 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X30] == 0x7fb7eb6068 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_X31] == 0x7ffffff950 - assert details[lief.ELF.CorePrStatus.REGISTERS.AARCH64_PC] == 0x5580b86f50 - - arm_vfp = notes[2] + status = prstatus.status + + assert status.cursig == 5 + assert status.sigpend == 0 + assert status.sighold == 0 + assert status.pid == 8104 + assert status.ppid == 0 + assert status.pgrp == 0 + assert status.sid == 0 + + assert status.utime.sec == 0 + assert status.utime.usec == 0 + + assert status.stime.sec == 0 + assert status.stime.usec == 0 + + assert status.cutime.sec == 0 + assert status.cutime.usec == 0 + + assert status.cstime.sec == 0 + assert status.cstime.usec == 0 + + regs = prstatus.register_values + assert len(regs) == 34 + + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X0.value] == 0x5580b86f50 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X1.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X2.value] == 0x1 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X3.value] == 0x7fb7e2e160 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X4.value] == 0x7fb7e83030 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X5.value] == 0x4 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X6.value] == 0x6f6c2f617461642f + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X7.value] == 0x2f706d742f6c6163 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X8.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X9.value] == 0xa + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X10.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X11.value] == 0xA + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X12.value] == 0x0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X13.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X14.value] == 0x878ca62ae01a9a5 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X15.value] == 0x7fb7e7a000 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X16.value] == 0x7fb7c132c8 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X17.value] == 0x7fb7bb0adc + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X18.value] == 0x7fb7c1e000 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X19.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X20.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X21.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X22.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X23.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X24.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X25.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X26.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X27.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X28.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X29.value] == 0 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X30.value] == 0x7fb7eb6068 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.X31.value] == 0x7ffffff950 + assert regs[lief.ELF.CorePrStatus.Registers.AARCH64.PC.value] == 0x5580b86f50 + + fpregset = notes[2] + assert fpregset.type == lief.ELF.Note.TYPE.CORE_FPREGSET # Check NT_NOTE # ================= siginfo = notes[3] - assert siginfo.is_core - assert siginfo.type_core == lief.ELF.NOTE_TYPES_CORE.SIGINFO + assert siginfo.type == lief.ELF.Note.TYPE.CORE_SIGINFO - # Check details - details = siginfo.details - assert details.signo == 5 - assert details.sigcode == 0 - assert details.sigerrno == 1 + assert siginfo.signo == 5 + assert siginfo.sigcode == 0 + assert siginfo.sigerrno == 1 # Check NT_AUXV # ================= - auxv = notes[4] + auxv: lief.ELF.CoreAuxv = notes[4] - assert auxv.is_core - assert auxv.type_core == lief.ELF.NOTE_TYPES_CORE.AUXV + assert auxv.type == lief.ELF.Note.TYPE.CORE_AUXV # Check details - details = auxv.details - - assert len(details.values) == 18 - assert details[lief.ELF.CoreAuxv.TYPES.PHDR] == 0x5580b86040 - assert details[lief.ELF.CoreAuxv.TYPES.PHENT] == 0x38 - assert details[lief.ELF.CoreAuxv.TYPES.PHNUM] == 0x9 - assert details[lief.ELF.CoreAuxv.TYPES.PAGESZ] == 4096 - assert details[lief.ELF.CoreAuxv.TYPES.BASE] == 0x7fb7e93000 - assert details[lief.ELF.CoreAuxv.TYPES.FLAGS] == 0 - assert details[lief.ELF.CoreAuxv.TYPES.ENTRY] == 0x5580b86f50 - assert details[lief.ELF.CoreAuxv.TYPES.UID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.EUID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.GID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.EGID] == 2000 - assert details[lief.ELF.CoreAuxv.TYPES.PLATFORM] == 0x7ffffffb58 - assert details[lief.ELF.CoreAuxv.TYPES.HWCAP] == 0xff - assert details[lief.ELF.CoreAuxv.TYPES.CKLTCK] == 0x64 - assert details[lief.ELF.CoreAuxv.TYPES.SECURE] == 0 - assert details[lief.ELF.CoreAuxv.TYPES.RANDOM] == 0x7ffffffb48 - assert details[lief.ELF.CoreAuxv.TYPES.EXECFN] == 0x7fffffffec - assert details[lief.ELF.CoreAuxv.TYPES.SYSINFO_EHDR] == 0x7fb7e91000 + values = auxv.values + assert len(values) == 18 + assert values[lief.ELF.CoreAuxv.TYPE.PHDR] == 0x5580b86040 + assert values[lief.ELF.CoreAuxv.TYPE.PHENT] == 0x38 + assert values[lief.ELF.CoreAuxv.TYPE.PHNUM] == 0x9 + assert values[lief.ELF.CoreAuxv.TYPE.PAGESZ] == 4096 + assert values[lief.ELF.CoreAuxv.TYPE.BASE] == 0x7fb7e93000 + assert values[lief.ELF.CoreAuxv.TYPE.FLAGS] == 0 + assert values[lief.ELF.CoreAuxv.TYPE.ENTRY] == 0x5580b86f50 + assert values[lief.ELF.CoreAuxv.TYPE.UID] == 2000 + assert values[lief.ELF.CoreAuxv.TYPE.EUID] == 2000 + assert values[lief.ELF.CoreAuxv.TYPE.GID] == 2000 + assert values[lief.ELF.CoreAuxv.TYPE.EGID] == 2000 + assert values[lief.ELF.CoreAuxv.TYPE.TGT_PLATFORM] == 0x7ffffffb58 + assert values[lief.ELF.CoreAuxv.TYPE.HWCAP] == 0xff + assert values[lief.ELF.CoreAuxv.TYPE.CLKTCK] == 0x64 + assert values[lief.ELF.CoreAuxv.TYPE.SECURE] == 0 + assert values[lief.ELF.CoreAuxv.TYPE.RANDOM] == 0x7ffffffb48 + assert values[lief.ELF.CoreAuxv.TYPE.EXECFN] == 0x7fffffffec + assert values[lief.ELF.CoreAuxv.TYPE.SYSINFO_EHDR] == 0x7fb7e91000 # Check NT_FILE # ================= - note = notes[5] - - assert note.is_core - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.FILE + note: lief.ELF.CoreFile = notes[5] - # Check details - details = note.details - files = details.files + assert note.type == lief.ELF.Note.TYPE.CORE_FILE - assert len(files) == len(details) - assert 22 == len(details) + files = note.files + assert len(files) == len(note) + assert 22 == len(files) assert files[0].start == 0x5580b86000 assert files[0].end == 0x5580b88000 @@ -320,23 +301,19 @@ def test_core_arm64(): def test_core_write(tmp_path: Path): core = lief.parse(get_sample('ELF/ELF64_x86-64_core_hello.core')) note = core.notes[1] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS - details = note.details + assert note.type == lief.ELF.Note.TYPE.CORE_PRSTATUS - details[lief.ELF.CorePrStatus.REGISTERS.X86_64_RIP] = 0xBADC0DE + note[lief.ELF.CorePrStatus.Registers.X86_64.RIP] = 0xBADC0DE note = core.notes[5] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.AUXV - details = note.details + assert note.type == lief.ELF.Note.TYPE.CORE_AUXV - details[lief.ELF.CoreAuxv.TYPES.ENTRY] = 0xBADC0DE + note[lief.ELF.CoreAuxv.TYPE.ENTRY] = 0xBADC0DE note = core.notes[4] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.SIGINFO + assert note.type == lief.ELF.Note.TYPE.CORE_SIGINFO orig_siginfo_len = len(note.description) - details = note.details - - details.sigerrno = 0xCC + note.sigerrno = 0xCC output = tmp_path / "elf.core" @@ -349,20 +326,17 @@ def test_core_write(tmp_path: Path): assert core_new is not None note = core_new.notes[1] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.PRSTATUS - details = note.details + assert note.type == lief.ELF.Note.TYPE.CORE_PRSTATUS - assert details[lief.ELF.CorePrStatus.REGISTERS.X86_64_RIP] == 0xBADC0DE + assert note[lief.ELF.CorePrStatus.Registers.X86_64.RIP] == 0xBADC0DE note = core_new.notes[5] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.AUXV - details = note.details + assert note.type == lief.ELF.Note.TYPE.CORE_AUXV - assert details[lief.ELF.CoreAuxv.TYPES.ENTRY] == 0xBADC0DE + assert note[lief.ELF.CoreAuxv.TYPE.ENTRY] == 0xBADC0DE note = core_new.notes[4] - assert note.type_core == lief.ELF.NOTE_TYPES_CORE.SIGINFO + assert note.type == lief.ELF.Note.TYPE.CORE_SIGINFO assert len(note.description) == orig_siginfo_len - details = note.details - assert details.sigerrno == 0xCC + assert note.sigerrno == 0xCC diff --git a/tests/elf/test_elf.py b/tests/elf/test_elf.py index 3acfc20a57..184419c88f 100644 --- a/tests/elf/test_elf.py +++ b/tests/elf/test_elf.py @@ -122,12 +122,14 @@ def test_notes(): assert n2.name == "GNU" assert n3.name == "GNU" - assert n1.type == lief.ELF.NOTE_TYPES.ABI_TAG - assert n2.type == lief.ELF.NOTE_TYPES.BUILD_ID - assert n3.type == lief.ELF.NOTE_TYPES.GOLD_VERSION + assert n1.type == lief.ELF.Note.TYPE.GNU_ABI_TAG + assert n2.type == lief.ELF.Note.TYPE.GNU_BUILD_ID + assert n3.type == lief.ELF.Note.TYPE.GNU_GOLD_VERSION - assert n1.details.abi == lief.ELF.NOTE_ABIS.LINUX - assert n1.details.version == [2, 6, 32] + assert isinstance(n1, lief.ELF.NoteAbi) + + assert n1.abi == lief.ELF.NoteAbi.ABI.LINUX + assert n1.version == [2, 6, 32] assert list(n2.description) == [0x7e, 0x68, 0x6c, 0x7d, 0x79, 0x9b, 0xa4, 0xcd, diff --git a/tests/elf/test_notes.py b/tests/elf/test_notes.py index 790400aa4c..287a2cf6d8 100644 --- a/tests/elf/test_notes.py +++ b/tests/elf/test_notes.py @@ -13,7 +13,7 @@ def test_change_note(tmp_path: Path): etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_etterlog.bin')) - build_id = etterlog[lief.ELF.NOTE_TYPES.BUILD_ID] + build_id = etterlog[lief.ELF.Note.TYPE.GNU_BUILD_ID] new_desc = [i & 0xFF for i in range(500)] build_id.description = new_desc @@ -22,25 +22,25 @@ def test_change_note(tmp_path: Path): etterlog_updated = lief.parse(output.as_posix()) - assert etterlog[lief.ELF.NOTE_TYPES.BUILD_ID] == etterlog_updated[lief.ELF.NOTE_TYPES.BUILD_ID] + assert etterlog[lief.ELF.Note.TYPE.GNU_BUILD_ID] == etterlog_updated[lief.ELF.Note.TYPE.GNU_BUILD_ID] def test_remove_note(tmp_path: Path): etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_etterlog.bin')) output = tmp_path / "etterlog" print(output) - build_id = etterlog[lief.ELF.NOTE_TYPES.BUILD_ID] + build_id = etterlog[lief.ELF.Note.TYPE.GNU_BUILD_ID] assert build_id is not None etterlog -= build_id etterlog.write(output.as_posix(), config) etterlog_updated = lief.parse(output.as_posix()) - assert lief.ELF.NOTE_TYPES.BUILD_ID not in etterlog_updated + assert lief.ELF.Note.TYPE.GNU_BUILD_ID not in etterlog_updated def test_add_note(tmp_path: Path): etterlog = lief.parse(get_sample('ELF/ELF64_x86-64_binary_etterlog.bin')) output = tmp_path / "etterlog" - note = lief.ELF.Note("Foo", lief.ELF.NOTE_TYPES.GOLD_VERSION, [123]) + note = lief.ELF.Note.create("Foo", lief.ELF.Note.TYPE.GNU_GOLD_VERSION, [1, 2]) etterlog += note @@ -48,10 +48,10 @@ def test_add_note(tmp_path: Path): etterlog_updated = lief.parse(output.as_posix()) - assert lief.ELF.NOTE_TYPES.GOLD_VERSION in etterlog_updated + assert lief.ELF.Note.TYPE.GNU_GOLD_VERSION in etterlog_updated - - # The string printed is largely irrelevant, but running print ensures no regression occurs in a previous Note::dump segfault + # The string printed is largely irrelevant, but running print ensures no + # regression occurs in a previous Note::dump segfault # https://github.com/lief-project/LIEF/issues/300 with StringIO() as temp_stdout: with redirect_stdout(temp_stdout): @@ -62,17 +62,16 @@ def test_android_note(tmp_path: Path): ndkr16 = lief.parse(get_sample('ELF/ELF64_AArch64_piebinary_ndkr16.bin')) output = tmp_path / "etterlog" - note = ndkr16.get(lief.ELF.NOTE_TYPES.ABI_TAG) - details = note.details - assert details.sdk_version == 21 - assert details.ndk_version[:4] == "r16b" - assert details.ndk_build_number[:7] == "4479499" + note: lief.ELF.AndroidIdent = ndkr16.get(lief.ELF.Note.TYPE.ANDROID_IDENT) + assert note.sdk_version == 21 + assert note.ndk_version[:4] == "r16b" + assert note.ndk_build_number[:7] == "4479499" - details.sdk_version = 15 - details.ndk_version = "r15c" - details.ndk_build_number = "123456" + note.sdk_version = 15 + note.ndk_version = "r15c" + note.ndk_build_number = "123456" - note = ndkr16.get(lief.ELF.NOTE_TYPES.ABI_TAG).details + note = ndkr16.get(lief.ELF.Note.TYPE.ANDROID_IDENT) assert note.sdk_version == 15 assert note.ndk_version[:4] == "r15c" @@ -82,7 +81,7 @@ def test_android_note(tmp_path: Path): ndkr15 = lief.parse(output.as_posix()) - note = ndkr15.get(lief.ELF.NOTE_TYPES.ABI_TAG).details + note = ndkr15.get(lief.ELF.Note.TYPE.ANDROID_IDENT) assert note.sdk_version == 15 assert note.ndk_version[:4] == "r15c" @@ -98,3 +97,9 @@ def test_issue_816(tmp_path: Path): elf.write(output.as_posix(), config) new = lief.parse(output.as_posix()) assert len(new.notes) == 40 + +def test_crashpad(): + RAW_CRASHPAD = "0900000008000000494e464f437261736870616400000000d85cf00300000000" + note = lief.ELF.Note.create(bytes.fromhex(RAW_CRASHPAD)) + assert note.type == lief.ELF.Note.TYPE.CRASHPAD + assert note.name == "Crashpad" diff --git a/tests/elf/test_parser.py b/tests/elf/test_parser.py index e6e3c14251..bfda877a08 100644 --- a/tests/elf/test_parser.py +++ b/tests/elf/test_parser.py @@ -135,3 +135,9 @@ def test_path_like(): def test_984(): elf = lief.ELF.parse(get_sample('ELF/issue_984_ilp32.o')) assert len(elf.sections) > 0 + +def test_975(): + elf = lief.ELF.parse(get_sample('ELF/issue_975_aarch64.o')) + for note in elf.notes: + print(note) + #assert len(elf.sections) > 0 diff --git a/tests/elf/test_parser_simple.py b/tests/elf/test_parser_simple.py index 911d86ecf9..bca0688cb8 100644 --- a/tests/elf/test_parser_simple.py +++ b/tests/elf/test_parser_simple.py @@ -105,11 +105,11 @@ def test_notes(): notes = TARGET.notes assert len(notes) == 2 - assert notes[0].details.abi == lief.ELF.NOTE_ABIS.LINUX - assert notes[0].description == [0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0] + assert notes[0].abi == lief.ELF.NoteAbi.ABI.LINUX + assert list(notes[0].description) == [0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0] assert notes[0].name == "GNU" - assert notes[0].type == lief.ELF.NOTE_TYPES.ABI_TAG - assert notes[0].details.version == [3, 2, 0] + assert notes[0].type == lief.ELF.Note.TYPE.GNU_ABI_TAG + assert notes[0].version == [3, 2, 0] def test_symbols_sections(): """ diff --git a/tests/elf/test_str_hash.py b/tests/elf/test_str_hash.py index 88a46d3137..a6baa5fab3 100644 --- a/tests/elf/test_str_hash.py +++ b/tests/elf/test_str_hash.py @@ -49,9 +49,7 @@ def test_hash(): assert hash(resolve.header) > 0 assert hash(etterlog.notes[0]) > 0 - assert hash(etterlog.notes[0].details) > 0 - #assert super(lief.ELF.NoteDetails, etterlog.notes[0].details) is None - #assert etterlog.notes[0].details is None + assert hash(etterlog.notes[0]) > 0 assert hash(etterlog.relocations[0]) > 0 assert hash(etterlog.sections[0]) > 0 assert hash(etterlog.segments[0]) > 0 @@ -109,7 +107,6 @@ def test_str(capsys): print(resolve.header) print(etterlog.notes[0]) - print(etterlog.notes[0].details) print(etterlog.relocations[0]) print(etterlog.sections[0]) print(etterlog.segments[0])