Skip to content

Commit

Permalink
Add support for ELF NT_GNU_PROPERTY_TYPE_0 (read-only)
Browse files Browse the repository at this point in the history
See: `tests/elf/test_notes.py` for API usage

Resolve: #975
  • Loading branch information
romainthomas committed Dec 2, 2023
1 parent e6503fe commit fac0e78
Show file tree
Hide file tree
Showing 44 changed files with 2,271 additions and 74 deletions.
154 changes: 154 additions & 0 deletions api/python/lief/ELF.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from typing import overload
import io
import lief # type: ignore
import lief.ELF # type: ignore
import lief.ELF.AArch64Feature # type: ignore
import lief.ELF.Binary # type: ignore
import lief.ELF.Builder # type: ignore
import lief.ELF.CoreAuxv # type: ignore
Expand All @@ -13,12 +14,31 @@ 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.NoteGnuProperty # type: ignore
import lief.ELF.NoteGnuProperty.Property # type: ignore
import lief.ELF.Section # type: ignore
import lief.ELF.Segment # type: ignore
import lief.ELF.SymbolVersionDefinition # type: ignore
import lief.ELF.SymbolVersionRequirement # type: ignore
import lief.ELF.X86Features # type: ignore
import lief.ELF.X86ISA # type: ignore
import os

class AArch64Feature(NoteGnuProperty.Property):
class FEATURE:
BTI: ClassVar[AArch64Feature.FEATURE] = ...
PAC: ClassVar[AArch64Feature.FEATURE] = ...
UNKNOWN: ClassVar[AArch64Feature.FEATURE] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.AArch64Feature.FEATURE: ...
@property
def value(self) -> int: ...
def __init__(self, *args, **kwargs) -> None: ...
@property
def features(self) -> list[lief.ELF.AArch64Feature.FEATURE]: ...

class ARCH:
AARCH64: ClassVar[ARCH] = ...
ALPHA: ClassVar[ARCH] = ...
Expand Down Expand Up @@ -1194,6 +1214,11 @@ class E_TYPE:
@property
def value(self) -> int: ...

class Generic(NoteGnuProperty.Property):
def __init__(self, *args, **kwargs) -> None: ...
@property
def raw_type(self) -> int: ...

class GnuHash(lief.Object):
def __init__(self) -> None: ...
@overload
Expand Down Expand Up @@ -1489,6 +1514,34 @@ class NoteAbi(Note):
@property
def version(self) -> Optional[list[int]]: ...

class NoteGnuProperty(Note):
class Property:
class TYPE:
AARCH64_FEATURES: ClassVar[NoteGnuProperty.Property.TYPE] = ...
GENERIC: ClassVar[NoteGnuProperty.Property.TYPE] = ...
NEEDED: ClassVar[NoteGnuProperty.Property.TYPE] = ...
NO_COPY_ON_PROTECTED: ClassVar[NoteGnuProperty.Property.TYPE] = ...
STACK_SIZE: ClassVar[NoteGnuProperty.Property.TYPE] = ...
UNKNOWN: ClassVar[NoteGnuProperty.Property.TYPE] = ...
X86_FEATURE: ClassVar[NoteGnuProperty.Property.TYPE] = ...
X86_ISA: ClassVar[NoteGnuProperty.Property.TYPE] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.NoteGnuProperty.Property.TYPE: ...
@property
def value(self) -> int: ...
def __init__(self, *args, **kwargs) -> None: ...
@property
def type(self) -> lief.ELF.NoteGnuProperty.Property.TYPE: ...
def __init__(self, *args, **kwargs) -> None: ...
def find(self, arg: lief.ELF.NoteGnuProperty.Property.TYPE, /) -> Optional[lief.ELF.NoteGnuProperty.Property]: ...
@property
def properties(self) -> list[Optional[lief.ELF.NoteGnuProperty.Property]]: ...

class NoteNoCopyOnProtected(NoteGnuProperty.Property):
def __init__(self, *args, **kwargs) -> None: ...

class OS_ABI:
AIX: ClassVar[OS_ABI] = ...
AMDGPU_HSA: ClassVar[OS_ABI] = ...
Expand Down Expand Up @@ -2604,6 +2657,11 @@ class Segment(lief.Object):
@property
def sections(self) -> lief.ELF.Segment.it_sections: ...

class StackSize(NoteGnuProperty.Property):
def __init__(self, *args, **kwargs) -> None: ...
@property
def stack_size(self) -> int: ...

class Symbol(lief.Symbol):
binding: lief.ELF.SYMBOL_BINDINGS
exported: bool
Expand Down Expand Up @@ -2702,6 +2760,102 @@ class VERSION:
@property
def value(self) -> int: ...

