boj-rs / basm-rs

Rust 코드를 컴파일한 후 실행 파일을 온라인 채점 환경에 제출할 수 있도록 변환합니다.
Other
108 stars 12 forks source link
assembly c rust
# basm.rs basm.rs Logo

basm.rs는 Rust 코드를 백준 온라인 저지를 비롯한 온라인 저지에 제출 가능한 프로그램으로 성능 저하 없이 변환해 주는 프로젝트입니다.

출력 파일 언어로는 C, Rust, JavaScript (wasm32), HTML을 지원합니다. 단, HTML은 제출용이 아니라 코드 공유를 목적으로 지원됩니다.

156KB의 자유를 누리십시오!

바로 시작하기

GitHub Codespaces에 접속하셔서 Codespace를 생성하시면 Visual Studio Code 창이 열립니다. GitHub 로그인이 필요합니다.

로컬 환경에서 개발하시려면 사용법 섹션의 설명을 참고해주세요.

소개

러스트(Rust)는 차세대 프로그래밍 언어로 C/C++보다 우수한 점이 여럿 있는데, 그 중 하나가 패키지 관리 기능입니다. 러스트에서는 프로젝트 설정 파일(Cargo.toml)에 사용하고자 하는 외부 라이브러리(crate, 크레이트)를 지정하면, 해당 라이브러리의 기능을 아주 쉽게 가져다 쓸 수 있습니다. crates.io, GitHub, 또는 로컬 컴퓨터에 있는 코드를 지정할 수 있어 선택의 폭이 매우 넓습니다. 바퀴를 재발명하지 않고 잘 만들어진 외부 라이브러리를 사용하면 실무에서는 개발 시간을 획기적으로 단축할 수 있으며, 알고리즘 문제 풀이 시에는 구현 시간을 획기적으로 단축하고 핵심 발상에 집중할 수 있습니다. 그렇지만 백준 온라인 저지를 비롯한 대부분의 온라인 저지에서는 아쉽게도 외부 라이브러리의 직접 사용이 지원되지 않습니다.

basm-rs를 사용하시면 외부 라이브러리를 이용해 알고리즘 문제 풀이를 할 수 있습니다. basm-rs는 로컬에서 외부 라이브러리를 포함하여 전체 프로젝트를 빌드하여 실행 파일을 생성한 다음, 생성된 실행 파일의 머신 코드(어셈블리 언어)를 템플릿에 적재합니다. 외부 라이브러리를 빌드 시 의존성에 포함하고 결과물로 생성된 머신 코드를 직접 제출하므로, 제출하는 소스 코드에 외부 라이브러리 코드가 포함되어 있습니다. 따라서 백준, 스택, 코드포스1, 폴리곤 등 문제 풀이 사이트에서 외부 라이브러리를 자유롭게 사용하실 수 있습니다.

또한, 다음과 같은 편의 기능을 제공합니다.

러스트의 풍성한 라이브러리 생태계를 활용하셔서 즐거운 문제 풀이를 하실 수 있기를 바랍니다.

1 코드포스 연습 시에는 사용이 가능하지만 코드포스 대회에서는 오픈 핵 과정의 원활한 진행을 위해 난독화를 금지하는 규정에 따라 현재 사용하실 수 없습니다. 이용에 주의 부탁드립니다.

효과

공백으로 구분된 a와 b를 받아 더한 결과를 출력하는 프로그램은 다음과 같이 작성할 수 있습니다.

use std::io::Read;
fn main() {
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    let mut input = s.split_whitespace().flat_map(str::parse);
    let a: i64 = input.next().unwrap();
    let b: i64 = input.next().unwrap();
    println!("{}", a + b);
}

이를 basm에서는 다음과 같이 작성할 수 있습니다.

basm에서는 main() 함수가 반드시 pub으로 선언되어야 컴파일이 가능함에 주의해 주세요.

