2016-11-09 3 views
0

J'ai un script de liaison qui relie le code pour imx6q (Cortex-A9):taille binaire énorme en ld Lier

OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 
OUTPUT_ARCH(arm) 
ENTRY(Reset_Handler) 
/* SEARCH_DIR(.) */ 
GROUP(libgcc.a libc.a) 
/* INPUT (crtbegin.o crti.o crtend.o crtn.o) */ 

MEMORY { 
/* IROM (rwx) : ORIGIN = 0x00000000, LENGTH = 96K */ 
    IRAM (rwx) : ORIGIN = 0x00900000, LENGTH = 256K 
    IRAM_MMU (rwx): ORIGIN = 0x00938000, LENGTH = 24K 
    IRAM_FREE(rwx): ORIGIN = 0x00907000, LENGTH = 196K 
    DDR (rwx) : ORIGIN = 0x10000000, LENGTH = 1024M 
} 

/* PROVIDE(__cs3_heap_start = _end); */ 

SECTIONS { 
    .vector (ORIGIN(IRAM) + LENGTH(IRAM) - 144):ALIGN (32) { 
    __ram_vectors_start = . ; 
    . += 72 ; 
    __ram_vectors_end = . ; 
    . = ALIGN (4); 
    } >IRAM 

    . = ORIGIN(DDR); 
    .text(.) :ALIGN(8) { 
     *(.entry) 
     *(.text) 
     /* __init_array_start = .; */ 
     /* __init_array_end = .; */ 
     . = ALIGN (4); 
     __text_end__ = .; 
    } >DDR 

    .data :ALIGN(8) { 
     *(.data .data.*) 
     __data_end__ = .; 
    } 

    .bss(__data_end__) : { 
     . = ALIGN (4); 
     __bss_start__ = .; 
     *(.shbss) 
     *(.bss .bss.* .gnu.linkonce.b.*) 
     *(COMMON) 
     __bss_end__ = .; 
    } 

    /*  . += 10K; */ 
    /*  . += 5K; */ 

    top_of_stacks = .; 
    . = ALIGN (4); 
    . += 8; 
    free_memory_start = .; 

    .mmu_page_table : { 
    __mmu_page_table_base__ = .; 
    . = ALIGN (16K); 
    . += 16K; 
    } >IRAM_MMU 

    _end = .; 
    __end = _end; 
    PROVIDE(end = .); 
} 

Quand je construit, la taille binaire est à seulement 6 Ko. Mais je ne peux pas ajouter de variable initialisée. Lorsque j'ajoute une variable initialisée, la taille binaire passe à ~ 246 Mo. Pourquoi donc? J'ai essayé de lier le segment de données à l'emplacement suivant la section de texte en spécifiant l'emplacement exact et en fournissant également> DDR pour le segment de données. Même si cela semble réduire la taille binaire à 6 Ko, le binaire ne parvient pas à démarrer. Comment puis-je garder mon code dans le DDR et les données, bss, empiler et tas dans le RAM interne lui-même, avec une taille binaire légère? J'ai lu dans un autre fil que "l'utilisation de la balise MEMORY dans le script du linker devrait résoudre le problème du gaspillage de mémoire", Comment cela peut-il être fait?

linker script wastes my memory

Plese ne demande rien d'autre si nécessaire. Je n'ai aucune expérience avec le script de l'éditeur de liens. S'il vous plaît aider

La readelf la sortie du binaire sans données initialisées données est la suivante,

There are 19 section headers, starting at offset 0xd804: 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .vector   NOBITS   0093ff80 007f80 000048 00 WA 0 0 32 
    [ 2] .text    PROGBITS  10000000 008000 0016fc 00 AX 0 0 8 
    [ 3] .text.vectors  PROGBITS  100016fc 0096fc 000048 00 AX 0 0 4 
    [ 4] .text.proc  PROGBITS  10001744 009744 000034 00 AX 0 0 4 
    [ 5] .bss    NOBITS   0093ffc8 007fc8 000294 00 WA 0 0 4 
    [ 6] .mmu_page_table NOBITS   00938000 008000 004000 00 WA 0 0 1 
    [ 7] .comment   PROGBITS  00000000 009778 00001f 01 MS 0 0 1 
    [ 8] .ARM.attributes ARM_ATTRIBUTES 00000000 009797 00003d 00  0 0 1 
    [ 9] .debug_aranges PROGBITS  00000000 0097d8 000108 00  0 0 8 
    [10] .debug_info  PROGBITS  00000000 0098e0 0018a7 00  0 0 1 
    [11] .debug_abbrev  PROGBITS  00000000 00b187 00056f 00  0 0 1 
    [12] .debug_line  PROGBITS  00000000 00b6f6 00080e 00  0 0 1 
    [13] .debug_frame  PROGBITS  00000000 00bf04 000430 00  0 0 4 
    [14] .debug_str  PROGBITS  00000000 00c334 0013dd 01 MS 0 0 1 
    [15] .debug_ranges  PROGBITS  00000000 00d718 000020 00  0 0 8 
    [16] .shstrtab   STRTAB   00000000 00d738 0000cb 00  0 0 1 
    [17] .symtab   SYMTAB   00000000 00dafc 000740 10  18 60 4 
    [18] .strtab   STRTAB   00000000 00e23c 000511 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

