• Aucun résultat trouvé

Pointeurs = adresse m´emoire #i n c l u d e

N/A
N/A
Protected

Academic year: 2022

Partager "Pointeurs = adresse m´emoire #i n c l u d e"

Copied!
17
0
0

Texte intégral

(1)

Pointeurs = adresse m´ emoire

#i n c l u d e <a v r / i o . h>

i n t main ( ){PORTB=0x 4 2 ;}

se compile avec avr-gcc -mmcu=atmega32u4 ...

1. locate avr/io.h : /usr/lib/avr/include/avr/io.h 2. dans /usr/lib/avr/include/avr/io.h :

# e l i f d e f i n e d ( AVR ATmega32U4 )

# i n c l u d e <a v r / iom32u4 . h>

3. dans /usr/lib/avr/include/avr/iom32u4.h :

#d e f i n e PORTB S F R I O 8 ( 0 x 0 5 )

4. dans /usr/lib/avr/include/avr/sfr defs.h

#d e f i n e MMIO BYTE ( mem addr ) (∗(v o l a t i l e u i n t 8 t ∗) ( mem addr ) )

#d e f i n e S F R I O 8 ( i o a d d r ) MMIO BYTE ( ( i o a d d r ) + SFR OFFSET )

Conclusion : PORTB=0x42 devient

1

(*(volatile uint8 t *)((0x05) + 0x20))=0x42;

1. avr-gcc -E

1 / 17

(2)

Passage de param` etres

Par valeur et par r´ ef´ erence (pointeur)

#i n c l u d e <s t d i o . h>

i n t f p (i n t∗ i ) {(∗i ) ++;r e t u r n(∗i ) ;} i n t f v (i n t i ) {i ++;r e t u r n( i ) ;}

i n t main ( ) {i n t i =3;

p r i n t f (" % d % d % d \ n ", i , f v ( i ) , i ) ; p r i n t f (" % d % d % d \ n ", i , f p (& i ) , i ) ; }

2 / 17

(3)

Passage de param` etres

Par valeur et par r´ ef´ erence (pointeur)

#i n c l u d e <s t d i o . h>

i n t f p (i n t∗ i ) {(∗i ) ++;r e t u r n(∗i ) ;} i n t f v (i n t i ) {i ++;r e t u r n( i ) ;}

i n t main ( ) {i n t i =3;

p r i n t f (" % d % d % d \ n ", i , f v ( i ) , i ) ; p r i n t f (" % d % d % d \ n ", i , f p (& i ) , i ) ; }

$ gcc -Wall -o t t.c

$ ./t 3 4 3 4 4 3

Les arguments de printf() sont ´ evalu´ es de droite ` a gauche sur x86 ! (mais ce comportement n’est pas standardis´ e)

Exemple du compilateur LLVM (compilateur clang) :

$ clang -Wall -o tt t.c

$ ./tt 3 4 3 3 4 4

3 / 17

(4)

Passage de param` etres

´ Economiser ressources (& temps) par les pointeurs sur les structures

#i n c l u d e <s t d i o . h>

#i n c l u d e <s t d l i b . h>

#i n c l u d e <t i m e . h> // u l i m i t −a : s t a c k s i z e s t r u c t m {i n t r e [ 1 0 2 4∗9 2 4 ] ;}; // ( k b y t e s , −s ) 8192

// 1024 x 1 0 2 4 s e g f a u l t e c a r ∗2∗ c o p i e s de m v o i d f 1 (s t r u c t m ∗a ) {a−>r e [ 1 ] = a−>r e [ 1 ] + 1 ;} // 2 . . 1 0 0 1 v o i d f 2 (s t r u c t m a ) {a . r e [ 1 ] = a . r e [ 1 ] + 1 ;} // t j s 2 i n t main ( )

