¿Hay alguna forma de inspeccionar el rpath actual en Linux?

83

Soy consciente de que es posible usarlo readelf -d <elf> | grep RPATHpara inspeccionar un binario dado desde el shell, pero ¿es posible hacer esto dentro de un proceso?

Algo como (mi llamada al sistema completamente inventada):

  /* get a copy of current rpath into buffer */
  sys_get_current_rpath(&buffer);

Estoy tratando de diagnosticar algunos problemas sospechosos de vinculación de SO en nuestra base de código y me gustaría inspeccionar el RPATH de esta manera si es posible (prefiero no tener que generar un script externo).

Justicle
fuente
1
Tenga en cuenta que al diagnosticar problemas de bibliotecas compartidas, también debe inspeccionar la etiqueta RUNPATH. Por lo tanto, debería grep PATHhacerlo. Depende del vinculador si se usa RPATH o RUNPATH, y existen diferencias sutiles pero importantes entre los dos: stackoverflow.com/a/52020177
Nicolas Capens

Respuestas:

54
#include <stdio.h>
#include <elf.h>
#include <link.h>

int main()
{
  const ElfW(Dyn) *dyn = _DYNAMIC;
  const ElfW(Dyn) *rpath = NULL;
  const char *strtab = NULL;
  for (; dyn->d_tag != DT_NULL; ++dyn) {
    if (dyn->d_tag == DT_RPATH) {
      rpath = dyn;
    } else if (dyn->d_tag == DT_STRTAB) {
      strtab = (const char *)dyn->d_un.d_val;
    }
  }

  if (strtab != NULL && rpath != NULL) {
    printf("RPATH: %s\n", strtab + rpath->d_un.d_val);
  }
  return 0;
}
Ruso empleado
fuente
1
es brillante, pero no funciona con $ ORIGIN. $ ORIGIN no se interpreta y la función lo devuelve tal cual. ¿Hay alguna forma de agregar la interpretación $ ORIGIN?
Jérôme
5
@ Jérôme Si está ejecutando en un entorno donde /procestá montado, entonces expandir $ORIGINes tan simple como readlink("/proc/self/exe", ...)luego terminar en NUL en la última barra.
Empleado ruso
Si bien la pregunta era específicamente sobre RPATH, me gustaría señalar que es igualmente importante verificar la DT_RUNPATHetiqueta si uno desea saber las rutas desde las que un binario podría estar cargando sus bibliotecas compartidas.
Nicolas Capens
154

Para el registro, aquí hay un par de comandos que mostrarán el rpathencabezado.

objdump -x binary-or-library |grep RPATH

Quizás una forma aún mejor de hacerlo es la siguiente:

readelf -d binary-or-library |head -20

El segundo comando también enumera las dependencias directas de otras bibliotecas seguidas de rpath.

Michael Dillon
fuente
7
En ubuntu 15.04 tengo que usar: objdump -x binary-or-library | grep RUNPATH
Andreas Roth
11
Esta respuesta no tiene nada que ver con la pregunta que se hizo (y está contenida en la pregunta en sí).
Empleado ruso
12

También puedes usar:

chrpath -l binary-or-library
Oscar Andreasson
fuente
En ubuntu:apt-get install -y chrpath
Toby Brull
1

Esto es lo que uso por conveniencia, como función de shell:

function getrpath {
    eu-readelf -d "${1:?}" | sed -e '/RUNPATH/{s~.*\[\(.*\)\]~\1~;n};d'
}

Esto consume la eu-readelfsalida de elfutilscomo:

Type              Value
NEEDED            Shared library: [libpq.so.5]
NEEDED            Shared library: [libc.so.6]
RUNPATH           Library runpath: [/some/path/to/lib]
....

y emite

 /some/path/to/lib

Debería funcionar bien con binutils en readelflugar de elfutils eu-readelftambién.

Craig Ringer
fuente