Linux From Scratch para Cubietruck – C1: introducción cadena de herramientas

1. ¿Qué cadena de herramientas?

En incrustado, gcc es el conjunto de herramientas más prominente en uso. Entre las distribuciones de las herramientas principales de gcc, «Linaro» se utilizará como referencia mucho en esta serie. Linaro soportar Linux y Android. Sus parches muy probablemente serán adoptadas por la corriente. Su exclusivo soporte para ARM lo convierten en un líder en la cadena de herramientas ARM, con el apoyo inmediato para los nuevos tableros de chips ARM / dev. Así que creo Linaro es una buena referencia para mi cubietruck A20 Cortex-A7 basado. Pero vamos a construir la cadena de herramienta directamente desde el más reciente fuente de aguas arriba en vez de desde la fuente Linaro, ya que la mayoría de los parches de Linaro se han portado de nuevo a la corriente. Si las condiciones lo exigen el uso de Linaro distribución específica debido a los parches no-portado hacia atrás, vamos a utilizar Linaro distribución directa.

2. Independientes contra entorno C Alojado en GCC

Según definición de la Comisión de Normas de C, hay dos modos de compilador C y el tiempo de ejecución, a saber, «independiente» y «conducido». . Estos dos modos sólo especifican el grado de la biblioteca de soporte, es decir, c biblioteca

Para independientes, estas cabeceras son obligatorios en C99:
 <float.h><limits.h><stdarg.h>, , <iso646.h>, <stdbool.h> ,<stdint.h>

En C11, se añaden dos cabeceras extra: (gcc no implementa C11 completamente todavía.)



Todas estas cabeceras son sólo const y definiciones de tipo. No hay sistema o sistema operativo cosas dependen de ellos. kernel Linux, y aplicación independiente integrado, gestor de arranque todas las vidas en el medio ambiente "independiente".

En "conducido" medio ambiente, la aplicación se ejecuta con la ayuda de una pila de servicios de la plataforma Un diagrama aclarar tales soportes:

entorno independiente:

Medio ambiente Hosted:

GCC apoyar tanto independiente y entorno alojado, y por defecto en modo hospedado Revise a continuación manual de gcc para obtener más información:

http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc / standards.html # Normas

¿Por qué nos molestamos con "independiente" y "conducido" cosas Porque:?.

En un mundo integrado, independiente es una forma canónica de la vida. ¡Tienes que lidiar con el gestor de arranque, el kernel, la biblioteca c directamente.
b. Construir cadena de herramientas GCC, conocimiento profundo de estos dos modos le ayudará a entender cómo bootstraps gcc sí mismo. Esto es muy importante cuando se intenta entiende cómo funciona compilador cruzado.

3. Alojado

Aquí está nuestro "hello.c". Se trabaja con la ayuda de "entorno alojado."

# include

int main (int argc, char * argv [])
{
printf (" hello world! n ");
return 0;

}

Desde que usamos "stdio.h", y no es parte de las cabeceras de entorno "independiente", estamos programando en entorno alojado. La función "printf" es proporcionado por la biblioteca estándar c. GCC por defecto "organizadas" modo también. Así que veamos lo Códigos generan cuando se compila este programa. Recuérdese por favor este programa se ejecuta en mi PC 7 debian linux. />

gcc-S hello.c-o hello.s
cat hello.s


# file este conjunto se genera a partir de "hello.c"

. archivo " hola.c "

# asigne una sección llamada" Rodata "- leer sólo los datos
# de colocar nuestro constante de cadena" hello world font-family: Courier New, Courier, "

. sección. Rodata
. LC0:
cadena " hola mundo "

# aquí es la sección. "texto" para mantener la instrucción ejecutable

texto

# declare" principal "como" función global ", por lo que podría ser visto por
# otros módulos / archivos mientras vinculado con la biblioteca estándar de C

GLOBL principal
escribe principal, la función @

# en entorno AMD64, llamadas a funciones siguen convención de llamada estricta Se llama "interfaz binaria de aplicación", es decir, ABI La especificación para AMD64 ABI está aquí:..
# http://www.x86-64.org/documentation/abi.pdf

# en nuestro ejemplo,

principal:.
LFB0:

construcción # stack frame siguiente API AMD64.

# cfi significa" llamar a información de la trama ". Es una directiva de extensión GCC gcc lo utilizan para descansar fotograma de la llamada anidada cuando se produce una excepción

cfi_startproc

# primer salvamento llamando registro base frame% RBP en pila

pushq% RBP
. cfi_def_cfa_offset 16
cfi_offset 6, -16

# guarda puntero de pila% rsp actual en% RBP, el registro de base de la chimenea

; movq% rsp, RBP%
;. cfi_def_cfa_register 6

# asigna 16 bytes en el marco de pila para almacenar variables temporales
subq $ 16,% rsp

# AMD64 ABI utilice"% RDI, rsi%,% rdx, rcx%,% r8 y r9% "para aprobar los parámetros de llamada de función
# de int main (int argc, char * argv []), "% edi" es "argc", y " rsi "es" argv "
# ya que vamos a llamar a otras funciones en "principal", "% edi,% rsi" conseguirá invalida durante
# llamada función anidada, por lo que los almacena en la pila de lugares temporales en primer lugar, en caso de que todavía # # Necesitamos acceder a ellos después de las llamadas funciones anidadas

; movl% edi, -4 (% RBP)
movq% rsi, -16 (% RBP)

# LC0 . es la dirección de la cadena "Hello World!" Cambiamos en% edi pasar como la
# primer parámetro para llamar a la función" puts "
. # pone es más que otra función en la biblioteca estándar de C Aquí está su prototipo:
#" int puts (const char * s); "

movl $ . LC0,% edi
llamada puts

