Skip to content

Commit d15b1c7

Browse files
committed
elf: implement GNU_PROPERTY_1_NEEDED support
1 parent e976496 commit d15b1c7

File tree

13 files changed

+229
-5
lines changed

13 files changed

+229
-5
lines changed

api/python/lief/ELF.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5159,7 +5159,7 @@ class Needed(NoteGnuProperty.Property):
51595159

51605160
def __int__(self) -> int: ...
51615161

5162-
UNKNOWN = 0
5162+
NEED = 0
51635163

51645164
INDIRECT_EXTERN_ACCESS = 1
51655165

api/python/src/ELF/objects/NoteDetails/properties/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ target_sources(pyLIEF PRIVATE
22
pyAArch64Feature.cpp
33
pyAArch64PAuth.cpp
44
pyGeneric.cpp
5+
pyNeeded.cpp
56
pyNoteNoCopyOnProtected.cpp
67
pyX86Features.cpp
78
pyX86ISA.cpp
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* Copyright 2017 - 2026 R. Thomas
2+
* Copyright 2017 - 2026 Quarkslab
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <string>
17+
18+
#include <nanobind/stl/vector.h>
19+
20+
#include "enums_wrapper.hpp"
21+
#include "ELF/pyELF.hpp"
22+
23+
#include "LIEF/ELF/NoteDetails/properties/Needed.hpp"
24+
25+
namespace LIEF::ELF::py {
26+
27+
template<>
28+
void create<Needed>(nb::module_& m) {
29+
using NEED = Needed::NEED;
30+
nb::class_<Needed, NoteGnuProperty::Property>
31+
Class(m, "Needed",
32+
R"doc(
33+
This class represents the ``GNU_PROPERTY_1_NEEDED`` note property
34+
which provides information about additional features the object file
35+
needs at runtime.
36+
)doc"_doc);
37+
38+
enum_<NEED>(Class, "NEED")
39+
.value("NEED", NEED::UNKNOWN, "")
40+
.value("INDIRECT_EXTERN_ACCESS", NEED::INDIRECT_EXTERN_ACCESS,
41+
"The object needs indirect external access")
42+
;
43+
44+
Class
45+
.def_prop_ro("needs", &Needed::needs,
46+
R"doc(
47+
Return the list of the needed features.
48+
)doc"_doc);
49+
}
50+
51+
}

api/python/src/ELF/objects/NoteDetails/pyNoteGnuProperty.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "LIEF/ELF/NoteDetails/properties/StackSize.hpp"
3131
#include "LIEF/ELF/NoteDetails/properties/NoteNoCopyOnProtected.hpp"
3232
#include "LIEF/ELF/NoteDetails/properties/Generic.hpp"
33+
#include "LIEF/ELF/NoteDetails/properties/Needed.hpp"
3334

3435
namespace LIEF::ELF::py {
3536

@@ -68,6 +69,7 @@ void create<NoteGnuProperty>(nb::module_& m) {
6869

6970
create<AArch64Feature>(m);
7071
create<AArch64PAuth>(m);
72+
create<Needed>(m);
7173
create<X86Features>(m);
7274
create<X86ISA>(m);
7375
create<StackSize>(m);

api/rust/cargo/lief/src/elf/note/properties.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,44 @@ impl std::fmt::Debug for NoCopyOnProtected<'_> {
576576
}
577577
}
578578

579-
/// Needed property
579+
#[allow(non_camel_case_types)]
580+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
581+
/// Flags for the `GNU_PROPERTY_1_NEEDED` property
582+
pub enum NeedFlag {
583+
UNKNOWN,
584+
/// The object needs indirect external access
585+
INDIRECT_EXTERN_ACCESS,
586+
}
587+
588+
impl From<u64> for NeedFlag {
589+
fn from(value: u64) -> Self {
590+
match value {
591+
0 => NeedFlag::UNKNOWN,
592+
1 => NeedFlag::INDIRECT_EXTERN_ACCESS,
593+
_ => NeedFlag::UNKNOWN,
594+
}
595+
}
596+
}
597+
598+
/// Needed property (`GNU_PROPERTY_1_NEEDED`)
599+
///
600+
/// This property conveys information about additional features that the
601+
/// object file needs at runtime (e.g. indirect external access).
580602
pub struct Needed<'a> {
581603
ptr: cxx::UniquePtr<ffi::ELF_NoteGnuProperty_Needed>,
582604
_owner: PhantomData<&'a ffi::ELF_NoteGnuProperty>,
583605
}
584606

607+
impl Needed<'_> {
608+
/// Return the list of needed features
609+
pub fn needs(&self) -> Vec<NeedFlag> {
610+
Vec::from(self.ptr.needs().as_slice())
611+
.into_iter()
612+
.map(NeedFlag::from)
613+
.collect()
614+
}
615+
}
616+
585617
impl NoteProperty for Needed<'_> {
586618
fn get_base(&self) -> &ffi::ELF_NoteGnuProperty_Property {
587619
self.ptr.as_ref().unwrap().as_ref()
@@ -601,6 +633,7 @@ impl std::fmt::Debug for Needed<'_> {
601633
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
602634
f.debug_struct("Needed")
603635
.field("type", &self.property_type())
636+
.field("needs", &self.needs())
604637
.finish()
605638
}
606639
}

