mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Roc linker library base setup
This commit is contained in:
parent
d5058041b0
commit
c6217ebfdb
10 changed files with 151 additions and 0 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -2219,6 +2219,16 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.26.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.7.2"
|
version = "1.7.2"
|
||||||
|
@ -3296,6 +3306,15 @@ dependencies = [
|
||||||
name = "roc_ident"
|
name = "roc_ident"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_linker"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"clap 3.0.0-beta.1",
|
||||||
|
"object 0.26.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_load"
|
name = "roc_load"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -32,6 +32,7 @@ members = [
|
||||||
"cli/cli_utils",
|
"cli/cli_utils",
|
||||||
"roc_std",
|
"roc_std",
|
||||||
"docs",
|
"docs",
|
||||||
|
"linker",
|
||||||
]
|
]
|
||||||
exclude = [ "ci/bench-runner" ]
|
exclude = [ "ci/bench-runner" ]
|
||||||
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
||||||
|
|
24
linker/Cargo.toml
Normal file
24
linker/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "roc_linker"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["The Roc Contributors"]
|
||||||
|
license = "UPL-1.0"
|
||||||
|
repository = "https://github.com/rtfeldman/roc"
|
||||||
|
edition = "2018"
|
||||||
|
description = "A surgical linker for Roc"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "roc_linker"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "link"
|
||||||
|
path = "src/main.rs"
|
||||||
|
test = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it
|
||||||
|
clap = { git = "https://github.com/rtfeldman/clap", branch = "master" }
|
||||||
|
object = { version = "0.26", features = ["read"] }
|
||||||
|
bumpalo = { version = "3.6.1", features = ["collections"] }
|
31
linker/README.md
Normal file
31
linker/README.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# The Roc Surgical Linker
|
||||||
|
|
||||||
|
This linker has the goal of being extremely slim lined and fast.
|
||||||
|
It is focused on the scope of only linking platforms to Roc applications.
|
||||||
|
This restriction enables ignoring most of linking.
|
||||||
|
|
||||||
|
## General Overview
|
||||||
|
|
||||||
|
This linker is run in 2 phases: preprocessing and surigical linking.
|
||||||
|
|
||||||
|
### Platform Preprocessor
|
||||||
|
|
||||||
|
1. Dynamically link the platform to a dummy Roc application dynamic library
|
||||||
|
1. Create metadata related to Roc dynamically linked functions
|
||||||
|
- Symbols that need to be redefined
|
||||||
|
- Call locations that need to be modified for each symbol
|
||||||
|
- Locations of special roc functions (roc_alloc, roc_dealloc, builtins, etc)
|
||||||
|
1. Modify the main executable to no longer be dynamically link
|
||||||
|
- Delete dependency on dynamic library
|
||||||
|
- Remove symbols from the dynamic table (maybe add them to the regular table?)
|
||||||
|
- Delete GOT and PLT entries
|
||||||
|
- Remove relocations from the dynamic table
|
||||||
|
- Add extra header information about new text and data section at end of file
|
||||||
|
|
||||||
|
### Surgical Linker
|
||||||
|
|
||||||
|
1. Copy over preprocessed platform as base
|
||||||
|
1. Append text and data of application, noting offset
|
||||||
|
- This could potentially have extra complication around section locations and updating the header
|
||||||
|
1. Surgically update all call locations in the platform
|
||||||
|
1. Surgically update call information in the application (also dealing with other relocations for builtins)
|
34
linker/src/lib.rs
Normal file
34
linker/src/lib.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use clap::{App, AppSettings, Arg};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub const CMD_PREPROCESS: &str = "preprocess";
|
||||||
|
pub const CMD_SURGERY: &str = "surgery";
|
||||||
|
pub const EXEC: &str = "EXEC";
|
||||||
|
pub const SHARED_LIB: &str = "SHARED_LIB";
|
||||||
|
|
||||||
|
pub fn build_app<'a>() -> App<'a> {
|
||||||
|
App::new("link")
|
||||||
|
.about("Preprocesses a platform and surgically links it to an application.")
|
||||||
|
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||||
|
.subcommand(
|
||||||
|
App::new(CMD_PREPROCESS)
|
||||||
|
.about("Preprocesses a dynamically linked platform to prepare for linking.")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(EXEC)
|
||||||
|
.help("The dynamically link platform executable")
|
||||||
|
.required(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(SHARED_LIB)
|
||||||
|
.help("The dummy shared library representing the Roc application")
|
||||||
|
.required(true),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.subcommand(
|
||||||
|
App::new(CMD_SURGERY).about("Links a preprocessed platform with a Roc application."),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preprocess() -> io::Result<()> {
|
||||||
|
panic!("sad");
|
||||||
|
}
|
17
linker/src/main.rs
Normal file
17
linker/src/main.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use roc_linker::{build_app, preprocess, CMD_PREPROCESS, CMD_SURGERY};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let matches = build_app().get_matches();
|
||||||
|
|
||||||
|
let exit_code = match matches.subcommand_name() {
|
||||||
|
None => Ok::<i32, io::Error>(-1),
|
||||||
|
Some(CMD_PREPROCESS) => {
|
||||||
|
preprocess()?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
Some(CMD_SURGERY) => Ok(0),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}?;
|
||||||
|
std::process::exit(exit_code);
|
||||||
|
}
|
1
linker/tests/.gitignore
vendored
Normal file
1
linker/tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.so
|
12
linker/tests/Makefile
Normal file
12
linker/tests/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
SHLIB_LDFLAGS = -shared -Wl,--allow-shlib-undefined
|
||||||
|
|
||||||
|
all: platform
|
||||||
|
|
||||||
|
platform: platform.c libapp.so
|
||||||
|
$(CC) -O2 -fPIC -o $@ $^
|
||||||
|
|
||||||
|
libapp.so: app.c
|
||||||
|
$(CC) -O2 -fPIC -shared -o $@ $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f platform libapp.so
|
3
linker/tests/app.c
Normal file
3
linker/tests/app.c
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void app() { printf("Hello World from the application"); }
|
9
linker/tests/platform.c
Normal file
9
linker/tests/platform.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void app();
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("Hello World from the platform");
|
||||||
|
app();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue