Welcome to Coding : Sécurité Programmation Réseaux

Search   in  

 Create an Account Home | Submit News Your Account Content | Topics | Top 10  


Accueil
· Home
· Listing des Articles
· Top 10
· Repository des Exploits

Les sujets / parties
· C / C ++
· Visual Basic
· Asm
· Reseaux
· Java
· Securite
· Divers

Utile
· Listing des Articles

· Telecharger
· Le Forum
· Liens
· Proposer un article

Top20 des Downloads
· 1: Etude des reseaux generalites et protocoles
· 2: Cheval de troie en VB avec sources
· 3: Netcat 1.1
· 4: Keylogger
· 5: Etudes des reseaux hauts debits architectures et protocoles
· 6: Ecoute de port
· 7: Etude du Smart Spoofing
· 8: Win Packet Capture Utils
· 9: Tutorial on Traffic Interception on Switched Lan using ARP spoofing
· 10: Cours de C

User Info
Welcome, Anonymous
Nickname
Password
(Register)
Membership:
Latest: longjohn
New Today: 0
New Yesterday: 2
Overall: 2216

People Online:
Visitors: 27
Members: 0
Total: 27

  
Gestion de la mémoire en C
Posted on Friday, November 12 @ 14:08:08 CET
Topic: C
C

	"Le langage C est souvent considéré comme un langage difficile et peu fiable. La seconde assertion n'est pas acceptable dans la mesure où la plupart des applications, y compris les L4G et RAD sont eux mêmes écrits en C.

En fait, ces idées reçues proviennent principalement de l'utilisation intensive des pointeurs. Si le C est souvent mal considéré, c'est bien souvent à cause de la méconnaissance du concept de pointeur et de la gestion de la mémoire qui lui est associé.

Le présent document se propose de présenter ces concepts depuis leurs fondements théoriques jusqu'à leur application pratique.

Il ne s'agit pas pour autant de définir les différentes notions avec la plus grande rigueur qui soit. Mon propos n'est pas de faire de l'initiation à l'assembleur, ni à l'électronique. Mon but est de présenter la gestion de la mémoire sous un angle différent de celui généralement adopté.

L'audience visée est principalement celle des développeurs ayant déjà été initiés au langage C. "

-- (Yann Langlais)

Notice Le présent document est publié sous la license « Verbatim Copying » telle que définie par la Free Software Fondation dans le cadre du projet GNU.
Toute copie ou diffusion de ce document dans son intégralité est permise (et même encouragée), quel qu'en soit le support à la seule condition que cette notice, inclant les copyrights, soit préservée.
Copyright (C) 2002, 2003, 2004 Yann LANGLAIS, ilay, Intrasys.
La plus récente version en date de ce document est sise à l'url http://ilay.org/yann/articles/mem/.
Toute remarque, suggestion ou correction est bienvenue et peut être adressée à Yann LANGLAIS, ilay.org.


Table des Matières Introduction Qu'est-ce qu'un pointeur? Organisation de la mémoire «virtuelle» d'un ordinateur Espace mémoire des programmes C Mémoire globale La pile Notion de type Types simples Alignement Types composés Tableaux Notion de pointeur Pointeurs et tableaux Pointeurs et structures Pointeurs sur fonctions Désignation des données Désignation par valeur Désignation par adresse Passages de paramètres Exemple récapitulatif Comment gérer la mémoire? Allocation sur la pile Allocation dynamique Manipulation dynamique de la mémoire Allocation de la mémoire: malloc() la fonction calloc() Désallocation de la mémoire: free() Réallocation de la mémoire : realloc() Fonctions annexes: memset(), memcpy(), memmove() Initialisation d'une zone memoire: memset() Copie de zone mémoire : memcpy() Déplacement de zone mémoire: Gestion des chaines de caractères: Rappels strcpy() strncpy() strcat() sprintf() et snprintf() Règles de base Erreurs liées à la mauvaise Notes Références Index
Introduction Le langage C est souvent considéré comme un langage difficile et peu fiable. La seconde assertion n'est pas acceptable dans la mesure où la plupart des applications, y compris les L4G et RAD sont eux mêmes écrits en C. En fait, ces idées reçues proviennent principalement de l'utilisation intensive des pointeurs. Si le C est souvent mal considéré, c'est bien souvent à cause de la méconnaissance du concept de pointeur et de la gestion de la mémoire qui lui est associé. Le présent document se propose de présenter ces concepts depuis leurs fondements théoriques jusqu'à leur application pratique. Il ne s'agit pas pour autant de définir les différentes notions avec la plus grande rigueur qui soit. Mon propos n'est pas de faire de l'initiation à l'assembleur, ni à l'électronique. Mon but est de présenter la gestion de la mémoire sous un angle différent de celui généralement adopté. L'audience visée est principalement celle des développeurs ayant déjà été initiés au langage C. (Table des matières)
La mémoire La mémoire physique de l'ordinateur La mémoire de l'ordinateur est assimilable, en première approximation à un long tableau continu. La largeur de ce tableau s'exprime en "bits".
En général, les cette taille comporte des subdivisions. En effet, pour une taille de 32bits, par exemple, un octet n'etant codé que sur 8bits, il est nécessaire, afin de ne pas perdre trop d'espace, de pouvoir stocker 4 octets différents par case de 32 bits et donc accéder de manière indépendante à ces 4 subdivisions.
Un bus 32bits est en général découpé en subdivisions de 8 et 16 bits. Chaque subdivision (octet) est numérotée. Cette numérotation correspond à une adresse mémoire.
Espace mémoire des programmes C Cette dernière vision des choses ne s'applique pas à la réalité virtuelle d'un processus. En effet, il est fréquent de voir des processus utiliser plus de mémoire que la quantité de RAM physique réellement disponible. Dans ce dernier cas, l'application utilise une partie de la mémoire RAM, mais aussi d'autres formes telle que le swap. Le système et les différents composants matériels (en particulier la "Memory Management Unit", MMU ou unité de gestion de la mémoire) se chargent d'agréger les différentes ressources (RAM, swap, disque dur, ...) et de faire croire aux processus que la mémoire est un vaste tableau homogène et contigu. Les mécanismes rendant possible cette illusion sont assez complexes dépassent de loin le cadre de ce document, mais ce sujet est largement couvert1. Il est cependant nécessaire de noter que les cases du "tableau-mémoire" ne sont pas réllement présentes (i.e. pointent réellement vers des zones de mémoire physique réelle) que lorsque celles-ci sont réellement utilisées. Pour chaque processus, cette zone contigüe s'étale de 0x00000000 à 0xFFFFFFFF. La zone inférieure à la zone de chargement du segment text du programme est réservée et ne peut être accédée en écriture.
La zone supérieure à la valeur de la macro PAGE_OFFSET est réservée pour le noyau (mapping noyau des zones de mémoire du processus). Cet espace mémoire est rempli selon certaines règles dépendantes des sytèmes et des architectures matérielles.
Figure 1 : utilisation de la mémoire pour chaque processus.
Zone programme Tout d'abord la zone de "programme", découpée en plusieurs segments dont :
  • Le segment texte (.text) contient le code machine du programme.
  • Le segment bss (.bss) contient les données non initialisées (variables globales du C). BSS signifie "Block Stating Symbol".
  • Le segment data (.data) contient les données initialisées du programmes (constantes globales).
