Skip to content

Commit d70ce01

Browse files
committed
build: Add FreeBSD support
Signed-off-by: Akira Moroo <[email protected]>
1 parent ead71cb commit d70ce01

File tree

5 files changed

+144
-62
lines changed

5 files changed

+144
-62
lines changed

.github/workflows/build.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ jobs:
3232
make fmt
3333
make -C apps/basic fmt
3434
test -z "$(git status --porcelain)"
35+
freebsd-build:
36+
name: FreeBSD Build
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Code checkout
40+
uses: actions/checkout@v4
41+
with:
42+
fetch-depth: 0
43+
- name: Build on FreeBSD
44+
uses: vmactions/freebsd-vm@v1
45+
with:
46+
arch: aarch64
47+
usesh: true
48+
prepare: |
49+
pkg install -y llvm
50+
run: |
51+
make clean
52+
make -C apps/basic clean
53+
make
54+
make -C apps/basic
55+
make fmt
56+
make -C apps/basic fmt
57+
test -z "$(git status --porcelain)"
3558
android-build:
3659
name: Android Cross Build
3760
runs-on: ubuntu-latest

Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ PROGS = libsvchook.so
66

77
CLANG_FORMAT ?= clang-format
88

9+
SYSCALL_RECORD ?= 0
10+
911
CLEANFILES = $(PROGS) *.o *.d
1012

1113
CFLAGS = -O3
@@ -16,14 +18,12 @@ CFLAGS += -Wall
1618
CFLAGS += -Wunused-function
1719
CFLAGS += -Wextra
1820
CFLAGS += -fPIC
21+
CFLAGS += -DSUPPLEMENTAL__SYSCALL_RECORD=$(SYSCALL_RECORD)
1922

20-
ifeq ($(SYSCALL_RECORD), 1)
21-
CFLAGS += -DSUPPLEMENTAL__SYSCALL_RECORD
22-
endif
23-
23+
LIBDL ?= -ldl
2424
LDFLAGS += -shared
2525
LDFLAGS += -rdynamic
26-
LDFLAGS += -ldl
26+
LDFLAGS += $(LIBDL)
2727