class X86Features(NoteGnuProperty.Property):
class FEATURE:
FXSR: ClassVar[X86Features.FEATURE] = ...
IBT: ClassVar[X86Features.FEATURE] = ...
LAM_U48: ClassVar[X86Features.FEATURE] = ...
LAM_U57: ClassVar[X86Features.FEATURE] = ...
MASK: ClassVar[X86Features.FEATURE] = ...
MMX: ClassVar[X86Features.FEATURE] = ...
SHSTK: ClassVar[X86Features.FEATURE] = ...
TMM: ClassVar[X86Features.FEATURE] = ...
UNKNOWN: ClassVar[X86Features.FEATURE] = ...
X86: ClassVar[X86Features.FEATURE] = ...
X87: ClassVar[X86Features.FEATURE] = ...
XMM: ClassVar[X86Features.FEATURE] = ...
XSAVE: ClassVar[X86Features.FEATURE] = ...
XSAVEC: ClassVar[X86Features.FEATURE] = ...
XSAVEOPT: ClassVar[X86Features.FEATURE] = ...
YMM: ClassVar[X86Features.FEATURE] = ...
ZMM: ClassVar[X86Features.FEATURE] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.X86Features.FEATURE: ...
@property
def value(self) -> int: ...

class FLAG:
NEEDED: ClassVar[X86Features.FLAG] = ...
NONE: ClassVar[X86Features.FLAG] = ...
USED: ClassVar[X86Features.FLAG] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.X86Features.FLAG: ...
@property
def value(self) -> int: ...
def __init__(self, *args, **kwargs) -> None: ...
@property
def features(self) -> list[tuple[lief.ELF.X86Features.FLAG,lief.ELF.X86Features.FEATURE]]: ...

class X86ISA(NoteGnuProperty.Property):
class FLAG:
NEEDED: ClassVar[X86ISA.FLAG] = ...
NONE: ClassVar[X86ISA.FLAG] = ...
USED: ClassVar[X86ISA.FLAG] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.X86ISA.FLAG: ...
@property
def value(self) -> int: ...

class ISA:
AVX: ClassVar[X86ISA.ISA] = ...
AVX2: ClassVar[X86ISA.ISA] = ...
AVX512BW: ClassVar[X86ISA.ISA] = ...
AVX512CD: ClassVar[X86ISA.ISA] = ...
AVX512DQ: ClassVar[X86ISA.ISA] = ...
AVX512ER: ClassVar[X86ISA.ISA] = ...
AVX512F: ClassVar[X86ISA.ISA] = ...
AVX512PF: ClassVar[X86ISA.ISA] = ...
AVX512VL: ClassVar[X86ISA.ISA] = ...
AVX512_4FMAPS: ClassVar[X86ISA.ISA] = ...
AVX512_4VNNIW: ClassVar[X86ISA.ISA] = ...
AVX512_BF16: ClassVar[X86ISA.ISA] = ...
AVX512_BITALG: ClassVar[X86ISA.ISA] = ...
AVX512_IFMA: ClassVar[X86ISA.ISA] = ...
AVX512_VBMI: ClassVar[X86ISA.ISA] = ...
AVX512_VBMI2: ClassVar[X86ISA.ISA] = ...
AVX512_VNNI: ClassVar[X86ISA.ISA] = ...
BASELINE: ClassVar[X86ISA.ISA] = ...
CMOV: ClassVar[X86ISA.ISA] = ...
FMA: ClassVar[X86ISA.ISA] = ...
I486: ClassVar[X86ISA.ISA] = ...
I586: ClassVar[X86ISA.ISA] = ...
I686: ClassVar[X86ISA.ISA] = ...
SSE: ClassVar[X86ISA.ISA] = ...
SSE2: ClassVar[X86ISA.ISA] = ...
SSE3: ClassVar[X86ISA.ISA] = ...
SSE4_1: ClassVar[X86ISA.ISA] = ...
SSE4_2: ClassVar[X86ISA.ISA] = ...
SSSE3: ClassVar[X86ISA.ISA] = ...
UNKNOWN: ClassVar[X86ISA.ISA] = ...
V2: ClassVar[X86ISA.ISA] = ...
V3: ClassVar[X86ISA.ISA] = ...
V4: ClassVar[X86ISA.ISA] = ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ELF.X86ISA.ISA: ...
@property
def value(self) -> int: ...
def __init__(self, *args, **kwargs) -> None: ...
@property
def values(self) -> list[tuple[lief.ELF.X86ISA.FLAG,lief.ELF.X86ISA.ISA]]: ...