et la readelf la sortie du binaire avec des données initialisées données est,

There are 20 section headers, starting at offset 0xd82c: 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .vector   NOBITS   0093ff80 007f80 000048 00 WA 0 0 32 
    [ 2] .text    PROGBITS  10000000 008000 0016fc 00 AX 0 0 8 
    [ 3] .text.vectors  PROGBITS  100016fc 0096fc 000048 00 AX 0 0 4 
    [ 4] .text.proc  PROGBITS  10001744 009744 000034 00 AX 0 0 4 
    [ 5] .data    PROGBITS  0093ffc8 007fc8 000004 00 WA 0 0 8 
    [ 6] .bss    NOBITS   0093ffcc 007fcc 000294 00 WA 0 0 4 
    [ 7] .mmu_page_table NOBITS   00938000 008000 004000 00 WA 0 0 1 
    [ 8] .comment   PROGBITS  00000000 009778 00001f 01 MS 0 0 1 
    [ 9] .ARM.attributes ARM_ATTRIBUTES 00000000 009797 00003d 00  0 0 1 
    [10] .debug_aranges PROGBITS  00000000 0097d8 000108 00  0 0 8 
    [11] .debug_info  PROGBITS  00000000 0098e0 0018b6 00  0 0 1 
    [12] .debug_abbrev  PROGBITS  00000000 00b196 000580 00  0 0 1 
    [13] .debug_line  PROGBITS  00000000 00b716 00080e 00  0 0 1 
    [14] .debug_frame  PROGBITS  00000000 00bf24 000430 00  0 0 4 
    [15] .debug_str  PROGBITS  00000000 00c354 0013dd 01 MS 0 0 1 
    [16] .debug_ranges  PROGBITS  00000000 00d738 000020 00  0 0 8 
    [17] .shstrtab   STRTAB   00000000 00d758 0000d1 00  0 0 1 
    [18] .symtab   SYMTAB   00000000 00db4c 000770 10  19 62 4 
    [19] .strtab   STRTAB   00000000 00e2bc 000513 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

Espérons que cela suffit ... !!!

Remarque: J'utilise bras-aucun-eabi-gcc pour la liaison.

+0

Pouvez-vous publier la sortie de 'readelf --sections' pour vos binaires? –

+0

La sortie a été ajoutée. Dans le second cas, la taille du binaire devient ~ 246 Mo comme compilé à 6 Ko dans le précédent .... – Ajeesh

+1

Il est évident (et des problèmes similaires (ou Q/A) sont sur SO). 'IRAM LENGTH = 256K' avec' DDR (256MB) - IRAM (9MB) ~ = 256MB' avec votre binaire augmente à 246MB. [Lisez à propos de VMA/LMA] (https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html) et utilisez-les comme terme de recherche.Un ** Binaire ** doit être un morceau contigu de bien binaire! Il n'y a pas d'information de section. Voyez-vous le problème? Les scripts gnu LD ont une directive de type 'AT' et le LMA/VMA pour résoudre ce problème. –

Répondre

1

Si vous n'avez pas l'expérience des scripts de liens, utilisez-en un qui fonctionne, ou créez ou empruntez un script plus simple. En voici une simple, et cela devrait montrer ce qui se passe le plus probablement.

MEMORY 
{ 
    bob : ORIGIN = 0x00001000, LENGTH = 0x100 
    ted : ORIGIN = 0x00002000, LENGTH = 0x100 
    alice : ORIGIN = 0x00003000, LENGTH = 0x100 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > bob 
    .data : { *(.text*) } > ted 
    .bss : { *(.text*) } > alice 
} 

Premier programme

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 

pas destiné à être un véritable programme juste créer quelques octets dans un segment est tout.

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 

12 octets en .text qui est à l'adresse 0x1000 en mémoire qui est exactement ce que nous lui avons demandé de faire. Si j'utilise -objcopy a.elf -O binary a.bin j'obtiens un fichier de 12 octets comme prévu, le format de fichier "binaire" est une image mémoire, en commençant par la première adresse qui a du contenu dans l'adresse espace et se terminant avec le dernier octet de contenu dans l'espace d'adressage. donc au lieu de 0x1000 + 12 octets le binaire est de 12 octets et l'utilisateur doit savoir qu'il doit être chargé à 0x1000.

