---
# System prepended metadata

title: 「你所不知道的 C 語言：動態連結器篇」 筆記
tags: [System Software, Computer Science]

---

---
title: 「你所不知道的 C 語言：動態連結器篇」 筆記
tags: Computer Science,System Software
description: 2019.08.07
---
「你所不知道的 C 語言：動態連結器篇」 筆記
===
###### 2019.08.07 *Copyright © 2019 by srhuang*

![](https://i.imgur.com/KyaeILQ.png)

[影片](https://youtu.be/7aYVDPuH2uI)
[講義](http://hackfoldr.org/dykc/https%253A%252F%252Fhackmd.io%252Fs%252FHkK7Uf4Ml)
Original by [jserv](http://wiki.csie.ncku.edu.tw/User/jserv)

---
## 跨越程式語言的交流：透過 C 語言

* lingua franca：https://youtu.be/7aYVDPuH2uI?t=34
    * 理解動態連結不僅是重新回顧 C 語言，更是透過橋接語言，深入理解系統運作
* P-code 與 Kenneth Bowles 教授：https://youtu.be/7aYVDPuH2uI?t=228
    * P-code 是種設計來執行於虛擬 CPU 上的機械碼，也就是所謂的 bytecode 的前身，後來 P-code 衍生來稱呼這類虛擬機器，像是 Java 虛擬機器或者 Visual BASIC 編譯出來的中間機械碼。

## 貌似簡單的問題：「如何得知 malloc/free 的呼叫次數？」

* 前言：https://youtu.be/7aYVDPuH2uI?t=476
* 簡單的作法：https://youtu.be/7aYVDPuH2uI?t=604
    * 透過巨集。
    * 沒更換到無法追蹤、C++ new/delete 無法追蹤、函式庫也無法追蹤。
    * 要徹底解決這問題，就需要動用到動態連結器 (dynamic linker)
* 動態連結 malloc_count.c：https://youtu.be/7aYVDPuH2uI?t=820
    * 使用 dlsym obtain address of a symbol in a shared object (malloc).
    * Function designator：將利用 dlsym 取得的 function address 指派給 function symbol name.
    * LD_PRELOAD=/tmp/libmcount.so ls：在執行 ls 之前，會先動態連結 ==libmcount.so==.
    * 這樣的技巧，我們稱為 interpositioning。
* TCMalloc (Google)：https://youtu.be/7aYVDPuH2uI?t=1785
    * glibc 2.3 malloc takes approximately 300 nanoseconds, the TCMalloc implementation takes approximately 50 nanoseconds.
    * Google Heap Checker/Profiler：https://gperftools.github.io/gperftools/heapprofile.html
* Dynamic linker tricks：https://youtu.be/7aYVDPuH2uI?t=2207
    * 幹壞事是進步的原動力。
* Dynamic Linker 簡述：https://youtu.be/7aYVDPuH2uI?t=2625
    * 動態連結器是可以直接執行的。
    * 動態連結器通常會在 /lib/ 目錄下。
    * glibc-abi。
* LD_PRELOAD 環境變數：https://youtu.be/7aYVDPuH2uI?t=3084
    * 需要搭配 dynamic linker。
    * 類似環境變數 PATH。
    * * GNU ld 有個選項 -Bsymbolic-functions 會影響 LD_PRELOAD 的行為
* Symbolism and ELF files：https://youtu.be/7aYVDPuH2uI?t=3333
* 用 LD_PRELOAD 替換動態連結的函式庫：https://youtu.be/7aYVDPuH2uI?t=3506

## “No such file or directory” 可能跟你猜想的不一樣

* 前言：https://youtu.be/7aYVDPuH2uI?t=3553
* linux 核心的程式碼 fs/binfmt_elf.c：https://youtu.be/7aYVDPuH2uI?t=3619
    * https://elixir.bootlin.com/linux/latest/source/fs/binfmt_elf.c
    * SVr4：UNIX System V (five) r4，第一個商業化的 UNIX。
    * load_elf_binary：Linux Kernel 中負責載入 ELF 格式的執行檔。
    * This is the program interpreter used for shared libraries.
    * requesting program interpreter : Dynamic Linker path.
* 延伸閱讀：https://youtu.be/7aYVDPuH2uI?t=4260
    * 《Binary Hacks》
    * ELF Hacks

## 複習 編譯器和最佳化原理

*  Compilation Unit：https://youtu.be/7aYVDPuH2uI?t=4554
    * A compilation unit is C source code that is compiled and treated as one logical unit.
    * 建議 local function 要宣告成 static，因為 Compiler 不能砍掉沒人使用的 non-static global variable。
* Preprocessor：https://youtu.be/7aYVDPuH2uI?t=4859
* DIGITAL UNIX：https://youtu.be/7aYVDPuH2uI?t=4970
* Scoping 的問題：https://youtu.be/7aYVDPuH2uI?t=5120
    * static 只能在同個 Compilation Unit 看得到。
    * Compilation Unit 會阻礙最佳化空間，non-static function 無法確定其他 Compilation Unit 是否有使用到。
    * 解法：LTO (Link Time Optimization)：當 function call 的成本大於執行 function 本身，在連結時期直接展開 function，將會大幅縮減載入時間。
* Modern C：https://youtu.be/7aYVDPuH2uI?t=5848
    * 一旦物件宣告為 static const，那麼編譯器就可以施加更多樣的最佳化策略。
* Shrinking the kernel with link-time optimization：https://youtu.be/7aYVDPuH2uI?t=6194
    * Optimize uClinux for ARM Cortex-M4：https://elinux.org/images/d/d4/Optimize_uClinux_for_ARM_Cortex-M4.pdf
    * Function inlining LTO：效能最佳化。
    * Constant folding LTO：空間最佳化。
    * Skymizer：台灣編譯器最佳化公司。

## Symbol Visibility

* 前言：https://youtu.be/7aYVDPuH2uI?t=6821
    * 預設的情況下，所有的 symbol 都是可以被 export。
* Why is the new C++ visibility support so useful？：https://youtu.be/7aYVDPuH2uI?t=7116
    * C++ Standard Template Library (STL) 產生出來的程式碼往往膨脹很快。
    * It reduces the size of your DSO(Dynamic Shared Object) by 5-20%.
    * you cut out the 60-80% of unnecessary symbols.
    * 需要 compiler and linker 的協助。
    * 使用：__attribute__ ((visibility ("hidden")))
* gcc 和 clang 都支援 visibility 屬性和 -fvisibility 編譯命令：https://youtu.be/7aYVDPuH2uI?t=7628
* Why symbol visibility is good：https://youtu.be/7aYVDPuH2uI?t=7867
    * weak symbol：以其他人為主，若無其他人，則使用自己的。
* sym.c：https://youtu.be/7aYVDPuH2uI?t=8080
    * Bind：GLOBAL / LOCAL / WEAK。

## 「作中學」：從實踐中學習

* min-dl：https://youtu.be/7aYVDPuH2uI?t=10980
* android_crazy_linker (Google)：https://youtu.be/7aYVDPuH2uI?t=11093
    * 讓 android 系統可以載入特定 native code。

## 總結：https://youtu.be/7aYVDPuH2uI?t=11296