linux - kid3 - mp3tag
Encabezados de archivo ELF (9)
Una pregunta rápida sobre los encabezados de archivos elf, parece que no encuentro nada útil sobre cómo agregar / cambiar campos en el encabezado de duela. Me gustaría poder cambiar los números mágicos y agregar una fecha de compilación al encabezado, y probablemente algunas otras cosas más.
Según tengo entendido, el vinculador crea la información del encabezado, pero no veo nada en el script LD que se refiera a él (aunque soy nuevo en los scripts ld).
Estoy usando gcc y compilando para ARM.
¡Gracias!
Actualizaciones:
- ok tal vez mi primera pregunta debería ser: ¿es posible crear / editar el archivo de encabezado en el momento del enlace?
Estoy bastante seguro de que una secuencia de comandos ld lo suficientemente compleja puede hacer lo que quieras. Sin embargo, no tengo idea de cómo.
Por otro lado, elfsh puede hacer todo tipo de manipulaciones a los objetos elfos, así que dale un giro.
No he hecho esto por un tiempo, pero no puedes agregar datos arbitrarios a un ejecutable. Si siempre anexa datos de tamaño fijo, sería trivial recuperar todo lo que agregue. El tamaño variable no sería mucho más difícil. Probablemente sea más fácil que jugar con encabezados de w / elf y potencialmente arruinar tus ejecutables.
No sé de los comandos de secuencia de comandos del enlazador que pueden hacer esto, pero puede hacerlo post-link usando el comando objcopy . La opción --add-section se puede usar para agregar una sección que contenga datos arbitrarios al archivo ELF. Si el encabezado ELF no contiene los campos que desea, solo haga una nueva sección y agréguela allí.
No terminé el libro, pero iirc Linkers and Loaders de John Levine tenía los detalles sangrientos que necesitaría para poder hacer esto.
Este enlace (binario teensy elf) fue la respuesta de alguien a otra pregunta, pero se adentra en las complejidades de un encabezado ELF con cierto detalle.
En consola Linux:
$ hombre ld
$ ld --verbose
HTH
En Solaris puede usar elfedit, pero creo que realmente está pidiendo soluciones para Linux. Linux no es UniX: P
Puede crear un archivo de objeto con campos informativos, como un número de versión, y vincular ese archivo para que se incluyan en el binario ELF resultante.
Ident
Por ejemplo, como parte de su proceso de compilación, puede generar, por ejemplo, info.c
que contenga una o más directivas #ident
:
#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"
Compilarlo:
$ gcc -c info.c
Verifique si la información está incluida:
$ readelf -p .comment info.o
String dump of section ''.comment'':
[ 1] Build: 1.2.3 (Halloween)
[ 1a] Environment: example.org
[ 33] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
Alternativamente, puede usar objdump -s --section .comment info.o
Tenga en cuenta que GCC también escribe su propio comentario, por defecto.
Verifique la información después de vincular un ejecutable ELF:
$ gcc -o main main.o info.o
$ readelf -p .comment main
String dump of section ''.comment'':
[ 0] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
[ 2c] Build: 1.2.3 (Halloween)
[ 45] Environment: example.org
Sección de comentarios
Usar #ident
en una unidad de traducción C es básicamente equivalente a crear una sección .comment
en un archivo de ensamblador. Ejemplo:
$ cat info.s
.section .comment
.string "Build: 1.2.3 (Halloween)"
.string "Environment: example.org"
$ gcc -c info.s
String dump of section ''.comment'':
[ 0] Build: 1.2.3 (Halloween)
[ 19] Environment: example.org
El uso de un nombre de sección poco común también funciona (p .section .blahblah
., .section .blahblah
). Pero .comment
es usado y entendido por otras herramientas. GNU también entiende la directiva .ident
, y esto es a lo que GCC traduce #ident
a.
Con símbolos
Para los datos a los que también desea acceder desde el ejecutable ELF, debe crear símbolos.
Objcopy
Supongamos que desea incluir algunos bytes mágicos almacenados en un archivo de datos:
$ cat magic.bin
2342
Convierte en un archivo de objeto con objcopy de GNU :
$ objcopy -I binary -O elf64-x86-64 -B i386 /
--rename-section .data=.rodata,alloc,load,readonly,data,contents /
magic.bin magic.o
Compruebe los símbolos:
$ nm magic.o
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start
Ejemplo de uso:
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
extern const char _binary_magic_bin_start[];
extern const char _binary_magic_bin_end[];
extern const unsigned char _binary_magic_bin_size;
static const size_t magic_bin_size = (uintptr_t) &_binary_magic_bin_size;
int main()
{
char s[23];
memcpy(s, _binary_magic_bin_start,
_binary_magic_bin_end - _binary_magic_bin_start);
s[magic_bin_size] = 0;
puts(s);
return 0;
}
Enlace todo junto:
$ gcc -g -o main_magic main_magic.c magic.o
GNU ld
GNU ld también puede convertir archivos de datos en archivos de objetos usando un esquema de nombres compatible con objcopy:
$ ld -r -b binary magic.bin -o magic-ld.o
A diferencia de objcopy, coloca los símbolos en .data
lugar de la sección .rodata
, sin embargo (ver objdump -h magic.o
).
incbin
En caso de que GNU objcopy no esté disponible, se puede usar GNU como directiva .incbin
para crear el archivo objeto (ensamblar con gcc -c incbin.s
):
.section .rodata
.global _binary_magic_bin_start
.type _binary_magic_bin_start, @object
_binary_magic_bin_start:
.incbin "magic.bin"
.size _binary_magic_bin_start, . - _binary_magic_bin_start
.global _binary_magic_bin_size
.type _binary_magic_bin_size, @object
.set _binary_magic_bin_size, . - _binary_magic_bin_start
.global _binary_magic_bin_end
.type _binary_magic_bin_end, @object
.set _binary_magic_bin_end, _binary_magic_bin_start + _binary_magic_bin_size
; an alternate way to include the size
.global _binary_magic_bin_len
.type _binary_magic_bin_len, @object
.size _binary_magic_bin_len, 8
_binary_magic_bin_len:
.quad _binary_magic_bin_size
xxd
Una alternativa más portátil que no requiere GNU objcopy ni GNU ya que es crear un archivo C intermedio y compilar y vincular eso. Por ejemplo, con xxd :
$ xxd -i magic.bin | sed ''s//(unsigned/)/const /1/'' > magic.c
$ gcc -c magic.c
$ nm magic.o
0000000000000000 R magic_bin
0000000000000008 R magic_bin_len
$ cat magic.c
const unsigned char magic_bin[] = {
0x32, 0x33, 0x34, 0x32, 0x0a
};
const unsigned int magic_bin_len = 5;
Es posible que pueda usar libmelf, un proyecto inactivo en carne fresca, pero disponible en LOPI - http://www.ipd.bth.se/ska/lopi.html
De lo contrario, puede obtener la especificación y (sobre) escribir el encabezado usted mismo.