Skip to content

Commit 1e410e6

Browse files
committed
Add API to remove dynamic entries (ELF)
API Changes (Python / C++): * lief.ELF.Binary.remove(DynamicEntry / DYNAMIC_TAGS) - Added * lief.ELF.Binary.remove_library
1 parent 7dce0f3 commit 1e410e6

File tree

5 files changed

+115
-4
lines changed

5 files changed

+115
-4
lines changed

api/python/ELF/objects/pyBinary.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,16 @@ void init_ELF_Binary_class(py::module& m) {
292292
"segment"_a, "size"_a,
293293
py::return_value_policy::reference)
294294

295+
.def("remove",
296+
static_cast<void (Binary::*)(const DynamicEntry&)>(&Binary::remove),
297+
"Remove the given " RST_CLASS_REF(lief.ELF.DynamicEntry) " from the dynamic table",
298+
"dynamic_entry"_a)
299+
300+
.def("remove",
301+
static_cast<void (Binary::*)(DYNAMIC_TAGS)>(&Binary::remove),
302+
"Remove **all** " RST_CLASS_REF(lief.ELF.DynamicEntry) " with the given " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) "",
303+
"tag"_a)
304+
295305
.def_property_readonly("has_notes",
296306
&Binary::has_notes,
297307
"``True`` if the binary contains notes")
@@ -338,6 +348,11 @@ void init_ELF_Binary_class(py::module& m) {
338348
"Check if the given library name exists in the current binary",
339349
"library_name"_a)
340350