@overload
def parse(filename: str, config: lief.ELF.ParserConfig = ...) -> Optional[lief.ELF.Binary]: ...
@overload
Expand Down
2 changes: 2 additions & 0 deletions api/python/src/ELF/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "LIEF/ELF/Note.hpp"
#include "LIEF/ELF/NoteDetails/AndroidIdent.hpp"
#include "LIEF/ELF/NoteDetails/NoteAbi.hpp"
#include "LIEF/ELF/NoteDetails/NoteGnuProperty.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp"
#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp"
Expand All @@ -57,6 +58,7 @@ namespace LIEF::ELF::py {

void init_notes(nb::module_& m) {
CREATE(Note, m);
CREATE(NoteGnuProperty, m);
CREATE(AndroidIdent, m);
CREATE(NoteAbi, m);
CREATE(CoreAuxv, m);
Expand Down
2 changes: 2 additions & 0 deletions api/python/src/ELF/objects/NoteDetails/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
target_sources(pyLIEF PRIVATE
pyAndroidIdent.cpp
pyNoteAbi.cpp
pyNoteGnuProperty.cpp
)

add_subdirectory(core)
add_subdirectory(properties)

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
target_sources(pyLIEF PRIVATE
pyAArch64Feature.cpp
pyGeneric.cpp
pyNoteNoCopyOnProtected.cpp
pyX86Features.cpp
pyX86ISA.cpp
pyStackSize.cpp
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* 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 <string>
#include <sstream>

#include <nanobind/stl/vector.h>

#include "enums_wrapper.hpp"
#include "ELF/pyELF.hpp"

#include "LIEF/ELF/NoteDetails/properties/AArch64Feature.hpp"

namespace LIEF::ELF::py {

template<>
void create<AArch64Feature>(nb::module_& m) {
nb::class_<AArch64Feature, NoteGnuProperty::Property>
Class(m, "AArch64Feature",
R"doc(
This class represents the `GNU_PROPERTY_AARCH64_FEATURE_1_AND` note.
)doc"_doc);

Class
.def_prop_ro("features", &AArch64Feature::features,
R"doc(
Return the list of the supported features.
)doc"_doc);

# define ENTRY(X, D) .value(to_string(AArch64Feature::FEATURE::X), AArch64Feature::FEATURE::X, D)
enum_<AArch64Feature::FEATURE>(Class, "FEATURE")
ENTRY(UNKNOWN, "")
ENTRY(BTI, "Support Branch Target Identification (BTI)")
ENTRY(PAC, "Support Pointer authentication (PAC)")
;
# undef ENTRY
}

}
36 changes: 36 additions & 0 deletions api/python/src/ELF/objects/NoteDetails/properties/pyGeneric.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* 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 "ELF/pyELF.hpp"

#include "LIEF/ELF/NoteDetails/properties/Generic.hpp"

namespace LIEF::ELF::py {

template<>
void create<Generic>(nb::module_& m) {
nb::class_<Generic, NoteGnuProperty::Property>(m, "Generic",
R"doc(
This class represents a property which doesn't have a concrete LIEF implementation.
)doc")
.def_prop_ro("raw_type", &Generic::type,
R"doc(
The original raw type as an integer. This value might depends
on the architecture and/or the file type.
)doc");

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* 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 "ELF/pyELF.hpp"

#include "LIEF/ELF/NoteDetails/properties/NoteNoCopyOnProtected.hpp"

namespace LIEF::ELF::py {

template<>
void create<NoteNoCopyOnProtected>(nb::module_& m) {
nb::class_<NoteNoCopyOnProtected, NoteGnuProperty::Property> Class(
m, "NoteNoCopyOnProtected",
R"doc(
This class provides an interface over the `GNU_PROPERTY_NO_COPY_ON_PROTECTED`
property. This property indicates that the linker shouldn't copy relocations
against protected symbols.
)doc"_doc
);

}

}
33 changes: 33 additions & 0 deletions api/python/src/ELF/objects/NoteDetails/properties/pyStackSize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* 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 "ELF/pyELF.hpp"

#include "LIEF/ELF/NoteDetails/properties/StackSize.hpp"

namespace LIEF::ELF::py {

template<>
void create<StackSize>(nb::module_& m) {
nb::class_<StackSize, NoteGnuProperty::Property>(m, "StackSize",
R"doc(
This class provides an interface over the `GNU_PROPERTY_STACK_SIZE` property
This property can be used by the loader to raise the stack limit.
)doc")
.def_prop_ro("stack_size", &StackSize::stack_size);

}

}
Loading

0 comments on commit fac0e78

Please sign in to comment.