From 96513397f9a8d596ac2ddae1719933e77d64759a Mon Sep 17 00:00:00 2001 From: doinkythederp Date: Mon, 9 Sep 2024 17:26:42 -0700 Subject: [PATCH] feat: initialize repository --- .cargo/config.toml | 6 + .github/ISSUE_TEMPLATE/bug_report.md | 30 +++ .github/ISSUE_TEMPLATE/feature_request.md | 38 +++ .github/ISSUE_TEMPLATE/small_issue.md | 26 ++ .github/PULL_REQUEST_TEMPLATE.md | 11 + .github/workflows/rust.yml | 61 +++++ .gitignore | 88 +++++++ .vscode/settings.json | 19 ++ Cargo.toml | 11 + LICENSE | 21 ++ README.md | 3 + armv7a-vex-v5.json | 23 ++ flake.nix | 31 +++ packages/vex-libunwind-sys/Cargo.toml | 26 ++ packages/vex-libunwind-sys/build.rs | 6 + packages/vex-libunwind-sys/link/libunwind.a | Bin 0 -> 47624 bytes packages/vex-libunwind-sys/src/lib.rs | 270 ++++++++++++++++++++ packages/vex-libunwind/Cargo.toml | 26 ++ packages/vex-libunwind/src/lib.rs | 132 ++++++++++ rust-toolchain.toml | 4 + 20 files changed, 832 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/small_issue.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/rust.yml create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 armv7a-vex-v5.json create mode 100644 flake.nix create mode 100644 packages/vex-libunwind-sys/Cargo.toml create mode 100644 packages/vex-libunwind-sys/build.rs create mode 100644 packages/vex-libunwind-sys/link/libunwind.a create mode 100644 packages/vex-libunwind-sys/src/lib.rs create mode 100644 packages/vex-libunwind/Cargo.toml create mode 100644 packages/vex-libunwind/src/lib.rs create mode 100644 rust-toolchain.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..4d012be --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[build] +target = "./armv7a-vex-v5.json" + +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] +build-std-features = ["compiler-builtins-mem"] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..bfce5c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,30 @@ +--- +name: Bug report +about: Something is not working as expected +title: '' +labels: type:bug, repro:required +assignees: '' + +--- + +## Bug Description + + +## Code to reproduce + + +## Expected vs. actual behavior + + +## Additional information + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..6578f37 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,38 @@ +--- +name: Feature request +about: Propose an idea or new feature +title: '' +labels: enhancement +assignees: '' + +--- + +## What's the motivation for this feature? + + +## Describe the solution you'd like + + +## Describe the drawbacks, if any + + +## Describe the alternative solutions, if any + + +## Additional context + diff --git a/.github/ISSUE_TEMPLATE/small_issue.md b/.github/ISSUE_TEMPLATE/small_issue.md new file mode 100644 index 0000000..e7240a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/small_issue.md @@ -0,0 +1,26 @@ +--- +name: Small issue +about: Report a small problem (e.g. typo) +title: '' +labels: type:bug, repro:needed +assignees: '' + +--- + +## Problem Description + + +## Screenshots + + +## Additional information + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f77dbcb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +## Describe the changes this PR makes. Why should it be merged? + +## Additional Context + diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..7917e7e --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,61 @@ +name: Rust + +on: [push, pull_request] + +jobs: + # Check and lint are separated because linting doesn't seem to fail + # if there are errors are outside of the PR's changes. + check: + name: Check + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly-2024-02-07 + override: true + + - name: Check + uses: actions-rs/cargo@v1 + with: + command: check + args: --lib --bins --examples --all-features + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy + - uses: giraffate/clippy-action@v1 + with: + reporter: "github-pr-check" + github_token: ${{ secrets.GITHUB_TOKEN }} + clippy_flags: --lib --bins --examples --all-features + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - name: Setup | Checkout + uses: actions/checkout@v2 + + - name: Setup | Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly-2024-02-07 + override: true + + - name: Setup | Install Rustfmt + run: rustup component add rustfmt + + - name: Format + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0df57c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,88 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eae21cb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "cSpell.words": [], + "rust-analyzer.cargo.allTargets": false, + "rust-analyzer.check.targets": [ + "${workspaceFolder}/armv7a-vex-v5.json" + ], + "rust-analyzer.cargo.extraArgs": [ + "--examples", + "--lib", + "--bins" + ], + "rust-analyzer.cargo.features": "all", + "rust-analyzer.check.command": "clippy", + "rust-analyzer.showUnlinkedFileNotification": false, + "files.trimTrailingWhitespace": true, + "files.trimFinalNewlines": true, + "files.insertFinalNewline": true, + "files.eol": "\n", +} diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..384a904 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +members = ["packages/*"] +resolver = "2" + +[workspace.lints.rust] +rust_2018_idioms = { level = "warn", priority = -1 } +missing_docs = "warn" +unsafe_op_in_unsafe_fn = "deny" + +[workspace.lints.clippy] +missing_const_for_fn = "warn" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2ce05ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 vexide Contributors + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..35f3b9d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# vex-libunwind + +> High-level Rust bindings for libunwind on VEX V5 robots diff --git a/armv7a-vex-v5.json b/armv7a-vex-v5.json new file mode 100644 index 0000000..c80ad26 --- /dev/null +++ b/armv7a-vex-v5.json @@ -0,0 +1,23 @@ +{ + "cpu": "cortex-a9", + "arch": "arm", + "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + "disable-redzone": true, + "emit-debug-gdb-scripts": false, + "env": "newlib", + "executables": true, + "features": "+thumb2,+neon,+vfp3", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "llvm-target": "armv7a-none-eabi", + "max-atomic-width": 64, + "panic-strategy": "abort", + "post-link-args": { + "ld.lld": ["--gc-sections", "--nostdlib", "-Tv5.ld", "-znorelro"] + }, + "relocation-model": "static", + "target-pointer-width": "32", + "os": "none", + "vendor": "vex", + "default-uwtable": true +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..cf797dc --- /dev/null +++ b/flake.nix @@ -0,0 +1,31 @@ +{ + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + cargo-v5.url = "github:vexide/cargo-v5"; + rust-overlay.url = "github:oxalica/rust-overlay"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; + rust-overlay.inputs.flake-utils.follows = "flake-utils"; + + cargo-v5.inputs.nixpkgs.follows = "nixpkgs"; + cargo-v5.inputs.flake-utils.follows = "flake-utils"; + }; + + outputs = { nixpkgs, flake-utils, cargo-v5, rust-overlay, ... }: + (flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + cargo-v5' = cargo-v5.packages.${system}.default; + in { + devShell = pkgs.mkShell { + buildInputs = with pkgs; [ + (rust-bin.nightly."2024-02-07".default.override { + extensions = [ "rust-src" "rust-analyzer" "clippy" ]; + }) + cargo-v5' + ]; + }; + })); +} diff --git a/packages/vex-libunwind-sys/Cargo.toml b/packages/vex-libunwind-sys/Cargo.toml new file mode 100644 index 0000000..decdf16 --- /dev/null +++ b/packages/vex-libunwind-sys/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "vex-libunwind-sys" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "FFI bindings to libunwind for VEX V5 robots" +keywords = ["vex", "v5", "unwind", "libunwind"] +categories = [ + "external-ffi-bindings", + "embedded", + "science::robotics", + "no-std::no-alloc", +] +authors = [ + "vexide", + "doinkythederp ", + "Tropical", + "Gavin Niederman ", +] +repository = "https://github.com/vexide/vex-libunwind" +homepage = "https://vexide.dev" + +[dependencies] + +[lints] +workspace = true diff --git a/packages/vex-libunwind-sys/build.rs b/packages/vex-libunwind-sys/build.rs new file mode 100644 index 0000000..9d3df67 --- /dev/null +++ b/packages/vex-libunwind-sys/build.rs @@ -0,0 +1,6 @@ +#![allow(missing_docs)] + +fn main() { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + println!("cargo:rustc-link-search=native={manifest_dir}/link"); +} diff --git a/packages/vex-libunwind-sys/link/libunwind.a b/packages/vex-libunwind-sys/link/libunwind.a new file mode 100644 index 0000000000000000000000000000000000000000..1713b2945c5810d7a593e36fea8f3f75d71150ca GIT binary patch literal 47624 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

