Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ABI 是什麼?跟 API 不一樣嗎?

ABI 是什麼?跟 API 不一樣嗎?

儘管 Application Binary Interface (ABI) 通常就比較少人提起,但它的重要性不亞於更常聽到的 Application Programming Interface (API);例如我們到現在還能跑十年前編譯好的程式這件事,就是因爲有 ABI 才有辦法達成(精確地來說是 ABI 相容性的概念)。

這次議程中我們會介紹到底什麼是 ABI、它跟 API 有什麼不同、討論 ABI 相容性及列出 ABI 不相容時會發生什麼事、還有舉出一些 ABI 的實例(Linux Kernel ABI、Python's stable ABI、Foreign Function Interface)。

shunghsiyu

August 01, 2024
Tweet

More Decks by shunghsiyu

Other Decks in Programming

Transcript

  1. ABI 是什麼? 跟 API 不一樣嗎? What is an ABI, and

    how it differs from API? Shung-Hsi Yu COSCUP 2024 1
  2. Shung-Hsi Yu @shunghsiyu 任職於 SUSE Kernel Engineer 維護 SLES &

    openSUSE 作業系統核心裡 BPF 的部分 maintains BPF in SLES & openSUSE kernel 5 自介 About me
  3. 23 保證 Guarantee Python 保證 range(2) 從 0 開始 GitLab

    保證 …/tree 會列出 repo 的所有檔案名稱
  4. 24 保證 Guarantee Python 保證 range(2) 從 0 開始 glibc

    保證 printf() 會寫到 stdout GitLab 保證 …/tree 會列出 repo 的所有檔案名稱
  5. 30 Binary Programming long y_square(struct point *p) { return p->y

    * p->y; } 00000000100001010011010100000011 00000010101001010000010100110011 00000000000000001000000001100111
  6. 31 Binary Programming long y_square(struct point *p) { return p->y

    * p->y; } y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  7. 32 Binary Programming long y_square(struct point *p) { return p->y

    * p->y; } y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  8. 33 Binary Programming long y_square(struct point *p) { return p->y

    * p->y; } y_square: ld a0, 8(a0) mul a0, a0, a0 ret compiler
  9. 38 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  10. 39 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  11. 40 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } 函式庫 shared library
  12. 41 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  13. 42 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } 函式庫 header library header
  14. 43 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  15. 44 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } 應用程式 application
  16. 45 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ...
  17. 47 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ...
  18. 48 // geo-v1.h struct point { long x; long y;

    }; long y_square(struct point *); // geo-v1.c -> geo.so #include <geo-v1.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  19. 49 Binary Programming long y_square(struct point *p) { return p->y

    * p->y; } y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  20. 50 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } long y_square(struct point *p) { return p->y * p->y; } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ... y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  21. 51 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } long y_square(struct point *p) { return p->y * p->y; } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ... y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  22. 53 // geo-v2.h struct point { long x; long y;

    long z; // this is new }; long y_square(struct point *); // geo-v2.c -> geo.so #include <geo-v2.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  23. 54 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } long y_square(struct point *p) { return p->y * p->y; } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ... y_square: ld a0, 8(a0) mul a0, a0, a0 ret
  24. 55 // geo-v3.h struct point { long z; // so

    rebellious long x; long y; }; long y_square(struct point *); // geo-v3.c -> geo.so #include <geo-v3.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  25. 56 Binary Programming int main(void) { struct point p =

    { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); } long y_square(struct point *p) { return p->y * p->y; } main: li a1, 1 sd a1, 0(a0) li a1, 2 sd a1, 8(a0) ... call y_square ... y_square: ld a0, 12(a0) mul a0, a0, a0 ret
  26. 57 // geo-v1.h struct point { long x; // at

    offset 0 long y; // at offset 8 }; long y_square(struct point *); // geo-v2.c -> geo.so #include <geo-v2.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  27. 58 // geo-v2.h struct point { long x; // at

    offset 0 long y; // at offset 8 long z; // at offset 16 }; long y_square(struct point *); // geo-v2.c -> geo.so #include <geo-v2.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  28. 59 // geo-v3.h struct point { long z; // at

    offset 0 long x; // at offset 8 long y; // at offset 16 }; long y_square(struct point *); // geo-v2.c -> geo.so #include <geo-v2.h> long y_square(struct point *p) { return p->y * p->y; } // main.c -> main #include <geo-v1.h> int main(void) { struct point p = { .x = 1, .y = 2, }; /* you get y2 == 4 */ long y2 = y_square(&p); }
  29. 61 // geo.h struct point; // opaque pointer struct point

    *init(); void set_x(struct point *, long); void set_y(struct point *, long); // main.c #include <geo.h> int main(void) { struct point *p = init(); set_x(p, 1); set_y(p, 2); long y2 = y_square(p); }
  30. 66 $ rpm -q --provides glibc libc.so.6(GLIBC_2.10)(64bit) libc.so.6(GLIBC_2.11)(64bit) ... libc.so.6(GLIBC_2.39)(64bit)

    libc.so.6(GLIBC_2.4)(64bit) libc.so.6(GLIBC_2.5)(64bit) libc.so.6(GLIBC_2.6)(64bit) libc.so.6(GLIBC_2.7)(64bit) libc.so.6(GLIBC_2.8)(64bit) libc.so.6(GLIBC_2.9)(64bit)
  31. 77 Arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 i386 ebx

    ecx edx esi edi ebp x86-64 rdi rsi rdx r10 r8 r9 aarch64 x0 x1 x2 x3 x4 x5 riscv a0 a1 a2 a3 a4 a5
  32. 78 Arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 i386 ebx

    ecx edx esi edi ebp x86-64 rdi rsi rdx r10 r8 r9 aarch64 x0 x1 x2 x3 x4 x5 riscv a0 a1 a2 a3 a4 a5
  33. 79 Arch/ABI arg1 arg2 arg3 arg4 i386 ebx ecx edx

    esi x86-64 rdi rsi rdx r10 aarch64 x0 x1 x2 x3 riscv a0 a1 a2 a3
  34. 109 int openat(int dirfd, const char *pathname, int flags, ...

    /* mode_t mode */ ); int openat2(int dirfd, const char *pathname, const struct open_how *how, size_t size);
  35. 110 int openat(int dirfd, const char *pathname, int flags, ...

    /* mode_t mode */ ); int openat2(int dirfd, const char *pathname, const struct open_how *how, size_t size);
  36. 120

  37. 128

  38. 132 #include <stdio.h> int main(void) { /* Can you use

    printf in Python? */ printf("Hello %s!\n", "world"); }
  39. 133 #!/usr/bin/python3 import ctypes # We can load _any_ shared

    library # Let's use the ubiquitous libc here libc = ctypes.CDLL('libc.so.6') # This is the _exact_ same printf you # get in C libc.printf(b'Hello %s!\n', b'world')
  40. 135 Ruby → C Java → C Go → C

    Python → Swift Julia → Rust
  41. 138 eBPF BoF Day 2, 12:20-13:20 @TR613 Linux Kernel Development

    Day 2, 13:30-14:10 @TR411 Bird of a Feathers @COSCUP
  42. 142

  43. 143