{t i m e t t 1 , t 2 , t 3 ; i n t k ; s t r u c t m mat ;

mat . r e [ 1 ] = 1 ; t i m e (& t 1 ) ;

f o r ( k =0; k<1000; k++) f 1 (&mat ) ; t i m e (& t 2 ) ; f o r ( k =0; k<1000; k++) f 2 ( mat ) ; t i m e (& t 3 ) ;

p r i n t f (" t1 =% d t2 =% d \ r \ n ", t 2−t 1 , t 3−t 2 ) ; // t 1 =0 t 2 =8 }

TIME(2) Linux Programmer’s Manual TIME(2)

NAME

time - get time in seconds SYNOPSIS

#include <time.h>

time_t time(time_t *t); 4 / 17

(5)

Passage de param` etres

#i n c l u d e <s t d i o . h>

i n t main ( ) {i n t a =8 , b =5;

p r i n t f (" % d ", a∗b ) ; }

gcc -S fichier.c

movl $8, -4(%rbp) movl $5, -8(%rbp) movl -4(%rbp), %eax imull -8(%rbp), %eax movl %eax, %esi tandis que

gcc -O2 -S fichier.c movl $40, %esi gcc a pr´ ecalcul´ e le r´ esultat

5 / 17

(6)

Types et endianness

#i n c l u d e <s t d i o . h>

#i n c l u d e <a r p a / i n e t . h> // / u s r / i n c l u d e / n e t i n e t / i n . h l o n g main ( )

{l o n g i =0x 1 2 3 4 5 6 7 8 ; l o n g ∗i i ;

c h a r c c [ 8 ] ={1 , 2 , 3 , 4 , 5 , 6 , 7 , 8}; c h a r ∗c ;

p r i n t f (" % d \ n ",s i z e o f( i ) ) ; c =(c h a r∗)& i ;

p r i n t f (" % x % x % x % x \ n ", c [ 0 ] , c [ 1 ] , c [ 2 ] , c [ 3 ] ) ; // i n t e r n e t i s b i g e n d i a n : MSB on l o w e s t a d d r e s s // x 8 6 i s l i t t l e e n d i a n : LSB on l o w e s t a d d r e s s

i i =(l o n g∗) c c ; p r i n t f (" % x \ n ",∗i i ) ;

p r i n t f (" % x \ n ", h t o n l (∗i i ) ) ; }

6 / 17

(7)

Types et endianness

#i n c l u d e <s t d i o . h>

#i n c l u d e <a r p a / i n e t . h> // / u s r / i n c l u d e / n e t i n e t / i n . h l o n g main ( )

{i n t i =0x 1 2 3 4 5 6 7 8 ; i n t ∗i i ;

c h a r c c [ 8 ] ={1 , 2 , 3 , 4 , 5 , 6 , 7 , 8}; c h a r ∗c ;

p r i n t f (" % d \ n ",s i z e o f( i ) ) ; c =(c h a r∗)& i ;

p r i n t f (" % x % x % x % x \ n ", c [ 0 ] , c [ 1 ] , c [ 2 ] , c [ 3 ] ) ; // i n t e r n e t i s b i g e n d i a n : MSB on l o w e s t a d d r e s s // x 8 6 i s l i t t l e e n d i a n : LSB on l o w e s t a d d r e s s

i i =(i n t∗) c c ;

p r i n t f (" % x \ n ",∗i i ) ;

p r i n t f (" % x \ n ", h t o n l (∗i i ) ) ; }

8

78 56 34 12 4030201 1020304

sur model name : Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz

7 / 17

(8)

Passage de param` etres de type arbitraire

Passage de param` etre lors de la cr´ eation de tˆ ache dans FreeRTOS

2

BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,

const char * const pcName, unsigned short usStackDepth, void *pvParams, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask

);

void vTaskCode( void * pvParameters ) { for( ;; ) { /* Task code goes here. */ } }

Gestion des interruptions dans le noyau Linux

3

int request_irq(unsigned int irq,

irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags,

const char *dev_name, void *dev_id);

void free_irq(unsigned int irq, void *dev_id);

Passage de param` etre par void* : on fournit l’emplacement m´ emoire contenant le param` etre sans en pr´ eciser l’organisation.

2. https://www.freertos.org/a00125.html

3. https://www.oreilly.com/library/view/linux-device-drivers/0596005903/ch10.html

8 / 17

(9)

Passage de param` etres de type arbitraire

#i n c l u d e <s t d i o . h>

v o i d m a f o n c t i o n (v o i d∗ param ) {l o n g ∗p=(l o n g∗) param ;

p r i n t f (" % lx ",∗p ) ; }

i n t main ( ) {l o n g l =0x 4 2 ;

m a f o n c t i o n (& l ) ; }

$ gcc -Wall -o t t.c

$ ./t 42

Comment passer 4 entiers en argument du mˆ eme prototype de fonction ?

9 / 17

(10)

Passage de param` etres de type arbitraire

#i n c l u d e <s t d i o . h>

s t r u c t mon param {l o n g p1 ;l o n g p2 ;l o n g p3 ;l o n g p4 ;}; v o i d m a f o n c t i o n (v o i d∗ param )

{s t r u c t mon param ∗p=(s t r u c t mon param∗) param ;

p r i n t f (" % lx % lx % lx % lx \ n ", p−>p1 , p−>p2 , p−>p3 , p−>p4 ) ; }

i n t main ( )

{s t r u c t mon param p ={. p1=0x42 , . p2=0x43 , . p3=0x44 , . p4=0x 4 5}; m a f o n c t i o n (&p ) ;

}

$ gcc -Wall -o t t.c

$ ./t 42 43 44 45

La notation (utilis´ee par exemple dans la d´eclaration desfopsdu noyau Linux4) est identique `a s t r u c t m o n p a r a m e t r e p ;

p . p1=0x 4 2 ; p . p2=0x 4 3 ; p . p3=0x 4 4 ; p . p4=0x 4 5 ;

4. https://www.tldp.org/LDP/lkmpg/2.4/html/c577.htm: “you should be aware that any member of the structure which you don’t explicitly assign will be initialized to NULL by gcc”

10 / 17

(11)

Pointeurs de fonctions

Une fonction n’est qu’une adresse m´ emoire ` a laquelle saute le processeur (assignation du PC) lors de son appel :

#i n c l u d e <s t d i o . h>

i n t f 1 (v o i d) {r e t u r n( 1 ) ;}

i n t f 2 (v o i d) {r e t u r n( 2 ) ;}

i n t f 3 (i n t i ,i n t j ) {r e t u r n( i +j ) ;} i n t main ( )

{i n t (∗m a f o n c t i o n ) (v o i d) ; i n t (∗f o n c t i o n ) (i n t,i n t) ;

m a f o n c t i o n=&f 1 ; p r i n t f (" % d ", ( m a f o n c t i o n ) ( ) ) ; m a f o n c t i o n=&f 2 ; p r i n t f (" % d ", ( m a f o n c t i o n ) ( ) ) ; f o n c t i o n=&f 3 ; p r i n t f (" % d \ n ", ( f o n c t i o n ) ( 1 , 2 ) ) ; }

$ gcc -Wall -o function function.c

$ ./function 1 2 3

⇒ possibilit´ e de dynamiquement modifier le comportement d’un programme au cours de son ex´ ecution (e.g. pour s’adapter ` a un nouvel environnement)