Le tas (heap) Ensuite, vient le tas (heap). C'est la mémoire allouée dynamiquement avec les fonctions de type malloc(). La croissance de cette zone s'effectue vers les adresses hautes. L'adresse de base du tas est donnée par la fonction sbrk(0) avant toute allocation ou par brk(0). Le mémoire libre Vient la zone de mémoire libre", ou mémoire non allouée. Elle est consommée par le tas.
La réservation d'une zone suppémentaire se fait avec la fonction sbrk(taillesupp) ou taillesup est la taille de la zone à réserver. Zone de liens dynamiques Après cette zone de mémoire libre, une partie de la mémoire est réservée pour les bibliothèques dynamiques (links), chargées soit lors du chargement de l'exécutable quand les bibliothèques ont été référencées lors de la phase d'édition de liens (symboles nécessaires à la compilation), soit pendant l'exéction du programme et par le programme lui même par l'appel aux fonctions dlopen() et dlsym() (programmation de greffons, chargement de modules ...). La pile (stack) Enfin, la dernière zone de l'espace utilisateur est la pile. La pile commence, à l'inverse des autres zones, à l'adresse la plus haute (soit théoriquement PAGE_OFFSET-1). La pile croit donc vers les adresses basses.
La pile se compose de boites ou cadres (frames). Chacune de ces boites correspont à une procédure ou fonction. La fonction main() sera la boite 1 (seconde sur la pile). Si main() appelle une fonction "toto()", alors, lorsque le programme passera dans toto(), une boite numérotée 2 sera placée sur la pile, au "dessus" de la boite numérotée 1 de main().
A la sortie de la fonction toto(), la boite numéro 2 sera détruite (dépilée/modification de la topographie ou mapping de la mémoire virtelle).
Chaque boite contient les variables locales à la procédure (i.e. définie sur la pile), l'adresse de retour de la procédure, une sauvegarde des paramères passée en entrée à la procédure, voire aussi une copie de tout ou partie de la zone de registres du microprocesseur. Une boite, ou frame, n'est donc valide que tant que l'on ne sort pas de la fonction à laquelle elle est associée.
Il n'est donc possible d'utiliser un pointeur sur une zone de mémoire réservée sur la pile que dans la fonction où cette mémoire est réservée et les sous fonctions appelées par cette fonction.
Des la sortie d'une fonction, la zone la frame associée à cette fonction est éliminée de la carte de la mémoire virtuelle. La zone occupée par l'ancienne frame se retrouve donc contenir des données aléatoires. En corrolaires : La pile est réservée statiquement. Il est impossible de changer dynamiquement sa taille.
Une pile est alloué localement :
  • pour le programme (variable globale non statique, ou définie comme externe),
  • pour le fichier en cours (variable globale statique),
  • pour la fonction en cours (variables définies en début de fonction).
