Skip to content

Commit 55120aa

Browse files
committed
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@google.com> Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D119641
1 parent 2e487da commit 55120aa

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_loader_object(
2+
crt1
3+
SRC
4+
start.cpp
5+
DEPENDS
6+
libc.config.linux.app_h
7+
libc.include.sys_syscall
8+
libc.src.__support.OSUtil.osutil
9+
libc.src.string.memcpy
10+
COMPILE_OPTIONS
11+
-fno-omit-frame-pointer
12+
-ffreestanding # To avoid compiler warnings about calling the main function.
13+
)

libc/loader/linux/aarch64/start.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//===-- Implementation of crt for aarch64 ---------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "config/linux/app.h"
10+
#include "include/sys/syscall.h"
11+
#include "src/__support/OSUtil/syscall.h"
12+
13+
#include <linux/auxvec.h>
14+
#include <linux/elf.h>
15+
#include <stdint.h>
16+
17+
extern "C" int main(int, char **, char **);
18+
19+
// Source documentation:
20+
// https://github.com/ARM-software/abi-aa/tree/main/sysvabi64
21+
22+
namespace __llvm_libc {
23+
24+
AppProperties app;
25+
26+
} // namespace __llvm_libc
27+
28+
using __llvm_libc::app;
29+
30+
struct Args {
31+
// In the ARM64 ABI, arguments are usually passed in registers. x0 is a
32+
// doubleword register, so this is 64 bit.
33+
uint64_t argc;
34+
35+
// C++ Doesn't have flexible arrays: P1039 proposes to fix this, but for now
36+
// we just fake it. Even if argc is zero, "argv[argc] shall be a null
37+
// pointer" (ISO C 5.1.2.2.1) so one is fine.
38+
uint64_t argv[1];
39+
};
40+
41+
// TODO: Would be nice to use the aux entry structure from elf.h when available.
42+
struct AuxEntry {
43+
uint64_t type;
44+
uint64_t value;
45+
};
46+
47+
extern "C" void _start() {
48+
uintptr_t *frame_ptr =
49+
reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
50+
51+
// Skip the Frame Pointer and the Link Register
52+
// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
53+
// Section 6.2.3
54+
55+
Args *args = reinterpret_cast<Args *>(frame_ptr + 2);
56+
57+
// After the argv array, is a 8-byte long NULL value before the array of env
58+
// values. The end of the env values is marked by another 8-byte long NULL
59+
// value. We step over it (the "+ 1" below) to get to the env values.
60+
uint64_t *env_ptr = args->argv + args->argc + 1;
61+
uint64_t *env_end_marker = env_ptr;
62+
while (*env_end_marker)
63+
++env_end_marker;
64+
65+
// After the env array, is the aux-vector. The end of the aux-vector is
66+
// denoted by an AT_NULL entry.
67+
for (AuxEntry *aux_entry = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
68+
aux_entry->type != AT_NULL; ++aux_entry) {
69+
switch (aux_entry->type) {
70+
case AT_PAGESZ:
71+
app.pageSize = aux_entry->value;
72+
break;
73+
default:
74+
break; // TODO: Read other useful entries from the aux vector.
75+
}
76+
}
77+
78+
// TODO: Init TLS
79+
80+
__llvm_libc::syscall(SYS_exit,
81+
main(args->argc, reinterpret_cast<char **>(args->argv),
82+
reinterpret_cast<char **>(env_ptr)));
83+
}

0 commit comments

Comments
 (0)