donc changer cela un peu:

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 
.data 
some_data: .word 0x12345678 

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 
    [ 2] .data    PROGBITS  00002000 002000 000004 00 WA 0 0 1 

Maintenant, nous avons 12 octets à 0x1000 et 4 octets à 0x2000, alors -O binaire doit nous donner une image mémoire du premier octet défini au dernier donc ce serait 0x1000 + 4. Bien sûr, 4100 octets, c'est exactement ce qu'il a fait.

.text 
.globl _start 
_start: 
mov r0,r1 
mov r1,r2 
b . 
.data 
some_data: .word 0x12345678 
.bss 
some_more_data: .word 0 

qui donne

Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00001000 001000 00000c 00 AX 0 0 4 
    [ 2] .data    PROGBITS  00002000 002000 000004 00 WA 0 0 1 
    [ 3] .bss    NOBITS   00003000 003000 000004 00 WA 0 0 1 

Maintenant, je ne suis un fichier 4100 octets, et qui est en fait pas surprenant, on suppose que l'amorçage va à zéro .bss Alors que na pas pousser le " fichier binaire ".

Il existe une relation intime. Une conception au niveau du système. Entre le script de l'éditeur de liens et le bootstrap. Pour ce que vous essayez de faire (juste ram no rom), vous pouvez probablement sortir avec un script d'éditeur beaucoup plus simple, à égalité avec celui que j'ai, mais si vous vous intéressez à .bss étant mis à zéro alors il y a quelques astuces que vous pouvez utilisation:

MEMORY 
{ 
    ram : ORIGIN = 0x00001000, LENGTH = 0x3000 
} 
SECTIONS 
{ 
    .text : { *(.text*) } > ram 
    .bss : { *(.text*) } > ram 
    .data : { *(.text*) } > ram 
} 