# ahora" hola mundo "quedó impreso en la salida estándar de" puts ", es el momento de volver de" principal "

# de acuerdo con ABI AMD64, el valor devuelto de la función se debe colocar dentro de"% eax "
movl $ 0,% eax

# "salir" se ajustará fun marco de llamada para que podamos devolver la forma función de llamada
#" licencia "es equivalente a" movq% RBP,% rsp; POPQ% RBP "
dejar
. cfi_def_cfa 7, 8

# ahora volver de main ();
ret
cfi_endproc


LFE0:


# directiva tamaño calculará el tamaño en bytes de la función" principal fuente-familia "
#".-principal "significa" current_address - dirección del principal font-family: Courier New, Courier, "
Tamaño principal,-principal.

# éstos son general "comentarios como" la información generada por el ensamblador de GNU.

ident GCC ": (Debian 4.7. 2-5) 4.7.2 "
. sección. note.GNU-stack, "", @ progbits

Ahora podemos ver la concepto de ABI, que generalmente es la función de la convención de llamada en un hardware específico + entorno de sistema operativo y cómo se pasan los parámetros de la función durante la llamada de función. Podemos ver también que "printf ()" se aplica realmente por "puts ()" en la biblioteca c. Pasemos.


gcc-c-o hello.s hello.o

nm hello.o
0000000000000000 T principal
U puts

# dos símbolos que se encuentran. "pone" es símbolo indefinido, ya que se define en las bibliotecas de c. ; "principal" se define por hello.c ya

objdump - h hello.o


hello.o: formato de archivo elf64 -x86-64


Secciones:

Nombre Ind Tamaño VMA ; LMA File off ALGN
0 de texto 00000020 0000000000000000 0000000000000000 00000040 2 *. * 2

; CONTENIDOS, ALLOC, CARGA, RELOC, READONLY, CÓDIGO

1 datos 00000000 0000000000000000 0000000000000000 00000060 2 ** 2
CONTENIDO, ALLOC, CARGA, DE DATOS

2. bss 00000000 ; 0000000000000000 0000000000000000 00000060 2 ** 2

ALLOC
3 Rodata 0000000d 0000000000000000 0000000000000000 00000060 2 ** 0

<. div> CONTENIDOS, ALLOC, CARGA, READONLY, DATOS

4. comentario ; 0000001d 0000000000000000 0000000000000000 0000006d 2 ** 0

Contenidos, READONLY
5 note.GNU-stack 00000000 0000000000000000 0000000000000000 0000008a 2 ** 0 .

;. CONTENIDOS, READONLY

6 eh_frame 00000038 0000000000000000 0000000000000000 00000090 2 ** 3

CONTENIDO, ALLOC, CARGA, RELOC, READONLY, DATOS



objdump-d hello.o

hola . o: formato de archivo elf64-x86-64



.

Desmontaje de la sección de texto:


0000000000000000 :
0: 55 empujar% RBP

1: 48 89 e5 ; mov% rsp, RBP%

4: 48 83 ec 10 sub $ 0x10,% rsp

8: <= span class" Apple-tab-palmo "style =" white-space: pre; " > 89 fc 7d mov ;% edi,-0x4 (% RBP)
b: 48 89 75 f0 ; mov% rsi,-0x10 (% RBP)

f: bf 00 00 00 00 mov $ 0x0,% edi

14: e8 00 00 00 00 callq 19 <; principal 0 x19>

19: b8 00 00 00 00 mov $ 0x0,% eax

1e: c9 leaveq
1f: c3 ; retq

Podemos ver en el código compilado desmontado coincide con los que vemos de "hello.s". La única advertencia es que todavía no sabemos donde se encuentra la función de "puts", por lo que gcc generar una "rellocation entrada "para los" puts ". Cuando enlazador" ld "vincular la biblioteca estándar de C con hello.o para generar el ejecutable final, ld llenará en la dirección correcta para" puts ".

objdump-r hello.o


hello.o: archivo formato elf64-x86-64


REGISTROS DE REUBICACIÓN PARA [texto.]:

OFFSET TIPO ; VALOR

0000000000000010 R_X86_64_32 . Rodata

0000000000000015 R_X86_64_PC32 pone 0 xfffffffffffffffc

El tipo de entrada es rellocation" R_X86_64_PC32 "

Básicamente, significa el modo de direccionamiento es "relativo al PC", que es relativo a la instrucción de puntero "PC". En la generada código,


e8 00 00 00 00 callq 19
gcc quedan atrás 4 bytes de espacio "00 00 00 00" (32 bits) para que enlazador para rellenar el último discurso de "puts" " 0xfffffffffffffffc" es el y el desplazamiento "-4", ya que cuando la CPU de Intel se ejecuta la instrucción actual, los puntos de PC para el inicio de siguiente instrucción. gcc decirle ld cuánto compensar las necesidades que se deben ajustar al calcular la dirección "PC relativa". Reubicación en AMD64 enlazador / ABI en sí es un gran tema en sí mismo. Vamos a detenemos aquí.


Finalmente, le gustaría gcc a enlazar la librería c para nosotros para que podamos tener un programa ejecutable.



$ gcc-o hola hello.o
$ file hola
hola: ELF 64-bit LSB ejecutable, x86-64, versión 1 (SYSV), vinculada dinámicamente (usa libs compartidos), para GNU / Linux 2.6.26, BUILDID [SHA1] = 0xec632a61cbc60ae56758920e1916ffdec3ea6ad9, no despojado

$ ldd hola

linux-vdso.so.1 => (0x00007fffa43ff000)
libc.so.6 => / lib/x86_64-linux-gnu/libc.so. 6 (0x00007fb4d3848000)

/ lib64/ld-linux-x86-64.so.2 (0x00007fb4d3bfb000)

$ . / hola

hola mundo
http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *