Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Construction d'un ELF et désassemblage (gdb - linux - x86)

12 réponses
Avatar
Kevin Denis
Bonjour,

Tout d'abord, je ne suis pas certain d'être dans le bon groupe et m'en excuse
si c'est le cas.

Soit un programme simple en C, que je désassemble:
$ gdb -q a.out
(gdb) list
1 #include <stdio.h>
2
3 int main()
4 {
5 int i;
6 for(i=0; i < 10; i++)
7 {
8 printf("Hello World!\n");
9 }
10 }
(gdb) disas main
Dump of assembler code for function main:
0x08048384 <main+0>: lea ecx,[esp+0x4]
0x08048388 <main+4>: and esp,0xfffffff0
0x0804838b <main+7>: push DWORD PTR [ecx-0x4]
0x0804838e <main+10>: push ebp
0x0804838f <main+11>: mov ebp,esp
0x08048391 <main+13>: push ecx
0x08048392 <main+14>: sub esp,0x14
0x08048395 <main+17>: mov DWORD PTR [ebp-0x8],0x0
0x0804839c <main+24>: jmp 0x80483b1 <main+45>
0x0804839e <main+26>: sub esp,0xc
0x080483a1 <main+29>: push 0x8048480
0x080483a6 <main+34>: call 0x80482b4 <puts@plt>
0x080483ab <main+39>: add esp,0x10
0x080483ae <main+42>: inc DWORD PTR [ebp-0x8]
0x080483b1 <main+45>: cmp DWORD PTR [ebp-0x8],0x9
0x080483b5 <main+49>: jle 0x804839e <main+26>
0x080483b7 <main+51>: mov ecx,DWORD PTR [ebp-0x4]
0x080483ba <main+54>: leave
0x080483bb <main+55>: lea esp,[ecx-0x4]
0x080483be <main+58>: ret
End of assembler dump.
(gdb)

J'ai quelques questions:
Tout d'abord je suis surpris de la structure du programme. <main+17>:
On met EBP-8 à 0. Puis on jump en fin de programme ou la comparaison
est faite. On remonte en <main+26> pour faire la boucle réelle.

Pourquoi n'avons nous pas en fait une mise à 0 de la valeur. Une
comparaison. Si inférieur ou égale, alors on jumpe à l'affiche
d'HelloWorld, puis un jump en début, ou on incrémente etc.. Si
la valeur est = à 10, alors on jump en fin de programme.

--> Est-ce du à une option de compilation de gcc? J'ai seulement
utilise gcc -g prog.c.
gcc -v
Lecture des spécification à partir de
/usr/lib/gcc/i486-slackware-linux/4.3.3/specs
Target: i486-slackware-linux
Configuré avec: ../gcc-4.3.3/configure --prefix=/usr --libdir=/usr/lib
--enable-shared --enable-bootstrap
--enable-languages=ada,c,c++,fortran,java,objc --enable-threads=posix
--enable-checking=release --with-system-zlib --disable-libunwind-exceptions
--enable-__cxa_atexit --enable-libssp --with-gnu-ld --verbose --with-arch=i486
--target=i486-slackware-linux --build=i486-slackware-linux
--host=i486-slackware-linux
Modèle de thread: posix
gcc version 4.3.3 (GCC)


Je ne comprends pas non plus cette série d'actions:
0x0804839e <main+26>: sub esp,0xc
0x080483a1 <main+29>: push 0x8048480
0x080483a6 <main+34>: call 0x80482b4 <puts@plt>
0x080483ab <main+39>: add esp,0x10

Pourquoi est-ce qu'il n'y a pas un simple
mov DWORD PTR [esp],0xXXXXXXX avec XXXXXXX l'adresse contenant ma
chaîne "Hello World" suivi d'un call à la fonction printf ?

Merci
--
Kevin

2 réponses

1 2
Avatar
Samuel DEVULDER
Jean-Marc Desperrier a écrit :
Mickaël Wolff wrote:
L'idée est que GCC analyse le premier paramètre de printf. Ceci permet
de détecter les bogues de format évidents, mais aussi d'optimiser
lorsqu'on utilise printf



Ah. De mon point de vue, il pourrait remplacer systématiquement lorsque
l'appel n'a qu'un seul argument. Comportement indéfini, je fais ce que
je veux, tout cela ...




Hum.. je me demande s'il fait cela lorsque l'utilisateur a redéfini lui
même son propre printf(). Dans ce cas là on peut avoir des surprises (e
particulier ceux qui utilisent gcc dans des environnements un peu "nus"
où il faut tout re-écrire soi-même).

sam.
Avatar
espie
In article <4b9a8f55$0$24307$,
Samuel DEVULDER wrote:
Jean-Marc Desperrier a écrit :
Mickaël Wolff wrote:
L'idée est que GCC analyse le premier paramètre de printf. Ceci permet
de détecter les bogues de format évidents, mais aussi d'optimiser
lorsqu'on utilise printf



Ah. De mon point de vue, il pourrait remplacer systématiquement lorsque
l'appel n'a qu'un seul argument. Comportement indéfini, je fais ce que
je veux, tout cela ...




Hum.. je me demande s'il fait cela lorsque l'utilisateur a redéfini lui
même son propre printf(). Dans ce cas là on peut avoir des surprises (e
particulier ceux qui utilisent gcc dans des environnements un peu "nus"
où il faut tout re-écrire soi-même).



Ben evidemment qu'il fait cela, a partir du moment ou tu as fait
#include <stdio.h>
ca fait partie des comportements mandates par la norme.
C'est meme pour ca que tu une option -ffreestanding depuis maintenant
quelques annees dans gcc...
1 2