Demoscene.fr BBS

Articles et discussions techniques => Code => Topic started by: flure on 18 May 2011 à 22:53:04

Title: 4ko sous Linux
Post by: flure on 18 May 2011 à 22:53:04
Salut,

Est-ce que quelqu'un a déjà essayé de faire des 4k sous Linux ?
Je suis en train de bosser là dessus, et je cherche à diminuer la taille de l'exécutable de base, j'aimerais savoir si vous avez quelques trucs et astuces.


Et actuellement je teste le chargement dynamique des fonctions de bibliothèques avec dlopen/dlsym, on verra ce que ça va donner...

J'ai essayé d'écrire le code en asm, mais mes premiers essais n'ont pas été très concluants : rien que pour ouvrir une fenêtre SDL et quitter tout de suite, on dépasse les 2ko (avant compression), du coup je ne sais pas si ça vaut le coup de faire un tel investissement...

Donc voilà si vous avez d'autres astuces, je suis preneur !
Title: Re : 4ko sous Linux
Post by: LLB on 19 May 2011 à 00:17:27
J'avais gardé ce lien passionnant de côté : http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html (http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html)
À la fin, c'est vraiment limite (bidouilles du header elf), mais il y a pas mal d'astuces utiles avant.
Title: Re : 4ko sous Linux
Post by: nystep on 19 May 2011 à 08:16:29
http://in4k.untergrund.net/index.php?title=Linux (http://in4k.untergrund.net/index.php?title=Linux)

il faut vraiment tout leur dire rah la la c'est pas vrai ça ;)
Title: Re : 4ko sous Linux
Post by: xtrium on 19 May 2011 à 09:39:55
Avec TiTS on a fait pas mal d'expérimentations pour les 4k sous nux, en gros ce qui en ressort, c'est :
- avec gcc, le -Os n'est pas forcément l'idéal après compression - essayer -O1 voire -O2 peut permettre de grignoter quelques octets.
- Comme dit plus haut, GC masher est d'une aide précieuse, les ELF kickers aussi... sstrip est vraiment bien utile ;)
- pour le chargement des libs avec dlopen, Wiz avait pondu un truc pas mal du tout, faudrait que je retrouve ça.

Le dropper avec lzma est actuellement le mieux qui puisse se faire sous nux. Je n'ai jamais eu un seul souci avec ça de mon côté, peut être que ton stub shell déconne... . Le seul inconvénient majeur étant que si on veut transmettre les arguments à l'exécutable droppé on doit rallonger pas mal ledit stub... bon, pour une 4k, en général, osef, mais pour mon synthé par exemple c'est gênant.
Après, j'ai lu quelque part qu'UPX permet désormais de compresser en lzma... à confirmer.

Si tu veux, flure, j'ai sstrip en version elf32, et un build custom pour elf64... je pourrai te faire une petite archive en rentrant ce soir :)
Title: Re : 4ko sous Linux
Post by: flure on 19 May 2011 à 09:40:05
LLB : j'avais déjà vu ton lien, effectivement sur la fin il est un peu hardcore, je voulais essayer d'éviter d'aller jusque là :)
nystep : merci pour le lien, je le connaissais pas. Le trick de l'intro qui se compile à l'exécution, c'est GENIAL !!! Je vais tester ça dès que possible :D
Title: Re : 4ko sous Linux
Post by: flure on 19 May 2011 à 09:43:29
xtrium : ah ouais je veux bien ton sstrip :)
Title: Re : 4ko sous Linux
Post by: xtrium on 19 May 2011 à 10:18:54
En fait, j'ai accès au git d'ici, donc j'ai pu te faire la petite archive qui va bien.
reduce est un script qui s'occupe de strip/sstrip/lzma+stub sur l'exe que tu lui passe, en choisissant automatiquement le bon sstrip selon l'archi pour laquelle l'exe a été compilé.

Cadeau ! :)
Title: Re : 4ko sous Linux
Post by: flure on 19 May 2011 à 10:28:49
Et sinon, vous pensez quoi du trick de compresser le code source, et que le stub décompresse et compile juste avant l'exécution ?
Normalement le code source devrait mieux compresser que l'exécutable non ?
Title: Re : 4ko sous Linux
Post by: LLB on 19 May 2011 à 11:21:16
Et dans quelques jours, tu demanderas à Shader Minifier d'accepter le C en entrée ? :)