La pile représente la proportion de la mémoire de travail utilisée temporairement pour un traitement particulier. % cat frameshow.c #include int function3(int a, int b, int c, int d) { int i_3 = 0x30303030; printf("in function3 "); return 0x3F3F3F3F; } int function2(int a, int b, int c, int d) { int i_2 = 0x20202020; printf("in function2 "); function3(0xCCCCCCC1, 0xCCCCCCC2, 0xCCCCCCC3, 0xCCCCCCC4); return 0x2F2F2F2F; } int function1(int a, int b, int c, int d) { int i_1 = 0x10101010; printf("in function1 "); function2(0xBBBBBBB1, 0xBBBBBBB2, 0xBBBBBBB3, 0xBBBBBBB4); return 0x1F1F1F1F; } int final(int a, int b) { int i_final = 0x0FF00FF0; return i_final; } int main() { int i_main = 0x12345678; printf("in main "); function1(0xAAAAAAA1, 0xAAAAAAA2, 0xAAAAAAA3, 0xAAAAAAA4); final(0xDDDDDDD1, 0xDDDDDDD2); return 0; } % cc -g frameshow.c -o frameshow % dis frameshow **** DISASSEMBLER **** disassembly for frameshow section .text _start() 106b8: bc 10 20 00 clr %fp 106bc: e0 03 a0 40 ld [%sp + 64], %l0 106c0: 13 00 00 83 sethi %hi(0x20c00), %o1 106c4: e0 22 60 54 st %l0, [%o1 + 0x54] 106c8: a2 03 a0 44 add %sp, 68, %l1 106cc: 13 00 00 83 sethi %hi(0x20c00), %o1 106d0: e2 22 60 50 st %l1, [%o1 + 0x50] 106d4: 13 00 00 83 sethi %hi(0x20c00), %o1 106d8: e2 22 60 44 st %l1, [%o1 + 0x44] 106dc: a5 2c 20 02 sll %l0, 2, %l2 106e0: a4 04 a0 04 add %l2, 4, %l2 106e4: a4 04 40 12 add %l1, %l2, %l2 106e8: 27 00 00 83 sethi %hi(0x20c00), %l3 106ec: e8 04 e0 38 ld [%l3 + 0x38], %l4 106f0: 80 a5 20 00 cmp %l4, 0 106f4: 12 80 00 03 bne 0x10700 106f8: 01 00 00 00 nop 106fc: e4 24 e0 38 st %l2, [%l3 + 56] 10700: 2b 00 00 00 sethi %hi(__fsr_init_value), %l5 10704: aa 15 60 00 or %l5, __fsr_init_value, %l5 ! __fsr_init_value 10708: 80 90 00 15 orcc %g0, %l5, %g0 1070c: 02 80 00 12 be 0x10754 10710: 01 00 00 00 nop 10714: ad 2d 60 02 sll %l5, 2, %l6 10718: ae 0d a3 00 and %l6, 768, %l7 1071c: ac 0d 60 3f and %l5, 63, %l6 10720: ac 15 80 17 or %l6, %l7, %l6 10724: ab 2d a0 16 sll %l6, 22, %l5 10728: 29 00 00 83 sethi %hi(0x20c00), %l4 1072c: a8 15 20 3c or %l4, 0x3c, %l4 ! __crt_scratch 10730: c1 2d 00 00 st %fsr, [%l4] 10734: ec 05 00 00 ld [%l4], %l6 10738: ae 20 00 17 sub %g0, %l7, %l7 1073c: af 3d e0 1f sra %l7, 31, %l7 10740: af 2d e0 1e sll %l7, 30, %l7 10744: ac 2d 80 17 andn %l6, %l7, %l6 10748: ac 15 80 15 or %l6, %l5, %l6 1074c: ec 25 00 00 st %l6, [%l4] 10750: c1 0d 00 00 ld [%l4], %fsr 10754: 9c 23 a0 20 sub %sp, 32, %sp 10758: 80 90 00 01 orcc %g0, %g1, %g0 1075c: 02 80 00 04 be 0x1076c 10760: 90 10 00 01 mov %g1, %o0 10764: 40 00 40 f1 call atexit 10768: 01 00 00 00 nop 1076c: 11 00 00 42 sethi %hi(0x10800), %o0 10770: 40 00 40 ee call atexit 10774: 90 12 22 7c or %o0, 636, %o0 10778: 11 00 00 83 sethi %hi(0x20c00), %o0 1077c: d0 02 20 48 ld [%o0 + 0x48], %o0 10780: 80 90 00 08 orcc %g0, %o0, %g0 10784: 12 80 00 09 bne 0x107a8 10788: 01 00 00 00 nop 1078c: 11 00 00 83 sethi %hi(0x20c00), %o0 10790: d0 02 20 4c ld [%o0 + 0x4c], %o0 10794: 80 90 00 08 orcc %g0, %o0, %g0 10798: 02 80 00 04 be 0x107a8 1079c: 01 00 00 00 nop 107a0: 40 00 40 e2 call atexit 107a4: 01 00 00 00 nop 107a8: 40 00 00 b2 call _init 107ac: 01 00 00 00 nop 107b0: 90 10 00 10 mov %l0, %o0 107b4: 92 10 00 11 mov %l1, %o1 107b8: 94 10 00 12 mov %l2, %o2 107bc: 96 10 00 13 mov %l3, %o3 107c0: 40 00 00 88 call main 107c4: 01 00 00 00 nop 107c8: 40 00 40 db call exit 107cc: 01 00 00 00 nop 107d0: 40 00 40 dc call _exit 107d4: 01 00 00 00 nop 107d8: 00 01 00 00 unimp 0x10000 107dc: 00 01 00 00 unimp 0x10000 107e0: 00 01 00 00 unimp 0x10000 107e4: 00 01 00 00 unimp 0x10000 function3() 107e8: 9d e3 bf 98 save %sp, -104, %sp 107ec: f6 27 a0 50 st %i3, [%fp + 80] 107f0: f4 27 a0 4c st %i2, [%fp + 76] 107f4: f2 27 a0 48 st %i1, [%fp + 72] 107f8: f0 27 a0 44 st %i0, [%fp + 68] 107fc: 21 0c 0c 0c sethi %hi(0x30303000), %l0 10800: a0 14 20 30 or %l0, 0x30, %l0 ! 0x30303030 10804: e0 27 bf f8 st %l0, [%fp - 8] 10808: 21 00 00 42 sethi %hi(0x10800), %l0 1080c: a0 14 22 b8 or %l0, 0x2b8, %l0 ! 0x10ab8 10810: 40 00 40 cf call printf 10814: 90 14 00 00 or %l0, %g0, %o0 10818: 21 0f cf cf sethi %hi(0x3f3f3c00), %l0 1081c: a0 14 23 3f or %l0, 0x33f, %l0 ! 0x3f3f3f3f 10820: 10 80 00 04 ba 0x10830 10824: e0 27 bf fc st %l0, [%fp - 4] 10828: 10 80 00 02 ba 0x10830 1082c: 01 00 00 00 nop 10830: e0 07 bf fc ld [%fp - 4], %l0 10834: b0 14 00 00 or %l0, %g0, %i0 10838: 81 c7 e0 08 ret 1083c: 81 e8 00 00 restore 10840: 00 01 00 00 unimp 0x10000 10844: 00 01 00 00 unimp 0x10000 10848: 00 01 00 00 unimp 0x10000 1084c: 00 01 00 00 unimp 0x10000 function2() 10850: 9d e3 bf 98 save %sp, -104, %sp 10854: f6 27 a0 50 st %i3, [%fp + 80] 10858: f4 27 a0 4c st %i2, [%fp + 76] 1085c: f2 27 a0 48 st %i1, [%fp + 72] 10860: f0 27 a0 44 st %i0, [%fp + 68] 10864: 21 08 08 08 sethi %hi(0x20202000), %l0 10868: a0 14 20 20 or %l0, 0x20, %l0 ! 0x20202020 1086c: e0 27 bf f8 st %l0, [%fp - 8] 10870: 21 00 00 42 sethi %hi(0x10800), %l0 10874: a0 14 22 c8 or %l0, 0x2c8, %l0 ! 0x10ac8 10878: 40 00 40 b5 call printf 1087c: 90 14 00 00 or %l0, %g0, %o0 10880: 21 0c cc cc sethi %hi(0x33333000), %l0 10884: a0 1c 3c c1 xor %l0, -831, %l0 10888: 23 0c cc cc sethi %hi(0x33333000), %l1 1088c: a2 1c 7c c2 xor %l1, -830, %l1 10890: 25 0c cc cc sethi %hi(0x33333000), %l2 10894: a4 1c bc c3 xor %l2, -829, %l2 10898: 27 0c cc cc sethi %hi(0x33333000), %l3 1089c: a6 1c fc c4 xor %l3, -828, %l3 108a0: 90 14 00 00 or %l0, %g0, %o0 108a4: 92 14 40 00 or %l1, %g0, %o1 108a8: 94 14 80 00 or %l2, %g0, %o2 108ac: 7f ff ff cf call function3 108b0: 96 14 c0 00 or %l3, %g0, %o3 108b4: 21 0b cb cb sethi %hi(0x2f2f2c00), %l0 108b8: a0 14 23 2f or %l0, 0x32f, %l0 ! 0x2f2f2f2f 108bc: 10 80 00 04 ba 0x108cc 108c0: e0 27 bf fc st %l0, [%fp - 4] 108c4: 10 80 00 02 ba 0x108cc 108c8: 01 00 00 00 nop 108cc: e0 07 bf fc ld [%fp - 4], %l0 108d0: b0 14 00 00 or %l0, %g0, %i0 108d4: 81 c7 e0 08 ret 108d8: 81 e8 00 00 restore 108dc: 00 01 00 00 unimp 0x10000 108e0: 00 01 00 00 unimp 0x10000 108e4: 00 01 00 00 unimp 0x10000 108e8: 00 01 00 00 unimp 0x10000 108ec: 00 01 00 00 unimp 0x10000 function1() 108f0: 9d e3 bf 98 save %sp, -104, %sp 108f4: f6 27 a0 50 st %i3, [%fp + 80] 108f8: f4 27 a0 4c st %i2, [%fp + 76] 108fc: f2 27 a0 48 st %i1, [%fp + 72] 10900: f0 27 a0 44 st %i0, [%fp + 68] 10904: 21 04 04 04 sethi %hi(0x10101000), %l0 10908: a0 14 20 10 or %l0, 0x10, %l0 ! 0x10101010 1090c: e0 27 bf f8 st %l0, [%fp - 8] 10910: 21 00 00 42 sethi %hi(0x10800), %l0 10914: a0 14 22 d8 or %l0, 0x2d8, %l0 ! 0x10ad8 10918: 40 00 40 8d call printf 1091c: 90 14 00 00 or %l0, %g0, %o0 10920: 21 11 11 11 sethi %hi(0x44444400), %l0 10924: a0 1c 3f b1 xor %l0, -79, %l0 10928: 23 11 11 11 sethi %hi(0x44444400), %l1 1092c: a2 1c 7f b2 xor %l1, -78, %l1 10930: 25 11 11 11 sethi %hi(0x44444400), %l2 10934: a4 1c bf b3 xor %l2, -77, %l2 10938: 27 11 11 11 sethi %hi(0x44444400), %l3 1093c: a6 1c ff b4 xor %l3, -76, %l3 10940: 90 14 00 00 or %l0, %g0, %o0 10944: 92 14 40 00 or %l1, %g0, %o1 10948: 94 14 80 00 or %l2, %g0, %o2 1094c: 7f ff ff c1 call function2 10950: 96 14 c0 00 or %l3, %g0, %o3 10954: 21 07 c7 c7 sethi %hi(0x1f1f1c00), %l0 10958: a0 14 23 1f or %l0, 0x31f, %l0 ! 0x1f1f1f1f 1095c: 10 80 00 04 ba 0x1096c 10960: e0 27 bf fc st %l0, [%fp - 4] 10964: 10 80 00 02 ba 0x1096c 10968: 01 00 00 00 nop 1096c: e0 07 bf fc ld [%fp - 4], %l0 10970: b0 14 00 00 or %l0, %g0, %i0 10974: 81 c7 e0 08 ret 10978: 81 e8 00 00 restore 1097c: 00 01 00 00 unimp 0x10000 10980: 00 01 00 00 unimp 0x10000 10984: 00 01 00 00 unimp 0x10000 10988: 00 01 00 00 unimp 0x10000 1098c: 00 01 00 00 unimp 0x10000 final() 10990: 9d e3 bf 98 save %sp, -104, %sp 10994: f2 27 a0 48 st %i1, [%fp + 72] 10998: f0 27 a0 44 st %i0, [%fp + 68] 1099c: 21 03 fc 03 sethi %hi(0xff00c00), %l0 109a0: a0 14 23 f0 or %l0, 0x3f0, %l0 ! 0xff00ff0 109a4: e0 27 bf f8 st %l0, [%fp - 8] 109a8: e0 07 bf f8 ld [%fp - 8], %l0 109ac: 10 80 00 04 ba 0x109bc 109b0: e0 27 bf fc st %l0, [%fp - 4] 109b4: 10 80 00 02 ba 0x109bc 109b8: 01 00 00 00 nop 109bc: e0 07 bf fc ld [%fp - 4], %l0 109c0: b0 14 00 00 or %l0, %g0, %i0 109c4: 81 c7 e0 08 ret 109c8: 81 e8 00 00 restore 109cc: 00 01 00 00 unimp 0x10000 109d0: 00 01 00 00 unimp 0x10000 109d4: 00 01 00 00 unimp 0x10000 109d8: 00 01 00 00 unimp 0x10000 109dc: 00 01 00 00 unimp 0x10000 main() 109e0: 9d e3 bf 98 save %sp, -104, %sp 109e4: 21 04 8d 15 sethi %hi(0x12345400), %l0 109e8: a0 14 22 78 or %l0, 0x278, %l0 ! 0x12345678 109ec: e0 27 bf f8 st %l0, [%fp - 8] 109f0: 21 00 00 42 sethi %hi(0x10800), %l0 109f4: a0 14 22 e8 or %l0, 0x2e8, %l0 ! 0x10ae8 109f8: 40 00 40 55 call printf 109fc: 90 14 00 00 or %l0, %g0, %o0 10a00: 21 15 55 55 sethi %hi(0x55555400), %l0 10a04: a0 1c 3e a1 xor %l0, -351, %l0 10a08: 23 15 55 55 sethi %hi(0x55555400), %l1 10a0c: a2 1c 7e a2 xor %l1, -350, %l1 10a10: 25 15 55 55 sethi %hi(0x55555400), %l2 10a14: a4 1c be a3 xor %l2, -349, %l2 10a18: 27 15 55 55 sethi %hi(0x55555400), %l3 10a1c: a6 1c fe a4 xor %l3, -348, %l3 10a20: 90 14 00 00 or %l0, %g0, %o0 10a24: 92 14 40 00 or %l1, %g0, %o1 10a28: 94 14 80 00 or %l2, %g0, %o2 10a2c: 7f ff ff b1 call function1 10a30: 96 14 c0 00 or %l3, %g0, %o3 10a34: 21 08 88 88 sethi %hi(0x22222000), %l0 10a38: a0 1c 3d d1 xor %l0, -559, %l0 10a3c: 23 08 88 88 sethi %hi(0x22222000), %l1 10a40: a2 1c 7d d2 xor %l1, -558, %l1 10a44: 90 14 00 00 or %l0, %g0, %o0 10a48: 7f ff ff d2 call final 10a4c: 92 14 40 00 or %l1, %g0, %o1 10a50: 10 80 00 04 ba 0x10a60 10a54: c0 27 bf fc st %g0, [%fp - 4] 10a58: 10 80 00 02 ba 0x10a60 10a5c: 01 00 00 00 nop 10a60: e0 07 bf fc ld [%fp - 4], %l0 10a64: b0 14 00 00 or %l0, %g0, %i0 10a68: 81 c7 e0 08 ret 10a6c: 81 e8 00 00 restore section .init _init() 10a70: 9d e3 bf a0 save %sp, -96, %sp 10a74: 81 c7 e0 08 ret 10a78: 81 e8 00 00 restore section .fini _fini() 10a7c: 9d e3 bf a0 save %sp, -96, %sp 10a80: 81 c7 e0 08 ret 10a84: 81 e8 00 00 restore % dbx frameshow Reading frameshow Reading ld.so.1 Reading libc.so.1 Reading libdl.so.1 Reading libc_psr.so.1 dbx> alias P="print -f0x%x" dbx> print main main = &main() at 0x109e0 dbx> print function1 function1 = &function1(int a, int b, int c, int d) at 0x108f0 dbx> print function2 function2 = &function2(int a, int b, int c, int d) at 0x10850 dbx> print function3 function3 = &function3(int a, int b, int c, int d) at 0x107e8 dbx> stop in main (2) stop in main dbx> run Running: frameshow (process id 28873) stopped in main at line 31 in file "frameshow.c" 31 int i_main = 0x12345678; dbx> next stopped in main at line 32 in file "frameshow.c" 32 printf("in main "); dbx> P $sp $sp = 0xffbef3e0 dbx> P $fp $fp = 0xffbef448 dbx> ex $sp, $fp 0xffbef3e0: 0x12345678 0x00000000 0x00000000 0x00000000 0xffbef3f0: 0x00000000 0x00000000 0x00000000 0xff3dc890 0xffbef400: 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0xffbef410: 0x00000000 0x00000000 0xffbef448 0x000107c0 0xffbef420: 0x00000000 0x00000000 0x00000003 0xffbef4ac 0xffbef430: 0x00000004 0xffbef4b4 0x00000005 0xffbef5fc 0xffbef440: 0x12345678 0x00000000 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0xff319c04 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x00000000 0xff3420d8 0xff33e5d8 0xffffffff o4-o7 0x000222e8 0xff29bc20 0xffbef3e0 0xff29bc20 l0-l3 0x12345678 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0xff3dc890 i0-i3 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 i4-i7 0x00000000 0x00000000 0xffbef448 0x000107c0 y 0x00000000 ccr 0x00000000 pc 0x000109f0:main+0x10 sethi %hi(0x10800), %l0 npc 0x000109f4:main+0x14 or %l0, 0x2e8, %l0 dbx> next stopped in main at line 33 in file "frameshow.c" 33 function1(0xAAAAAAA1, 0xAAAAAAA2, 0xAAAAAAA3, 0xAAAAAAA4); dbx> step stopped in function1 at line 18 in file "frameshow.c" 18 int i_1 = 0x10101010; dbx> next stopped in function1 at line 19 in file "frameshow.c" 19 printf("in function1 "); dbx> next stopped in function1 at line 20 in file "frameshow.c" 20 function2(0xBBBBBBB1, 0xBBBBBBB2, 0xBBBBBBB3, 0xBBBBBBB4); dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex $sp, 0xffbef448 0xffbef378: 0x00010ad8 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 input parameters 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c previous stack end and return address in main 0xffbef3b8: 0xffbef3e0 0x000109f8 0x00000000 0x00000000 0xffbef3c8: 0x00000000 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 parameters passed 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 function1 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xffbef428: 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 value of i_main on stack 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef378 0x00010918 l0-l3 0x00010ad8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c y 0x00000000 ccr 0x00000099 pc 0x00010920:function1+0x30 sethi %hi(0x44444400), %l0 npc 0x00010924:function1+0x34 xor %l0, -0x4f, %l0 dbx> step stopped in function2 at line 11 in file "frameshow.c" 11 int i_2 = 0x20202020; dbx> next stopped in function2 at line 12 in file "frameshow.c" 12 printf("in function2 "); dbx> next stopped in function2 at line 13 in file "frameshow.c" 13 function3(0xCCCCCCC1, 0xCCCCCCC2, 0xCCCCCCC3, 0xCCCCCCC4); dbx> P $sp $sp = 0xffbef310 dbx> P $fp $fp = 0xffbef378 dbx> ex $sp, 0xffbef448 0xffbef310: 0x00010ac8 0x00000000 0x00000000 0x00000000 0xffbef320: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef330: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef340: 0x00000000 0x00000000 0xffbef378 0x0001094c 0xffbef350: 0xffbef5fc 0x00000000 0x00000000 0x00000000 0xffbef360: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef370: 0x20202020 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xffbef380: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef390: 0x00000000 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xffbef3a0: 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef3b0: 0xffbef3e0 0x00010a2c 0xffbef3e0 0xbbbbbbb1 0xffbef3c0: 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0xffbef3d0: 0x00000000 0xff29bc20 0x10101010 0x000109f8 0xffbef3e0: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3f0: 0x00000000 0x00000000 0x00000000 0xff3dc890 0xffbef400: 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 0xffbef410: 0x00000000 0x00000000 0xffbef448 0x000107c0 0xffbef420: 0x00000000 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xffbef430: 0xaaaaaaa4 0x000222e8 0xff29bc20 0xffbef5fc 0xffbef440: 0x12345678 0x00000000 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef310 0x00010878 l0-l3 0x00010ac8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 i4-i7 0x00000000 0x00000000 0xffbef378 0x0001094c y 0x00000000 ccr 0x00000099 pc 0x00010880:function2+0x30 sethi %hi(0x33333000), %l0 npc 0x00010884:function2+0x34 xor %l0, -0x33f, %l0 dbx> step stopped in function3 at line 5 in file "frameshow.c" 5 int i_3 = 0x30303030; dbx> next stopped in function3 at line 6 in file "frameshow.c" 6 printf("in function3 "); dbx> next stopped in function3 at line 7 in file "frameshow.c" 7 return 0x3F3F3F3F; dbx> P $sp $sp = 0xffbef2a8 dbx> P $fp $fp = 0xffbef310 dbx> ex $sp, 0xffbef448 0xffbef2a8: 0x00010ab8 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x00000000 0xccccccc1 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x00000000 0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xffbef428: 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0000000d 0xff340284 0xff343a54 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef2a8 0x00010810 l0-l3 0x00010ab8 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 i4-i7 0x00000000 0x00000000 0xffbef310 0x000108ac y 0x00000000 ccr 0x00000099 pc 0x00010818:function3+0x30 sethi %hi(0x3f3f3c00), %l0 npc 0x0001081c:function3+0x34 or %l0, 0x33f, %l0 dbx> next stopped in function3 at line 8 in file "frameshow.c" 8 } dbx> next stopped in function2 at line 14 in file "frameshow.c" 14 return 0x2F2F2F2F; dbx> P $sp $sp = 0xffbef310 dbx> P $fp $fp = 0xffbef378 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0xccccccc1 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0xbbbbbbb1 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x00000000 0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xffbef428: 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 o4-o7 0x00000000 0x00000000 0xffbef310 0x000108ac l0-l3 0xccccccc1 0xccccccc2 0xccccccc3 0xccccccc4 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 i4-i7 0x00000000 0x00000000 0xffbef378 0x0001094c y 0x00000000 ccr 0x00000099 pc 0x000108b4:function2+0x64 sethi %hi(0x2f2f2c00), %l0 npc 0x000108b8:function2+0x68 or %l0, 0x32f, %l0 dbx> next stopped in function2 at line 15 in file "frameshow.c" 15 } dbx> next stopped in function1 at line 21 in file "frameshow.c" 21 return 0x1F1F1F1F; dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f 0xffbef378: 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x10101010 0x000109f8 0xaaaaaaa1 0xaaaaaaa2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xaaaaaaa1 0xffbef428: 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0xffbef5fc 0x12345678 0x00000000 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x2f2f2f2f 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 o4-o7 0x00000000 0x00000000 0xffbef378 0x0001094c l0-l3 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xbbbbbbb4 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xaaaaaaa1 0xaaaaaaa2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a2c y 0x00000000 ccr 0x00000099 pc 0x00010954:function1+0x64 sethi %hi(0x1f1f1c00), %l0 npc 0x00010958:function1+0x68 or %l0, 0x31f, %l0 dbx> next stopped in function1 at line 22 in file "frameshow.c" 22 } dbx> next stopped in main at line 34 in file "frameshow.c" 34 final(0xDDDDDDD1, 0xDDDDDDD2); dbx> step stopped in final at line 25 in file "frameshow.c" 25 int i_final = 0x0FF00FF0; dbx> next stopped in final at line 26 in file "frameshow.c" 26 return i_final; dbx> P $sp $sp = 0xffbef378 dbx> P $fp $fp = 0xffbef3e0 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f 0xffbef378: 0x0ff00ff0 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x0ff00ff0 0x1f1f1f1f 0xddddddd1 0xddddddd2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xddddddd1 0xffbef428: 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0x00000000 0x12345678 0x00010764 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x00000000 0x00000000 0x00000000 0x00000000 o4-o7 0x00000000 0x00000000 0xffbef378 0x00000000 l0-l3 0x0ff00ff0 0x00000000 0x00000000 0x00000000 l4-l7 0x00000000 0x00000000 0x00000000 0x00000000 i0-i3 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 i4-i7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 y 0x00000000 ccr 0x00000099 pc 0x000109a8:final+0x18 ld [%fp - 0x8], %l0 npc 0x000109ac:final+0x1c ba final+0x2c dbx> next stopped in final at line 27 in file "frameshow.c" 27 } dbx> next stopped in main at line 35 in file "frameshow.c" 35 return 0; dbx> P $sp $sp = 0xffbef3e0 dbx> P $fp $fp = 0xffbef448 dbx> ex 0xffbef2a8, 0xffbef448 0xffbef2a8: 0x3f3f3f3f 0x00000000 0x00000000 0x00000000 0xffbef2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2c8: 0x3f3f3f3f 0xccccccc2 0xccccccc3 0xccccccc4 0xffbef2d8: 0x00000000 0x00000000 0xffbef310 0x000108ac 0xffbef2e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef2f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef308: 0x30303030 0x3f3f3f3f 0x2f2f2f2f 0xccccccc2 0xffbef318: 0xccccccc3 0xccccccc4 0x00000000 0x00000000 0xffbef328: 0x00000000 0x00000000 0x2f2f2f2f 0xbbbbbbb2 0xffbef338: 0xbbbbbbb3 0xbbbbbbb4 0x00000000 0x00000000 0xffbef348: 0xffbef378 0x0001094c 0xffbef5fc 0xccccccc1 0xffbef358: 0xccccccc2 0xccccccc3 0xccccccc4 0x00000000 0xffbef368: 0x00000000 0x00000000 0x20202020 0x2f2f2f2f 0xffbef378: 0x0ff00ff0 0x00000000 0x00000000 0x00000000 0xffbef388: 0x00000000 0x00000000 0x00000000 0x00000000 0xffbef398: 0x0ff00ff0 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0xffbef3a8: 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 0xffbef3b8: 0xffbef3e0 0xbbbbbbb1 0xbbbbbbb2 0xbbbbbbb3 0xffbef3c8: 0xbbbbbbb4 0x00000000 0x00000000 0xff29bc20 0xffbef3d8: 0x0ff00ff0 0x0ff00ff0 0xddddddd1 0xddddddd2 0xffbef3e8: 0xaaaaaaa3 0xaaaaaaa4 0x00000000 0x00000000 0xffbef3f8: 0x00000000 0xff3dc890 0x00000001 0xffbef4ac 0xffbef408: 0xffbef4b4 0x00020c00 0x00000000 0x00000000 0xffbef418: 0xffbef448 0x000107c0 0x00000000 0xddddddd1 0xffbef428: 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 0x000222e8 0xffbef438: 0xff29bc20 0x00000000 0x12345678 0x00010764 0xffbef448: 0x00000001 dbx> regs current frame: [1] g0-g3 0x00000000 0x0000000a 0x00000000 0x00000000 g4-g7 0x00000000 0x00000000 0x00000000 0x00000000 o0-o3 0x0ff00ff0 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 o4-o7 0x000222e8 0xff29bc20 0xffbef3e0 0x00010a48 l0-l3 0xddddddd1 0xddddddd2 0xaaaaaaa3 0xaaaaaaa4 l4-l7 0x00000000 0x00000000 0x00000000 0xff3dc890 i0-i3 0x00000001 0xffbef4ac 0xffbef4b4 0x00020c00 i4-i7 0x00000000 0x00000000 0xffbef448 0x000107c0 y 0x00000000 ccr 0x00000099 pc 0x00010a50:main+0x70 ba main+0x80 npc 0x00010a54:main+0x74 st %g0, [%fp - 0x4] La mémoire C Un programme C gère la mémoire de trois façons différentes:
  • La mémoire globale du segment data, accessible depuis n'importe quel endroit du programme, où sont stockées les données statiques globales,
  • La mémoire globale du tas, accessible depuis n'importe quel endroit du programme, où sont stockées les données dynamiquement allouées (malloc, réalloc, free, ...)
  • La mémoire locale aussi appelée la pile, accessible localement seulement, où sont passés les paramètres des fonctions et stockées les données locales et temporaires.