11 / 17

(12)

Pointeurs de fonctions

Exemple d’utilisation de pointeurs de fonctions :

5

/∗ F u n c t i o n s p o i n t e r w h i c h a r e i n i t i a l i z e d i n e M B I n i t ( ) . D e p e n d i n g on t h e mode (RTU o r A S C I I ) t h e a r e s e t t o t h e c o r r e c t i m p l e m e n t a t i o n s . ∗/

s t a t i c pvMBFrameStart pvMBFrameStartCur ;

s t a t i c pvMBFrameStop pvMBFrameStopCur ;

c a s e MB RTU :

pvMBFrameStartCur = eMBRTUStart ;

pvMBFrameStopCur = eMBRTUStop ;

. . .

c a s e MB ASCII :

pvMBFrameStartCur = e M B A S C I I S t a r t ;

pvMBFrameStopCur = eMBASCIIStop ;

peMBFrameSendCur = eMBASCIISend ;

avec

6

t y p e d e f v o i d ( ∗pvMBFrameStart ) ( v o i d ) ; t y p e d e f v o i d ( ∗pvMBFrameStop ) ( v o i d ) ;

fournit la capacit´ e de fonctions polymorphiques (C++) au C.

5. https://github.com/cwalter-at/freemodbus/modbus/mb.c

6. https://github.com/cwalter-at/freemodbus/modbus/include/mbframe.h

12 / 17

