[libc-commits] [libc] 55120aa - Implement basic loader for Linux aarch64

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Tue Feb 15 19:42:49 PST 2022


Author: Jeff Bailey
Date: 2022-02-16T03:42:44Z
New Revision: 55120aad4e34a8cb591029cd2788e833c17e077c

URL: https://github.com/llvm/llvm-project/commit/55120aad4e34a8cb591029cd2788e833c17e077c
DIFF: https://github.com/llvm/llvm-project/commit/55120aad4e34a8cb591029cd2788e833c17e077c.diff

LOG: Implement basic loader for Linux aarch64

This implements a basic arm64 loader for Linux, and all the currently
enabled linker tests pass.  TLS is not implemented, and functions
using it will have undefined behaviour.  Notably, the TLS test is
currently disabled on x86_64.

Much of the structure is copied from x86_64 to allow for a refactoring
of the start code between architectures.

Tested:
ninja libc_loader_tests on aarch64-linux.

Co-authored-by: Raman Tenneti <rtenneti at google.com>

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D119641

Added: 
    libc/loader/linux/aarch64/CMakeLists.txt
    libc/loader/linux/aarch64/start.cpp

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/libc/loader/linux/aarch64/CMakeLists.txt b/libc/loader/linux/aarch64/CMakeLists.txt
new file mode 100644
index 0000000000000..c8fa53bf3d753
--- /dev/null
+++ b/libc/loader/linux/aarch64/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_loader_object(
+  crt1
+  SRC
+    start.cpp
+  DEPENDS
+    libc.config.linux.app_h
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.string.memcpy
+  COMPILE_OPTIONS
+    -fno-omit-frame-pointer
+    -ffreestanding # To avoid compiler warnings about calling the main function.
+)

diff  --git a/libc/loader/linux/aarch64/start.cpp b/libc/loader/linux/aarch64/start.cpp
new file mode 100644
index 0000000000000..c8ee619e12b30
--- /dev/null
+++ b/libc/loader/linux/aarch64/start.cpp
@@ -0,0 +1,83 @@
+//===-- Implementation of crt for aarch64 ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "config/linux/app.h"
+#include "include/sys/syscall.h"
+#include "src/__support/OSUtil/syscall.h"
+
+#include <linux/auxvec.h>
+#include <linux/elf.h>
+#include <stdint.h>
+
+extern "C" int main(int, char **, char **);
+
+// Source documentation:
+// https://github.com/ARM-software/abi-aa/tree/main/sysvabi64
+
+namespace __llvm_libc {
+
+AppProperties app;
+
+} // namespace __llvm_libc
+
+using __llvm_libc::app;
+
+struct Args {
+  // In the ARM64 ABI, arguments are usually passed in registers.  x0 is a
+  // doubleword register, so this is 64 bit.
+  uint64_t argc;
+
+  // C++ Doesn't have flexible arrays: P1039 proposes to fix this, but for now
+  // we just fake it.  Even if argc is zero, "argv[argc] shall be a null
+  // pointer" (ISO C 5.1.2.2.1) so one is fine.
+  uint64_t argv[1];
+};
+
+// TODO: Would be nice to use the aux entry structure from elf.h when available.
+struct AuxEntry {
+  uint64_t type;
+  uint64_t value;
+};
+
+extern "C" void _start() {
+  uintptr_t *frame_ptr =
+      reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
+
+  // Skip the Frame Pointer and the Link Register
+  // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
+  // Section 6.2.3
+
+  Args *args = reinterpret_cast<Args *>(frame_ptr + 2);
+
+  // After the argv array, is a 8-byte long NULL value before the array of env
+  // values. The end of the env values is marked by another 8-byte long NULL
+  // value. We step over it (the "+ 1" below) to get to the env values.
+  uint64_t *env_ptr = args->argv + args->argc + 1;
+  uint64_t *env_end_marker = env_ptr;
+  while (*env_end_marker)
+    ++env_end_marker;
+
+  // After the env array, is the aux-vector. The end of the aux-vector is
+  // denoted by an AT_NULL entry.
+  for (AuxEntry *aux_entry = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
+       aux_entry->type != AT_NULL; ++aux_entry) {
+    switch (aux_entry->type) {
+    case AT_PAGESZ:
+      app.pageSize = aux_entry->value;
+      break;
+    default:
+      break; // TODO: Read other useful entries from the aux vector.
+    }
+  }
+
+  // TODO: Init TLS
+
+  __llvm_libc::syscall(SYS_exit,
+                       main(args->argc, reinterpret_cast<char **>(args->argv),
+                            reinterpret_cast<char **>(env_ptr)));
+}


        


More information about the libc-commits mailing list