From b328a92f0e3c648bad7ef47a98f1db75e545789a Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 24 Jul 2024 22:39:59 -0400 Subject: initial commit --- .gitignore | 3 +++ Dockerfile | 15 +++++++++++++++ Makefile | 15 +++++++++++++++ README.md | 22 ++++++++++++++++++++++ hi.s | 31 +++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 hi.s diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e389069 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.sw? +*.o +./hi diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1c6845e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +# build image: latest alpine plus the following packages: +# - binutils: for as and ld +# - make: for gnu make +FROM docker.io/alpine:latest AS build +COPY . /src +WORKDIR /src +RUN apk add binutils make && \ + make && \ + wc -c ./hi + +# output image which contains a single 384 byte statically-linked arm64 +# binary named "/hi" +FROM scratch +COPY --from=build /src/hi /hi +CMD ["/hi"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b5d8aae --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +APP=./hi +OBJS=hi.o + +.PHONY=all + +all: $(APP) + +$(APP): $(OBJS) + ld -s -o $(APP) $(OBJS) + +hi.o: hi.s + as -o hi.o hi.s + +clean: + $(RM) $(APP) $(OBJS) diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b545d7 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +Critical infrastructure. + +Compiles to 384 byte statically-linked arm64 linux binary and a ~4k +container image. + +Build, run, and view binary size on an arm64 linux system: + + > make + ... + > ./hi + alonzo sucks! + > wc -c ./hi + 384 ./hi + > + +Build container image, then check image size: + + > podman build -t hi:latest . + ... + > podman images --format '{{.Size}}' hi + 3.83 kB + > diff --git a/hi.s b/hi.s new file mode 100644 index 0000000..90190cb --- /dev/null +++ b/hi.s @@ -0,0 +1,31 @@ +// hi.s: print "alonzo sucks!" to standard output and then exit. +// +// uses write() and exit() linux system calls directly to elide libc and +// assembles to a static, 384 byte arm64 binary. + +// entry point +// +// uses 32-bit registers (wN) instead of 64-bit registers (xN) to +// save a few bytes in the assembled binary +.text +.global _start +_start: + // write(stdout, msg, len) + mov w0, #1 // stdout fd (1) + ldr w1, =msg // message + mov w2, len // message length + mov w8, #64 // write() (64) + svc #0 // call write() + + // exit(0) + mov w0, #0 // exit code (0) + mov w8, #93 // exit() (93) + svc #0 // call exit() + +// message and message length +// +// technically the message belongs in the .rodata section, but sticking +// it here allows it to be packed after _start and the saves ~60 bytes +// in the assembled binary +msg: .ascii "alonzo sucks!\n" // message (14 bytes) +len = . - msg // message length -- cgit v1.2.3