assurez-vous qu'il est au moins un élément .data et votre « binaire » aura l'image avec bss déjà remis à zéro, le bootstrap a simplement besoin de régler le pointeur de pile (s) et sauter principal (si c'est pour C). Quoi qu'il en soit, j'espère que vous pouvez voir que le saut de 12 octets à 4100 octets était dû à l'ajout d'un élément .data et que le format "binaire" devait remplir le fichier "binaire" pour que le fichier soit mémoire image de l'adresse la plus basse avec des données à l'adresse la plus élevée avec des données (de 0x1000 à 0x2000 + sizeof (.data) -1 dans ce cas). Changer le script de l'éditeur de liens, le 0x1000 et le 0x2000 et tout cela change. Remplacez-les par .text à 0x2000 et .data à 0x1000, maintenant le fichier "binaire" doit être 0x2000-0x1000 + sizeof (.text) plutôt que 0x2000-0x1000 + sizeof (.data). ou 0x100C octets au lieu de 0x1004. retournez au premier script de lieur et faites .data à 0x20000000 maintenant le "binaire" sera 0x20000000-0x1000 + sizeof (.data) parce que c'est combien d'information comprenant le remplissage est exigé pour faire une image de mémoire dans un seul dossier.

Il est très probable que c'est ce qui se passe. Comme démontré ici, la taille du fichier est passée de 12 octets à 4100 en ajoutant simplement un mot de données.

EDIT.

Eh bien, si vous horscharge les données puis votre variable initialisées être initialisés habitude, il est aussi simple que cela

unsigned int x = 5;

ne sera pas un 5 si vous supprimez (NOLOAD) .data.

Comme cela a été indiqué et indiqué à nouveau, vous pouvez placer les données dans le secteur .text, puis utiliser plus de script d'éditeur de liens foo, pour que le bootstrap trouve ces données.

MÉMOIRE { bob: ORIGIN = 0x00001000, LONGUEUR = 0x100 ted: ORIGIN = 0x00002000, longueur = 0x100 alice: ORIGIN = 0x00003000, longueur = 0x100 } SECTIONS { .text: {(.text)}> bob .data: {(.text)}> AT> ted bob .bss: {(.text)}> alice AT> bob }

Cela crée un fichier "binaire" de 16 octets. les 12 octets d'instruction et les 4 octets de .data. Mais vous ne savez pas où se trouvent les données à moins de faire du codage en dur, ce qui est une mauvaise idée.C'est où des choses comme bss_start et bss_end se trouvent dans votre script de liaison.

quelque chose comme ça

MEMORY 
    { 
     bob : ORIGIN = 0x00001000, LENGTH = 0x100 
     ted : ORIGIN = 0x00002000, LENGTH = 0x100 
     alice : ORIGIN = 0x00003000, LENGTH = 0x100 
    } 
    SECTIONS 
    { 
     .text : { *(.text*) } > bob 
     .data : { 
      __data_start__ = .; 
      *(.data*) 
     } > ted AT > bob 
     __data_end__ = .; 
     __data_size__ = __data_end__ - __data_start__; 
     .bss : { *(.text*) } > alice AT > bob 
    } 

    .text 
    .globl _start 
    _start: 
    mov r0,r1 
    mov r1,r2 
    b . 


hello: 
    .word __data_start__ 
    .word __data_end__ 
    .word __data_size__ 

    .data 
    some_data: .word 0x12345678 

qui nous donne.

Disassembly of section .text: 

00001000 <_start>: 
    1000: e1a00001 mov r0, r1 
    1004: e1a01002 mov r1, r2 
    1008: eafffffe b 1008 <_start+0x8> 

0000100c <hello>: 
    100c: 00002000 andeq r2, r0, r0 
    1010: 00002004 andeq r2, r0, r4 
    1014: 00000004 andeq r0, r0, r4 

Disassembly of section .data: 

00002000 <__data_start__>: 
    2000: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000 

et le toolchain/éditeur de liens crée et remplit les noms définis dans le script de liaison, et les remplit ensuite dans votre code quand il résout ces externals. Ensuite, votre bootstrap doit utiliser ces variables (et plus que je n'ai pas inclus ici où trouver le .data dans le fichier .text que vous connaissez ci-dessus qu'il y a 4 octets et ils doivent atterrir à 0x2000 mais où dans le 0x1000 .text Les scripts de l'éditeur de liens gnu sont très sensibles à l'endroit où vous définissez ces variables avant ou après que les parenthèses peuvent avoir des résultats différents

C'est pourquoi je l'ai mentionné Si vous utilisez une RAM, et que vous voulez utiliser .data et mettre à zéro .bss, vous devez mettre le .data et la taille et l'emplacement de .bss dans la zone flash/rom et le bootstrap a pour copier et zéro Vous pouvez également choisir de ne pas utiliser .data ni .bss

unsigned int x=5; 
unsigned int y; 

à la place

unsigned int x; 
unsigned int y; 
... 
x=5; 
y=0; 

Oui, il est pas aussi efficace taille binaire sage, mais des scripts de liens sont très toolchain dépendants et avec gnu par exemple au fil du temps le script éditeur de liens langauge/règles changent, ce qui a fonctionné sur un avant La version majeure de gnu ld ne fonctionne pas nécessairement sur le courant ou le suivant, j'ai donc dû ré-architecturer mon script d'éditeur de liens minimal au fil des ans. Comme démontré ici, vous pouvez utiliser vos outils de ligne de commande pour expérimenter avec les paramètres et les emplacements et voir ce que la chaîne d'outils a produit.

En fin de compte, il semble que vous avez ajouté des informations dans .data, mais que vous voulez dire NOLOAD, ce qui signifie que .data n'est pas là/utilisé vos variables ne sont pas initialisées correctement, alors pourquoi changer le code tout cela pour arriver seulement à ne pas fonctionner de toute façon? Soit avoir .data et l'utiliser correctement, avoir la bonne paire de bootstrap et de script d'éditeur de liens, ou si c'est seulement ram juste emballer tout dans le même espace RAM, ou ne pas utiliser le format "binaire" que vous utilisez, utilisez elf ou Ihex ou srec ou autre.

Un autre astuce selon votre système est de construire le binaire pour ram, tout emballé, puis avoir un autre programme qui entoure ce binaire fonctionne de ROM et des copies à ram et sauts. Prenez le programme de 16 octets au-dessus, écrivez un autre qui inclut les 16 octets de cette construction, et les copie à 0x1000, puis branche à 0x1000. Selon le système et la technologie flash/rom et l'interface que vous souhaiterez peut-être faire de toute façon, le système de mon travail de jour utilise un flash spi pour démarrer, qui sont connus pour avoir des problèmes de lecture ... Donc, la solution la plus rapide, la plus propre et la plus fiable consiste à faire le saut de copie avant de faire quoi que ce soit d'autre. Rendre le script de l'éditeur de liens beaucoup plus facile en tant qu'effet secondaire gratuit.

+0

Le problème semble être parti quand j'ai ajouté (NOLOAD) aux sections de données. Y a-t-il un moyen de s'assurer? – Ajeesh

+1

'NOLOAD' implique que la section de données ne fait pas partie du binaire. Ce que vous devez faire (si vous n'avez pas seulement BSS ou zéro mémoire initialisée) est de mettre les valeurs de données initiales dans l'image principale et avoir le code de démarrage le copier à l'emplacement final. (Adresse de mémoire de chargement LMA et adresse de mémoire virtuelle VMA qui est l'adresse absolue finale réelle à laquelle tout assembleur doit se référer), –