mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-04-28 05:14:33 +00:00
Improve API for ELF RUN_PATH / RPATH
This commit is contained in:
parent
1e410e6c95
commit
c375a47da7
@ -37,7 +37,12 @@ void init_ELF_DynamicEntryRpath_class(py::module& m) {
|
||||
py::class_<DynamicEntryRpath, DynamicEntry>(m, "DynamicEntryRpath")
|
||||
.def(py::init<const std::string &>(),
|
||||
"Constructor from (r)path",
|
||||
"path"_a)
|
||||
"path"_a = "")
|
||||
|
||||
.def(py::init<const std::vector<std::string> &>(),
|
||||
"Constructor from a list of paths",
|
||||
"paths"_a)
|
||||
|
||||
.def_property("name",
|
||||
[] (const DynamicEntryRpath& obj) {
|
||||
return safe_string_converter(obj.name());
|
||||
@ -52,6 +57,34 @@ void init_ELF_DynamicEntryRpath_class(py::module& m) {
|
||||
static_cast<setter_t<const std::string&>>(&DynamicEntryRpath::rpath),
|
||||
"Return path value")
|
||||
|
||||
|
||||
.def_property("paths",
|
||||
static_cast<getter_t<std::vector<std::string> >>(&DynamicEntryRpath::paths),
|
||||
static_cast<setter_t<const std::vector<std::string>&>>(&DynamicEntryRpath::paths),
|
||||
"Paths as a list")
|
||||
|
||||
.def("insert",
|
||||
&DynamicEntryRpath::insert,
|
||||
"Insert a ``path`` at the given ``position``",
|
||||
"position"_a, "path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
.def("append",
|
||||
&DynamicEntryRpath::append,
|
||||
"Append the given ``path`` ",
|
||||
"path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
|
||||
.def("remove",
|
||||
&DynamicEntryRpath::remove,
|
||||
"Remove the given ``path`` ",
|
||||
"path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
.def(py::self += std::string())
|
||||
.def(py::self -= std::string())
|
||||
|
||||
.def("__eq__", &DynamicEntryRpath::operator==)
|
||||
.def("__ne__", &DynamicEntryRpath::operator!=)
|
||||
.def("__hash__",
|
||||
|
@ -37,21 +37,53 @@ void init_ELF_DynamicEntryRunPath_class(py::module& m) {
|
||||
py::class_<DynamicEntryRunPath, DynamicEntry>(m, "DynamicEntryRunPath")
|
||||
.def(py::init<const std::string &>(),
|
||||
"Constructor from (run)path",
|
||||
"path"_a)
|
||||
"path"_a = "")
|
||||
|
||||
.def(py::init<const std::vector<std::string> &>(),
|
||||
"Constructor from a list of paths",
|
||||
"paths"_a)
|
||||
|
||||
.def_property("name",
|
||||
[] (const DynamicEntryRunPath& obj) {
|
||||
return safe_string_converter(obj.name());
|
||||
},
|
||||
static_cast<setter_t<const std::string&>>(&DynamicEntryRunPath::name),
|
||||
"Return path value")
|
||||
"Runpath raw value")
|
||||
|
||||
.def_property("runpath",
|
||||
[] (const DynamicEntryRunPath& obj) {
|
||||
return safe_string_converter(obj.runpath());
|
||||
},
|
||||
static_cast<setter_t<const std::string&>>(&DynamicEntryRunPath::runpath),
|
||||
"Return path value")
|
||||
"Runpath raw value")
|
||||
|
||||
.def_property("paths",
|
||||
static_cast<getter_t<std::vector<std::string> >>(&DynamicEntryRunPath::paths),
|
||||
static_cast<setter_t<const std::vector<std::string>&>>(&DynamicEntryRunPath::paths),
|
||||
"Paths as a list")
|
||||
|
||||
.def("insert",
|
||||
&DynamicEntryRunPath::insert,
|
||||
"Insert a ``path`` at the given ``position``",
|
||||
"position"_a, "path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
.def("append",
|
||||
&DynamicEntryRunPath::append,
|
||||
"Append the given ``path`` ",
|
||||
"path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
|
||||
.def("remove",
|
||||
&DynamicEntryRunPath::remove,
|
||||
"Remove the given ``path`` ",
|
||||
"path"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
|
||||
.def(py::self += std::string())
|
||||
.def(py::self -= std::string())
|
||||
|
||||
.def("__eq__", &DynamicEntryRunPath::operator==)
|
||||
.def("__ne__", &DynamicEntryRunPath::operator!=)
|
||||
|
@ -28,6 +28,7 @@ namespace ELF {
|
||||
class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
|
||||
|
||||
public:
|
||||
static constexpr char delimiter = ':';
|
||||
using DynamicEntry::DynamicEntry;
|
||||
|
||||
DynamicEntryRpath(const Elf64_Dyn* header);
|
||||
@ -36,6 +37,9 @@ class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
|
||||
|
||||
DynamicEntryRpath(const std::string& name = "");
|
||||
|
||||
//! @brief Constructor from a list of paths
|
||||
DynamicEntryRpath(const std::vector<std::string>& paths);
|
||||
|
||||
DynamicEntryRpath& operator=(const DynamicEntryRpath&);
|
||||
DynamicEntryRpath(const DynamicEntryRpath&);
|
||||
|
||||
@ -45,6 +49,22 @@ class DLL_PUBLIC DynamicEntryRpath : public DynamicEntry {
|
||||
const std::string& rpath(void) const;
|
||||
void rpath(const std::string& name);
|
||||
|
||||
//! @brief Paths as a list
|
||||
std::vector<std::string> paths(void) const;
|
||||
void paths(const std::vector<std::string>& paths);
|
||||
|
||||
//! @brief Insert a ``path`` at the given ``position``
|
||||
DynamicEntryRpath& insert(size_t pos, const std::string path);
|
||||
|
||||
//! @brief Append the given ``path``
|
||||
DynamicEntryRpath& append(const std::string& path);
|
||||
|
||||
//! @brief Remove the given ``path``
|
||||
DynamicEntryRpath& remove(const std::string& path);
|
||||
|
||||
DynamicEntryRpath& operator+=(const std::string& path);
|
||||
DynamicEntryRpath& operator-=(const std::string& path);
|
||||
|
||||
virtual void accept(Visitor& visitor) const override;
|
||||
|
||||
virtual std::ostream& print(std::ostream& os) const override;
|
||||
|
@ -27,23 +27,46 @@ namespace ELF {
|
||||
class DLL_PUBLIC DynamicEntryRunPath : public DynamicEntry {
|
||||
|
||||
public:
|
||||
static constexpr char delimiter = ':';
|
||||
using DynamicEntry::DynamicEntry;
|
||||
|
||||
DynamicEntryRunPath(const Elf64_Dyn* header);
|
||||
DynamicEntryRunPath(const Elf32_Dyn* header);
|
||||
DynamicEntryRunPath(void);
|
||||
|
||||
//! @brief Constructor from (run)path
|
||||
DynamicEntryRunPath(const std::string& name = "");
|
||||
|
||||
//! @brief Constructor from a list of paths
|
||||
DynamicEntryRunPath(const std::vector<std::string>& paths);
|
||||
|
||||
DynamicEntryRunPath& operator=(const DynamicEntryRunPath&);
|
||||
DynamicEntryRunPath(const DynamicEntryRunPath&);
|
||||
|
||||
//! @brief Runpath raw value
|
||||
virtual const std::string& name(void) const override;
|
||||
virtual void name(const std::string& name) override;
|
||||
|
||||
//! @brief Runpath raw value
|
||||
const std::string& runpath(void) const;
|
||||
void runpath(const std::string& runpath);
|
||||
|
||||
//! @brief Paths as a list
|
||||
std::vector<std::string> paths(void) const;
|
||||
void paths(const std::vector<std::string>& paths);
|
||||
|
||||
//! @brief Insert a ``path`` at the given ``position``
|
||||
DynamicEntryRunPath& insert(size_t pos, const std::string path);
|
||||
|
||||
//! @brief Append the given ``path``
|
||||
DynamicEntryRunPath& append(const std::string& path);
|
||||
|
||||
//! @brief Remove the given ``path``
|
||||
DynamicEntryRunPath& remove(const std::string& path);
|
||||
|
||||
DynamicEntryRunPath& operator+=(const std::string& path);
|
||||
DynamicEntryRunPath& operator-=(const std::string& path);
|
||||
|
||||
virtual void accept(Visitor& visitor) const override;
|
||||
|
||||
virtual std::ostream& print(std::ostream& os) const override;
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "LIEF/ELF/DynamicEntryRpath.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
namespace LIEF {
|
||||
namespace ELF {
|
||||
@ -39,6 +41,14 @@ DynamicEntryRpath::DynamicEntryRpath(const std::string& rpath) :
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DynamicEntryRpath::DynamicEntryRpath(const std::vector<std::string>& paths) :
|
||||
DynamicEntry::DynamicEntry{DYNAMIC_TAGS::DT_RPATH, 0},
|
||||
rpath_{""}
|
||||
{
|
||||
this->paths(paths);
|
||||
}
|
||||
|
||||
const std::string& DynamicEntryRpath::name(void) const {
|
||||
return this->rpath_;
|
||||
}
|
||||
@ -57,6 +67,70 @@ void DynamicEntryRpath::rpath(const std::string& rpath) {
|
||||
this->name(rpath);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> DynamicEntryRpath::paths(void) const {
|
||||
std::stringstream ss;
|
||||
ss.str(this->rpath());
|
||||
std::string path;
|
||||
std::vector<std::string> paths;
|
||||
while (std::getline(ss, path, DynamicEntryRpath::delimiter)) {
|
||||
paths.push_back(path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
void DynamicEntryRpath::paths(const std::vector<std::string>& paths) {
|
||||
this->rpath_ = std::accumulate(
|
||||
std::begin(paths),
|
||||
std::end(paths),
|
||||
std::string(""),
|
||||
[] (std::string path, const std::string& new_entry) {
|
||||
return path.empty() ? new_entry : path + DynamicEntryRpath::delimiter + new_entry;
|
||||
});
|
||||
}
|
||||
|
||||
DynamicEntryRpath& DynamicEntryRpath::append(const std::string& path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
paths.push_back(path);
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRpath& DynamicEntryRpath::remove(const std::string& path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
paths.erase(std::remove_if(
|
||||
std::begin(paths),
|
||||
std::end(paths),
|
||||
[&path] (const std::string& p) {
|
||||
return p == path;
|
||||
}), std::end(paths));
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRpath& DynamicEntryRpath::insert(size_t pos, const std::string path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
|
||||
if (pos == paths.size()) {
|
||||
return this->append(path);
|
||||
}
|
||||
|
||||
if (pos > paths.size()) {
|
||||
throw corrupted(std::to_string(pos) + " is out of ranges");
|
||||
}
|
||||
paths.insert(std::begin(paths) + pos, path);
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRpath& DynamicEntryRpath::operator+=(const std::string& path) {
|
||||
return this->append(path);
|
||||
}
|
||||
|
||||
DynamicEntryRpath& DynamicEntryRpath::operator-=(const std::string& path) {
|
||||
return this->remove(path);
|
||||
}
|
||||
|
||||
void DynamicEntryRpath::accept(Visitor& visitor) const {
|
||||
DynamicEntry::accept(visitor);
|
||||
visitor(*this); // Double dispatch to avoid down-casting
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
namespace LIEF {
|
||||
namespace ELF {
|
||||
@ -39,6 +41,16 @@ DynamicEntryRunPath::DynamicEntryRunPath(const std::string& runpath) :
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DynamicEntryRunPath::DynamicEntryRunPath(const std::vector<std::string>& paths) :
|
||||
DynamicEntry::DynamicEntry{DYNAMIC_TAGS::DT_RUNPATH, 0},
|
||||
runpath_{""}
|
||||
{
|
||||
this->paths(paths);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::string& DynamicEntryRunPath::name(void) const {
|
||||
return this->runpath_;
|
||||
}
|
||||
@ -52,11 +64,74 @@ const std::string& DynamicEntryRunPath::runpath(void) const {
|
||||
return this->name();
|
||||
}
|
||||
|
||||
|
||||
void DynamicEntryRunPath::runpath(const std::string& runpath) {
|
||||
this->name(runpath);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> DynamicEntryRunPath::paths(void) const {
|
||||
std::stringstream ss;
|
||||
ss.str(this->runpath());
|
||||
std::string path;
|
||||
std::vector<std::string> paths;
|
||||
while (std::getline(ss, path, DynamicEntryRunPath::delimiter)) {
|
||||
paths.push_back(path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
void DynamicEntryRunPath::paths(const std::vector<std::string>& paths) {
|
||||
this->runpath_ = std::accumulate(
|
||||
std::begin(paths),
|
||||
std::end(paths),
|
||||
std::string(""),
|
||||
[] (std::string path, const std::string& new_entry) {
|
||||
return path.empty() ? new_entry : path + DynamicEntryRunPath::delimiter + new_entry;
|
||||
});
|
||||
}
|
||||
|
||||
DynamicEntryRunPath& DynamicEntryRunPath::append(const std::string& path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
paths.push_back(path);
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRunPath& DynamicEntryRunPath::remove(const std::string& path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
paths.erase(std::remove_if(
|
||||
std::begin(paths),
|
||||
std::end(paths),
|
||||
[&path] (const std::string& p) {
|
||||
return p == path;
|
||||
}), std::end(paths));
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRunPath& DynamicEntryRunPath::insert(size_t pos, const std::string path) {
|
||||
std::vector<std::string> paths = this->paths();
|
||||
|
||||
if (pos == paths.size()) {
|
||||
return this->append(path);
|
||||
}
|
||||
|
||||
if (pos > paths.size()) {
|
||||
throw corrupted(std::to_string(pos) + " is out of ranges");
|
||||
}
|
||||
paths.insert(std::begin(paths) + pos, path);
|
||||
this->paths(paths);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicEntryRunPath& DynamicEntryRunPath::operator+=(const std::string& path) {
|
||||
return this->append(path);
|
||||
}
|
||||
|
||||
DynamicEntryRunPath& DynamicEntryRunPath::operator-=(const std::string& path) {
|
||||
return this->remove(path);
|
||||
}
|
||||
|
||||
void DynamicEntryRunPath::accept(Visitor& visitor) const {
|
||||
DynamicEntry::accept(visitor);
|
||||
visitor(*this); // Double dispatch to avoid down-casting
|
||||
|
@ -157,6 +157,50 @@ class TestDynamic(TestCase):
|
||||
|
||||
self.assertTrue(all(e.tag != lief.ELF.DYNAMIC_TAGS.NEEDED for e in binadd.dynamic_entries))
|
||||
|
||||
def test_runpath_api(self):
|
||||
sample = LibAddSample()
|
||||
libadd = lief.parse(sample.libadd)
|
||||
binadd = lief.parse(sample.binadd)
|
||||
|
||||
rpath = lief.ELF.DynamicEntryRunPath()
|
||||
rpath = binadd.add(rpath)
|
||||
self.logger.debug(rpath)
|
||||
rpath += "/tmp"
|
||||
|
||||
self.logger.debug(rpath)
|
||||
|
||||
self.assertEqual(rpath.paths, ["/tmp"])
|
||||
self.assertEqual(rpath.runpath, "/tmp")
|
||||
|
||||
rpath.insert(0, "/foo")
|
||||
|
||||
self.assertEqual(rpath.paths, ["/foo", "/tmp"])
|
||||
self.assertEqual(rpath.runpath, "/foo:/tmp")
|
||||
|
||||
rpath.paths = ["/foo", "/tmp", "/bar"]
|
||||
|
||||
self.logger.debug(rpath)
|
||||
|
||||
self.assertEqual(rpath.paths, ["/foo", "/tmp", "/bar"])
|
||||
self.assertEqual(rpath.runpath, "/foo:/tmp:/bar")
|
||||
|
||||
rpath -= "/tmp"
|
||||
|
||||
self.logger.debug(rpath)
|
||||
|
||||
self.assertEqual(rpath.runpath, "/foo:/bar")
|
||||
|
||||
rpath.remove("/foo").remove("/bar")
|
||||
|
||||
self.logger.debug(rpath)
|
||||
|
||||
self.assertEqual(rpath.runpath, "")
|
||||
|
||||
|
||||
|
||||
self.logger.debug(rpath)
|
||||
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||
def test_change_libname(self):
|
||||
@ -187,7 +231,7 @@ class TestDynamic(TestCase):
|
||||
libadd_needed.name = new_name
|
||||
|
||||
# Add a RPATH entry
|
||||
rpath = lief.ELF.DynamicEntryRpath(sample.directory)
|
||||
rpath = lief.ELF.DynamicEntryRunPath(sample.directory)
|
||||
rpath = binadd.add(rpath)
|
||||
self.logger.debug(rpath)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user