// basm/src/solution.rs
use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
pub fn main() {
    let mut reader: Reader = Default::default();
    let mut writer: Writer = Default::default();
    let a = reader.i64();
    let b = reader.i64();
    writer.println(a + b);
}

사용법

basm.rs는 그 자체로 완전한 Rust cargo 프로젝트입니다.

basm/src/solution.rs main() 에 원하는 코드를 삽입하시고, 일반적인 cargo 프로젝트와 같은 방식으로 빌드 / 실행할 수 있습니다.

cargo run 및 cargo run --release로 프로그램을 실행할 수 있고 cargo test나 cargo bench를 이용하여 테스트 및 성능 측정을 할 수 있습니다. 다만 로컬 환경에서 개발이 끝난 후 온라인 저지에 제출할 수 있는 형태로 빌드하기 위해서는 반드시 아래에 설명된 전용 스크립트를 사용해야 합니다.

Windows 환경에서 빌드하는 방법입니다.

Linux (WSL 포함) 환경에서 빌드하는 방법입니다.

macOS (AArch64) 환경에서 빌드하는 방법입니다.

디버깅

Windows 11 64비트, Windows Subsystems for Linux 2 (WSL2)에서 테스트되었습니다. 다른 환경에서 작동에 문제가 있을 시 이슈를 남겨주세요.

  1. Windows 또는 Linux에서 Visual Studio Code를 설치하신 다음, rust-analyzer 확장 및 CodeLLDB 확장을 설치해주세요. WSL을 사용하시는 경우 반드시 WSL 내부에 확장을 설치하셔야 합니다.

  2. F5를 눌러 디버깅을 진행해주세요.

  3. 디버깅이 완료된 후에는 위의 "사용법"에 기술된 대로 release.sh 등을 실행하시면 Release 모드로 최종 프로그램을 빌드하실 수 있습니다.

주의사항

문제 해결

예제: 큰 수 A+B (BOJ 10757)

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

그런 다음, Cargo.toml의 [dependencies] 항목에 다음을 추가합니다.

dashu = { version = "0.4.2", default-features = false }

basm/src/solution.rs를 다음과 같이 수정합니다.

use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
use alloc::string::ToString;
use core::str::FromStr;
use dashu::Integer;

pub fn main() {
    let mut reader: Reader = Default::default();
    let mut writer: Writer = Default::default();
    let a = Integer::from_str(&reader.word()).unwrap();
    let b = Integer::from_str(&reader.word()).unwrap();
    let ans = &a + &b;
    writer.println(ans.to_string());
}

이제 로컬에서 빌드합니다.

Windows

다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C 코드가 출력됩니다.

./release-64bit-windows.cmd > output.c

생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)

cl output.c /F268435456
output

Microsoft C/C++ 컴파일러 clPATH에 있어야 하며 기타 환경 변수가 잘 설정되어 있어야 컴파일이 문제없이 진행됩니다. 따라서 가급적 x64 Native Tools Command Prompt for VS 2022 (로컬 환경에 따라 연도는 2022가 아닐 수 있음)에서 실행하는 것이 좋습니다.

Linux

다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C 코드가 출력됩니다.

./release-64bit.sh > output.c

생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)

gcc output.c -o output
chmod +x ./output
./output

32비트 환경(코드포스, 코드포스 폴리곤 등)에 제출 가능한 C 코드로 빌드하려면 다음과 같이 할 수 있습니다.

./release-32bit.sh > output-32.c

마찬가지로 생성된 코드를 컴파일하여 실행합니다. (이를 실행하는 로컬 환경은 64비트라고 가정하고 있습니다)

gcc output-32.c -o output-32 -m32
chmod +x ./output-32
./output-32

예제: 할 수 있다(BOJ 1287)

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

그런 다음, Cargo.toml의 [dependencies] 항목에 다음을 추가합니다.

nom = { version = "7.1.3", default-features = false, features = ["alloc"] }
dashu = { version = "0.4.2", default-features = false }

basm/src/solution.rs를 다음과 같이 수정합니다.

use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
use alloc::string::ToString;
use core::str::FromStr;
use dashu::Integer;

use nom::{
    IResult,
    branch::alt,
    bytes::complete::{tag, take_while},
    character::is_digit,
    character::complete::one_of,
    combinator::{all_consuming, map_res},
    multi::many0,
    sequence::{delimited, pair},
};

fn number_literal(input: &str) -> IResult<&str, Integer> {
    map_res(take_while(|x: char| is_digit(x as u8)), |s: &str| Integer::from_str(s))(input)
}
fn op(input: &str) -> IResult<&str, char> {
    one_of("+-*/")(input)
}
fn wrapped(input: &str) -> IResult<&str, Integer> {
    delimited(tag("("), expr, tag(")"))(input)
}
fn number(input: &str) -> IResult<&str, Integer> {
    alt((number_literal, wrapped))(input)
}
fn expr(input: &str) -> IResult<&str, Integer> {
    map_res(
        pair(number, many0(pair(op, number))),
        |x| -> Result<Integer, usize> {
            let (mut a, mut b) = (Integer::ZERO, x.0);
            for p in x.1 {
                match p.0 {
                    '+' => { (a, b) = (a + b, p.1); },
                    '-' => { (a, b) = (a + b, -p.1); },
                    '*' => { b *= p.1; },
                    '/' => if p.1 == Integer::ZERO { return Err(1); } else { b /= p.1; },
                    _ => unreachable!()
                }
            }
            Ok(a + b)
        }
    )(input)
}

pub fn main() {
    let mut reader: Reader = Default::default();
    let mut writer: Writer = Default::default();
    let input = reader.word();
    if let Ok((_, ans)) = all_consuming(expr)(&input) {
        writer.println(ans.to_string());
    } else {
        writer.println("ROCK");
    };
}

이후 실행 과정은 위의 "큰 수 A+B"와 동일하게 진행하면 됩니다.

예제: 오름세(BOJ 3745)

이 예제는 하나의 입력 파일에 여러 개의 테스트 케이스가 있지만 개수가 따로 주어지지 않을 때 파일의 끝(end-of-file; EOF)을 검출하여 프로그램을 적절히 종료하는 방법을 보여줍니다.

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

basm/src/solution.rs를 다음과 같이 수정합니다.

use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
use core::cmp::max;
pub fn main() {
    let mut reader: Reader = Default::default();
    let mut writer: Writer = Default::default();
    let mut x = [usize::MAX; 100_001]; // x[i] = minimum end-value of "len >= i" increasing seq.
    while !reader.is_eof_skip_whitespace() {
        let n = reader.usize();
        let mut ans = 0;
        x[0] = 0;
        for i in 0..n {
            x[i + 1] = usize::MAX;
            let v = reader.usize();
            let (mut lo, mut hi) = (0, i);
            while lo < hi {
                let mid = (lo + hi + 1) / 2;
                if x[mid] < v { lo = mid; } else { hi = mid - 1; }
            }
            let ans_new = lo + 1;
            x[ans_new] = v;
            ans = max(ans, ans_new);
        }
        writer.println(ans);
    }
}

이후 실행 과정은 위의 "큰 수 A+B"와 동일하게 진행하면 됩니다.

예제: 정수 N개의 합(BOJ 15596)

이 예제는 basm-rs를 이용해 러스트로 함수 구현 문제를 해결하는 방법을 보여줍니다.

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

basm/src/solution.rs를 다음과 같이 수정합니다. 이때, main 함수는 모듈이 로드될 때 정확하게 한 번만 실행됩니다. 따라서 필요한 경우 프로그램의 전역 상태를 초기화하는 루틴을 main 함수에 작성해도 됩니다. 만약 main 함수에 작성할 내용이 없더라도 제거하면 컴파일 오류가 발생하므로 빈 함수로 남겨두어야 합니다.

is_local_env()는 프로그램이 로컬에서 cargo run 등에 의해 실행되고 있으면 true를, 온라인 저지에 제출하기 위해 템플릿에 적재된 경우 false를 반환합니다. 따라서 이를 이용하면 구현한 함수를 콘솔 입출력으로 테스트하고 코드 수정 없이 온라인 저지 제출용으로 빌드할 수 있습니다.

use alloc::vec::Vec;
use basm::platform::is_local_env;
use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
use basm_macro::basm_export;

pub fn main() {
    if is_local_env() {
        let mut reader: Reader = Default::default();
        let mut writer: Writer = Default::default();
        let n = reader.usize();
        let mut a = Vec::new();
        for _ in 0..n {
            a.push(reader.i32());
        }
        let ans = sum(&mut a);
        writer.println(ans);
    }
}

#[basm_export]
fn sum(a: &mut Vec::<i32>) -> i64 {
    a.iter().map(|&x| x as i64).sum()
}

함수 구현 문제는 일반 프로그램과는 빌드 방법이 다르며, 출력 형식은 64비트(x86-64) C++ 코드만 지원됩니다.

Windows

다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C++ 코드가 출력됩니다.

./release-64bit-windows-fn-impl.cmd > output.cpp

Linux

다음 스크립트를 실행하면 64비트 환경(백준 온라인 저지 등)에 제출 가능한 C++ 코드가 출력됩니다.

./release-64bit-fn-impl.sh > output.cpp

노트

예제: IOI 2016 Aliens(BOJ 20090)

이 예제는 basm-rs의 함수 구현 기능 지원을 이용해 IOI 2016에 출제된 Aliens 문제를 해결하는 예시입니다.

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

basm/src/solution.rs를 다음과 같이 수정합니다.

use basm::platform::is_local_env;
use basm::platform::io::{Reader, ReaderTrait, Writer, Print};
use basm_macro::basm_export;
use alloc::vec;
use alloc::vec::Vec;

pub fn main() {
    if is_local_env() {
        let mut reader: Reader = Default::default();
        let mut writer: Writer = Default::default();
        let n = reader.i32();
        let m = reader.i32();
        let k = reader.i32();
        let (mut r, mut c) = (vec![], vec![]);
        for _ in 0..n {
            r.push(reader.i32());
            c.push(reader.i32());
        }
        let ans = take_photos(n, m, k, r, c);
        writer.println(ans);
    }
}

fn deduplicate(n: i32, r: Vec::<i32>, c: Vec::<i32>) -> Vec::<(i32, i32)> {
    let mut tmp: Vec<(i32, i32)> = (0..n as usize).map(|i| if r[i] < c[i] { (r[i], c[i]) } else { (c[i], r[i]) }).collect();
    tmp.sort_unstable();
    let mut out: Vec<(i32, i32)> = vec![];
    for (rr, cc) in tmp {
        if !out.is_empty() && out[out.len() - 1].0 == rr {
            out.pop();
        }
        if !out.is_empty() && out[out.len() - 1].1 >= cc {
            continue;
        }
        out.push((rr, cc));
    }
    out
}

/* minimum hull that expects strictly decreasing slopes */
struct ConvexHullTrickLinear {
    v: Vec::<(i64, i64, usize)>,
    last_m: i64
}

impl ConvexHullTrickLinear {
    fn new() -> Self {
        Self { v: vec![], last_m: i64::MAX }
    }
    fn push(&mut self, m: i64, b: i64, user_data: usize) {
        assert!(m < self.last_m);
        while self.v.len() >= 2 {
            let (m1, b1, _) = self.v[self.v.len() - 2];
            let (m2, b2, _) = self.v[self.v.len() - 1];
            if (b2 - b1) * (m2 - m) < (b - b2) * (m1 - m2) {
                break;
            }
            self.v.pop();
        }
        self.v.push((m, b, user_data));
        self.last_m = m;
    }
    fn query(&self, x: i64) -> (i64, usize) {
        assert!(!self.v.is_empty());
        let (mut lo, mut hi) = (0, self.v.len() - 1);
        while lo < hi {
            let mid = (lo + hi) / 2;
            let (m1, b1, _) = self.v[mid];
            let (m2, b2, _) = self.v[mid + 1];
            if m1 * x + b1 < m2 * x + b2 {
                hi = mid;
            } else {
                lo = mid + 1;
            }
        }
        let (m, b, user_data) = self.v[lo];
        (m * x + b, user_data)
    }
}