Title: Re : 4ko sous Linux
Post by: maracuja on 19 May 2011 à 11:41:14
upx sait comprimer en lzma.
Title: Re : 4ko sous Linux
Post by: flure on 19 May 2011 à 11:59:04
LLB : comment t'as deviné ? :P
Bon par contre cette soluce de compresser le source me paraît difficile quand on a de la musique sous forme d'objet précompilé, genre 4klang... Mais ça doit être jouable quand même, juste que le dropper deviendra un peu plus gros ;)
Title: Re : 4ko sous Linux
Post by: flure on 23 May 2011 à 22:42:29
Quelqu'un a déjà chargé des fonctions de la SDL et OpenGL via dlopen/dlsym (équivalents de LoadLibrary et GetProcAddress sous Windows) ?
Là je galère, pour la SDL aucun problème, mais dès que je charge les fonctions OpenGL elles sont bien chargées (j'ai checké les pointeurs et dlerror) mais ça fige... en fait ça n'ouvre carrément pas la fenêtre...

[EDIT] j'ai trouvé. il faut faire un dlclose sur la lib OpenGL avant de passer à la suite. Par contre SDL ne pose pas ce soucis !
[re-EDIT] c'est même pire que ça, il faut faire un dlclose pour OpenGL mais il ne faut pas le faire pour SDL !!! je tombe des nues là...
Title: Re : 4ko sous Linux
Post by: flure on 23 May 2011 à 22:58:12
Euh non en fait c'est pire que tout. Dès que j'utilise une fonction OpenGL, ça me fait un segfault... Je crois qu'il faut que j'arrête pour ce soir sinon je vais m'énerver comme Patapom :P
Title: Re : 4ko sous Linux
Post by: Patapom on 23 May 2011 à 23:41:24
JE SUIS PAS ENERVE !!! >:(
Title: Re : 4ko sous Linux
Post by: flure on 23 May 2011 à 23:44:22
Hahaha mais bien sûr :D

Bon moi par contre je suis un peu deg : j'ai viré tous les chargements dynamiques, j'ai compilé en linkant de manière "traditionnelle"... Et là, oh stupeur. Mon exe final (compression comprise) est plus petit d'une centaine d'octets... GRUMPF, ça valait le coup que je me prenne la tête :/
Title: Re : 4ko sous Linux
Post by: kernel_error on 05 July 2011 à 02:46:13
  • J'ai essayé le linker Bold de Alrj, il fait vraiment de tout petits exécutables, mais (sur ma machine en tout cas) ils font un segfault ;(

Si t'es sous Archlinux (x86 ou x64) c'est normal, c'est fait exprès, ils aiment transgresser les compatibilités des standards tel que l'ABI/TIS. Bref j'irai pas troller sur cet OS, promis :D.
Bon, il existe un gros trick (de pete) qui permet de resoudre les symboles dynamiquement mais pas avec dlopen/dlsym, ça marche un peu de la même manière mais en plus tricky.
En gros, tu écris tout l'en-tête de ton executable elf en asm, tu as un tableau de hash correspondant à chacun de tes symboles (avec une routine de hash sur 10 instructions), ensuite,
une fois l'elf lancé, tu dois recuperer l'adresse de la première lib en mémoire, tu fouines cette lib, tu hash chaque symbole de la lib et tu compares avec un de tes hash et ainsi de suite pour chaque symbole.
Ça marche plutot bien niveau taille, perso j'ai une fenetre SDL avec un contexte GL, un petit fragment shader et j'en arrive à 930 bytes une fois compressé avec lzma et encore, là j'ai du ajouté
quelques modifs au trick (une GROSSE routine de ~50 instructions) pour que ça tourne sur Archlinux.
Normalement il me semble que Bold (j'ai pas regarder le source code, c'est du python /o\) a repris le concept mais seulement sous x64 (pour je ne sais plus quelle raison, la simplicité de la table
des symboles un truc du genre), je suis moi aussi dans l'optique de dev un linker qui reprend le principe quand j'aurai un peu plus de temps :x

PS: http://pouet.net/topic.php?which=5392&page=1 (http://pouet.net/topic.php?which=5392&page=1) pour suivre tout l'histoire, en tout cas ce trick (aussi utilisé chez les vxers/et autres méchants pirates) est absolument genial.
Title: Re : 4ko sous Linux
Post by: ulrick on 05 July 2011 à 12:22:00
Hahaha mais bien sûr :D

Bon moi par contre je suis un peu deg : j'ai viré tous les chargements dynamiques, j'ai compilé en linkant de manière "traditionnelle"... Et là, oh stupeur. Mon exe final (compression comprise) est plus petit d'une centaine d'octets... GRUMPF, ça valait le coup que je me prenne la tête :/

Bravo flure ;). Keep it up!
Title: Re : 4ko sous Linux
Post by: Saorel on 21 July 2011 à 12:36:57
Bonjour,

Je découvre la programmation ou l'on se soucie de la taille de l'exécutable, et j'aimerais avoir quelque renseignement, jusqu'à l'intervention de kernel_error, j'avais compris ce qu'il fallait faire, et mes tests étaient concluant. Mais ce post vend du rêves pour moi, moins d'1kb pour un shader et une fenetre! Quelqu'un pourrait-il m'expliquer ? (euh je suis sous Arch x64 - pas taper)

J'avais commencé un effet pour la DemoJS, mais finalement je penses le passer en 4kb étant donné qu'il s'agit d'une scène entièrement réalisé au sein d'un fragment shader, aussi ce tips m'aiderait beaucoup! Mon objectif est de releaser cette prod' fin août.

Je vous remercie de votre aide précieuse!
Title: Re : 4ko sous Linux
Post by: flure on 21 July 2011 à 21:20:11
Saorel, voici mes techniques. Je ne peux pas utiliser Bold parce que ça fait des segfault, et pourtant je ne suis pas sous archlinux mais ubuntu !
Le premier problème c'est que sous Ubuntu, OSS n'est plus installé par défaut, donc je passe par SDL_audio pour la musique. C'est dommage, j'aurais gagné pas mal de place. J'utilise l'eeeeeexcellent 4klang pour la musique. Enfin, "mon" musicien utilise 4klang dans modplug tracker, ça génère un fichier .o pour linux (ou .obj pour windows) et je n'ai qu'à lier avec et copicoller le tuto pour faire passer ça dans SDL_audio. C'est très simple.
Ensuite, comme toi, je fais tout dans un shader. Pour gagner de la place, minimise le shader en utilisant shader minifier de notre ami LLB. C'est du dotnet et chez moi ça ne marche pas avec mono, alors LLB a eu l'extrême bonté d'en faire une version en ligne.
Pour les options de compile, utilise -O1 ça compressera mieux que -Os ;)
Et aussi, je compile en 32 bits, parce que ça prend moins de place, par contre du coup il faut avoir les libs de compatibilité.
Et pour la liaison, je fais ça normalement avec SDL SDL_audio et GL. J'avais fait des tests avec dlopen/dlsym en pensant que je gagnerais de la place, mais en fait non. Il me reste encore à tester le trick de kernel_error, mais pour l'instant je me concentre sur ce que je mets dans mon shader ;)
Ensuite, utilise sstrip des Elf-kickers pour supprimer tous les symboles inutiles de l'exécutable.
Finalement, tu le compresses avec lzma et tu le colles à un petit script d'auto-extraction-exécution.