2828
C_SRCS = main.c
2929
OBJS = $(C_SRCS:.c=.o)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Read [my blog post (ja)](https://retrage.github.io/2024/07/31/svc-hook.html/) fo
1414

1515
## Target Platform
1616

17-
svc-hook supports ARM64 Linux.
17+
svc-hook supports ARM64 Linux and FreeBSD.
1818

1919
## Build
2020

apps/basic/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ OBJS = $(C_SRCS:.c=.o)
2424
all: $(PROGS)
2525

2626
$(PROGS): $(OBJS)
27-
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
27+
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
2828

2929
clean:
3030
-@rm -rf $(CLEANFILES)

main.c

Lines changed: 114 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,17 @@
1818
#include <sys/stat.h>
1919
#include <unistd.h>
2020

21-
#ifdef SUPPLEMENTAL__SYSCALL_RECORD
21+
#ifdef __FreeBSD__
22+
#define PROCFS_MAP "/proc/self/map"
23+
#else
24+
#define PROCFS_MAP "/proc/self/maps"
25+
#endif
26+
27+
#ifndef SUPPLEMENTAL__SYSCALL_RECORD
28+
#define SUPPLEMENTAL__SYSCALL_RECORD 0
29+
#endif
30+
31+
#if SUPPLEMENTAL__SYSCALL_RECORD
2232
/*
2333
* SUPPLEMENTAL: syscall record without syscalls
2434
*/
@@ -203,7 +213,7 @@ static long (*hook_fn)(int64_t a1, int64_t a2, int64_t a3, int64_t a4,
203213
long syscall_hook(int64_t x0, int64_t x1, int64_t x2, int64_t x3, int64_t x4,
204214
int64_t x5, int64_t x8, /* syscall NR */
205215
int64_t retptr) {
206-
#ifdef SUPPLEMENTAL__SYSCALL_RECORD
216+
#if SUPPLEMENTAL__SYSCALL_RECORD
207217
bm_increment(x8);
208218
#endif /* SUPPLEMENTAL__SYSCALL_RECORD */
209219
return hook_fn(x0, x1, x2, x3, x4, x5, x8, retptr);
@@ -498,72 +508,121 @@ static void scan_exec_code(char *code, size_t code_size, int mem_prot,
498508
close(fd);
499509
}
500510

501-
/* entry point for binary scanning */
511+
#ifdef __FreeBSD__
512+
/* entry point for binary scanning on FreeBSD */
502513
static void scan_code(void) {
503514
LIST_INIT(&head);
504515

505516
FILE *fp = NULL;
506517
/* get memory mapping information from procfs */
507-
assert((fp = fopen("/proc/self/maps", "r")) != NULL);
508-
{
509-
char buf[4096];
510-
while (fgets(buf, sizeof(buf), fp) != NULL) {
511-
/* we do not touch stack memory */
512-
if (strstr(buf, "[stack]") != NULL) {
513-
continue;
514-
}
515-
int i = 0;
516-
char addr[65] = {0};
517-
int64_t addr_start = 0;
518-
int64_t addr_end = 0;
519-
int mem_prot = 0;
520-
char *c = strtok(buf, " ");
521-
while (c != NULL) {
522-
switch (i) {
523-
case 0:
524-
strncpy(addr, c, sizeof(addr) - 1);
525-
break;
526-
case 1: {
527-
for (size_t j = 0; j < strlen(c); j++) {
528-
if (c[j] == 'r') mem_prot |= PROT_READ;
529-
if (c[j] == 'w') mem_prot |= PROT_WRITE;
530-
if (c[j] == 'x') mem_prot |= PROT_EXEC;
531-
}
532-
size_t k = 0;
533-
for (k = 0; k < strlen(addr); k++) {
534-
if (addr[k] == '-') {
535-
addr[k] = '\0';
536-
break;
537-
}
538-
}
539-
addr_start = strtol(&addr[0], NULL, 16);
540-
addr_end = strtol(&addr[k + 1], NULL, 16);
541-
} break;
542-
case 5: {
543-
char *path = NULL;
544-
size_t path_len = 0;
545-
/* get the path of the code */
546-
if (c[0] == '/') {
547-
path = strndup(c, sizeof(buf) - 1);
548-
path_len = strnlen(path, sizeof(buf) - 1);
549-
path[path_len - 1] = '\0';
550-
}
551-
/* scan code if the memory is executable */
518+
assert((fp = fopen(PROCFS_MAP, "r")) != NULL);
519+
char buf[4096];
520+
while (fgets(buf, sizeof(buf), fp) != NULL) {
521+
/* we do not touch stack memory */
522+
if (strstr(buf, "[stack]") != NULL) {
523+
continue;
524+
}
525+
int mem_prot = 0;
526+
int i = 0;
527+
char from_addr[65] = {0};
528+
char to_addr[65] = {0};
529+
char *c = strtok(buf, " ");
530+
while (c != NULL) {
531+
switch (i) {
532+
case 0:
533+
strncpy(from_addr, c, sizeof(from_addr) - 1);
534+
break;
535+
case 1:
536+
strncpy(to_addr, c, sizeof(to_addr) - 1);
537+
break;
538+
case 5:
539+
for (size_t j = 0; j < strlen(c); j++) {
540+
if (c[j] == 'r') mem_prot |= PROT_READ;
541+
if (c[j] == 'w') mem_prot |= PROT_WRITE;
542+
if (c[j] == 'x') mem_prot |= PROT_EXEC;
543+
}
544+
break;
545+
case 9:
546+
if (strncmp(c, "COW", 3) == 0) {
547+
int64_t from = strtol(&from_addr[0], NULL, 16);
548+
int64_t to = strtol(&to_addr[0], NULL, 16);
552549
if (mem_prot & PROT_EXEC) {
553-
scan_exec_code((char *)addr_start, (size_t)addr_end - addr_start,
554-
mem_prot, path);
550+
scan_exec_code((char *)from, (size_t)to - from, mem_prot, NULL);
551+
}
552+
}
553+
break;
554+
}
555+
if (i == 9) break;
556+
c = strtok(NULL, " ");
557+
i++;
558+
}
559+
}
560+
fclose(fp);
561+
}
562+
#else
563+
/* entry point for binary scanning on Linux */
564+
static void scan_code(void) {
565+
LIST_INIT(&head);
566+
567+
FILE *fp = NULL;
568+
/* get memory mapping information from procfs */
569+
assert((fp = fopen(PROCFS_MAP, "r")) != NULL);
570+
char buf[4096];
571+
while (fgets(buf, sizeof(buf), fp) != NULL) {
572+
/* we do not touch stack memory */
573+
if (strstr(buf, "[stack]") != NULL) {
574+
continue;
575+
}
576+
int mem_prot = 0;
577+
int i = 0;
578+
char addr[65] = {0};
579+
int64_t addr_start = 0;
580+
int64_t addr_end = 0;
581+
char *c = strtok(buf, " ");
582+
while (c != NULL) {
583+
switch (i) {
584+
case 0:
585+
strncpy(addr, c, sizeof(addr) - 1);
586+
break;
587+
case 1:
588+
for (size_t j = 0; j < strlen(c); j++) {
589+
if (c[j] == 'r') mem_prot |= PROT_READ;
590+
if (c[j] == 'w') mem_prot |= PROT_WRITE;
591+
if (c[j] == 'x') mem_prot |= PROT_EXEC;
592+
}
593+
size_t k = 0;
594+
for (k = 0; k < strlen(addr); k++) {
595+
if (addr[k] == '-') {
596+
addr[k] = '\0';
597+
break;
555598
}
556-
break;
557599
}
600+
addr_start = strtol(&addr[0], NULL, 16);
601+
addr_end = strtol(&addr[k + 1], NULL, 16);
602+
break;
603+
case 5: {
604+
char *path = NULL;
605+
size_t path_len = 0;
606+
if (c[0] == '/') {
607+
path = strndup(c, sizeof(buf) - 1);
608+
path_len = strnlen(path, sizeof(buf) - 1);
609+
path[path_len - 1] = '\0';
610+
}
611+
if (mem_prot & PROT_EXEC) {
612+
scan_exec_code((char *)addr_start, (size_t)addr_end - addr_start,
613+
mem_prot, path);
614+
}
615+
break;
558616
}
559-
if (i == 5) break;
560-
c = strtok(NULL, " ");
561-
i++;
562617
}
618+
if (i == 5) break;
619+
c = strtok(NULL, " ");
620+
i++;
563621
}
564622
}
565623
fclose(fp);
566624
}
625+
#endif
567626

568627
/* entry point for binary rewriting */
569628
static void rewrite_code(void) {
@@ -817,7 +876,7 @@ static void load_hook_lib(void) {
817876
}
818877

819878
__attribute__((constructor(0xffff))) static void __svc_hook_init(void) {
820-
#ifdef SUPPLEMENTAL__SYSCALL_RECORD
879+
#if SUPPLEMENTAL__SYSCALL_RECORD
821880
bm_init();
822881
#endif /* SUPPLEMENTAL__SYSCALL_RECORD */
823882
scan_code();

0 commit comments

Comments
 (0)