Exemple : #include #include static int i_stat = 4; /* Stocké dans le segment data */ int i_glob; /* Stocké dans le segment bss */ int *pi_pg; /* Stocké dans le segment bss */ /* main est stocké dans le segment text de la zone de programme */ int main(int nargs, char **args) { /* paramètres nargs et args stockés dans la frame numéro 1 de la pile */ int *pi_loc; /* dans la frame 1 de la pile */ void *sbrk0; /* nécessaire pour stocker l'adresse de base avant le premier malloc */ sbrk0 = (void *) sbrk(0); if (!(pi_loc = (int *) malloc(sizeof(int) * 16))) /* réservation de 16 x sizeof(int) sur le tas */ return 1; if (!(pi_pg = (int *) malloc(sizeof(int) * 8))) { /* réservation de 8 x sizeof(int) sur le tas */ free(pi_loc); return 2; } printf("adresse de i_stat = 0x%08x (zone programme, segment data) ", &i_stat); printf("adresse de i_glob = 0x%08x (zone programme, segment bss) ", &i_glob); printf("adresse de pi_pg = 0x%08x (zone programme, segment bss) ", &pi_pg); printf("adresse de main = 0x%08x (zone programme, segment text) ", main); printf("adresse de nargs = 0x%08x (pile frame 1) ", &nargs); printf("adresse de args = 0x%08x (pile frame 1) ", &args); printf("adresse de pi_loc = 0x%08x (pile frame 1) ", &pi_loc); printf("sbrk(0) (heap) = 0x%08x (tas) ", sbrk0); printf("pi_loc = 0x%08x (tas) ", pi_loc); printf("pi_pg = 0x%08x (tas) ", pi_pg); free(pi_pg); free(pi_loc); return 0; } Donne sous Sparc/Solaris : adresse de i_stat = 0x00020c70 (zone programme, segment data) adresse de i_glob = 0x00020ca4 (zone programme, segment bss) adresse de pi_pg = 0x00020ca8 (zone programme, segment bss) adresse de main = 0x0001068c (zone programme, segment text) adresse de nargs = 0xffbeefa4 (pile frame 1) adresse de args = 0xffbeefa8 (pile frame 1) adresse de pi_loc = 0xffbeef4c (pile frame 1) sbrk(0) (heap) = 0x00020c00 (tas) pi_loc = 0x00020cb8 (tas) pi_pg = 0x00020d08 (tas) Parallèlement, l'utilitaire elfdump donne : index value size type bind oth ver shndx name [17] 0x00020c68 0x00000000 SECT LOCL D 0 .data [21] 0x00020c88 0x00000000 SECT LOCL D 0 .bss [47] 0x00020c70 0x00000004 OBJT LOCL D 0 .data i_stat [60] 0x00020ca4 0x00000004 OBJT GLOB D 0 .bss i_glob [68] 0x0001068c 0x000001e0 FUNC GLOB D 0 .text main [80] 0x00020ca8 0x00000004 OBJT GLOB D 0 .bss pi_pg On notera que la variables pi_pg est stockée dans le segment bss mais que les données pointées par la variable sont elles stockées dans le tas.

