Supposons que j’ai une fonction comme ci-dessous:
# cat 003.c int foo(int a, int b) { return a+b; }
Et comstackz-le comme ceci:
gcc -S 003.c
Obtient le résultat d’assemblage suivant:
.file "003.c" .text .globl foo .type foo, @function foo: .LFB2: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: movl %edi, -4(%rbp) movl %esi, -8(%rbp) movl -8(%rbp), %edx movl -4(%rbp), %eax addl %edx, %eax leave ret .LFE2: .size foo, .-foo /* size of the function foo, how to get it?*/
La dernière ligne ci-dessus donne la taille de la fonction. Où le compilateur stocke-t-il la taille? Puis-je obtenir la taille de la fonction d’une manière ou d’une autre dans mon programme d’origine C en utilisant C ou inline asm ?
Les informations sur la taille d’une fonction sont stockées dans les atsortingbuts ELF pour le symbole (nom) correspondant. C exemple de code comment parsingr cela par programme se trouve au bas de la page de gelf_getsym(3ELF)
Solaris pour gelf_getsym(3ELF)
(libelf existe également sous Linux, * BSD et MacOS, vous devez également rechercher le champ st_size
de la structure GElf_Sym
), mais vous pouvez également utiliser objdump / elfdump (Solaris) / readelf (Linux) pour la tâche suivante:
$ objdump -h -d --section = .text foo3.o foo3.o: format de fichier elf64-x86-64 Sections: Nom Idx Taille VMA LMA Fichier sur Algn 0 .text 00000012 0000000000000000 0000000000000000 00000040 2 ** 2 CONTENU, ALLOC, LOAD, READONLY, CODE [...] Déassembly de la section .text: 0000000000000000: 0: 55 push% rbp 1: 48 89 e5 mov% rsp,% rbp 4: 89 7j fc mov% edi, 0xfffffffffffffffc (% rbp) 7: 89 75 f8 mov% esi, 0xfffffffffffffff8 (% rbp) a: 8b 45 f8 mov 0xfffffffffffffff8 (% rbp),% eax d: 03 45 ajouts 0xfffffffffffffffc (% rbp),% eax 10: c9 quitte 11: c3 retq
Ceci est pour une compilation non optimisée de votre code, tandis que la version optimisée est:
$ objdump -h -d --section = .text foo3.o foo3.o: format de fichier elf64-x86-64 Sections: Nom Idx Taille VMA LMA Fichier sur Algn 0 .text 00000004 0000000000000000 0000000000000000 00000040 2 ** 4 CONTENU, ALLOC, LOAD, READONLY, CODE [...] Déassembly de la section .text: 0000000000000000: 0: 8j 04 37 lea (% rdi,% rsi, 1),% eax 3: c3 retq
Notez le changement de “taille” de 0x12
à 4
? C’est ce qui vient de la directive .size
assembler.
L’astuce consistant à essayer d’utiliser un assemblage en ligne pour vous donner des tailles de fonction / des emplacements de code ne tient pas compte du code collé généré par le compilateur (prologs d’entrée de fonction / épilogues de sortie, génération de code en ligne, …), ni pour le compilateur. -orderering inline assembly (gcc est notoire pour le faire), donc ce n’est généralement pas une bonne idée de faire confiance à cela. En fin de compte, cela dépend de ce que vous essayez exactement de faire …
Edit: Quelques références supplémentaires, externes ainsi que sur stackoverflow:
sizeof(function)
Pourquoi ne pas prendre la différence du pointeur de la fonction et l’adresse actuelle à la fin de la fonction? Jetez un coup d’œil à cette question pour récupérer l’adresse IP actuelle: Obtenir l’adresse de l’instruction actuelle pour x86 , peut-être que ce code, volé dans la réponse :
unsigned long get_PC() { unsigned long current_instruction; __asm__ __volatile__ ( "movq 8(%rbp), %rax\n\t" : "=a" (current_instruction) ); return current_instruction; }
ferait l’affaire,