链接

链接可重定位目标文件

hello.c

#include <stdio.h>

void hello(void) {
    printf("hello\n");
}

main.c

void hello(void);

int main() {
    hello();
    return 0;
}
  1. 生成可重定位目标文件 clang -c main.c hello.c
  2. 链接
    SDK=`xcrun --show-sdk-path -sdk macosx`
    ld main.o hello.o -lSystem -L $SDK/usr/lib
    

链接静态库

  1. 生成可重定位目标文件 clang -c main.c hello.c
  2. 生成静态库 ar rcs libhello.a hello.o
  3. 链接
    SDK=`xcrun --show-sdk-path -sdk macosx`
    ld main.o -lhello -L. -lSystem -L $SDK/usr/lib
    

链接动态库

  1. 生成动态库(共享目标文件)clang -shared -fpic -o libhello.so hello.c
  2. 链接
    SDK=`xcrun --show-sdk-path -sdk macosx`
    ld main.o -lhello -L. -lSystem -L $SDK/usr/lib
    

运行时加载动态库

import Foundation

let handle = dlopen("./libhello.so", RTLD_LAZY)
if let hello = dlsym(handle, "hello") {
    let hello = unsafeBitCast(hello, to: (@convention(c) () -> Void).self)
    hello()
    dlclose(handle)
}

打桩

编译时打桩

// myabs.c
#include <stdlib.h>
#include <stdio.h>

int myabs(int x) {
    printf("called abs\n");
    return abs(x);
}
// stdlib.h
#define abs(x) myabs(x)

int myabs(int x);
// main.c
#include <stdlib.h>
#include <stdio.h>

int main() {
    int x = abs(-1);
    printf("%d\n", x);
    return 0;
}
  1. clang -c myabs.c
  2. clang -I. main.c myabs.o