On Wednesday, December 02, 2015 12:27:42 Ruslan Baratov wrote: > On 02-Dec-15 05:13, Alexander Neundorf wrote: ... > > well, the RPATH entry was not designed to be patched, > > RPATH designed to be patched. And since it's a third time I'm making > this statement please provide any arguments if you don't agree. > > Here is mine (comes from wikipedia, https://en.wikipedia.org/wiki/Rpath): > > The rpath of an executable or shared library is an optional entry > in the > .dynamic section of the ELF executable or shared libraries, with > the type > DT_RPATH, called the DT_RPATH attribute. It can be stored there at > link time by > the linker. Tools such as chrpath and patchelf can create or MODIFY > the entry > later. > > Man chrpath (http://linux.die.net/man/1/chrpath): > > -r <path> | --replace <path> > Replace current rpath or runpath setting with the path given
It doesn't matter and it is nitpicking: the RPATH entry has some size, and its content cannot simply be changed. I.e. it could be replaced with a string of the same length or a shorter one, but not a longer one. CMake works around this by extending the build RPATH artificially with ":" at the end I think, patchelf works around this by making the whole executable one page bigger if the new entry is longer. If RPATH was _designed_ to be patchable, tools could just do it, instead of having to implement workarounds for longer strings. E.g. the linker would support a command line argument how much space it should reserve for the RPATH entry, or something like that. > > any other string in an executable could be patched too: > RPATH and C++ string literals have not the same nature. E.g. on my Linux > machine RPATH string goes to ".dynstr" section and C++ literal to > ".rodata" section. > The difference is quite huge. By parsing ELF headers you can figure out > RPATH offset and be 100% sure that patching is totally correct and > doesn't affect other binary or general executable logic. RPATH is just a > hint for linker. > Changing bytes in .rodata is much trickier. E.g. how do you distinguish > two strings: > > void print_some_info() { > const char* path = "/usr/local"; // must not be changed > std::cout << "General note: user specific packages usually installed > to " << path << std::endl; > } > > void parse_resources() { > const char* resources_path = "/usr/local"; // want to change it in future > std::string myresource = resources_path + "/foo/some.file"; > } > > What if compiler merge them? By using a very special string which is very unlikely to be used by something else, like e.g. "$$$_CMAKE_I_AM_NOT_INSTALLED_$$$". Maybe it could even be put into a custom ELF section, and then tools could just look at that section (... but then it's ELF-only). I would actually (despite it being hacky) trust the uniqueness of a string like the one above. Probably the string could be made even more unique by embedding the target name or something using cmake functionality. > (Just a general note, not related to how you want to implement resources > trick) > > > const char* my_builddir_flag = "$$$$_I_M_NOT_INSTALLED_$$$$"; > > > > ... > > > > if (*my_builddir_flag) > > > > { > > > > ... code when not installed > > > > } > > > > else > > > > { > > > > ... code for the installed version > > > > } > > > > Just search for that string in the executable and replace the first > > byte with a '\0'. > > Still can violates logic. What if I want to print string to resources in > next format: > 1. "-" x size of path to resources (compiler can figure out it at > compile time!) > 2. path to resources > 3. "-" x size of path to resources > > If you pass "/usr/local" output will be (nice): > > -------------- > /usr/local > -------------- > > If you pass "/home/username", output will be (nice): > > ------------------------ > /home/username > ------------------------ > > If you pass "$$$$_I_M_NOT_INSTALLED_$$$$" then change string to > "/usr/local" after install (ugly, not what I expect!): > > --------------------------- > /usr/local > --------------------------- Sorry, I don't understand. The idea above was only for solving the question "am I installed ?" yes/no, not "where am I installed ?". > > Not sure there is a simple tool to do that, but writing one shouldn't > > be hard. > > sed? :) I have never used sed on binary files. Does that work ? Alex
-- Powered by www.kitware.com Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Kitware offers various services to support the CMake community. For more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: http://public.kitware.com/mailman/listinfo/cmake