De même, la variable pi_loc est stockée sur la pile, mais les données vers lesquelles elle pointe sont stockées sur le tas.

A retenir :
  • La mémoire d'un processus est assimilable à un espace contigu,
  • Cet espace est organisé en différents groupes fonctionnels,
  • Les données d'un programme ne sont pas toutes stockées au même endroit en fonction de leur portée et de leur mode de réservation.
(Table des matières)
Le tas Exploration du tas principes d'un allocateur memoire Un allocateur mémoire est un ensemble de routine responsable de la gestion du tas. Bien qu'un processus pense avoir toute la mémoire pour lui, il faut néanmoins s'assurer d'une part que cette mémoire est réellement disponible (et ne s'envolera pas toute seule lors de modifications des pages mémoires par la mmu), et d'autre part que les variables d'une fonction ne soit pas écrasées par une celles d'une autre. Par ailleurs, les différentes sous parties d'un programme ne nécessitent pas de conserver toute la mémoire allouée pendant toute la durée de l'exécution. Par exemple, lorsque l'on referme un fichier, il est préférable libérer toute la mémoire qui lui correspond. Cet espace se verra de nouveau disponible pour ouvrir un autre document. En résumé, l'allocateur doit se charger des taches suivantes:
  • réservation de pages mémoire auprès du noyau (brk/sbrk)
  • segmentation et réservation de ces pages en fonction des besoins
  • remise à disposition de la mémoire précédement allouée
La réservation de pages mémoire est normalement transparent vis à vis de l'utilisateur. Par contre, la réservation et la libération de la mémoire sont des opérations en interface avec le programmeur. Les points d'entrée de ces deux opérations sont les fonctions malloc() et free(). A ces 2 opérations viennent s'ajouter realloc(), qui permet de modifier la taille d'uen zone allouée. Allocateur minimaliste Voyons tout d'abord un allocateur minimaliste qui ne libère pas réellement la mémoire, mais dont nous pourrons nous servir le cas échéant pour débugger la mémoire. Allocateur standards L'allocateur minimaliste ne répond pas au problème de la libération. Il a de plus l'inconvéniant d'appeler des routines systèmes (sbrk) peu performantes à chaque malloc. La pile Notion de type Un des points les plus importants lorsque l'on parle de langage évolué est la notion de typage. Nous ne parlerons pas de la notion théorique de typage, mais de la notion pratique.
Dans la pratique, un ordinateur ne reconnait aucun type de donnée quant à son stockage en mémoire. Il n'existe pas une mémoire spécifique pour les entiers et une autre pour les caractères. La seule exception à cette règle se trouve dans les registres des microprocesseurs qui, eux, pour des raisons de performances, différencient les nombres entiers des nombres réels.
La notion de type « de bas niveau » correspond à la taille mémoire sur laquelle est encodée une entité. Le type définit donc la taille de la donnée à manipuler. (Table des matières)
Types simples Les types simples sont les types prédéfinis par le langage C: char, short, int, long, float, double, et les pointeurs (void *). Il est à noter que quel que soit le «type» de pointeur (char *, int * double *, void *), la taille d'encodage est toujours la même. Aussi, un pointeur générique peut être appelé void *.
Ces types ont des tailles fixées pour une architecture donnée, mais varient d'une architecture à l'autre. Il semble même que la taille d'un « octet » n'ai pas toujours été de 8bits2
Il est impératif de ne pas supposer de leur taille si l'on recherche la portabilité. On pourra utiliser sizeof(type) en lieu et place de la taille supposée. 1 #include 2 int main(void) { 3 printf("sizeof(char) = %d ", sizeof(char)); 4 printf("sizeof(short) = %d ", sizeof(short)); 5 printf("sizeof(int) = %d ", sizeof(int)); 6 printf("sizeof(long) = %d ", sizeof(long)); 7 printf("sizeof(long long) = %d ", sizeof(long long));3 8 printf("sizeof(float) = %d ", sizeof(float)); 9 printf("sizeof(double) = %d ", sizeof(double)); 10 printf("sizeof(void *) = %d ", sizeof(void *)); 11 printf("sizeof(char *) = %d ", sizeof(char *)); 12 printf("sizeof(int *) = %d ", sizeof(int *)); 13 printf("sizeof(double *) = %d ", sizeof(double *)); 14 return 0; 15 } donne sur linux iX86: sizeof(char) = 1 sizeof(short) = 2 sizeof(int) = 4 sizeof(long) = 4 sizeof(long long) = 84 sizeof(float) = 4 sizeof(double) = 8 sizeof(void *) = 4 sizeof(char *) = 4 sizeof(int *) = 4 sizeof(double *) = 4 A retenir:
  • D'un point de vue pratique, le type des données en mémoire est assimilable à la taille des données
  • Il ne faut jamais préjuger de la taille d'un type, mais utiliser sizeof()
  • Tous les pointeurs ont la même taille sur une architecture donnée. Cette taille est cohérente avec la taille du bus mémoire.

(Table des matières)
Alignement Comme nous l'avons vu dans la description de la mémoire virtuelle, la mémoire est comparable à un tableau.
On ne peut, en théorie, accéder directement qu'a une case entière dont la taille correspond à la taille de la mémoire (32bits). Il n'est donc pas possible d'accéder directement à une fraction d'une case mémoire.
Or comme nous venons de le voir, les types de donnés n'ont pas obligatoirement des tailles identiques à la taille de la mémoire.
Prennons par exemple le caractère char. Celui-ci est codé sur un seul octet. Mais, dans le cas d'une mémoire de 32bits, la taille d'une case est de 4 octets. On devra donc laisser, théoriquement, 3 octets vides.
Dans la pratique, les choses sont un peu plus complexes car même si la taille du bus mémoire est prépondérante, tous les octets sont directement numérotés. Il est donc possible, par l'entremise d'outils inclus dans les microprocesseurs et les compilateurs, d'accéder à des données de 1, 2 ou 4 octets directement.
Certaines architectures imposent cependant certaines contraintes d'alignement: les données ne peuvent être stockées qu'à des adresses multiples de la taille sur laquelle est codée ces données et au maximum, à des adresses multiples de la taille du bus.

Pour vérifier si l'architecture possède une contrainte d'alignement, il suffit de compiler et de lancer le programme suivant: 1 int main(void) { 2 struct s { char a, b, c, d, e, f, g, h, i, j;} t; 3 int *pi; 4 pi = (int *) &(t.a); 5 printf("pi = %p, i = %d ", pi, *pi); 6 pi = (int *) &(t.b); 7 printf("pi = %p, i = %d ", pi, *pi); 8 pi = (int *) &(t.c); 9 printf("pi = %p, i = %d ", pi, *pi); 10 pi = (int *) &(t.d); 11 printf("pi = %p, i = %d ", pi, *pi); 12 pi = (int *) &(t.e); 13 printf("pi = %p, f = %d ", pi, *pi); 14 pi = (int *) &(t.f); 15 printf("pi = %p, i = %d ", pi, *pi); 16 pi = (int *) &(t.g); 17 printf("pi = %p, i = %d ", pi, *pi); 18 return 0; 19 } Si le programme se termine normalement, alors l'architecture n'impose pas de contrainte. Dans le cas contraire, le programme s'arrêtera brutalement avec un signal de type bus error et génèrera un core.
Pour linux AMD Athlon, le programme tourne normalement. Sur Solaris/UltraSparc, le programme s'arrète avec un "Bus error" ligne 5.
A retenir:
  • La mémoire est adressable de plusieurs manières différentes.
  • Lorsque l'architecture impose des contraintes d'alignement, l'adresse d'une donnée est un multiple de la taille des données adressées si cette taille est inférieure à la taille du bus mémoire, ou multiple de la taille du bus .
  • Nous avons vu que le typage constituait un canevas d'interprêtation de la mémoire. Réciproquement, n'importe quelle zone mémoire peut être interprètée par un type ou un autre pour peu que l'alignement soit respecté.

(Table des matières)
Types composés Les types composés peuvent être définis comme des agrégats de types simples ou/et composés. La définition de types composés se fait à l'aide du mot réservé «struct», suivi de la description des différent composants.
Ces types composés définis par « struct » fonctionnent comme les types simples en ce qui concerne l'assignation5: 1 #include 2 int main(void) { 3 struct s1 {int a, b;} A, B; 4 A.a = 1, A.b = 2, B.a = 3, B.b = 4; 5 A = B; 6 printf("A.a = %d A.b = %d ", A.a, A.b); 7 return 0; 8 } donne: A.a = 3 A.b = 4 Par contre, il est impossible de faire des comparaisons sur ces types complexes (comme par exemple A==B).
La séquence des composants tient un rôle important dans la définition des types composés. En effet en raison des contraintes d'alignement précitées, les trois structures suivantes n'utiliseront pas la même quantité de mémoire: 1 #include 2 struct fin { 3 char a; 4 char b; 5 char c; 6 char d; 7 float x; 8 float y; 9 float z; 10 }; 11 struct moyen { 12 char a; 13 char b; 14 float x; 15 char c; 16 char d; 17 float y; 18 float z; 19 }; 20 struct large { 21 char a; 22 float x; 23 char b; 24 float y; 25 char c; 26 float z; 27 char d; 28 }; 29 int main(void) { 30 printf("sizeof(char) = %d ", sizeof(char)); 31 printf("sizeof(float) = %d ", sizeof(float)); 32 printf("4 * sizeof(char) + 3 * sizeof(float) = %d ", 4 * sizeof(char) + 3 * sizeof(float)); 33 printf("sizeof(fin) = %d ", sizeof(struct fin)); 34 printf("sizeof(moyen) = %d ", sizeof(struct moyen)); 35 printf("sizeof(large = %d ", sizeof(struct large)); 36 return 0; 37 } donne les valeurs suivantes (linux iX86/AMD): sizeof(char) = 1 sizeof(float) = 4 4 * sizeof(char) + 3 * sizeof(float) = 16 sizeof(fin) = 16 sizeof(moyen) = 20 sizeof(large) = 28 Dans le cas de la structure « fin », la séquence optimise la trace mémoire de la structure. Les 4 caractères sont contigus dans 1 case memoire de 32 bits, suivis de 3 float dont la taille est ici de 4 octets chacuns.

Dans le cas de la structure « large », la trace mémoire est maximale: pour chaque caractère, 4 octets sont occupés pour 1 seul de réellement utilisé.

Dans le cas de la structure « moyen », la trace mémoire n'est pas complètement optimisée et les 2 couple de « char » sont codés sur chacun 4 octets.

A retenir:
  • L'ordre des données définies dans une structure influe sur la taille de la mémoire utilisée afin de respecter les contraintes d'alignement (même si l'architecture n'en possède a priori pas).
  • De même que les types simples, les types complexes constituent un canevas d'interprêtation de la mémoire. Réciproquement, toute zone de mémoire respectant les contraintes d'alignement peut être interprêtée par une structure.

(Table des matières)
Tableaux Les tableaux sont des zones de mémoires réservées et censées rec

 
Liens connexes
· Plus à propos de C
· Nouvelles transmises par Romain_Le_Guen


L'article le plus lu à propos de C:
Programmer un sniffeur (sniffer ?) de deux facons.


Article Rating
Average Score: 4
Votes: 2


Please take a second and vote for this article:

Excellent
Very Good
Good
Regular
Bad


Options

 Format imprimable Format imprimable


PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Page Generation: 2.54 Seconds