fn solve_single(pts: &Vec::<(i32, i32)>, p: i64) -> (i64, usize) {
    const FACTOR: i64 = 2;

    let l = |i: usize| -> i64 { pts[i - 1].0 as i64 - 1 };
    let r = |i: usize| -> i64 { pts[i - 1].1 as i64 };

    let n = pts.len();
    let mut dp = vec![(0, 0)];
    let mut cht = ConvexHullTrickLinear::new();
    cht.push(-2 * l(1) * FACTOR, l(1) * l(1) * FACTOR, 0);
    for i in 1..=n {
        /* Query CHT */
        let (val, argmax) = cht.query(r(i));
        let dp_i = val + r(i) * r(i) * FACTOR;
        dp.push((dp_i - p, argmax + 1));

        /* Update CHT */
        if i < n {
            if l(i+1) <= r(i) {
                cht.push(-2 * l(i+1) * FACTOR, dp[i].0 - r(i) * r(i) * FACTOR + 2 * l(i+1) * r(i) * FACTOR, dp[i].1);
            } else {
                cht.push(-2 * l(i+1) * FACTOR, dp[i].0 + l(i+1) * l(i+1) * FACTOR, dp[i].1);
            }
        }
    }
    dp[n]
}

#[basm_export]
fn take_photos(n: i32, _m: i32, k: i32, r: Vec::<i32>, c: Vec::<i32>) -> i64 {
    const RANGE: i64 = 1_000_000_000_001;

    let pts = deduplicate(n, r, c);
    let (mut p_lo, mut p_hi) = (-RANGE, RANGE);
    while p_lo < p_hi {
        let p_mid = (p_lo + p_hi + 1 + 2*RANGE) / 2 - RANGE;
        let p_ans = solve_single(&pts, 2 * p_mid - 1);
        if p_ans.1 <= k as usize {
            p_lo = p_mid;
        } else {
            p_hi = p_mid - 1;
        }
    }
    let mut p_opt = 2 * p_lo - 1;
    let ans = solve_single(&pts, p_opt);
    let mut override_count = false;
    if p_opt > 0 {
        p_opt = 0;
    } else if ans.1 < k as usize {
        p_opt += 1;
        override_count = true;
    }
    let ans = solve_single(&pts, p_opt);
    (ans.0 + if override_count { k as i64 } else { ans.1 as i64 } * p_opt) / 2
}

빌드 및 실행은 이전 함수 구현 예제와 동일합니다. 로컬에서 cargo run을 입력하고 아래 테스트 케이스를 입력하면 25가 출력되어야 합니다.

5 7 2
0 3
4 4
4 6
4 5
4 6

예제: 숫자 야구 F(BOJ 18160)

이 예제는 basm-rs의 함수 구현 기능 지원을 이용해 함수 가져오기(import)를 하는 방법을 보여줍니다.

이 프로젝트를 다운로드 또는 클론한 다음, 위의 "주의사항"에 나열된 대로 Nightly Rust를 셋업합니다.

basm/src/solution.rs를 다음과 같이 수정합니다.

use alloc::{format, string::String, vec::Vec};
use basm::serialization::Pair;
use basm_macro::{basm_export, basm_import};
pub fn main() {}

basm_import! {
    fn guess(b: String) -> Pair::<i32, i32>;
}

static mut ALL: Vec<i32> = Vec::new();
static mut N: i32 = 0;

