Je Rog
El título es claro, podemos cargar una biblioteca por dl_open
etc..
Pero, ¿cómo puedo obtener la firma de funciones en él?
lobo de fecha
Esta respuesta no puede ser contestada en general. Técnicamente, si compiló su ejecutable con información de depuración exhaustiva (el código aún puede ser una versión de lanzamiento optimizada), entonces el ejecutable contendrá secciones adicionales, proporcionando algún tipo de reflectividad del binario. En los sistemas *nix (usted se refirió a dl_open
) esto se implementa a través de ENANO datos de depuración en secciones adicionales del DUENDE binario. Similar funciona para Binarios universales de Mach en Mac OS X.
Sin embargo, Windows PE usa un formato completamente diferente, por lo que, lamentablemente, DWARF no es realmente multiplataforma (en realidad, en las primeras etapas de desarrollo de mi motor 3D, implementé un cargador ELF/DWARF para Windows, de modo que pudiera usar un formato común para varios motores). módulos, por lo que con un esfuerzo serio se puede hacer).
Si no desea implementar sus propios cargadores o depurar accesores de información, puede incrustar la información de reflexión a través de algunos símbolos adicionales exportados (mediante algún esquema de nomenclatura estándar) que se refieren a una tabla de nombres de funciones, mapeándose a su firma. En el caso de los archivos fuente C, escribir un analizador para extraer la información del archivo fuente en sí es bastante trivial. C ++ OTOH es tan notoriamente difícil de analizar correctamente, que necesita un compilador completo para hacerlo bien. Para ello se desarrolló GCCXML, técnicamente un GCC que emite el AST en formato XML en lugar de un objeto binario. El XML emitido es mucho más fácil de analizar.
A partir de la información extraída, cree un archivo fuente con algún tipo de lista/matriz/etc. estructura que describe cada función. Si no exporta directamente el símbolo de cada función, sino que inicializa algún campo en la estructura de reflexión con el puntero de función, obtendrá un esquema de exportación anotado realmente agradable y limpio. Técnicamente, también podría colocar esta información en una sección específica del binario, pero colocarla en la sección de datos de solo lectura también funciona.
Sin embargo, si recibe un binario de terceros, digamos que en el peor de los casos se ha compilado desde una fuente C, sin información de depuración y todos los símbolos no referenciados externamente eliminados, está bastante jodido. Lo mejor que pudo hacer fue aplicar un análisis binario de la forma en que la función accede a los distintos lugares en los que se pueden pasar parámetros.
Esto solo le dirá la cantidad de parámetros y el tamaño de cada valor de parámetro, pero no el tipo o el nombre/significado. Cuando se aplica ingeniería inversa a algún programa (por ejemplo, análisis de malware o auditoría de seguridad), uno de los principales esfuerzos es identificar el tipo y el significado de los parámetros que se pasan a las funciones. Recientemente me encontré con un controlador que tuve que revertir para fines de depuración, y no puede creer lo asombrado que estaba por el hecho de que encontré símbolos de C++ en un módulo del kernel de Linux (no puede usar C++ en el kernel de Linux de una manera sensata ), pero también aliviado, porque el cambio de nombre de C++ me proporcionó mucha información.
En Linux (o Mac) puede usar una combinación de “nm” y “c++filt” (para bibliotecas C++)
nm mylibrary.así | filtro c++
o
nm mylibrary.a | filtro c++
“nm” le dará la forma destrozada y “c++filt” intentará ponerlos en un formato más legible por humanos. Es posible que desee utilizar algunas opciones en nm para filtrar los resultados, especialmente si la biblioteca es grande (o puede “agrupar” el resultado final para encontrar un elemento en particular)
-
En mi Mac tuve que hacer
nm -D -Ca mylibrary.so | c++filt
– Colín
23 de abril de 2019 a las 19:12
jman
No, esto no es posible. La firma de una función no significa nada en tiempo de ejecución, es una información útil en tiempo de compilación para que el compilador valide su programa.
-
No creo que esta declaración sea precisa, básicamente estás diciendo categóricamente que no es posible. Hay muchas cosas que se pueden hacer para recuperar una firma; puede consultar la convención de llamadas y, si puede utilizar el análisis de contaminación, puede realizar un seguimiento de los argumentos de otras firmas conocidas y devolver los tipos a la función deseada.
– Adán Miller
27 de agosto de 2014 a las 13:49
no puedes La biblioteca publica una API pública en un encabezado o necesita conocer la firma por algún otro medio.
Los parámetros de una función en el nivel inferior dependen de cuántos argumentos de pila en el marco de pila considere y cómo los interprete. Por lo tanto, una vez que la función se compila en el código objeto, no es posible obtener la firma de esa manera. Una posibilidad remota es desensamblar el código y leer cómo funciona para saber el número de parámetros, pero aun así el tipo sería difícil o imposible de determinar. En una palabra, no es posible.
mpontillo
Esta información no está disponible. Ni siquiera el depurador sabe:
$ cat foo.c
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char foo[10] = { 0 };
char bar[10] = { 0 };
printf("%s\n", "foo");
memcpy(bar, foo, sizeof(foo));
return 0;
}
$ gcc -g -o foo foo.c
$ gdb foo
Reading symbols from foo...done.
(gdb) b main
Breakpoint 1 at 0x4005f3: file foo.c, line 5.
(gdb) r
Starting program: foo
Breakpoint 1, main (argc=1, argv=0x7fffffffe3e8) at foo.c:5
5 {
(gdb) ptype printf
type = int ()
(gdb) ptype memcpy
type = int ()
(gdb)
Puede encontrar el artículo de Wikipedia sobre la manipulación de nombres informativo, para ver la información codificada en los nombres de código de objeto para C frente a C ++ y cómo varía según el compilador: en.wikipedia.org/wiki/Name_mangling
– HostileFork dice que no confíes en SE
30 de julio de 2011 a las 5:57
@Hostil Fork, en un soltero
.so
,es posible tener diferentes manglings de nombres?– Je Rog
30 de julio de 2011 a las 6:07
Como se indica en el artículo de Wikipedia, el nombre mangling en C es solo para admitir las convenciones de Windows y no aparecería en
.so
archivos Para C++ sí, aparecen diferentes modificaciones del mismo nombre de función en una.so
para admitir la función de lenguaje de sobrecarga. en.wikipedia.org/wiki/Function_overloading– HostileFork dice que no confíes en SE
30 de julio de 2011 a las 6:30
Dado que la cantidad de idiomas populares ha aumentado en gran medida en las últimas 2 décadas, ¿no sería justo decir que agregar algunos metadatos introspectivos a los archivos elf ayudaría a todos? ELF no solo se usa en C/C++ y sería un buen paso en la dirección correcta para mejorar los archivos binarios con información, permitiendo la vinculación, por ejemplo, a bibliotecas compartidas, sin importar el idioma en el que se escribieron.
– BitTickler
9 de marzo de 2022 a las 23:32