Bon, c'est très loin d'être aussi efficace que crinkler sous Windows, mais au moins on aura le mérite de faire de la 4k sous Linux !
Title: Re : 4ko sous Linux
Post by: kernel_error on 24 July 2011 à 14:08:20
@flure: dis moi ce que ça te donne:
Code: [Select]
readelf -a /usr/lib/libSDL-1.2.so.0 | grep HASH

Histoire de savoir si la communauté d'Ubuntu est aussi pourri que celle d'Archlinux.
Title: Re : 4ko sous Linux
Post by: flure on 24 July 2011 à 14:13:45
Code: [Select]
florent@florent-desktop:~$ readelf -a /usr/lib/libSDL-1.2.so.0 | grep HASH
  [ 2] .gnu.hash         GNU_HASH         00000000000001f0  000001f0
 0x000000006ffffef5 (GNU_HASH)           0x1f0

En effet ça a pas l'air terrible...
Title: Re : 4ko sous Linux
Post by: kernel_error on 24 July 2011 à 21:19:15
Et c'est le drame... c'est normal que ça segfault, il manque l'ancienne section hash.
Pour la petite histoire, binutils ont dev une nouvelle (datant de 2006) section gnu_hash qu'est beaucoup plus rapide que l'ancienne section hash (c'est utilisé pour la résolution de symbole),
néanmoins cette section gnu_hash n'est pas standardisée, c'est pourquoi on peut compiler avec les deux sections, sachant que la section gnu_hash reste prioritaire!
La seul raison, qui poussent ces connards de mainteneurs à compiler seulement avec la section gnu_hash, est de gagner quelques octets sans même se rendre compte
des conséquences que cela peut engendrer.

PS: Sous ubuntu server, l'ancienne section hash y est bien présente, de même que sous n'importe quelle branch de Debian (et slackware, et d'autres distrib sérieuses).

J'ai ""porté"" la 1k flow2 pour les OS de merdes, essaye voir si ça marche: http://kernel-error.tuxfamily.org/public/Demoscene/flow2-fixed.tar.gz (http://kernel-error.tuxfamily.org/public/Demoscene/flow2-fixed.tar.gz)
Title: Re : 4ko sous Linux
Post by: alrj on 29 July 2011 à 19:08:42
Les détails gores:
D'après la spec ELF, l'entrée DT_HASH de la table DYNAMIC est obligatoire, voir par exemple http://www.skyfree.org/linux/references/ELF_Format.pdf (http://www.skyfree.org/linux/references/ELF_Format.pdf) page 43.

GNU n'aurait pas dû offrir une option --hash-style=gnu, et les distributions ne devraient pas l'utiliser. Les bibliothèques résultantes ne sont plus conformes au format ELF.

De mon point de vue, c'est un bug qui doit être remonté vers votre distrib, pas vers Bold  ::)
Title: Re : 4ko sous Linux
Post by: flure on 30 July 2011 à 15:10:22
Intéressant.
Je ferai bien un rapport de bug, mais le temps que ça soie corrigé, la Buenzli sera passée ;)
En attendant, je vais faire sans, tant pis...
Title: Re : 4ko sous Linux
Post by: alrj on 30 July 2011 à 20:55:42
Et voilà, vous m'avez eu... La version git de Bold supporte (normalement) .gnu.hash  ;D
Il y a sans doute moyen d'optimiser un peu en repensant l'algo ou en utilisant d'autres registres. Ce sera pour plus tard.
(hint: git clone http://git.alrj.org/git/bold.git (http://git.alrj.org/git/bold.git))
Les plus pressés peuvent simplement utiliser le fichier bold_ibh-x86_64.o joint, à mettre dans /usr/lib/bold/ à la place de l'ancien.

Par contre, j'ai dû contourner un bug très étrange, décrit dans le commentaire du code suivant:
Code: [Select]
        cmp [rdx], dword 4                ; DT_HASH == 4
        jne .no_hash                      ; Why the heck does it segfault when
          mov ecx, [rsi+4]                ; I use cmove ecx, [rsi+4] instead
        .no_hash:                         ; of this jne construction ????

Pour d'autres entrées de la table DYNAMIC, j'utilise les "cmove" sans problème. Quelqu'un aurait une idée ?
Title: Re : 4ko sous Linux
Post by: alrj on 30 July 2011 à 22:24:18
Ne cherchez plus pour mon problème de cmove, on a trouvé. L'instruction ira toujours lire [rsi+4], sauf que ça pointe n'importe où quand [rdx] ne vaut pas 4 comme attendu.
Le mov est conditionnel, mais la lecture de la source est inconditionnelle.
Title: Re : 4ko sous Linux
Post by: flure on 31 July 2011 à 02:55:13
Alrj, je t'aime :D

Je teste ça demain (parce que là faut pas déconner il est quand même un peu tard)
Title: Re : 4ko sous Linux
Post by: alrj on 31 July 2011 à 12:34:07
Tiens-moi au courant du résultat :)
Et si d'autres personnes sous Arch pouvaient également tester, ça m'arrangerait bien.
Title: Re : 4ko sous Linux
Post by: flure on 31 July 2011 à 14:11:35
Chose promise, chose dûe : ça marche  !!!
Et ça me fait gagner environ 500 octets.
Maintenant il me reste à trouver comment utiliser 4klang en 64 bits...
Title: Re : 4ko sous Linux
Post by: alrj on 31 July 2011 à 14:56:19
Bonne nouvelle pour moi, mais j'ai peur que ce soit perdu pour toi si 4klang ne fournit pas une version 64bit.