#[basm_export]
fn init(_t: i32, n: i32) {
    unsafe {
        (*core::ptr::addr_of_mut!(ALL)).clear();
        N = n;
        let pow10_n = 10i32.pow(n as u32);
        'outer: for i in 0..pow10_n {
            let mut digits = [false; 10];
            let mut j = i;
            for _ in 0..n {
                let d = (j % 10) as usize;
                if digits[d] {
                    continue 'outer;
                }
                digits[d] = true;
                j /= 10;
            }
            (*core::ptr::addr_of_mut!(ALL)).push(i);
        }
    }
}

fn check(mut x: i32, mut y: i32) -> Pair<i32, i32> {
    let mut digits_x = [false; 10];
    let mut digits_y = [false; 10];
    let mut strikes = 0;
    let mut balls = 0;
    unsafe {
        for _ in 0..N {
            let d_x = (x % 10) as usize;
            let d_y = (y % 10) as usize;
            if d_x == d_y {
                strikes += 1;
            }
            if digits_x[d_y] {
                balls += 1;
            }
            if digits_y[d_x] {
                balls += 1;
            }
            digits_x[d_x] = true;
            digits_y[d_y] = true;
            x /= 10;
            y /= 10;
        }
    }
    Pair::<i32, i32>(strikes, balls)
}

#[basm_export]
fn game() {
    let mut all = unsafe { (*core::ptr::addr_of!(ALL)).clone() };
    let n = unsafe { N };
    loop {
        let query = all[0];
        let query_str = if n == 3 {
            format!("{:03}", query)
        } else {
            format!("{:04}", query)
        };
        let out = guess(query_str);
        if out == Pair(n, 0) {
            break;
        }
        let mut all_new = Vec::new();
        for x in all {
            if check(x, query) == out {
                all_new.push(x);
            }
        }
        all = all_new;
    }
}

빌드 및 실행은 이전 함수 구현 예제와 동일합니다.

Open Source Attributions

base85

Copyright (c) 2016-2018 Rafa Garcia <rafagarcia77@gmail.com>.

Permission is hereby  granted, free of charge, to any  person obtaining a copy
of this software and associated  documentation files (the "Software"), to deal
in the Software  without restriction, including without  limitation the rights
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

MINT64 OS

/**
 *  file    ApplicationLoader.c
 *  date    2009/12/26
 *  author  kkamagui
 *          Copyright(c)2008 All rights reserved by kkamagui
 *  brief   응용프로그램을 로드하여 실행하는 로더(Loader)에 관련된 함수를 정의한 소스 파일
 */
(brief in English:
    source file defining functions for loader that loads and runs applications)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

========

The ELF parsing and relocation routines in basm-rs were adapted
from the following implementation of MINT64OS, licensed under GPLv2+:
    https://github.com/kkamagui/mint64os/blob/master/02.Kernel64/Source/Loader.c

Unlike all other parts of basm-rs, which are under the MIT license,
the files implementing ELF parsing and relocation are exceptionally
licensed under GPLv2+ since it is derived from an existing GPLv2+
implementation, "Loader.c" (see above). Although GPLv2+ mandates
licensing the project in its entirety as GPLv2+, the original author
has kindly granted us permission to confine the GPLv2+ license to
the parts explicitly derived from "Loader.c".

There are currently three files licensed under GPLv2+:
    scripts/static-pie-elf2bin.py
    basm-std/src/platform/loader/amd64_elf.rs
    basm-std/src/platform/loader/i686_elf.rs

Micro LZMA decoder

Copyright (c) 2022, Ilya Kurdyukov
All rights reserved.

Micro LZMA decoder for x86 (static)
Micro LZMA decoder for x86_64 (static)

This software is distributed under the terms of the
Creative Commons Attribution 3.0 License (CC-BY 3.0)
http://creativecommons.org/licenses/by/3.0/

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

dlmalloc-rs

Copyright (c) 2014 Alex Crichton

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

Go

Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
   * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Rust

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.