Skip to content

Commit b6a01e4

Browse files
committed
GitHub Actions
1 parent cf50b2d commit b6a01e4

13 files changed

Lines changed: 369 additions & 118 deletions

File tree

.github/workflows/build.yaml

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
name: Build
2+
3+
on:
4+
pull_request:
5+
push:
6+
paths-ignore:
7+
- "*.md"
8+
- "LICENSE*"
9+
workflow_dispatch:
10+
11+
permissions:
12+
# For npm publish provenance
13+
id-token: write
14+
15+
env:
16+
BUILD_PROFILE: release-lto
17+
CARGO_INCREMENTAL: 0
18+
19+
jobs:
20+
check:
21+
name: Check
22+
runs-on: ubuntu-latest
23+
env:
24+
RUSTFLAGS: -D warnings
25+
steps:
26+
- name: Install dependencies
27+
run: |
28+
sudo apt-get update
29+
sudo apt-get -y install libgtk-3-dev
30+
- name: Checkout
31+
uses: actions/checkout@v6
32+
- name: Setup Rust toolchain
33+
uses: dtolnay/rust-toolchain@stable
34+
with:
35+
components: clippy
36+
- name: Cache Rust workspace
37+
uses: Swatinem/rust-cache@v2
38+
- name: Cargo check
39+
run: cargo check --all-targets --all-features --workspace
40+
- name: Cargo clippy
41+
run: cargo clippy --all-targets --all-features --workspace
42+
43+
fmt:
44+
name: Format
45+
runs-on: ubuntu-latest
46+
env:
47+
RUSTFLAGS: -D warnings
48+
steps:
49+
- name: Checkout
50+
uses: actions/checkout@v6
51+
- name: Setup Rust toolchain
52+
# We use nightly options in rustfmt.toml
53+
uses: dtolnay/rust-toolchain@nightly
54+
with:
55+
components: rustfmt
56+
- name: Cargo fmt
57+
run: cargo fmt --all --check
58+
59+
deny:
60+
name: Deny
61+
runs-on: ubuntu-latest
62+
strategy:
63+
matrix:
64+
checks:
65+
# - advisories
66+
- bans licenses sources
67+
# Prevent new advisories from failing CI
68+
continue-on-error: ${{ matrix.checks == 'advisories' }}
69+
steps:
70+
- uses: actions/checkout@v6
71+
- uses: EmbarkStudios/cargo-deny-action@v2
72+
with:
73+
command: check ${{ matrix.checks }}
74+
75+
test:
76+
name: Test
77+
strategy:
78+
matrix:
79+
platform: [ ubuntu-latest, windows-latest, macos-latest ]
80+
fail-fast: false
81+
runs-on: ${{ matrix.platform }}
82+
steps:
83+
- name: Install dependencies
84+
if: matrix.platform == 'ubuntu-latest'
85+
run: |
86+
sudo apt-get update
87+
sudo apt-get -y install libgtk-3-dev
88+
- name: Checkout
89+
uses: actions/checkout@v6
90+
- name: Setup Rust toolchain
91+
uses: dtolnay/rust-toolchain@stable
92+
- name: Cache Rust workspace
93+
uses: Swatinem/rust-cache@v2
94+
- name: Cargo test
95+
run: cargo test --release --all-features --workspace
96+
97+
build:
98+
name: Build delink
99+
env:
100+
CARGO_BIN_NAME: delink
101+
strategy:
102+
matrix:
103+
include:
104+
- platform: ubuntu-latest
105+
target: x86_64-unknown-linux-gnu.2.31
106+
target_base: x86_64-unknown-linux-gnu
107+
name: linux-x86_64
108+
packages: libgtk-3-dev
109+
build: zigbuild
110+
- platform: windows-latest
111+
target: x86_64-pc-windows-msvc
112+
name: windows-x86_64
113+
build: build
114+
- platform: macos-latest
115+
target: x86_64-apple-darwin
116+
name: macos-x86_64
117+
build: build
118+
- platform: macos-latest
119+
target: aarch64-apple-darwin
120+
name: macos-arm64
121+
build: build
122+
fail-fast: false
123+
runs-on: ${{ matrix.platform }}
124+
steps:
125+
- name: Install dependencies
126+
if: matrix.packages != ''
127+
run: |
128+
sudo apt-get update
129+
sudo apt-get -y install ${{ matrix.packages }}
130+
- name: Checkout
131+
uses: actions/checkout@v6
132+
- name: Install uv
133+
if: matrix.build == 'zigbuild'
134+
uses: astral-sh/setup-uv@v7
135+
- name: Install cargo-zigbuild
136+
if: matrix.build == 'zigbuild'
137+
run: |
138+
uv tool install cargo-zigbuild==0.20.1 --with-executables-from ziglang==0.15.1
139+
echo "CARGO_ZIGBUILD_ZIG_PATH=$(uv tool dir)/cargo-zigbuild/bin/python-zig" >> $GITHUB_ENV
140+
- name: Setup Rust toolchain
141+
uses: dtolnay/rust-toolchain@stable
142+
with:
143+
targets: ${{ matrix.target_base || matrix.target }}
144+
- name: Cache Rust workspace
145+
uses: Swatinem/rust-cache@v2
146+
with:
147+
key: ${{ matrix.target }}
148+
- name: Cargo build
149+
run: >
150+
cargo ${{ matrix.build }} --profile ${{ env.BUILD_PROFILE }} --target ${{ matrix.target }} --bin ${{ env.CARGO_BIN_NAME }}
151+
- name: Upload artifacts
152+
uses: actions/upload-artifact@v7
153+
with:
154+
name: ${{ env.CARGO_BIN_NAME }}-${{ matrix.name }}
155+
path: |
156+
target/${{ matrix.target_base || matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}
157+
target/${{ matrix.target_base || matrix.target }}/${{ env.BUILD_PROFILE }}/${{ env.CARGO_BIN_NAME }}.exe
158+
if-no-files-found: error
159+
160+
check-version:
161+
name: Check package versions
162+
if: startsWith(github.ref, 'refs/tags/')
163+
runs-on: ubuntu-latest
164+
needs: [ build ]
165+
steps:
166+
- name: Checkout
167+
uses: actions/checkout@v6
168+
- name: Check git tag against package versions
169+
shell: bash
170+
run: |
171+
set -eou pipefail
172+
tag='${{github.ref}}'
173+
tag="${tag#refs/tags/}"
174+
version=$(grep '^version' Cargo.toml | head -1 | awk -F' = ' '{print $2}' | tr -d '"')
175+
version="v$version"
176+
if [ "$tag" != "$version" ]; then
177+
echo "::error::Git tag doesn't match the Cargo version! ($tag != $version)"
178+
exit 1
179+
fi
180+
181+
release-github:
182+
name: Release (GitHub)
183+
if: startsWith(github.ref, 'refs/tags/')
184+
runs-on: ubuntu-latest
185+
needs: [ check-version ]
186+
permissions:
187+
contents: write
188+
steps:
189+
- name: Download artifacts
190+
uses: actions/download-artifact@v4
191+
with:
192+
pattern: delink-*
193+
path: artifacts
194+
- name: Rename artifacts
195+
working-directory: artifacts
196+
run: |
197+
set -euo pipefail
198+
mkdir ../out
199+
for dir in */; do
200+
for file in "$dir"*; do
201+
base=$(basename "$file")
202+
name="${base%.*}"
203+
ext="${base##*.}"
204+
if [ "$ext" = "$base" ]; then
205+
ext=""
206+
else
207+
ext=".$ext"
208+
fi
209+
arch="${dir%/}" # remove trailing slash
210+
arch="${arch##"$name-"}" # remove bin name
211+
dst="../out/${name}-${arch}${ext}"
212+
mv "$file" "$dst"
213+
done
214+
done
215+
ls -R ../out
216+
- name: Release
217+
uses: softprops/action-gh-release@v2
218+
with:
219+
files: out/*
220+
draft: true
221+
generate_release_notes: true

Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ delink-x86_64 = { path = "crates/delink-x86_64" }
4242
delink-x86 = { path = "crates/delink-x86" }
4343
delink-pe = { path = "crates/delink-pe" }
4444

45-
[profile.release]
46-
lto = "thin"
45+
[profile.release-lto]
46+
inherits = "release"
47+
lto = "fat"
48+
strip = "debuginfo"
4749
codegen-units = 1
50+
51+
[profile.release-min]
52+
inherits = "release-lto"
53+
opt-level = "z"

crates/delink-aarch64/src/recover.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! * `adrp` + `add` pair → ADR_PREL_PG_HI21 + ADD_ABS_LO12_NC
77
//! * `adrp` + `ldr/ldst` pair → ADR_PREL_PG_HI21 + LDST{n}_ABS_LO12_NC
88
//! * `adrp` + `ldr` where target lands in `.got`
9-
//! → ADR_GOT_PAGE + LD64_GOT_LO12_NC
9+
//! → ADR_GOT_PAGE + LD64_GOT_LO12_NC
1010
//!
1111
//! Pairing is a per-function register-tracking pass. State is reset at every
1212
//! function boundary (best effort: any unconditional branch, return, or call).
@@ -359,11 +359,8 @@ fn write_regs(mnemonic: &str, ops: &[arm64::Arm64Operand]) -> Vec<u32> {
359359
|| mnemonic == "stur"
360360
|| mnemonic == "sturb"
361361
|| mnemonic == "sturh"
362-
{
363-
0
364-
} else if matches!(mnemonic, "cmp" | "cmn" | "tst" | "ccmp" | "ccmn") {
365-
0
366-
} else if mnemonic.starts_with('b')
362+
|| matches!(mnemonic, "cmp" | "cmn" | "tst" | "ccmp" | "ccmn")
363+
|| mnemonic.starts_with('b')
367364
|| matches!(mnemonic, "ret" | "cbz" | "cbnz" | "tbz" | "tbnz")
368365
{
369366
0

crates/delink-cli/src/main.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ fn aarch64_reloc_name(t: u32) -> String {
364364
fn open_binary<'a>(mmap: &'a memmap2::Mmap, path: &Path) -> Result<delink_core::Binary<'a>> {
365365
delink_core::Binary::load(&mmap[..])
366366
.with_context(|| format!("failed to load {}", path.display()))
367-
.map_err(Into::into)
368367
}
369368

370369
fn mmap_file(path: &Path) -> Result<memmap2::Mmap> {
@@ -451,7 +450,7 @@ fn cmd_list_cus(path: &Path, contains: &str, limit: usize) -> Result<()> {
451450
})
452451
.collect();
453452
rows.sort_by_key(|(b, _, _)| *b);
454-
println!("{:>10} {:>6} {}", "bytes", "funcs", "name");
453+
println!("{:>10} {:>6} name", "bytes", "funcs");
455454
for (bytes, funcs, name) in rows.iter().take(limit) {
456455
println!("{:>10} {:>6} {}", bytes, funcs, name);
457456
}
@@ -521,7 +520,7 @@ fn cmd_pe_list_cus(exe_path: &Path, pdb_path: &Path, contains: &str, limit: usiz
521520
.collect();
522521
rows.sort_by_key(|(b, _, _)| *b);
523522

524-
println!("{:>10} {:>6} {}", "text bytes", "funcs", "name");
523+
println!("{:>10} {:>6} name", "text bytes", "funcs");
525524
for (bytes, funcs, name) in rows.iter().take(limit) {
526525
println!("{:>10} {:>6} {}", bytes, funcs, name);
527526
}

crates/delink-core/src/cu.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl CuIndex {
6868
let mut headers = dwarf.units();
6969
let mut cu_id = 0usize;
7070
while let Some(header) = headers.next()? {
71-
let unit = dwarf.unit(header.clone())?;
71+
let unit = dwarf.unit(header)?;
7272
if let Some(cu) = build_unit(dwarf, header, &unit, abbrev_section, line_section, cu_id)?
7373
{
7474
units.push(cu);
@@ -122,12 +122,12 @@ fn build_unit<'a>(
122122

123123
let debug_info_range = compute_debug_info_range(&unit_header);
124124
let debug_abbrev_range =
125-
compute_debug_abbrev_range(unit_header.debug_abbrev_offset().0 as usize, abbrev_section);
125+
compute_debug_abbrev_range(unit_header.debug_abbrev_offset().0, abbrev_section);
126126
let debug_line_range = root
127127
.attr_value(gimli::DW_AT_stmt_list)
128128
.and_then(|v| match v {
129-
AttributeValue::DebugLineRef(off) => Some(off.0 as usize),
130-
AttributeValue::SecOffset(o) => Some(o as usize),
129+
AttributeValue::DebugLineRef(off) => Some(off.0),
130+
AttributeValue::SecOffset(o) => Some(o),
131131
_ => None,
132132
})
133133
.and_then(|off| compute_debug_line_range(off, line_section));
@@ -462,20 +462,6 @@ fn attr_string<'a>(
462462
Ok(Some(owned))
463463
}
464464

465-
fn attr_u64<'a>(
466-
entry: &DebuggingInformationEntry<DwarfSlice<'a>>,
467-
name: gimli::DwAt,
468-
) -> Result<Option<u64>> {
469-
match entry.attr_value(name) {
470-
Some(AttributeValue::Udata(v)) => Ok(Some(v)),
471-
Some(AttributeValue::Data1(v)) => Ok(Some(v as u64)),
472-
Some(AttributeValue::Data2(v)) => Ok(Some(v as u64)),
473-
Some(AttributeValue::Data4(v)) => Ok(Some(v as u64)),
474-
Some(AttributeValue::Data8(v)) => Ok(Some(v)),
475-
_ => Ok(None),
476-
}
477-
}
478-
479465
fn attr_address<'a>(
480466
dwarf: &Dwarf<DwarfSlice<'a>>,
481467
unit: &Unit<DwarfSlice<'a>>,

crates/delink-core/src/inspect.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,10 @@ fn count_dyn_relocs(binary: &Binary<'_>) -> Vec<(String, usize)> {
9898
if entsize == 0 {
9999
continue;
100100
}
101-
let is_rela = sh.sh_type(endian) == object::elf::SHT_RELA;
102101
let entry_count = data.len() as u64 / entsize;
103102
for i in 0..entry_count {
104103
let off = (i * entsize) as usize;
105-
let r_info = if is_rela {
106-
read_u64(&data[off + 8..off + 16])
107-
} else {
108-
read_u64(&data[off + 8..off + 16])
109-
};
104+
let r_info = read_u64(&data[off + 8..off + 16]);
110105
let r_type = (r_info & 0xffff_ffff) as u32;
111106
*counts.entry(r_type).or_default() += 1;
112107
}
@@ -165,12 +160,7 @@ pub fn format_text(r: &InspectReport) -> String {
165160
writeln!(out).unwrap();
166161

167162
writeln!(out, "SECTIONS").unwrap();
168-
writeln!(
169-
out,
170-
" {:<28} {:>16} {:>10} {}",
171-
"name", "addr", "size", "kind"
172-
)
173-
.unwrap();
163+
writeln!(out, " {:<28} {:>16} {:>10} kind", "name", "addr", "size").unwrap();
174164
for s in &r.sections {
175165
writeln!(
176166
out,

0 commit comments

Comments
 (0)