x zyTMKitGC{@^FwO7&8m>Xm7Wzs{!<5DVn|)0@Vk)}@Jp)|Li!F-CLyFQbu{4W$qFId zLCVIv%*y4xX>c=Mh7?DKs{)jD`sgjgYjvvan6byhC*VUc2m5bgqI_YW*! ztPsMT!E8J%Y^)H{cMLNLA>2L8#;ea{;wXeWirIL)!F_r@csD!w%?@6(lfT;GTO7O= zC;wIl?^Y-Oc86c<;H`D??{M($aPrqV{3jf|PdNFl4qmI1-|q119lZ5Ue%!%}JNb7x z{6+_Fqm$q1;B`9rcRT!M2XC{J-{s(SIr%*fe~*KAkCUHp@Dfh`R)@dW!MoSV-{#XB@oGIQgG-_@slEbn+TDlZI}15I&H-r>LK==-9R|A?dS5hs6-!|!$Q_B#2GIe3pb z`A<0fmmRz>JNaL6@V?^YKjrXGJ9tk!`6(wq<>Y_W$^WX8@6~@M@oSkw9EETdmwkTQ z@8mz@i*!2v5(- zgLBkEsq#&lpRew>nxF)--*))Z4u2&LlR)_v;Tw@w9;{P;V&^061>w1}D-T|$%A`rT z5-1OTRBg%PuUCI2JV$1EaG83))#TLIK)-<20uO6tp3&F%kj%e zk#r$m2Tl*(s){YXT-~Zlh3EC)^xz$;%;L+{9jZ!r&V18@t*YAM%T=rTsKrkY##PMX z%keACO~P}fF+JF+R$6?y!i#mnFV^{8s@>wt@uYZ{@N0B_LiJdDxk{+}gs;~5+th!z z_;UOr^d;ddb^d46UW+eRpHa^UUxB(W5AIM`6hcq}`|pPxewFZ?iOYkZQ-AE_f6w7x z6Q0-Q(}M#F53=acguk6uyrk)t)tRFjwWQ_tHA|Z2U5l4lvYy|6&uO%na$x+|114r_INM9gTROJj z#lndi)xUmM`Rwm1JN@zB`1OYDGsiiwbA0jQy-z%6e{jzIKuU5HRvqzxb;y+UT%R@kzp|9%RQESB@WA8!jqYxAN;;|Z@BCS z-u>XRm%V$zOlPRN+M_HN!{G=2!sDxWfxv)tu65_U>fL9r24$!+KkXa+=BIhXf5ekx z`Fb3dz2@CxE<57gV=nulmtPgj$Tf-_uN5e_kJQL5&B$qc{!HuvU56~%*9Pj_cVkAr znE69epP;;Un)6qlUDcq^f~S3_NTK%(snL527zX&k_8<CX50cAFy?;zgW$OK~_z4=L9NMjo6z$tbiuUX$Mf);T-RV)k z-CmLMpb=!To+?27dfMQ~4~aY|L)9ja`gq@!e9&rSv0p|(*)MgyqQA0U*l!uCws_Pp z|Du!!WvJ@)sGt8m$p>Yq`jkhRzXJ6+=OmtQ0Idd1kw^M|@}Nh^zlnRlL7yNGz5B?6rpQC@e)6EFLH+vv5*P;P34_e}M`<_E zX7JR@`k-E|2l})g&;iOr-)>Oq)%6a22g!pz&wS_uwAKrVjNZq=Fd(xKB=~|i9|ynf zjsGCpV7kF(KXq}`l7FsVf zCRE!6xhC?sb-zMrv(Pm{*9u)Hv`uJS=q90?h4u*T6S__4eL|B$`-MIrbU^5Cp?ifs zArz)+J5xgU3w>7T0ilCJ4+?!==pms)LJtdlS?H@mj|e>~^qA1&LWhOEA@rosQ$kM* zJtOpOq3;M)7>BHHo>xfuoC^B^&o87ULT3u)b1O{ed_cbZ4}xhl=BJmn}u>dAd&`gl-nvBeYNGHlg7T z0ilCJ4+?!==pms)LJtdlS?H@mj|e>~^qA1&LWhOEA@rosQ$kM*JtOpOq3;Og0*K=< zEVPgm^J}rt5}`AN&JtQCG$OP@Xr<6d&`gl-nvBeYNGHlgBlGawrvChp{=H-p z@cC(@iMQSUXz3)nkfmmFJQ@G3)JgOwhqB4?%Dtg8sa}m&*3GYLP1H!q@pV{!)vIP+ zoziYiuo zB@`IA61Kb6GfE!ol@EuAU!R^3RHG$yn%cN*-0njc(=VMR#N@bbQ(~voFB-RjKcH z=3$7OlSDo_OOt#vKDQGlGp`4>fCcKCub;HYjqS+fRgpu^(&T@#KDUxgc3%8!5ewQp zD3Tl5&&>;*C1K&ZAIi^-KTayIo}7}FzU&X~=ho)P zp|d0=vP+ofsK&WHF&*EB&*j-9sIaS?ds~ciOE(lZ!^pihx3j&U$L!y*dd)9p6SfZs zKW*>)0(YK!ZRk~l{sC_*b|M=0K%34Mdoynz%-hhtWefJ;@ao0-n*O|vz1>@Ta3A`7 z!`+wiy@*Vx!{JQC=MaAn5kKMU=*l%A-N@k)i@b8{EV-ex$kAql_u^UP`jIyak@kJ} zEONNr;^TeqEOLX$GkAy3BFAS4j2s>f$?Na1C5J~v^2+g<0pl;9OUPHx#ki+z9^+P=4*BG+Ms6YEx#akmB=M%;-Yx_2Xp;%%xEcwR3yK_{ zS+Ij)2at&4o*kAP?J(b&FnA9j?Lx$u$n`Doo@ZjcV9074SdMi`Y-1mvji>-`g26k9 z1j-rv`0Rrn40{U>@ZYzOa@2#{nK~G}n~-kX*KgU!wxS%%@tF+#_wC~|7VOU^7`#6e zIb$E6v9N<-FGqdg*td^z)bl|RHh3R^oNeD;%f8DYYwY`yhv(bJXE}&xg2Cf6479=6 zr@-5Rc?|#L$@%tCj(D?mZl>?Ng>>7#{g!=KK-SoICpsvxYo&Z4%GvWZ<(R(+2c)JS zltHdS%8*cwf%n2~y$7K;f^_z)s}Lzid*=$C@z?Z2Wa&U%4EsDe-(SkHJh2#z-Y0Ni z>pg1udyUAk+_ZvhKbnBY`M?B&cY(+m`_@3t4#vKFJUQP!%2Cf85jJ>ykJYyC4a>f{ zkfj{U)lbQ`ZyoS92^NXLd)>i11H4M)v!3UR9Pw%e&-lS-R_tK>c-)io{h%Dn6N|y< z-2*w>kFvVVyum(X{OGy)SVlaA-LC*H0&hlfC$g$ja@rQL}`u!~687w6Gc(*{##%r|jt`j-pJui61 zj}>|R;Crml>-#}DmM0d2@#AX9*?QMldh11w<@S4cz8`CV*GwP@2JcCcGxqTr89SK% z@~$W6+ebO-`KSmRynlfl{`=>dxMg1q>6Bx+PZnj@^MO3}wTYaukI%%|!PxhGPtLcG za@2FZ2pjvp3pv}qKFhvF$Qt|hyf53nFfyL76dSxs$k}-Pz%%QnWftD&1<&}wdCm^T zk29W}?+4}R2eBATvD1#;eU=}~MULfufXR;7ra$ioz_Z{@FnAw_obAT}%a5BNOgZAc zAb7@)6_}UoVEnk|BBwt?j^&BPVDw%IIa}{x%a5Byj^+Ny!}Hf`Yk>DMfg~8bM+}~% z9|c|n$Il_M{~JHPE_h~oEW^BH2jj;po?Ook$)p_ZF=NT-{eh$RjO9lQTn0d(*)SFZ7-lryu;vk--ZIp7A4!dCm?7`f5+k_k(iugIEkk?-h{K?cpV> zdgv{|G4-w$IhMQI@nbRYDvUCb15r0Pcq=SF_;n@YN4ww|Kh{x+6%6z)PtNy)auhXR zYBGLocl7pKetZJ*M(fDKrB4c_lMczc0o#(ArS_dUTgew@zZ$Im@E-w(=B zlvoT#?+Him0n3l|BFA#ksoDMNZ6xOMV=CnA_B{l=D9W>a;}+gkf@l2bXCW(?_PD{5 z^ZlS4?I9L}@neaj_mt(wMv-H=0nuyPV*q%(<~PCM#T~qNfER%f{pdub9PxGtp7G;k z9zUM*#*gRo`0@IG$vB=1$=MUnp;;tr7`-l*W2b;(SeKkZ<~M`F5+55c1x%M**i_|XkH z?T5&{WBIX54D@TBoZqh~M|+6HVElN+(Rky=lmin#2aRztiO*#4nFjl^gn>ye8Yg6Dkn9z zF?$$tyRk<429CdtNK@I4^wrb}4pq-J$SdNJ7YrVTSC-t->#=tOY%#&e&9AA++KkoT z8#&KjtTnZ@b>2?q=iZC;iP>74zZdJraaD7AiMOwsO6t9OM!5G4_ofJ9-;xmazw!3_ zxIG=%oeH6zivntGI=DME1DD68plQ{Ey~40piP_JB^4wd6d!{grJoi2^$LQJVQk0$9 z#ywzeOXD^EqC)J0av@}!qPxbzC|e1>0Q;h>0AGgVW>D^}!+kz5-4@V$=~}ThP~7Dvf>d{Jb#siP8A5OV_KEVXF=v z2qd{r9{0^coqQ`01x9rHSU5U3c11mG#ePkp8tgd|-J$pOyy8{(g#Fhp8ZO3uuy>}X z4i%50AH$V(+8(?;ulHT!9$CSm6!uBkIXVM4EU$)ui#^!FIvsk3kVakHr;WC#{v`K! z;T~70`;ltYVKAoa)8B8W8T6~*2*upi?NZJbJ1!$0n8W%^D4 zb%MQ>N(-$#t?%na|6k}+sKXb3vU0RiJ*4-rRcPZ%jIBGTJ~Ub!?bm%BeRhOA`^TO0 zF)qNX=4R~mguR0>E?B?Z3rh_>HP(c^y&|A1KxcwBgK{q^j`w{)49LERx=!`=3Q~~>m>3gcbDA~ikyoOfkK8FrnIu(0O!S6lAI4Iq+mi|j5gmJMt%{c;nSm&u`j3d+^$NS|Nzvzn(5-(8J zKUx5vjzqlu%V?XopPyH5DrEmRWT_8(IcDaX!RNAU#XRBL`aar<@lIRw*@-36S?%P! zCk)Yg4vQ)*;u^O>I(U~j7x`1D6W-OjnE6sP!~(N@lNMjrE^o;NAG4En+) zPmR&HaP*O}!pI|Ugi9V8L!Cd#y_9%9@O5Fn#@=38^EJ;QoUh$^8h&8EKyMB=dS6Ca z&clJEH`ikiP=Ef${;u$UZ5pS1bcs~@JJ4-xE=1qHAd3Ft_;FCmhrRuGwI8hea1Z=Q zdVZjoAD#bouKVzL?jF#&259Vm@4d|XH*dHIqcz#sZP4+p2dDt_p z=wamf=RllGPTw;3P44}slGw8lZC-))38MW&yY+c*M5RzCgQ;{VdKLD{yMOe@k;g|u z&99%}zHUueo}G>sj1Hph??>I>{`G^qah$+$3Un^)y`ZFEv`}4=4q!h)%;zIvV1EGn zU1FcZ(ZF=j%eK#88-&%zMlf&e48&4z`bla=3;jl0UyOc53@wj-&f}@l z*KnL(j{YS;r*Zm;mGyV!;u}qg2?qH1+#Z3t}k30{}{M0N0;hxhl+ZT z_PwmIzZ&cdM_)g2MLFsQ=?cr;}w1AZ+On-{)wl*hWDS#)5?3tgs{N{V2u<{n9>_ynf=eLOn-QGjKjciB(*yfVQMlu*chb?PDX@ z%kN37H`1KD0R6KI;5)HiBv!NneYk%#g!)NhE%I5^&y3Z(MsS|g{VU4{__TdK`pWDb z!>oU<9cc^CU$lp^A&lE_nn^uIfi&hy^j zH-pK1=RK9Oe-JdNuM{%{a(xTFEt8EStX8bRZ^38d<1A){T;GOov+}*G)l35SYRbmT=5p=T zl#OR<&%->Qy_quF**>Kz8xN;aD}?ZMscehNtX!6t55P%kNL}vW@u{gy;NDBwc(XH^ zIO1MQb_n5Vq&7Pt>**xQU*+Ikl_ecgS37*AgIDR~S2=i9PJXphzS_y3>*V7sYX$D5 zlLvkERK6AW!r~UpcQiMrPOBS2Ff=grBAHR;p#fbLO3{ z(7xU$Zs#s-YPf#6*?yq)jukZv@G3xOSG=`n6LuM_ZPtA2hVCxD717$)TvN+e1vYH$ zO?3Byt*vSGfLfP8q_=x>>-Bhz;O_O@$-v~?wz{RYxw{AN4Rj^?@XBJ(yy(2nL~r{% zYz^SP^WuExS7-ATK)(0l<@qlJc6Qy>Eot%|V$QE3V=LK?4c+mM){aemt$1yr_tR2H zzrc~R2tK5o>-)<1?6UZ}y1g^ev2@#pj-I~G?yihsQcb?xlI|@%n>+eC{DjpViLF~Q z>Dvo z4^w_C+J_YReWb|edkf5;8T9gFq)2ZjMLN&VLHq!4pU|YxexZC$p7{epcMIJsbY{rI zmk)e4g_K z^9hFcsv~=z%5~Nl=jM47$@T8wc@%TL?lJCElB-&B3&~rB?H%pwJI#!VU4QVNKQ{Ss z)Z{$hDPbI|8SEYz%^&02QJg#D;$z8ErD)WfC zO(kOfsXnLqIfb$f_f`gZ4VLV)8ET1SLFZd#KvLJ$t->F(O%=_Q|OAF zMWZX4XRNrZ$g>TZoU)!9t>f07<6OuglFR%YV));T4Z$1od_ z$5@i+kWcPvPVhiE*BV zM(;ik&u@?8;16gd?~lQ|$HChNya+@%erF>Zye|o!@xy+;5MsK{NMG>ed_O2hKZwO( z^!}-%_mJgBg~+ko--})|K6V4ZVAyzXIQH$eg&=6^`9h@Q*td^z)N>WV5KOTG9N6{z zs%2lL$g$i?56`b>z5~d)-2{VI<=`E+@c7dN<%qWg2ej4H^UL5lpP4{8hPymD-;bl< zS>F82VdU21!1m)5^v;4D+n0AWD93VtiUaC3^?V$B1$YxE$FK_rHeMKDEKfZCghDy; z-^79Khcdq}A&-H13~5i!_k(gQZ+?y;9>Y&?VCyZ0UNisIBA;?Bw+Q8JKMKL`N4g0H zj}KkicxAxDf9(g?00wWa;F#ei=SOj^a_fZee zZ;ylE_gRV!9^Y}d@fs~Zc-P0^eL?VyAI+wr1=INPO;67EgL3r4+(9yWzv1XzXZcZY z>HUT1HR{&lfWM)eVDMgZ@HPXl2|{ZTdAG^<@uuJzKN@MA6%6!6(1T;&56V&0+_^G( zFNB<3e+Ml;8X#}<-tOV~?Xd!2{O#WagE!Z~I}E%Ogy_c-M1!|d@Qfd?n%`3)!(jaQ zlqcu=K{@(CEC!=D;ppWv+h%+$6FHW9S@eSFa1?kIa!g|Io^tT|fXDLmqezb7Z2rTwa0yyA2*2{%W-dS))B2ch>GN1D1Wft4BGO`+{R%1bF6Lj%?rGxP!OPs^?WAN4)KV zXZ)zooU{q c_int; + + pub fn unw_init_local(cur: *mut unw_cursor_t, ctx: *mut unw_context_t) -> c_int; + + pub fn unw_step(cur: *mut unw_cursor_t) -> c_int; + + pub fn unw_get_reg(cur: *mut unw_cursor_t, reg: unw_regnum_t, val: *mut unw_word_t) -> c_int; + + pub fn unw_get_fpreg(cur: *mut unw_cursor_t, reg: unw_regnum_t, val: *mut unw_fpreg_t) + -> c_int; + + pub fn unw_set_reg(cur: *mut unw_cursor_t, reg: unw_regnum_t, val: unw_word_t) -> c_int; + + pub fn unw_set_fpreg(cur: *mut unw_cursor_t, reg: unw_regnum_t, val: unw_fpreg_t) -> c_int; + + pub fn unw_resume(cur: *mut unw_cursor_t) -> c_int; + + #[cfg(target_arch = "arm")] + // Save VFP registers in FSTMX format (instead of FSTMD). + pub fn unw_save_vfp_as_X(cur: *mut unw_cursor_t); + + pub fn unw_regname(cur: *mut unw_cursor_t, reg: unw_regnum_t) -> *const c_char; + + pub fn unw_get_proc_info(cur: *mut unw_cursor_t, info: *mut unw_proc_info_t) -> c_int; + + pub fn unw_is_fpreg(cur: *mut unw_cursor_t, reg: unw_regnum_t) -> c_int; + + pub fn unw_is_signal_frame(cur: *mut unw_cursor_t) -> c_int; + + pub fn unw_get_proc_name( + cur: *mut unw_cursor_t, + buf: *mut c_char, + len: usize, + offp: *mut unw_word_t, + ) -> c_int; + + pub static mut unw_local_addr_space: unw_addr_space_t; +} + +/// Instruction pointer +pub const UNW_REG_IP: unw_regnum_t = -1; +/// Stack pointer +pub const UNW_REG_SP: unw_regnum_t = -2; + +// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1. +// Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3. +// In this scheme, even though the 64-bit floating point registers D0-D31 +// overlap physically with the 32-bit floating pointer registers S0-S31, +// they are given a non-overlapping range of register numbers. +// +// Commented out ranges are not preserved during unwinding. +pub const UNW_ARM_R0: unw_regnum_t = 0; +pub const UNW_ARM_R1: unw_regnum_t = 1; +pub const UNW_ARM_R2: unw_regnum_t = 2; +pub const UNW_ARM_R3: unw_regnum_t = 3; +pub const UNW_ARM_R4: unw_regnum_t = 4; +pub const UNW_ARM_R5: unw_regnum_t = 5; +pub const UNW_ARM_R6: unw_regnum_t = 6; +pub const UNW_ARM_R7: unw_regnum_t = 7; +pub const UNW_ARM_R8: unw_regnum_t = 8; +pub const UNW_ARM_R9: unw_regnum_t = 9; +pub const UNW_ARM_R10: unw_regnum_t = 10; +pub const UNW_ARM_R11: unw_regnum_t = 11; +pub const UNW_ARM_R12: unw_regnum_t = 12; +pub const UNW_ARM_SP: unw_regnum_t = 13; // Logical alias for UNW_REG_SP +pub const UNW_ARM_R13: unw_regnum_t = 13; +pub const UNW_ARM_LR: unw_regnum_t = 14; +pub const UNW_ARM_R14: unw_regnum_t = 14; +pub const UNW_ARM_IP: unw_regnum_t = 15; // Logical alias for UNW_REG_IP +pub const UNW_ARM_R15: unw_regnum_t = 15; +// 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31. +pub const UNW_ARM_S0: unw_regnum_t = 64; +pub const UNW_ARM_S1: unw_regnum_t = 65; +pub const UNW_ARM_S2: unw_regnum_t = 66; +pub const UNW_ARM_S3: unw_regnum_t = 67; +pub const UNW_ARM_S4: unw_regnum_t = 68; +pub const UNW_ARM_S5: unw_regnum_t = 69; +pub const UNW_ARM_S6: unw_regnum_t = 70; +pub const UNW_ARM_S7: unw_regnum_t = 71; +pub const UNW_ARM_S8: unw_regnum_t = 72; +pub const UNW_ARM_S9: unw_regnum_t = 73; +pub const UNW_ARM_S10: unw_regnum_t = 74; +pub const UNW_ARM_S11: unw_regnum_t = 75; +pub const UNW_ARM_S12: unw_regnum_t = 76; +pub const UNW_ARM_S13: unw_regnum_t = 77; +pub const UNW_ARM_S14: unw_regnum_t = 78; +pub const UNW_ARM_S15: unw_regnum_t = 79; +pub const UNW_ARM_S16: unw_regnum_t = 80; +pub const UNW_ARM_S17: unw_regnum_t = 81; +pub const UNW_ARM_S18: unw_regnum_t = 82; +pub const UNW_ARM_S19: unw_regnum_t = 83; +pub const UNW_ARM_S20: unw_regnum_t = 84; +pub const UNW_ARM_S21: unw_regnum_t = 85; +pub const UNW_ARM_S22: unw_regnum_t = 86; +pub const UNW_ARM_S23: unw_regnum_t = 87; +pub const UNW_ARM_S24: unw_regnum_t = 88; +pub const UNW_ARM_S25: unw_regnum_t = 89; +pub const UNW_ARM_S26: unw_regnum_t = 90; +pub const UNW_ARM_S27: unw_regnum_t = 91; +pub const UNW_ARM_S28: unw_regnum_t = 92; +pub const UNW_ARM_S29: unw_regnum_t = 93; +pub const UNW_ARM_S30: unw_regnum_t = 94; +pub const UNW_ARM_S31: unw_regnum_t = 95; +// 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP. +// 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX) +pub const UNW_ARM_WR0: unw_regnum_t = 112; +pub const UNW_ARM_WR1: unw_regnum_t = 113; +pub const UNW_ARM_WR2: unw_regnum_t = 114; +pub const UNW_ARM_WR3: unw_regnum_t = 115; +pub const UNW_ARM_WR4: unw_regnum_t = 116; +pub const UNW_ARM_WR5: unw_regnum_t = 117; +pub const UNW_ARM_WR6: unw_regnum_t = 118; +pub const UNW_ARM_WR7: unw_regnum_t = 119; +pub const UNW_ARM_WR8: unw_regnum_t = 120; +pub const UNW_ARM_WR9: unw_regnum_t = 121; +pub const UNW_ARM_WR10: unw_regnum_t = 122; +pub const UNW_ARM_WR11: unw_regnum_t = 123; +pub const UNW_ARM_WR12: unw_regnum_t = 124; +pub const UNW_ARM_WR13: unw_regnum_t = 125; +pub const UNW_ARM_WR14: unw_regnum_t = 126; +pub const UNW_ARM_WR15: unw_regnum_t = 127; +// 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC} +// 134-143 -- Reserved +// 144-150 -- R8_USR-R14_USR +// 151-157 -- R8_FIQ-R14_FIQ +// 158-159 -- R13_IRQ-R14_IRQ +// 160-161 -- R13_ABT-R14_ABT +// 162-163 -- R13_UND-R14_UND +// 164-165 -- R13_SVC-R14_SVC +// 166-191 -- Reserved +pub const UNW_ARM_WC0: unw_regnum_t = 192; +pub const UNW_ARM_WC1: unw_regnum_t = 193; +pub const UNW_ARM_WC2: unw_regnum_t = 194; +pub const UNW_ARM_WC3: unw_regnum_t = 195; +// 196-199 -- wC4-wC7 (Intel wireless MMX control) +// 200-255 -- Reserved +pub const UNW_ARM_D0: unw_regnum_t = 256; +pub const UNW_ARM_D1: unw_regnum_t = 257; +pub const UNW_ARM_D2: unw_regnum_t = 258; +pub const UNW_ARM_D3: unw_regnum_t = 259; +pub const UNW_ARM_D4: unw_regnum_t = 260; +pub const UNW_ARM_D5: unw_regnum_t = 261; +pub const UNW_ARM_D6: unw_regnum_t = 262; +pub const UNW_ARM_D7: unw_regnum_t = 263; +pub const UNW_ARM_D8: unw_regnum_t = 264; +pub const UNW_ARM_D9: unw_regnum_t = 265; +pub const UNW_ARM_D10: unw_regnum_t = 266; +pub const UNW_ARM_D11: unw_regnum_t = 267; +pub const UNW_ARM_D12: unw_regnum_t = 268; +pub const UNW_ARM_D13: unw_regnum_t = 269; +pub const UNW_ARM_D14: unw_regnum_t = 270; +pub const UNW_ARM_D15: unw_regnum_t = 271; +pub const UNW_ARM_D16: unw_regnum_t = 272; +pub const UNW_ARM_D17: unw_regnum_t = 273; +pub const UNW_ARM_D18: unw_regnum_t = 274; +pub const UNW_ARM_D19: unw_regnum_t = 275; +pub const UNW_ARM_D20: unw_regnum_t = 276; +pub const UNW_ARM_D21: unw_regnum_t = 277; +pub const UNW_ARM_D22: unw_regnum_t = 278; +pub const UNW_ARM_D23: unw_regnum_t = 279; +pub const UNW_ARM_D24: unw_regnum_t = 280; +pub const UNW_ARM_D25: unw_regnum_t = 281; +pub const UNW_ARM_D26: unw_regnum_t = 282; +pub const UNW_ARM_D27: unw_regnum_t = 283; +pub const UNW_ARM_D28: unw_regnum_t = 284; +pub const UNW_ARM_D29: unw_regnum_t = 285; +pub const UNW_ARM_D30: unw_regnum_t = 286; +pub const UNW_ARM_D31: unw_regnum_t = 287; +// 288-319 -- Reserved for VFP/Neon +// 320-8191 -- Reserved +// 8192-16383 -- Unspecified vendor co-processor register. diff --git a/packages/vex-libunwind/Cargo.toml b/packages/vex-libunwind/Cargo.toml new file mode 100644 index 0000000..8b31745 --- /dev/null +++ b/packages/vex-libunwind/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "vex-libunwind" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "High-level Rust bindings for libunwind on VEX V5 robots" +keywords = ["vex", "v5", "unwind", "libunwind", "backtrace"] +categories = ["api-bindings", "embedded", "science::robotics", "no-std"] +authors = [ + "vexide", + "Gavin Niederman ", + "doinkythederp ", + "Tropical", +] +repository = "https://github.com/vexide/vex-libunwind" +homepage = "https://vexide.dev" +readme = "../../README.md" + +[dependencies] +snafu = { version = "0.8.4", default-features = false, features = [ + "unstable-core-error", +] } +vex-libunwind-sys = { version = "0.1.0", path = "../vex-libunwind-sys" } + +[lints] +workspace = true diff --git a/packages/vex-libunwind/src/lib.rs b/packages/vex-libunwind/src/lib.rs new file mode 100644 index 0000000..e26b01f --- /dev/null +++ b/packages/vex-libunwind/src/lib.rs @@ -0,0 +1,132 @@ +//! High-level Rust bindings for libunwind on VEX V5 robots +#![no_std] + +use core::{cell::RefCell, mem::MaybeUninit}; +use vex_libunwind_sys::*; + +use snafu::Snafu; + +/// An error that can occur during unwinding. +#[derive(Debug, Snafu)] +pub enum UnwindError { + /// Unspecified/general error. + Unspecified, + /// Out of memory + NoMemory, + /// Invalid register number + BadRegisterNumber, + /// Attempt to write to a read-only register + WriteToReadOnlyRegister, + /// Stop unwinding + StopUnwinding, + /// Invalid instruction pointer + InvalidIP, + /// Bad frame + BadFrame, + /// Unsupported operation or bad value + BadValue, + /// Unwind info has unsupported version + BadVersion, + /// No unwind info found + NoInfo, + /// An error with an unknown error code occured + #[snafu(display("libunwind error {code}"))] + Unknown { + /// The error's code + code: uw_error_t, + }, +} + +impl UnwindError { + /// Creates a `Result` that is `Ok` if the error code represents a success + /// and `Err` if it represents an error. + pub const fn from_code(code: uw_error_t) -> Result<(), UnwindError> { + if code == error::UNW_ESUCCESS { + Ok(()) + } else { + Err(match code { + error::UNW_EUNSPEC => UnwindError::Unspecified, + error::UNW_ENOMEM => UnwindError::NoMemory, + error::UNW_EBADREG => UnwindError::BadRegisterNumber, + error::UNW_EREADONLYREG => UnwindError::WriteToReadOnlyRegister, + error::UNW_ESTOPUNWIND => UnwindError::StopUnwinding, + error::UNW_EINVALIDIP => UnwindError::InvalidIP, + error::UNW_EBADFRAME => UnwindError::BadFrame, + error::UNW_EINVAL => UnwindError::BadValue, + error::UNW_EBADVERSION => UnwindError::BadVersion, + error::UNW_ENOINFO => UnwindError::NoInfo, + code => UnwindError::Unknown { code }, + }) + } + } +} + +/// Holds context about an unwind operation. +pub struct UnwindContext { + inner: unw_context_t, +} + +impl UnwindContext { + /// Creates an new unwind context for the current point of execution. + #[inline(always)] // Inlining keeps this function from appearing in backtraces + pub fn new() -> Result { + let mut inner = MaybeUninit::::uninit(); + // SAFETY: `unw_getcontext` initializes the context struct. + let inner = unsafe { + let code = unw_getcontext(inner.as_mut_ptr()); + UnwindError::from_code(code)?; + inner.assume_init() + }; + Ok(Self { inner }) + } + + /// Returns the underlying libunwind object. + pub fn as_mut_ptr(&mut self) -> *mut unw_context_t { + &mut self.inner + } +} + +/// Allows access to information about stack frames. +pub struct UnwindCursor<'a> { + inner: RefCell, + lifetime: core::marker::PhantomData<&'a mut UnwindContext>, +} + +impl<'a> UnwindCursor<'a> { + /// Creates an unwind cursor for the given context. + pub fn new(context: &'a mut UnwindContext) -> Result { + let mut cursor = MaybeUninit::::uninit(); + // SAFETY: `unw_init_local` initializes the cursor struct. + let cursor = unsafe { + let code = unw_init_local(cursor.as_mut_ptr(), context.as_mut_ptr()); + UnwindError::from_code(code)?; + cursor.assume_init() + }; + Ok(Self { + inner: RefCell::new(cursor), + lifetime: core::marker::PhantomData, + }) + } + + /// Steps to the next frame of the unwind cursor. + /// + /// Returns true if was another frame to step to or false + /// if the cursor has reached the end. + pub fn step(&mut self) -> bool { + let code = unsafe { unw_step(&mut *self.inner.borrow_mut()) }; + code == UNW_STEP_SUCCESS + } + + /// Returns the value of the given register for the current frame. + pub fn get_register(&self, register: unw_regnum_t) -> Result { + let mut reg_value = 0; + let code = unsafe { unw_get_reg(&mut *self.inner.borrow_mut(), register, &mut reg_value) }; + UnwindError::from_code(code)?; + Ok(reg_value) + } + + /// Returns whether the current frame is a signal frame. + pub fn is_signal_frame(&self) -> bool { + unsafe { unw_is_signal_frame(&mut *self.inner.borrow_mut()) > 0 } + } +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..a2fae3f --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2024-02-07" +components = ["rust-src"] +targets = ["armv7a-none-eabi"]