This is the mail archive of the
libc-hacker@cygnus.com
mailing list for the glibc project.
changing embedded RPATH in existing executables.
- To: egcs@cygnus.com, libc-hacker@cygnus.com, linux-gcc@vger.rutgers.edu
- Subject: changing embedded RPATH in existing executables.
- From: peeterj@ca.ibm.com
- Date: Wed, 28 Apr 1999 12:19:21 -0400
Hello,
I would like to be able to change the embedded rpath in executable and
shared libraries using libbfd. The development platform in question here
is linux/i386.
[ I was also thinking of using something similar (presuming it's possible)
to change the NEEDED tags for redhat glibc-2.1 built executables so that
they can be run on non-redhat glibc-2.1 distributions. Redhat 6.0 has
used a different SONAME for it's glibc-2.1 built libstdc++.so.2.9.0 then
any of the other glibc-2.1distributions, so ISVs and other external package
creators will have to build separate executables/packages for redhat
glibc-2.1 and for any other glibc-2.1 based distributions if they use C++.
The other possibilty would be for everybody to ship their own libstdc++
(and use -Wl,-rpath to force it to be used instead of the system one) so
that their binaries will work on different distributions. However, I am
not sure this is feasable because of the GPL. ]
Based on objdump, and some of the libbfd elf code I wrote the program below
that can be used to find the RPATH start in the ELF .dynamic section, but
now that I have found it I don't know how to write modifications back into
the section. I tried bfd_openw instead of bfd_openr, but the code to find
the RPATH doesn't work after doing that (the bfd_check_format_matches call
fails).
Can anybody provide me with some hints for the next step.
Peeter
--
#include "bfd.h"
#include <stdlib.h>
#include <stdio.h>
#include "sysdep.h"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
#include "elf-bfd.h"
int main (int argc, char **argv)
{
bfd *file;
char **matching;
asection *s;
bfd_init ();
if (argc != 2)
abort();
file = bfd_openr (argv[1], "elf32-i386");
if (!file)
abort();
#if 0
if (!bfd_set_format(file, bfd_object))
abort();
#endif
if (!bfd_check_format_matches (file, bfd_object, &matching))
abort();
s = bfd_get_section_by_name (file, ".dynamic");
if (s != NULL)
{
int elfsec;
unsigned long link;
bfd_byte *extdyn, *extdynend;
size_t extdynsize;
void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
bfd_byte *dynbuf = NULL;
dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
if (dynbuf == NULL)
abort();
if (! bfd_get_section_contents (file, s, (PTR) dynbuf, (file_ptr) 0,
s->_raw_size))
abort();
elfsec = _bfd_elf_section_from_bfd_section (file, s);
if (elfsec == -1)
abort();
link = elf_elfsections (file)[elfsec]->sh_link;
extdynsize = get_elf_backend_data (file)->s->sizeof_dyn;
swap_dyn_in = get_elf_backend_data (file)->s->swap_dyn_in;
extdyn = dynbuf;
extdynend = extdyn + s->_raw_size;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
const char * tag = NULL;
(*swap_dyn_in) (file, (PTR) extdyn, &dyn);
if (dyn.d_tag == DT_RPATH)
tag = "RPATH";
if (dyn.d_tag == DT_SONAME)
tag = "SONAME";
if (tag)
{
const char *string;
string = bfd_elf_string_from_elf_section (file, link,
dyn.d_un.d_val);
if (string == NULL)
abort();
printf ("%s:%s\n", tag, string);
// strcpy((char *)string, "x");
}
}
#if 0
{
bfd * out;
asection * snew;
out = bfd_create("out", file);
if (!out)
abort();
snew = bfd_get_section_by_name (out, ".dynamic"); // doesn't work
if (!snew)
abort();
if (! bfd_set_section_contents (out, snew, (PTR) dynbuf, (file_ptr)
0,
s->_raw_size))
abort();
bfd_close(out);
}
#endif
}
bfd_close (file);
return 0;
}