IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Administration système Discussion :

Créer un fichier ELF sans même GNU/ld [Infos]


Sujet :

Administration système

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif Avatar de Hibou57
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    852
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 852
    Par défaut Créer un fichier ELF sans même GNU/ld
    GCC est un compilateur imposant. Avoir un compilateur légé est chose aisée : on peut penser à nasm. Seulement, la création des fichier ELF passe toujours par LD. Le problème de LD c'est qu'il fait partie de l'environnement de développement standard qui lui-même dépend de libc6/glibc2... et libc6/glibc2 est une librairie trop lourde pour être utilisable sur les petits systèmes.

    Mais il existe une solution qui vous permettra de créer des fichiers ELF sans même passer par un lieur. L'avantage de cette solution et qu'elle vous permet de créer des véritable fichiers ELF sous un environnement restreint, et vous permettra même, le fin-du-fin, de faire de la cross-compilation, c'est à dire de créer sous Windows des binaires ELF destinés à fonctionner sous Linux.

    Ceci, je l'espère, rendra service à tous/toutes ceux/celles qui travail sur des adaptation de Linux (petit PCs, système embarqué à peu de frais, etc).

    Vous pourrez conculter un exposé détaillé de la question ici : Création de fichier ELF pour Linux, sans utiliser de lieur.

    La solution passe par l'utilisation de deux pattern au choix. Vous utiliserez le premier pour les applications nécessitant un segement de code ainsi qu'un segment de données en lecture/écriture. Le second pattern sera à utiliser pour les applications ne nécessitant qu'un segement de code (notez que les donnée en lecture seule pourront être placées dans le segment de code).

    Sans plus tarder, allons droit au but, voici les deux patterns éditable :

    elf-with-data.asm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
     
    ; (hint:tabulation size is 3)
    ; (date-dd-mm-yyyy:03/01/2007)
     
    ; Creating a fully functional ELF file without even GNU/ld
    ; ---------------------------------------------------------
    ; 
    ; This a pattern file which allow you to create ELF executable without
    ; even a linker in hands. This is useful for custom installation with
    ; low resource, such as old PC. Indeed, the usual way is to use GNU/ld,
    ; but unfortunatly, ld rely on glibc, which is very-very hugh en
    ; outrageously resource consuming.
    ;
    ; You can use it with nasm (the syntax used here is the one of nasm).
    ; A static version of nasm if very light (between 150 and 200KB). So
    ; with a static version of e3 (which is no more than 13KB), and
    ; a few text files documentations about syscalls and some other good
    ; stuff, you can have a real developpement environement under less
    ; than the quarter of an 1.44M floppy disk.
    ;
    ; Please visit http://www.les-ziboux.rasama.org/elf-without-ld.html
    ; for updates. In the futur, I will mirror a very small static version
    ; of nasm (102KB), a static version of e3, and some useful texte
    ; documentation.
    ;
    ; You can use this pattern in any project... it is not mandatory, but this
    ; would be very nice of you to put this url on top of your product sources :
    ; http://www.les-ziboux.rasama.org/elf-without-ld.html
    ; Thank you :)
    ;
    ; To use this pattern, just edit the place between the BEGIN and END mark,
    ; both in code and data segment.
    ;
    ; If you code only adress read-only data, then you can use the other
    ; "elf-simple.asm", beceause is there are only read-only datas, it is
    ; best to put them in code segment.
    ;
    ; Finaly you have to compile your code with "nasm -f bin [-O2] yourcode.asm"
    ; (the -O parameter is optional, alghtough often requited because of
    ; short-jumps and some stuff like that).
     
    ; This file is full of comments... you may remove them after reading ;)
    ;
    ; Comments are welcome : les-ziboux@rasama.org (fr/en)
    ; You wanna learn Arabic ? -> http://www.les-ziboux.rasama.org (fr)
     
    cpu 386
    bits 32
     
    org 0x08048000 ; Linux applications are loaded at this virtual address.
     
    ; === Header ================================================================
     
    elf_header:
    .start
       db 0x7F, "ELF"          ; ELF signature                 -- constant
       db 1                    ; Architecture(1)               -- 1 = 32 bits
       db 1                    ; Data enconding                -- 1 = LSB-First
       db 1                    ; File version                  -- 1 = v1
       db 0,0,0,0,0,0,0,0,0    ; 9 bytes padding               -- should be zero
       dw 2                    ; Type                          -- 2 = executable
       dw 3                    ; Architecture(2)               -- 3 = i386
       dd 1                    ; ELF Version                   -- 1 = ELF-v1
       dd _start               ; Entry point adress in memory  -- virtual adress
       dd segments_table - $$  ; Segments table offset in file
       dd 0                    ; Sections table offset in file -- 0 = none)
       dd 0                    ; File's flags
       dw elf_header.size      ; ELF Header's size
       dw 32                   ; Segments table entries's size
       dw 2                    ; Number of segment descriptors
       dw 0                    ; Sections table entries's size -- 0 = none
       dw 0                    ; Number of sections descriptor -- 0 = none
       dw 0                    ; String table index            -- 0 = none
    .size equ $ - .start
     
    segments_table:
     
    code_segment_descriptor:
    .start:
       dd 1                    ; Type            -- 1 = loadable into memory
       dd 0                    ; Offset in file  -- include ELF header and table
       dd $$                   ; Virtual address in memory
       dd 0                    ; Physical adress -- 0 = no physical address
       dd code_size            ; Size in file
       dd code_size            ; Size in memory
       dd 5                    ; Permission flags -- 0x4 + 0x1 = read and execute
       dd 0x4                  ; Alignment in memory (and in file)
    .size equ $ - .start
     
    data_segment_descriptor:
    .start:
       dd 1                    ; Type -- 1 = loadable into memory
       dd _data - $$           ; Offset in file
       dd _data                ; Virtual adress in memory
       dd 0                    ; Physical adress -- 0 = no physical address
       dd data_size            ; Size in file
       dd data_size            ; Size in memory
       dd 6                    ; Permission flags -- 0x4 + 0x2 = read and write
       dd 0x4                  ; Alignment in memory (and in file)
    .size equ $ - .start
     
    ; === Code ==================================================================
     
    _code :
     
    _start: ; You can move the start label where-ever you want in code segment.
     
       ; ----- BEGIN of your code -----
     
       ; Here is a sample code which simply say good bye and terminate.
       ; It give an example of usage of both code segment and data
       ; segment. Although this example does write to data segment,
       ; the data segment is still fully writable. Note that read-only
       ; datas can also reside in code segment (you should use
       ; the pattern "elf-simple.asm" for this purpose).
       ; You can put your own code between the BEGIN and END mark.
       ; Do not modify something else, unless you're sure about what
       ; you are playing with.
     
       mov  eax, 4                ; function id for sys_write
       mov  ebx, 1                ; descriptor of standard output
       mov  ecx, message          ; offset of bytes to write
       mov  edx, message.length   ; number of bytes to write
       int  0x80                  ; syscall
     
       mov  eax, 1                ; function id for sys_exit
       mov  ebx, 0                ; return code from the program (0 mean Ok)
       int  0x80                  ; syscall
     
       ; ----- END of your code -----
     
    align 4
    code_size equ $ - $$
     
    ; === Data ==================================================================
     
    align 4
    _data:
     
       ; ----- BEGIN of your datas -----
     
       ; This is a simple data example. This data segment is writable.
       ; Note that you can put read-only data in the code segment. If you
       ; only have read-only data, and no writable data in you application,
       ; then putting them in code segmet, avoid the creation of a data
       ; segment, reducing a bit the size of the executable. For this
       ; purpose, use the other patten name "elf-simple.asm".
       ; You can put your own datas between the BEGIN and END mark.
       ; Do not modify something else, unless you're sure about what
       ; you are playing with.
     
    message:
       db "Bye, Au-revoir, Ma'a as-salama, Bisbald ... :)", 10
    .length equ $ - message
     
       ; ----- END of your datas -----
     
    align 4
    data_size equ $ - _data
    La deuxième version du pattern, pour les applications qui ne nécessite rien de plus qu'un simple segment de code.

    elf-simple.asm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    ; (hint:tabulation size is 3)
    ; (date-dd-mm-yyyy:03/01/2007)
     
    ; Creating a fully functional ELF file without even GNU/ld
    ; ---------------------------------------------------------
    ;
    ; There are no explanations here : read "elf-with-data.asm" for
    ; informations on usage and copyright.
    ;
    ; Compile: nasm -f bin [-O2] yourcode.asm
    ; Updates : http://www.les-ziboux.rasama.org/elf-without-ld.html
    ; Comments are welcome : les-ziboux@rasama.org (fr/en)
    ; You wanna learn Arabic ? -> http://www.les-ziboux.rasama.org (fr)
     
    cpu 386
    bits 32
     
    org 0x08048000 ; Linux applications are loaded at this virtual address.
     
    ; === Header ================================================================
     
    elf_header:
    .start
       db 0x7F, "ELF"          ; ELF signature                 -- constant
       db 1                    ; Architecture(1)               -- 1 = 32 bits
       db 1                    ; Data enconding                -- 1 = LSB-First
       db 1                    ; File version                  -- 1 = v1
       db 0,0,0,0,0,0,0,0,0    ; 9 bytes padding               -- should be zero
       dw 2                    ; Type                          -- 2 = executable
       dw 3                    ; Architecture(2)               -- 3 = i386
       dd 1                    ; ELF Version                   -- 1 = ELF-v1
       dd _start               ; Entry point adress in memory  -- virtual adress
       dd segments_table - $$  ; Segments table offset in file
       dd 0                    ; Sections table offset in file -- 0 = none)
       dd 0                    ; File's flags
       dw elf_header.size      ; ELF Header's size
       dw 32                   ; Segments table entries's size
       dw 1                    ; Number of segment descriptors -- just one (code)
       dw 0                    ; Sections table entries's size -- 0 = none
       dw 0                    ; Number of sections descriptor -- 0 = none
       dw 0                    ; String table index            -- 0 = none
    .size equ $ - .start
     
    segments_table:
     
    code_segment_descriptor:
    .start:
       dd 1                    ; Type            -- 1 = loadable into memory
       dd 0                    ; Offset in file  -- include ELF header and table
       dd $$                   ; Virtual address in memory
       dd 0                    ; Physical adress -- 0 = no physical address
       dd code_size            ; Size in file
       dd code_size            ; Size in memory
       dd 5                    ; Permission flags -- 0x4 + 0x1 = read and execute
       dd 0x4                  ; Alignment in memory (and in file)
    .size equ $ - .start
     
    ; === Code ==================================================================
     
    _code :
     
    _start: ; You can move the start label where-ever you want in code segment.
     
       ; ----- BEGIN of your code -----
     
       ; Here is a sample code which simply cleanly terminate :P
     
       mov  eax, 1                ; function id for sys_exit
       mov  ebx, 0                ; return code from the program (0 mean Ok)
       int  0x80                  ; syscall
     
       ; ----- END of your code -----
     
       ; You may have read-only data here as well ;)
     
    align 4
    code_size equ $ - $$

  2. #2
    Inactif Avatar de Hibou57
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    852
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 852
    Par défaut
    P.S. A l'occasion de mes expérimentations, j'ai découvert un bug dans la dernière version de nasm : dans certains cas nasm duplique le code binaire. Les détails de ce bug a été soumis sur sourceforge.net.

    Ce bug n'empêche pas le fonctionnement du programme, mais duplique inutilement le binaire produit, la partie dupliquée étant concaténé à la partie légitimement présente.


    P.P.S J'ai remarqué même un bug du forum en voulant ajouté ce précédent PS au précédent message : j'ai eu un message me disant que mon message était trop court et que je devais ajouter au moins caractère. Et en retirant le PS du message, rendant le message plus court... ça passait

    Y at-il quelqu'un a qui je peux envoyer un screen-short démontrant ce bug du forum ?

  3. #3
    Membre émérite
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Par défaut
    Par contre, ton url du premier post ne fonctionne pas (tu as dû te planter dans les balises )
    Software becomes slower faster than hardware becomes faster
    [size=1]
    http://xrenault.developpez.com

  4. #4
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    En fait la technique c'est juste de recréer les en-têtes et tout ce qui fait parti du format ELF directement dans le fichier asm.
    Je trouve ça très astucieux.
    Donc en extrapolant un peu, on peut créer des elf avec une structure aussi complexe qu'on veut (on pourra difficilement faire plus simple qu'un segment de code tout seul) pour peu qu'on ait de la doc sur le format elf.

    Je vais garder ces exemples dans un coin en attendant de pouvoir les étudier de plus près.


    Pour l'url qui marche pas : le lien est bien dans la balise url, mais l'url est absente de la balise.

  5. #5
    Inactif Avatar de Hibou57
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    852
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 852
    Par défaut
    Citation Envoyé par Celelibi
    En fait la technique c'est juste de recréer les en-têtes et tout ce qui fait parti du format ELF directement dans le fichier asm.
    Sur la page pour laquelle je donne le liens (que je vais corriger, et d'ailleur je vais mettre à jour la page), il y a un lien vers la référence ELF. J'ai choisi la plus à jour, la version 1.2, il faut y faire attention, parce que même sur les sites dédiés à Linux, on trouve presque toujours des lien vers la version 1.1 (comparer les deux fichiers, et vous verrer que la 1.2 est plus exaustive).

    Citation Envoyé par Celelibi
    Donc en extrapolant un peu, on peut créer des elf avec une structure aussi complexe qu'on veut (on pourra difficilement faire plus simple qu'un segment de code tout seul) pour peu qu'on ait de la doc sur le format elf.
    En fait, je pratique toujours de cette manière : vouloir une chose simple, qui répond au besoins minimum, et on a alors quelque chose de simple et de léger. Je faisais ça sous Windows aussi, quand je n'avais pas les outils nécéssaire (je n'avais pas le net)... j'avais créer un assembleur qui produisait des fichier exe de manière simple.

    Je trouve que c'est une bonne chose : vouloir une chose simple, l'implémenté simplement, et seulement ensuite ajouter des fonctionalité si nécéssaire quand le besoin s'en fait strictement ressentire. Dans le domaine du logiciel, je ne crois pas en l'universalité (donc pour moi un logiciel ne doit pas avoir comme objectif de répondre à tous les besoin imaginables... et dans ces derniers cas, il doit être personalisé au cas pas cas, par un contrat d'assistance spécifique par exemple), ni en la portabilité (comme je dis toujours, Linux c'est Linux et Windows c'est Windows, et ainsi on profite du système au maximum sans gaspillage et sans dommage), mais seulement en la méthode et en la documentation (la seule chose portable à mes yeux, ce sont les concept, les idées, et les shema algorithmique).

    .... mais pourquoi je raconte tout ça encore

    Je vais garder ces exemples dans un coin en attendant de pouvoir les étudier de plus près.

    Pour l'url qui marche pas : le lien est bien dans la balise url, mais l'url est absente de la balise.
    Alors, attent Celelibi... ne te précipite pas trop vite quand même, je ne voudrais pas t'induite en erreur, parce que le format ELF n'est pas tout, et il faut tenir compte aussi des spécificité de Linux. Le format ELF a une part qui défini des choses univellese, qui sont vraies sous tous les systèmes, mais chaque système restent libre d'ajouter des restriction supplémentaire, ou de définir une sémantique particulère pour certaines sections (par exemple sous Linux, la section .note embarque des informations sur la version de GCC employée pour compiler le binaire).

    Alors justement là, il y a un point sur lequel je n'arrive pas à trouver de répons claire : est-ce que oui ou non les segment de code et de donnée sous Linux doivent être obligatoirement aligné sur 4096 bytes. Parce dans le pattern en assembleur que je donne, il sont alignés sur 4 bytes (32 bits). Ca fonctionne sous mes kernel de testes... mais j'ai copier mes petits programme de teste sur un serveur débian, et là j'ai segfault. J'ai recompiler en changeant l'alignement pour 4096, et là ça marche.

    Dans les code source de Linux, il existe une macro qui défini un flag qui s'appel PF_ALIGNWARN et qui s'applique au i486 seulement... je n'y comprends rien. Parce que apparement, ça ne semble pas être interdit...

    Bref, d'autres considérations me passe par l'esprit, mais je n'ai pas le temps d'en parler tout de suite.

    Note pour Celelibi : si tu t'interesse toujours au package Ada pour la console, en fait c'est en voulant créer des programme minimiliste utilisant la console, et ne dépendant pas de la glibc, que j'en suis arrivé à m'interesser à l'assembleur sous Linux (je ne le pratiquais qu'avant sous DOS). Et donc ce que je vais apprendre sur la console Linux par ce moyen, me raménera à ce fameux package que je n'abandonne pas contrairement au apparences (mais je suis occupé à d'autres choses que le developpement... alors je ne peux pas y passer tout mon temps)

    Citation Envoyé par Pouic
    Par contre, ton url du premier post ne fonctionne pas (tu as dû te planter dans les balises )
    Pour le lien, je corrige tout de suite... au passage Pouic, j'adore ta signature

  6. #6
    Membre chevronné Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Par défaut
    Beau boulot.

    Les travaux de Brian Raiter (ELFkickers) devraient t' intéresser: il compresse le header pour réduire la taille du code (hello world en 59 octets). Le prog est moins portable (selon le noyau) mais c'est la démarche qui est intéressante.
    Avec ta méthode j'obtiens un "hello world" de 134 octets, par l' appel système 4. Pas mal!
    Par contre il faut un chmod+x.

Discussions similaires

  1. créer un fichier .txt sans le nommer
    Par tallent_e dans le forum Débuter
    Réponses: 2
    Dernier message: 22/02/2011, 12h15
  2. Réponses: 5
    Dernier message: 24/03/2009, 15h52
  3. Créer un fichier jar sans avoir de main()
    Par t.n.b.g dans le forum Général Java
    Réponses: 12
    Dernier message: 01/04/2008, 17h13
  4. [OpenOffice][Tableur] créer un fichier Calc sans le faire apparaitre
    Par getea85 dans le forum OpenOffice & LibreOffice
    Réponses: 2
    Dernier message: 19/12/2007, 16h56
  5. créer plusieurs fichiers dans le même répertoire
    Par mstic dans le forum Windows Forms
    Réponses: 5
    Dernier message: 16/04/2007, 17h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo