-
Notifications
You must be signed in to change notification settings - Fork 143
Support Arm dynamic linking #244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
1d33e85
9b5d5b5
41eba4f
e834b4e
ab0b13e
75e4386
31b8614
c182976
3fe323b
23712d9
5e89621
f4992ba
73a3d5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,10 +74,19 @@ To execute the snapshot test, install the packages below: | |
$ sudo apt-get install graphviz jq | ||
``` | ||
|
||
Additionally, because `shecc` supports the dynamic linking mode for the Arm architecture, | ||
it needs to install the ARM GNU toolchain to obtain the ELF interpreter and other dependencies: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mention https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads as well. |
||
```shell | ||
$ sudo apt-get install gcc-arm-linux-gnueabihf | ||
``` | ||
Another approach is to manually download and install the toolchain from [ARM Developer website](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads). | ||
|
||
Select "x86_64 Linux hosted cross toolchains" - "AArch32 GNU/Linux target with hard float (arm-none-linux-gnueabihf)" to download the toolchain. | ||
|
||
## Build and Verify | ||
|
||
Configure which backend you want, `shecc` supports ARMv7-A and RV32IM backend: | ||
``` | ||
```shell | ||
$ make config ARCH=arm | ||
# Target machine code switch to Arm | ||
|
||
|
@@ -86,13 +95,29 @@ $ make config ARCH=riscv | |
``` | ||
|
||
Run `make` and you should see this: | ||
```shell | ||
$ make | ||
CC+LD out/inliner | ||
GEN out/libc.inc | ||
CC out/src/main.o | ||
LD out/shecc | ||
SHECC out/shecc-stage1.elf | ||
SHECC out/shecc-stage2.elf | ||
``` | ||
|
||
Run `make LINK_MODE=dynamic` to use the dynamic linking mode and generate the dynamically linked compiler: | ||
```shell | ||
# If using the dynamic linking mode, you should add 'LINK_MODE=dynamic' for each 'make' command. | ||
$ make LINK_MODE=dynamic | ||
CC+LD out/inliner | ||
GEN out/libc.inc | ||
CC out/src/main.o | ||
LD out/shecc | ||
SHECC out/shecc-stage1.elf | ||
SHECC out/shecc-stage2.elf | ||
|
||
$ file out/shecc-stage2.elf | ||
out/shecc-stage2.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, not stripped | ||
``` | ||
|
||
For development builds with memory safety checks: | ||
|
@@ -103,22 +128,32 @@ $ make check-sanitizer | |
|
||
File `out/shecc` is the first stage compiler. Its usage: | ||
```shell | ||
$ shecc [-o output] [+m] [--no-libc] [--dump-ir] <infile.c> | ||
$ shecc [-o output] [+m] [--no-libc] [--dump-ir] [--dynlink] <infile.c> | ||
``` | ||
|
||
Compiler options: | ||
- `-o` : Specify output file name (default: `out.elf`) | ||
- `+m` : Use hardware multiplication/division instructions (default: disabled) | ||
- `--no-libc` : Exclude embedded C library (default: embedded) | ||
- `--dump-ir` : Dump intermediate representation (IR) | ||
- `--dynlink` : Use dynamic linking (default: disabled) | ||
|
||
Example: | ||
Example 1: static linking mode | ||
```shell | ||
$ out/shecc -o fib tests/fib.c | ||
$ chmod +x fib | ||
$ qemu-arm fib | ||
``` | ||
|
||
Example 2: dynamic linking mode | ||
|
||
Notice that `/usr/arm-linux-gnueabihf` is the ELF interpreter prefix. Since the path may be different if you manually install the ARM GNU toolchain instead of using `apt-get`, you should set the prefix to the actual path. | ||
```shell | ||
$ out/shecc --dynlink -o fib tests/fib.c | ||
$ chmod +x fib | ||
$ qemu-arm -L /usr/arm-linux-gnueabihf fib | ||
``` | ||
|
||
### IR Regression Tests | ||
|
||
To ensure the consistency of frontend (lexer, parser) behavior when working on it, the snapshot test is introduced. | ||
|
@@ -142,6 +177,7 @@ use `update-snapshot` / `check-snapshot` instead. | |
|
||
`shecc` comes with a comprehensive test suite (200+ test cases). To run the tests: | ||
```shell | ||
# Add 'LINK_MODE=dynamic' if using the dynamic linking mode. | ||
$ make check # Run all tests (stage 0 and stage 2) | ||
$ make check-stage0 # Test stage 0 compiler only | ||
$ make check-stage2 # Test stage 2 compiler only | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,50 @@ | ||||||
/* | ||||||
* shecc - Self-Hosting and Educational C Compiler. | ||||||
* | ||||||
* shecc is freely redistributable under the BSD 2 clause license. See the | ||||||
* file "LICENSE" for information on usage and redistribution of this file. | ||||||
*/ | ||||||
|
||||||
#pragma once | ||||||
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
/* Declarations of C standard library functions */ | ||||||
|
||||||
#define NULL 0 | ||||||
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
#define bool _Bool | ||||||
#define true 1 | ||||||
#define false 0 | ||||||
|
||||||
/* va_list support for variadic functions */ | ||||||
typedef int *va_list; | ||||||
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
/* File I/O */ | ||||||
typedef int FILE; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Defines FILE as int, which is ABI-incompatible with libc's opaque FILE type and will break dynamic linking with real stdio functions. (Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.) Prompt for AI agents
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
FILE *fopen(char *filename, char *mode); | ||||||
int fclose(FILE *stream); | ||||||
int fgetc(FILE *stream); | ||||||
char *fgets(char *str, int n, FILE *stream); | ||||||
int fputc(int c, FILE *stream); | ||||||
|
||||||
/* string-related functions */ | ||||||
int strlen(char *str); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. strlen should return size_t and accept const char *; current signature risks overflow and misses const-correctness. Prompt for AI agents
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. strlen signature is incorrect (missing const and wrong return type); this creates an incompatible prototype with libc and risks UB during dynamic linking. Prompt for AI agents
|
||||||
int strcmp(char *s1, char *s2); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add const to strcmp parameters for correctness and compatibility with libc. Prompt for AI agents
Suggested change
|
||||||
int strncmp(char *s1, char *s2, int len); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nonstandard strncmp signature (missing const, len should be size_t) is incompatible with libc and may mis-handle large sizes. (Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.) Prompt for AI agents
|
||||||
char *strcpy(char *dest, char *src); | ||||||
char *strncpy(char *dest, char *src, int len); | ||||||
char *memcpy(char *dest, char *src, int count); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nonstandard memcpy signature (return type and parameter types incorrect) is incompatible with libc and risks ABI mismatch. (Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.) Prompt for AI agents
✅ Addressed in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. memcpy should use void* for pointers, const on src, and size_t for count to match libc and avoid size truncation. Prompt for AI agents
|
||||||
int memcmp(void *s1, void *s2, int n); | ||||||
void *memset(void *s, int c, int n); | ||||||
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
/* formatted output string */ | ||||||
int printf(char *str, ...); | ||||||
int sprintf(char *buffer, char *str, ...); | ||||||
int snprintf(char *buffer, int n, char *str, ...); | ||||||
|
||||||
/* Terminating program */ | ||||||
void exit(int exit_code); | ||||||
void abort(void); | ||||||
|
||||||
/* Dynamic memory allocation/deallocation functions */ | ||||||
void *malloc(int size); | ||||||
void *calloc(int n, int size); | ||||||
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
DrXiao marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
void free(void *ptr); |
Uh oh!
There was an error while loading. Please reload this page.