2012-02-15 8 views
7

Al construir un proyecto de mcu desnudo basado en gcc, debe encargarse de la inicialización de las secciones .data y .bss durante el inicio.¿Cómo sé de dónde necesita la sección .data obtener los datos init? (linker de gcc)

La sección .bss es bastante sencilla ya que llené toda la sección hasta 0. Pero las variables en la sección .data deben tener sus datos de inicialización en rom/flash y deben copiarse durante el inicio.

¿Cómo puedo saber dónde se encuentran los datos con los valores de inicialización?

Tomemos un ejemplo.

Digamos que puedo crear dos variables globales en main.c

unsigned int my_global_variable_one = 1; 
unsigned int my_global_variable_two = 2; 

entonces puedo usar objdump en el archivo de objeto para ver en qué sección estarán en, pero no puedo encontrar nada en el objdump out poner donde se deben colocar los datos init.

$ arm-none-eabi-objdump --syms main.o | grep my_global_variable 
00000000 g  O .data 00000004 my_global_variable_one 
00000004 g  O .data 00000004 my_global_variable_two 

Luego puedo ver el elfo resultante para todo el sistema, en este caso main.elf.

$ arm-none-eabi-nm -n main.elf | grep my_global_variable 
20000000 D my_global_variable_one 
20000004 D my_global_variable_two 

¿Dónde puedo encontrar dónde están para poder copiar los datos? ¿Qué debo poner en mi secuencia de comandos del enlazador?

Debe estar en algo como .text o .rodata, pero ¿cómo puedo saberlo?

¿Cómo puedo verificar dónde se encuentran los datos de inicio de my_global_variable_one?

¿Puedo encontrar dónde están estos datos con cualquiera de los comandos binutils como readelf u objdump? se utiliza

/Gracias


Esto está en un STM32 (Cortex M3) MCU, y la versión Codebench de gcc.

Respuesta

9

El compilador coloca todos los códigos y algunos datos de solo lectura en la sección .text. También puede haber una sección .rodata. Usted puede tener la secuencia de comandos enlazador puesto que en una dirección de ROM algo como esto:

. = <rom-base-address>; 
.rodata : { *(.rodata) } 
<other read-only sections go here> 
.text : { *(.text) } 

El compilador pone todos los valores iniciales de los datos se pueden escribir en la sección .data, y todos los símbolos que no tienen un valor inicial de .bss. El .bss es fácil, simplemente coloca eso en la RAM. El .data quiere estar en la memoria RAM en tiempo de ejecución, pero en la ROM en el tiempo de carga, y el guión enlazador le permite hacer eso con el AT palabra clave:

. = <ram-base-address>; 
.bss : { *(.bss) } 
.data : AT (ADDR (.text) + SIZEOF (.text)) 
     { *(.data) } 

Esto significa que la sección de datos tiene ahora una ML diferente y VMA (Dirección de memoria de carga/Dirección de memoria virtual). Su programa esperará encontrar los datos en el VMA (la dirección de tiempo de ejecución), pero los datos realmente existirán en el LMA (puede que tenga que enseñarle su flash para hacerlo), que está justo después de la sección .text.

Si necesita saber dónde copiar desde y hacia allí, puede crear punteros en el script del enlazador. Por lo tanto, modificar el ejemplo anterior así:

.data : AT (ADDR (.text) + SIZEOF (.text)) 
     { _data_lma = LOADADDR(.data); _data_vma = .; 
      *(.data); 
      _data_size = SIZEOF (.data);} 

A continuación, puede hacer memcpy (_data_vma, _data_lma, _data_size) en el código de puesta en marcha (aunque puede que tenga que codificar manualmente que en ensamblador?) Esos símbolos aparecerán a su programa como constante globales que se resuelven en el momento del enlace. Por lo tanto, en el código ensamblador es posible que tenga algo como:

_data_lma_k: 
    .long _data_lma 

A continuación, el número se cifran con fuerza en la sección .text. Por supuesto, la sintaxis del ensamblador puede ser diferente en su plataforma.

Para obtener más información, consulte el manual de enlazador here

+0

Bueno me di cuenta de que los datos se agregan después de la sección .text, pero me ayudó a conseguir lo suficientemente cerca :) – Johan

Cuestiones relacionadas