(13)

Injection de code 7

#i n c l u d e <s y s /mman . h> // m p r o t e c t

#i n c l u d e <s t d l i b . h> // m a l l o c

#i n c l u d e <s t d i o . h> // p r i n t f i n t main ( )

{i n t k ;

u n s i g n e d c h a r i n s t r u c t i o n s [ 6 ] ={0 xb8 , 0 x2a , 0 x00 , 0 x00 , 0 x00 , 0 x c 3}; // o u t p u t o f → ,→objdump

m p r o t e c t ( (l o n g l o n g) i n s t r u c t i o n s & 0 x f f f f f f f f f f f f f 0 0 0 , 1 1 , PROT EXEC | → ,→PROT READ | PROT WRITE ) ;

i n t (∗f o o ) (v o i d) = (i n t (∗) ( ) ) i n s t r u c t i o n s ; i n t a=f o o ( ) ;

p r i n t f (" % d \ n ", a ) ; }

avec le code r´ esultant de objdump sur un exemple simple

i n t f u n c t i o n ( ) {r e t u r n 4 2 ;}

i n t main ( )

{i n t i =f u n c t i o n ( ) ; }

7. https://fosdem.org/2022/schedule/event/riscvadventures/attachments/slides/4815/export/events/

attachments/riscvadventures/slides/4815/Slides.pdf

13 / 17

(14)

Exemple du noyau Linux