api/rust/include/LIEF/rust/ELF/NoteGnuProperty.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class ELF_NoteGnuProperty_Needed : public ELF_NoteGnuProperty_Property {
102102
static_cast<const ELF_NoteGnuProperty_Property::lief_t&>(impl)
103103
) {}
104104

105+
auto needs() const {
106+
return to_vector(as<lief_t>(this).needs());
107+
}
108+
105109
static bool classof(const ELF_NoteGnuProperty_Property& prop) {
106110
return lief_t::classof(&prop.get());
107111
}

doc/sphinx/formats/elf/cpp.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,13 @@ AArch64 PAuth
258258
.. doxygenclass:: LIEF::ELF::AArch64PAuth
259259

260260

261+
----------
262+
263+
Needed
264+
******
265+
266+
.. doxygenclass:: LIEF::ELF::Needed
267+
261268
----------
262269

263270
No Copy on Protected

doc/sphinx/formats/elf/python.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,17 @@ AArch64 PAuth
358358

359359

360360

361+
Needed
362+
******
363+
364+
.. lief-inheritance:: lief._lief.ELF.Needed
365+
:top-classes: lief._lief.ELF.NoteGnuProperty.Property
366+
:parts: 2
367+
368+
.. autoclass:: lief.ELF.Needed
369+
370+
----------
371+
361372
No Copy on Protected
362373
********************
363374

include/LIEF/ELF/NoteDetails/properties/Needed.hpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,52 @@
1515
*/
1616
#ifndef LIEF_ELF_NOTE_DETAILS_PROPERTIES_NEEDED_H
1717
#define LIEF_ELF_NOTE_DETAILS_PROPERTIES_NEEDED_H
18+
#include <vector>
1819

20+
#include "LIEF/visibility.h"
1921
#include "LIEF/ELF/NoteDetails/NoteGnuProperty.hpp"
2022

2123
namespace LIEF {
24+
class BinaryStream;
25+
2226
namespace ELF {
2327

24-
class Needed : public NoteGnuProperty::Property {
28+
/// This class represents the ``GNU_PROPERTY_1_NEEDED`` note property.
29+
///
30+
/// This property provides information about additional features that the
31+
/// object file needs at runtime (e.g. indirect external access).
32+
class LIEF_API Needed : public NoteGnuProperty::Property {
2533
public:
2634
enum class NEED {
2735
UNKNOWN = 0,
28-
INDIRECT_EXTERN_ACCESS,
36+
INDIRECT_EXTERN_ACCESS, ///< The object needs indirect external access
2937
};
38+
39+
/// Return the list of needed features
40+
const std::vector<NEED>& needs() const {
41+
return needs_;
42+
}
43+
3044
static bool classof(const NoteGnuProperty::Property* prop) {
3145
return prop->type() == NoteGnuProperty::Property::TYPE::NEEDED;
3246
}
3347

48+
static std::unique_ptr<Needed> create(BinaryStream& stream);
49+
50+
void dump(std::ostream& os) const override;
51+
3452
~Needed() override = default;
53+
54+
protected:
55+
Needed(std::vector<NEED> needs) :
56+
NoteGnuProperty::Property(NoteGnuProperty::Property::TYPE::NEEDED),
57+
needs_(std::move(needs)) {}
58+
59+
std::vector<NEED> needs_;
3560
};
61+
62+
LIEF_API const char* to_string(Needed::NEED need);
63+
3664
}
3765
}
3866

src/ELF/NoteDetails/NoteGnuProperty.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "LIEF/ELF/NoteDetails/properties/StackSize.hpp"
3131
#include "LIEF/ELF/NoteDetails/properties/X86Feature.hpp"
3232
#include "LIEF/ELF/NoteDetails/properties/X86ISA.hpp"
33+
#include "LIEF/ELF/NoteDetails/properties/Needed.hpp"
3334
#include "LIEF/ELF/NoteDetails/properties/NoteNoCopyOnProtected.hpp"
3435

3536
#include "LIEF/BinaryStream/SpanStream.hpp"
@@ -117,7 +118,7 @@ inline std::unique_ptr<NoteGnuProperty::Property>
117118
(GNU_PROPERTY_UINT32_OR_LO <= type && type <= GNU_PROPERTY_UINT32_OR_HI))
118119
{
119120
switch (type) {
120-
// TODO(romain): We need to support GNU_PROPERTY_1_NEEDED
121+
case GNU_PROPERTY_1_NEEDED: return Needed::create(content);
121122
default: return Generic::create(type);
122123
}
123124
}

0 commit comments

Comments
 (0)