Estoy intentando desensamblar un archivo compuesto que consta de varias partes, una de las cuales es un núcleo sin comprimir intercalado entre varios otros archivos. Estoy tratando de encontrar la longitud exacta de la parte del núcleo, lo cual resulta difícil.
¿Hay alguna indicación en el encabezado de vmlinux de cuántos datos se supone que debe leer el gestor de arranque antes de ejecutarse, o se supone que todo el contenido del archivo vmlinux debe cargarse en el momento de la transferencia desde el gestor de arranque?
Respuesta1
La respuesta rápida es "no", pero si se trata de una imagen ELF, con un poco de piratería probablemente puedas encontrar el kernel. Vea el readelf
truco a continuación.
El gestor de arranque es responsable de conocer el formato de cualquier archivo en el que residan el kernel y el sistema de archivos raíz. Esto incluye conocer el tamaño del archivo del kernel, sea cual sea el formato. En PowePC y Blackfin, el gestor de arranque es responsable de descomprimir todo el kernel si está comprimido y escribirlo en su ubicación final en la RAM. En ARM, el kernel podría autodescomprimirse y el gestor de arranque solo necesita copiar el archivo del kernel sin formato en un lugar conveniente de la RAM e iniciar la ejecución.
Si el kernel se autodescomprime, entonces los símbolos que indican el tamaño del archivo del kernel comprimido pueden estar o no en algún lugar del código de descompresión al principio del archivo, dependiendo del algoritmo de descompresión utilizado, pero no hay forma de saberlo. saber dónde sin un mapa enlazador para la compilación específica del kernel. Ciertamente el gestor de arranque no tiene forma de saberlo.
El código del kernel sin comprimir está delimitado por dos símbolos, _stext
y _end
cuyas direcciones son el inicio y el final del kernel, pero no incluyen la extensión de ningún initramfs incluido, si un initramfs se ha vinculado al binario del kernel. El enlazador establece la extensión de initramfs en dos símbolos del núcleo __initramfs_start
y __initramfs_end
. Los cargadores de arranque generalmente no tienen la capacidad de leer la tabla de símbolos del kernel (está en el System.map
archivo) y sin esta capacidad no tendrían forma de saber dónde están los símbolos _end
y __initrams_end
en el archivo del kernel. Es decir, la posición de los símbolos no es un desplazamiento fijo desde el inicio del archivo binario. Se determina en el momento del enlace y puede variar según la configuración de compilación del kernel.
Para un kernel sin comprimir en formato ELF, probablemente pueda identificar el inicio del archivo vmlinux buscando el encabezado ELF ( 177 E L F
en el od -c
volcado del archivo compuesto). Luego puede hacer readelf -e
o objdump -h
en el resto del archivo desde este punto para encontrar la sección con el desplazamiento de archivo más alto ( .shstrtab
). Agregue el tamaño de la sección a este desplazamiento y eso lo llevará al final de vmlinux. Probé este método usando un PPC vmlinux sin desinstalar y obtuve un tamaño que coincidía exactamente con el tamaño del archivo vnlinux independiente. Después de eliminar el núcleo, este método arrojó un resultado de 1283 bytes menos que el tamaño de la imagen eliminada.
Los sistemas integrados suelen utilizar un formato de archivo como mkimage
para empaquetar el kernel, rootfs, árbol de dispositivos y otros componentes. U-boot, por ejemplo, reconoce mkimage, por lo que sabe dónde comienza y termina el binario del kernel dentro del archivo mkimage y sabe si el kernel está comprimido o no y en qué dirección RAM escribir el archivo del kernel.