Skip to content

Commit c375a47

Browse files
committed
Improve API for ELF RUN_PATH / RPATH
1 parent 1e410e6 commit c375a47

File tree

7 files changed

+307
-6
lines changed

7 files changed

+307
-6
lines changed

api/python/ELF/objects/pyDynamicEntryRpath.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ void init_ELF_DynamicEntryRpath_class(py::module& m) {
3737
py::class_<DynamicEntryRpath, DynamicEntry>(m, "DynamicEntryRpath")
3838
.def(py::init<const std::string &>(),
3939
"Constructor from (r)path",
40-
"path"_a)
40+
"path"_a = "")
41+
42+
.def(py::init<const std::vector<std::string> &>(),
43+
"Constructor from a list of paths",
44+
"paths"_a)
45+
4146
.def_property("name",
4247
[] (const DynamicEntryRpath& obj) {
4348
return safe_string_converter(obj.name());
@@ -52,6 +57,34 @@ void init_ELF_DynamicEntryRpath_class(py::module& m) {
5257
static_cast<setter_t<const std::string&>>(&DynamicEntryRpath::rpath),
5358
"Return path value")
5459

60+
61+
.def_property("paths",
62+
static_cast<getter_t<std::vector<std::string> >>(&DynamicEntryRpath::paths),
63+
static_cast<setter_t<const std::vector<std::string>&>>(&DynamicEntryRpath::paths),
64+
"Paths as a list")
65+
66+
.def("insert",
67+
&DynamicEntryRpath::insert,
68+
"Insert a ``path`` at the given ``position``",
69+
"position"_a, "path"_a,
70+
py::return_value_policy::reference)
71+
72+
.def("append",
73+
&DynamicEntryRpath::append,
74+
"Append the given ``path`` ",
75+
"path"_a,
76+
py::return_value_policy::reference)
77+
78+
79+
.def("remove",
80+
&DynamicEntryRpath::remove,
81+
"Remove the given ``path`` ",
82+
"path"_a,
83+
py::return_value_policy::reference)
84+
85+
.def(py::self += std::string())
86+
.def(py::self -= std::string())
87+
5588
.def("__eq__", &DynamicEntryRpath::operator==)
5689
.def("__ne__", &DynamicEntryRpath::operator!=)
5790
.def("__hash__",

api/python/ELF/objects/pyDynamicEntryRunPath.cpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,53 @@ void init_ELF_DynamicEntryRunPath_class(py::module& m) {
3737
py::class_<DynamicEntryRunPath, DynamicEntry>(m, "DynamicEntryRunPath")
3838
.def(py::init<const std::string &>(),
3939
"Constructor from (run)path",
40-
"path"_a)
40+
"path"_a = "")
41+
42+
.def(py::init<const std::vector<std::string> &>(),
43+
"Constructor from a list of paths",
44+
"paths"_a)
4145

4246
.def_property("name",
4347
[] (const DynamicEntryRunPath& obj) {
4448
return safe_string_converter(obj.name());
4549
},
4650
static_cast<setter_t<const std::string&>>(&DynamicEntryRunPath::name),
47-
"Return path value")
51+
"Runpath raw value")
4852

4953
.def_property("runpath",
5054
[] (const DynamicEntryRunPath& obj) {
5155
return safe_string_converter(obj.runpath());
5256
},
5357
static_cast<setter_t<const std::string&>>(&DynamicEntryRunPath::runpath),
54-
"Return path value")
58+
"Runpath raw value")
59+
60+
.def_property("paths",
61+
static_cast<getter_t<std::vector<std::string> >>(&DynamicEntryRunPath::paths),
62+
static_cast<setter_t<const std::vector<std::string>&>>(&DynamicEntryRunPath::paths),
63+
"Paths as a list")
64+
65+
.def("insert",
66+
&DynamicEntryRunPath::insert,
67+
"Insert a ``path`` at the given ``position``",
68+
"position"_a, "path"_a,
69+
py::return_value_policy::reference)
70+
71+
.def("append",
72+
&DynamicEntryRunPath::append,
73+
"Append the given ``path`` ",
74+
"path"_a,
75+
py::return_value_policy::reference)
76+
77+
78+
.def("remove",
79+
&DynamicEntryRunPath::remove,
80+
"Remove the given ``path`` ",
81+
"path"_a,
82+
py::return_value_policy::reference)
83+
84+
85+
.def(py::self += std::string())
86+
.def(py::self -= std::string())
5587

5688
.def("__eq__", &DynamicEntryRunPath::operator==)
5789
.def("__ne__", &DynamicEntryRunPath::operator!=)

include/LIEF/ELF/DynamicEntryRpath.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace ELF {
2828
class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
2929

3030
public:
31+
static constexpr char delimiter = ':';
3132
using DynamicEntry::DynamicEntry;
3233

3334
DynamicEntryRpath(const Elf64_Dyn* header);
@@ -36,6 +37,9 @@ class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
3637

3738
DynamicEntryRpath(const std::string& name = "");
3839

40+
//! @brief Constructor from a list of paths
41+
DynamicEntryRpath(const std::vector<std::string>& paths);
42+
3943
DynamicEntryRpath& operator=(const DynamicEntryRpath&);
4044
DynamicEntryRpath(const DynamicEntryRpath&);
4145

@@ -45,6 +49,22 @@ class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
4549
const std::string& rpath(void) const;
4650
void rpath(const std::string& name);
4751

52+
//! @brief Paths as a list
53+
std::vector<std::string> paths(void) const;
54+
void paths(const std::vector<std::string>& paths);
55+
56+
//! @brief Insert a ``path`` at the given ``position``
57+
DynamicEntryRpath& insert(size_t pos, const std::string path);
58+
59+
//! @brief Append the given ``path``
60+
DynamicEntryRpath& append(const std::string& path);
61+
62+
//! @brief Remove the given ``path``
63+
DynamicEntryRpath& remove(const std::string& path);
64+
65+
DynamicEntryRpath& operator+=(const std::string& path);
66+
DynamicEntryRpath& operator-=(const std::string& path);
67+
4868
virtual void accept(Visitor& visitor) const override;
4969

5070
virtual std::ostream& print(std::ostream& os) const override;

include/LIEF/ELF/DynamicEntryRunPath.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,46 @@ namespace ELF {
2727
class DLL_PUBLIC DynamicEntryRunPath : public DynamicEntry {
2828

2929
public:
30+
static constexpr char delimiter = ':';
3031
using DynamicEntry::DynamicEntry;
3132

3233
DynamicEntryRunPath(const Elf64_Dyn* header);
3334
DynamicEntryRunPath(const Elf32_Dyn* header);
3435
DynamicEntryRunPath(void);
3536

37+
//! @brief Constructor from (run)path
3638
DynamicEntryRunPath(const std::string& name = "");
3739

40+
//! @brief Constructor from a list of paths
41+
DynamicEntryRunPath(const std::vector<std::string>& paths);
42+
3843
DynamicEntryRunPath& operator=(const DynamicEntryRunPath&);
3944
DynamicEntryRunPath(const DynamicEntryRunPath&);
4045

46+
//! @brief Runpath raw value
4147
virtual const std::string& name(void) const override;
4248
virtual void name(const std::string& name) override;
4349

50+
//! @brief Runpath raw value
4451
const std::string& runpath(void) const;
4552
void runpath(const std::string& runpath);
4653

54+
//! @brief Paths as a list
55+
std::vector<std::string> paths(void) const;
56+
void paths(const std::vector<std::string>& paths);
57+
58+
//! @brief Insert a ``path`` at the given ``position``
59+
DynamicEntryRunPath& insert(size_t pos, const std::string path);
60+
61+
//! @brief Append the given ``path``
62+
DynamicEntryRunPath& append(const std::string& path);
63+
64+
//! @brief Remove the given ``path``
65+
DynamicEntryRunPath& remove(const std::string& path);
66+
67+
DynamicEntryRunPath& operator+=(const std::string& path);
68+
DynamicEntryRunPath& operator-=(const std::string& path);
69+
4770
virtual void accept(Visitor& visitor) const override;
4871

4972
virtual std::ostream& print(std::ostream& os) const override;

src/ELF/DynamicEntryRpath.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "LIEF/ELF/DynamicEntryRpath.hpp"
1717

1818
#include <iomanip>
19+
#include <numeric>
20+
#include <sstream>
1921

2022
namespace LIEF {
2123
namespace ELF {
@@ -39,6 +41,14 @@ DynamicEntryRpath::DynamicEntryRpath(const std::string& rpath) :
3941
{
4042
}
4143

44+
45+
DynamicEntryRpath::DynamicEntryRpath(const std::vector<std::string>& paths) :
46+
DynamicEntry::DynamicEntry{DYNAMIC_TAGS::DT_RPATH, 0},
47+
rpath_{""}
48+
{
49+
this->paths(paths);
50+
}
51+
4252
const std::string& DynamicEntryRpath::name(void) const {
4353
return this->rpath_;
4454
}
@@ -57,6 +67,70 @@ void DynamicEntryRpath::rpath(const std::string& rpath) {
5767
this->name(rpath);
5868
}
5969

70+
71+
std::vector<std::string> DynamicEntryRpath::paths(void) const {
72+
std::stringstream ss;
73+
ss.str(this->rpath());
74+
std::string path;
75+
std::vector<std::string> paths;
76+
while (std::getline(ss, path, DynamicEntryRpath::delimiter)) {
77+
paths.push_back(path);
78+
}
79+
return paths;
80+
}
81+
82+
void DynamicEntryRpath::paths(const std::vector<std::string>& paths) {
83+
this->rpath_ = std::accumulate(
84+
std::begin(paths),
85+
std::end(paths),
86+
std::string(""),
87+
[] (std::string path, const std::string& new_entry) {
88+
return path.empty() ? new_entry : path + DynamicEntryRpath::delimiter + new_entry;
89+
});
90+
}
91+
92+
DynamicEntryRpath& DynamicEntryRpath::append(const std::string& path) {
93+
std::vector<std::string> paths = this->paths();
94+
paths.push_back(path);
95+
this->paths(paths);
96+
return *this;
97+
}
98+
99+
DynamicEntryRpath& DynamicEntryRpath::remove(const std::string& path) {
100+
std::vector<std::string> paths = this->paths();
101+
paths.erase(std::remove_if(
102+
std::begin(paths),
103+
std::end(paths),
104+
[&path] (const std::string& p) {
105+
return p == path;
106+
}), std::end(paths));
107+
this->paths(paths);
108+
return *this;
109+
}
110+
111+
DynamicEntryRpath& DynamicEntryRpath::insert(size_t pos, const std::string path) {
112+
std::vector<std::string> paths = this->paths();
113+
114+
if (pos == paths.size()) {
115+
return this->append(path);
116+
}
117+
118+
if (pos > paths.size()) {
119+
throw corrupted(std::to_string(pos) + " is out of ranges");
120+
}
121+
paths.insert(std::begin(paths) + pos, path);
122+
this->paths(paths);
123+
return *this;
124+
}
125+
126+
DynamicEntryRpath& DynamicEntryRpath::operator+=(const std::string& path) {
127+
return this->append(path);
128+
}
129+
130+
DynamicEntryRpath& DynamicEntryRpath::operator-=(const std::string& path) {
131+
return this->remove(path);
132+
}
133+
60134
void DynamicEntryRpath::accept(Visitor& visitor) const {
61135
DynamicEntry::accept(visitor);
62136
visitor(*this); // Double dispatch to avoid down-casting

src/ELF/DynamicEntryRunPath.cpp

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
1717

1818
#include <iomanip>
19+
#include <numeric>
20+
#include <sstream>
1921

2022
namespace LIEF {
2123
namespace ELF {
@@ -39,6 +41,16 @@ DynamicEntryRunPath::DynamicEntryRunPath(const std::string& runpath) :
3941
{
4042
}
4143

44+
45+
DynamicEntryRunPath::DynamicEntryRunPath(const std::vector<std::string>& paths) :
46+
DynamicEntry::DynamicEntry{DYNAMIC_TAGS::DT_RUNPATH, 0},
47+
runpath_{""}
48+
{
49+
this->paths(paths);
50+
}
51+
52+
53+
4254
const std::string& DynamicEntryRunPath::name(void) const {
4355
return this->runpath_;
4456
}
@@ -52,11 +64,74 @@ const std::string& DynamicEntryRunPath::runpath(void) const {
5264
return this->name();
5365
}
5466

55-
5667
void DynamicEntryRunPath::runpath(const std::string& runpath) {
5768
this->name(runpath);
5869
}
5970

71+
72+
std::vector<std::string> DynamicEntryRunPath::paths(void) const {
73+
std::stringstream ss;
74+
ss.str(this->runpath());
75+
std::string path;
76+
std::vector<std::string> paths;
77+
while (std::getline(ss, path, DynamicEntryRunPath::delimiter)) {
78+
paths.push_back(path);
79+
}
80+
return paths;
81+
}
82+
83+
void DynamicEntryRunPath::paths(const std::vector<std::string>& paths) {
84+
this->runpath_ = std::accumulate(
85+
std::begin(paths),
86+
std::end(paths),
87+
std::string(""),
88+
[] (std::string path, const std::string& new_entry) {
89+
return path.empty() ? new_entry : path + DynamicEntryRunPath::delimiter + new_entry;
90+
});
91+
}
92+
93+
DynamicEntryRunPath& DynamicEntryRunPath::append(const std::string& path) {
94+
std::vector<std::string> paths = this->paths();
95+
paths.push_back(path);
96+
this->paths(paths);
97+
return *this;
98+
}
99+
100+
DynamicEntryRunPath& DynamicEntryRunPath::remove(const std::string& path) {
101+
std::vector<std::string> paths = this->paths();
102+
paths.erase(std::remove_if(
103+
std::begin(paths),
104+
std::end(paths),
105+
[&path] (const std::string& p) {
106+
return p == path;
107+
}), std::end(paths));
108+
this->paths(paths);
109+
return *this;
110+
}
111+
112+
DynamicEntryRunPath& DynamicEntryRunPath::insert(size_t pos, const std::string path) {
113+
std::vector<std::string> paths = this->paths();
114+
115+
if (pos == paths.size()) {
116+
return this->append(path);
117+
}
118+
119+
if (pos > paths.size()) {
120+
throw corrupted(std::to_string(pos) + " is out of ranges");
121+
}
122+
paths.insert(std::begin(paths) + pos, path);
123+
this->paths(paths);
124+
return *this;
125+
}
126+
127+
DynamicEntryRunPath& DynamicEntryRunPath::operator+=(const std::string& path) {
128+
return this->append(path);
129+
}
130+
131+
DynamicEntryRunPath& DynamicEntryRunPath::operator-=(const std::string& path) {
132+
return this->remove(path);
133+
}
134+
60135
void DynamicEntryRunPath::accept(Visitor& visitor) const {
61136
DynamicEntry::accept(visitor);
62137
visitor(*this); // Double dispatch to avoid down-casting

0 commit comments

Comments
 (0)