• [^] # Re: Je ne pas confondre ABI et API !

    Posté par . En réponse au journal Linux et les pilotes binaires.... Évalué à 10.

    Je vais essayer de préciser, pour ceux qui ont du mal avec ces notions (et j'espère ne pas trop me tromper).

    Dans le noyau on trouve principalement comme types de données des types de base (char, short, int, ...), des structs et des tableaux, L'API des sous-ensembles du noyau (pci, usb, vm, ...) définit un ensemble de de fonctions opérant sur ces types. Comme le précise inico, elle est plutôt stable.

    Quand ces types sont utilisés dans un code source, on les appelle par leur nom. Pour les types de bases, ils peuvent être "aliasés" (avec un typedef) quand ils ne sont pas manipulés directement par l'utilisateur de l'API (en général). Pour les structs, chacun de ses membres a un nom. Pour les tableaux, on indique un indice qui désigne l'élément d'un certain type (de base, ou un struct, ou un autre tableau).

    Tout ça, avec les fonctions, forme l'API, c'est compréhensible par un humain car c'est du code _source_. Le nom des types, des membres des structs restent les même pour chaque version majeure de l'API.

    Vient ensuite l'étape de la compilation. C'est alors que tout se corse pour l'humain : les types "aliasés" sont "traduis" en leur type de base, les membres des structs deviennent des offsets par rapport à l'adresse de base de la struct, les indices des tableaux sont aussi des offsets par rapport au début du tableau. Heureusement qu'on a gardé le linkage dynamique des fonctions (qui gardent donc leur nom et ne deviennent pas (directement) des nombres mais restent des symboles) sinon tout cet étalage de nombres vu par un humain parraitrait un beau bordel (ceux qui suivent jusqu'ici doivent se dire que je suis maso de ne pas déjà trouver ça un beau bordel, mais SI, l'assembleur c'est bô).

    Et c'est là que ça se corse pour les drivers binaires. La traduction précédente est effectuée en ayant une certaine définition de ces types & structs. Si un alias d'un type change (par exemple size_t devient unsigned short au lieu d'unsigned int) alors la "traduction" en code binaire ne sera pas la même, ou alors si un membre d'une struct est ajouté (même s'il ne fait pas partie de l'API, mais est utilisé en interne par exemple), tous les offsets de cette structure vont changer (ainsi que sa taille, pensez au sizeof()), ou si le types d'un tableau change, les offsets seront calculés différemment (je rappelle que ((char*)foo)[2] donne un résultat complètement différent de ((int *)foo)[2], même s'ils sont castés vers le même type après).

    Et tout cela SANS que l'API ait changé. Une simple recompilation aurait suffit pour un driver dont on a les sources.

    Donc l'ABI est complètement différente de l'API, merci inico de l'avoir rappelé.