Une structure file operations contient les pointeurs de fonctions vers les impl´ ementations des divers appels syst` eme

Exemple : drivers/acpi/battery.c

s t a t i c s t r u c t a c p i d r i v e r a c p i b a t t e r y d r i v e r = { . name = " b a t t e r y ",

. c l a s s = ACPI BATTERY CLASS , . i d s = b a t t e r y d e v i c e i d s ,

. f l a g s = ACPI DRIVER ALL NOTIFY EVENTS , . o p s = {. add = a c p i b a t t e r y a d d ,

. r e m o v e = a c p i b a t t e r y r e m o v e , . n o t i f y = a c p i b a t t e r y n o t i f y , },

. d r v . pm = &a c p i b a t t e r y p m , };

ou drivers/char/mem.c

s t a t i c c o n s t s t r u c t f i l e o p e r a t i o n s p o r t f o p s = { . l l s e e k = m e m o r y l s e e k ,

. r e a d = r e a d p o r t , . w r i t e = w r i t e p o r t , . o p e n = o p e n p o r t , };

s t a t i c i n t o p e n p o r t (s t r u c t i n o d e ∗i n o d e , s t r u c t f i l e ∗f i l p )

{r e t u r n c a p a b l e ( CAP SYS RAWIO ) ? 0 : −EPERM;} 14 / 17

(15)

Allocation de pointeurs ? !

NE JAMAIS FAIRE C ¸ A !

#i f n d e f A V R

#i n c l u d e <s t d i o . h>

#e n d i f

c h a r ∗ m a f o n c t i o n (i n t i )

{c h a r ∗c ;i f ( i ==0) c=" 8 7 6 5 4 3 2 1 "; e l s e c=" 1 2 3 4 5 6 7 8 ";}

i n t main ( )

{i n t k ;v o l a t i l e c h a r ∗c ; c=m a f o n c t i o n ( 0 ) ;

#i f n d e f A V R

f o r ( k =0; k<8; k++) p r i n t f (" % c ", c [ k ] ) ; p r i n t f (" \ n ") ;

#e n d i f }

$ gcc -o pointer pointer.c

$ ./pointer 87654321

15 / 17

(16)

Analyse du code assembleur

$ avr-gcc -o pointer pointer.c

$ file pointer

pointer: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped

$ avr-objdump -dStD pointer # D pour data section

00000018 <ma_fonction>:

18: cf 93 push r28 1a: df 93 push r29

1c: 00 d0 rcall .+0 ; alloc 2 bytes on stack 1e: 00 d0 rcall .+0 ; re 2 bytes on stack (c*) 20: cd b7 in r28, 0x3d ; read from stack 22: de b7 in r29, 0x3e ; read from stack 24: 9c 83 std Y+4, r25 ; 0x04 26: 8b 83 std Y+3, r24 ; 0x03 28: 8b 81 ldd r24, Y+3 ; 0x03 2a: 9c 81 ldd r25, Y+4 ; 0x04 2c: 89 2b or r24, r25

2e: 29 f4 brne .+10 ; 0x3a <ma_fonction+0x22>

30: 80 e6 ldi r24, 0x60 ; contenu de x60 en RAM 32: 90 e0 ldi r25, 0x00 ; 0

34: 9a 83 std Y+2, r25 ; 0x02 36: 89 83 std Y+1, r24 ; 0x01

38: 04 c0 rjmp .+8 ; 0x42 <__SREG__+0x3>

3a: 89 e6 ldi r24, 0x69 ; contenu de x69 en RAM 3c: 90 e0 ldi r25, 0x00 ; 0

3e: 9a 83 std Y+2, r25 ; renvoi du pointeur 40: 89 83 std Y+1, r24 ; contenu dans {r25,r24}

42: 00 00 nop

44: 0f 90 pop r0 ; pop 4 bytes du stack 46: 0f 90 pop r0

48: 0f 90 pop r0 4a: 0f 90 pop r0 4c: df 91 pop r29 4e: cf 91 pop r28 50: 08 95 ret

Disassembly of section .data:

00800060 <__data_start>:

800060: 38 37 cpi r19, 0x78 ; 120 800062: 36 35 cpi r19, 0x56 ; 86 800064: 34 33 cpi r19, 0x34 ; 52 800066: 32 31 cpi r19, 0x12 ; 18 800068: 00 31 cpi r16, 0x10 ; 16 80006a: 32 33 cpi r19, 0x32 ; 50 80006c: 34 35 cpi r19, 0x54 ; 84 80006e: 36 37 cpi r19, 0x76 ; 118 800070: 38 00 .word 0x0038 ; ????

avec Y (R29 :R28) : stocke l’adresse du tableau dans {Y+1,Y+2}

16 / 17

(17)

Analyse du code assembleur

$ avr-gcc -o pointer pointer.c

$ file pointer

pointer: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped

$ avr-objdump -dStD pointer # D pour data section

00000052 <main>:

52: cf 93 push r28

54: df 93 push r29

56: 00 d0 rcall .+0 ; 0x58 <main+0x6>

58: cd b7 in r28, 0x3d ; 61

5a: de b7 in r29, 0x3e ; 62

5c: 80 e0 ldi r24, 0x00 ; 0

5e: 90 e0 ldi r25, 0x00 ; 0

60: db df rcall .-74 ; 0x18 <ma_fonction>

62: 9a 83 std Y+2, r25 ; 0x02

64: 89 83 std Y+1, r24 ; 0x01

main relit {Y+1,Y+2} qui contient l’adresse du tableau en m´ emoire (pointeur)

’8’ ’7’ ’6’ ’5’ ’4’ ’3’ ’2’ ’1’ 0 ’1’ ’2’ ’3’ ’4’ ’5’ ’6’ ’7’ ’8’

0x800060

c sinon c si i==0

https://www.nongnu.org/avr- libc/user- manual/mem_sections.htmlNote that addr must be offset by adding 0x800000 to the real SRAM address so that the linker knows that the address is in the SRAM memory space. Thus, if you want the .data section to start at 0x1100, pass 0x801100 at the address to the linker.

17 / 17

Références

Documents relatifs

pour L n,p tel que deux éléments suessifs dièrent d'une et une seule position. L ′ n,p ) est l'ensemble des mots de Fibonai (resp. Luas) ayant.. un nombre impair

N’utilisez surtout pas la notation ln(z) si z n’est pas un r´ eel strictement

Il s’agit d’un devoir suppl´ ementaire qui ne sera pas

L’objet du probl` eme est d’´ etudier quelques propri´ et´ es d’un estimateur du param` etre p d’une loi g´ eom´ etrique..

Universit´ e Pierre &amp; Marie Curie Licence de Math´ ematiques L3 LM367 – Analyse complexe

Enoncer le th´ eor` eme de d´ erivation d’une int´ egrale ` a param` etre de

Soit F un sous espace vectoriel ferm´ e d’un espace de Hilbert muni d’un produit scalaire h., .i et d’une

[r]