351+
.def("remove_library",
352+
&Binary::remove_library,
353+
"Remove the given library",
354+
"library_name"_a)
355+
341356
.def("get_library",
342357
static_cast<no_const_func<DynamicEntryLibrary&, const std::string&>>(&Binary::get_library),
343358
"Return the " RST_CLASS_REF(lief.ELF.DynamicEntryLibrary) " with the given ``name``",
@@ -350,6 +365,9 @@ void init_ELF_Binary_class(py::module& m) {
350365

351366
.def(py::self += DynamicEntry())
352367

368+
.def(py::self -= DynamicEntry())
369+
.def(py::self -= DYNAMIC_TAGS())
370+
353371
.def("__getitem__",
354372
static_cast<Segment& (Binary::*)(SEGMENT_TYPES)>(&Binary::operator[]),
355373
"",

include/LIEF/ELF/Binary.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,15 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
101101
it_dynamic_entries dynamic_entries(void);
102102
it_const_dynamic_entries dynamic_entries(void) const;
103103

104+
//! @brief Add the given dynamic entry and return the entry added
104105
DynamicEntry& add(const DynamicEntry& entry);
105106

107+
//! @brief Remove the given dynamic entry
108+
void remove(const DynamicEntry& entry);
109+
110+
//! @brief Remove **all** dynamic entries with the given tag
111+
void remove(DYNAMIC_TAGS tag);
112+
106113
//! @brief Return binary's dynamic symbols
107114
it_symbols dynamic_symbols(void);
108115
it_const_symbols dynamic_symbols(void) const;
@@ -257,6 +264,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
257264
//! @brief Add a library as dependency
258265
DynamicEntryLibrary& add_library(const std::string& library_name);
259266

267+
//! @brief Remove the given library
268+
void remove_library(const std::string& library_name);
269+
260270
//! @brief Get the library object (DynamicEntryLibrary) from the given name
261271
DynamicEntryLibrary& get_library(const std::string& library_name);
262272

@@ -404,6 +414,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
404414
Binary& operator+=(const Section& section);
405415
Binary& operator+=(const Segment& segment);
406416

417+
Binary& operator-=(const DynamicEntry& entry);
418+
Binary& operator-=(DYNAMIC_TAGS tag);
419+
407420
Segment& operator[](SEGMENT_TYPES type);
408421
const Segment& operator[](SEGMENT_TYPES type) const;
409422

src/ELF/Binary.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ std::vector<std::string> Binary::get_abstract_imported_libraries(void) const {
137137
// ===============
138138

139139
it_dynamic_entries Binary::dynamic_entries(void) {
140-
return it_dynamic_entries{std::ref(this->dynamic_entries_)};
140+
return this->dynamic_entries_;
141141
}
142142

143143
it_const_dynamic_entries Binary::dynamic_entries(void) const {
144-
return it_const_dynamic_entries{std::cref(this->dynamic_entries_)};
144+
return this->dynamic_entries_;
145145
}
146146

147147

@@ -211,6 +211,38 @@ DynamicEntry& Binary::add(const DynamicEntry& entry) {
211211

212212
}
213213

214+
215+
void Binary::remove(const DynamicEntry& entry) {
216+
auto&& it_entry = std::find_if(
217+
std::begin(this->dynamic_entries_),
218+
std::end(this->dynamic_entries_),
219+
[&entry] (const DynamicEntry* e) {
220+
return *e == entry;
221+
});
222+
223+
if (it_entry == std::end(this->dynamic_entries_)) {
224+
std::stringstream ss;
225+
ss << entry;
226+
throw not_found("Can't find '" + ss.str() + "' in the dynamic table!");
227+
}
228+
229+
delete *it_entry;
230+
this->dynamic_entries_.erase(it_entry);
231+
}
232+
233+
234+
void Binary::remove(DYNAMIC_TAGS tag) {
235+
for (auto&& it = std::begin(this->dynamic_entries_);
236+
it != std::end(this->dynamic_entries_);) {
237+
if ((*it)->tag() == tag) {
238+
delete *it;
239+
it = this->dynamic_entries_.erase(it);
240+
} else {
241+
++it;
242+
}
243+
}
244+
}
245+
214246
// Symbols
215247
// =======
216248

@@ -1606,6 +1638,11 @@ DynamicEntryLibrary& Binary::add_library(const std::string& library_name) {
16061638
}
16071639

16081640

1641+
void Binary::remove_library(const std::string& library_name) {
1642+
this->remove(this->get_library(library_name));
1643+
}
1644+
1645+
16091646
DynamicEntryLibrary& Binary::get_library(const std::string& library_name) {
16101647
return const_cast<DynamicEntryLibrary&>(static_cast<const Binary*>(this)->get_library(library_name));
16111648
}
@@ -1636,7 +1673,8 @@ bool Binary::has_library(const std::string& name) const {
16361673
return it_needed != std::end(this->dynamic_entries_);
16371674
}
16381675

1639-
1676+
// Operator+=
1677+
// ==========
16401678
Binary& Binary::operator+=(const DynamicEntry& entry) {
16411679
this->add(entry);
16421680
return *this;
@@ -1652,7 +1690,20 @@ Binary& Binary::operator+=(const Segment& segment) {
16521690
return *this;
16531691
}
16541692

1693+
// Operator -=
1694+
// ===========
1695+
Binary& Binary::operator-=(const DynamicEntry& entry) {
1696+
this->remove(entry);
1697+
return *this;
1698+
}
1699+
1700+
Binary& Binary::operator-=(DYNAMIC_TAGS tag) {
1701+
this->remove(tag);
1702+
return *this;
1703+
}
16551704

1705+
// Operator[]
1706+
// ==========
16561707
Segment& Binary::operator[](SEGMENT_TYPES type) {
16571708
return this->get(type);
16581709
}

src/ELF/DynamicEntry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void DynamicEntry::array(const std::vector<uint64_t>&) {
9090
}
9191

9292
void DynamicEntry::accept(Visitor& visitor) const {
93-
visitor.visit(*this); // Double dispatch to avoid down-casting
93+
visitor(*this); // Double dispatch to avoid down-casting
9494
visitor.visit(this->value());
9595
visitor.visit(this->tag());
9696
}

tests/elf/test_dynamic.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,41 @@ def remove(self):
123123
if os.path.isdir(self.directory):
124124
shutil.rmtree(self.directory)
125125

126+
def __del__(self):
127+
self.remove()
128+
126129

127130
class TestDynamic(TestCase):
128131
def setUp(self):
129132
self.logger = logging.getLogger(__name__)
130133

131134

135+
def test_remove_library(self):
136+
sample = LibAddSample()
137+
libadd = lief.parse(sample.libadd)
138+
binadd = lief.parse(sample.binadd)
139+
140+
libadd_needed = binadd.get_library("libadd.so")
141+
binadd -= libadd_needed
142+
self.assertFalse(binadd.has_library("libadd.so"))
143+
144+
145+
def test_remove_tag(self):
146+
sample = LibAddSample()
147+
libadd = lief.parse(sample.libadd)
148+
binadd = lief.parse(sample.binadd)
149+
self.logger.debug("BEFORE")
150+
list(map(lambda e : self.logger.debug(e), binadd.dynamic_entries))
151+
self.logger.debug("")
152+
binadd -= lief.ELF.DYNAMIC_TAGS.NEEDED
153+
154+
self.logger.debug("AFTER")
155+
list(map(lambda e : self.logger.debug(e), binadd.dynamic_entries))
156+
self.logger.debug("")
157+
158+
self.assertTrue(all(e.tag != lief.ELF.DYNAMIC_TAGS.NEEDED for e in binadd.dynamic_entries))
159+
160+
132161
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
133162
def test_change_libname(self):
134163
sample = LibAddSample()

0 commit comments

Comments
 (0)