Welcome to the artifact for the USENIX VehicleSec 2026 submission of our paper, titled "RVDebloater: Mode-based Adaptive Firmware Debloating for Robotic Vehicles".
-
Clone the Repository
- Create an RVDebloater Project Directory and set the environment variable
$RVD_PROJ
mkdir rvd-project echo 'export RVD_PROJ=${HOME}/rvd-project' >> ${HOME}/.bashrc source ${HOME}/.bashrc
Change ${HOME}/rvd-project to the correct path and name if you use a different path or name
- Clone the RVDebloater repository:
cd ${RVD_PROJ} git clone https://github.com/anonymoussubmission26/RVDebloaterArtifact.git
- Rename the cloned repository folder from
RVDebloaterArtifacttoRVDebloater(required, as all scripts reference this path):
mv ${RVD_PROJ}/RVDebloaterArtifact ${RVD_PROJ}/RVDebloater
- Create an RVDebloater Project Directory and set the environment variable
-
Pre-requisites
-
If
gois already installed check the version- check version using
/usr/local/go/bin/go version
- If version is 1.17 or higher, skip to the next step, otherwise remove it with the following
and run
/usr/local/go/bin/go env GOPATH
sudo rm -rf [directory]on the resulting directory, for example:lastly runsudo rm -rf ${HOME}/gosudo rm -rf /usr/local/go
- check version using
-
Run the prereq script to install dependencies and set environment variables:
cd ${RVD_PROJ} ./RVDebloater/scripts/pre-req.sh source ${HOME}/.bashrc
The script does the following:
- Installs some dependencies for
SVFandgllvm - Installs our version of
gllvm(ap-gllvm) using go - Clones
ArduPilot(tagCopter-4.6.3) andPX4(tagv1.16.0) repositories torvd-projectdirectory - Builds and configures
SVF
Note: The setup process can take approximately 20 minutes on a standard PC configuration, as it installs LLVM among other dependencies.
- Installs some dependencies for
-
-
Instrumented Simulation
The
run-simulation.shscript does the following:- Builds ArduPilot (copter, plane, or Rover) using our modified version of gllvm (Please modify the commented instructions in the script according to your target vehicle)
- Extracts the whole program bitcode file
- Runs instrumentation on the bitcode file
- *Note:
instrument-ap.shscript supports two separate operations (instrumentation for profiling and instrumentation for monitoring), please comment or uncomment the corresponding sections of the script depending on which operation you intend to use. - AddDPFunc.so and AddTrack.so are for profiling. CallOverwrite.so and AddEnforce.so are for monitoring.*
- *Note:
- Recompiles the bitcode back to executable
- Runs the ArduPilot SITL simulation using the instrumented executable file
- The generated files including final executable and bitcode file are stored in
${AP_BIN}(e.g.,rvd-project/ardupilot/build/sitl/bin)
Run with:
cd ${RVD_PROJ} RVDebloater/scripts/run-simulation.sh
-
Running Vehicle In Simulation
The following instructions is for copter
-
Once the simulation has loaded, wait for the following 2 lines to appear in the console
AP: EKF3 IMU0 is using GPS
AP: EKF3 IMU1 is using GPS -
Then run the following 3 commands in the terminal:
mode guidedarm throttletakeoff 10
each of these commands should produce a message in the console indicating that the command was accepted, e.g.
Got COMMAND_ACK: DO_SET_MODE: ACCEPTEDaftermode guidedFor plane the commands would be:
qloiterarm throttlerc 3 1500rc 3 1700qloiter
-
Then try repositioning the vehicle
- Right-click anywhere on the mini map
- Select "Fly To"
- Press "OK" on the Altitude pop up window after entering the desired value
For rover the commands would be:
mode guidedarm throttle
-
The vehicle should begin moving to the selected location
-
The current setup doesn't require your intervention, as it uses an automatic script to run different missions.
Manual Control: By default,
run-simulation.shruns the simulation automatically. To control the vehicle manually, uncomment the following line in the script:${SIM_V_SCRIPT} -v ${VEHICLE} ${FRAME_ARG} --console --map -w -N
And comment out the following lines:
# cp ${RVD_PATH}/scripts/run_missionRover.py \ # ${AUTOTEST_BASE} # cp -r ${RVD_PATH}/mission ${AUTOTEST_BASE}/ # cd ${AP_PATH}/ArduCopter # cd ${AP_PATH}/ArduPlane # cd ${AP_PATH}/Rover # ${AUTO_MISSION}
-
The artifact requires Ubuntu 22.04 LTS and has been developed and tested exclusively on this distribution. Other Linux distributions are not automatically supported and may fail during build or simulation due to differences in library versions, package managers, or system paths.
All required software dependencies (including LLVM, SVF, and the modified version of gllvm) are installed and configured by scripts/pre-req.sh. The pre-req.sh script requires go version 1.17 or higher.
The artifact includes pre-defined mission files (in the missions directory) for each evaluated RV type: ArduCopter, ArduPlane, ArduRover, and PX4. The following pinned firmware versions are used to ensure reproducibility:
- ArduPilot: tag
Copter-4.6.3on the ArduPilot GitHub repository - PX4: tag
v1.16.0on the PX4-Autopilot GitHub repository
The pre-req.sh script automatically clones these exact tagged versions.
| Directory | Description |
|---|---|
SVF |
Modified SVF pointer analysis framework for firmware analysis |
callgraphs |
Pre-generated call graphs for each RV type (Copter, Plane, Rover) |
missions |
Flight or navigation mission definitions for RV simulation |
outputs |
Required functions identified by RVDebloater static analysis |
profiles |
RVDebloater profiler tool and profiling results |
scripts |
Primary scripts for running RVDebloater analysis and simulation |
The scripts are pre-configured to run RVDebloater in Rover (profiling) mode. To verify a successful installation, run:
cd ${RVD_PROJ}
RVDebloater/scripts/run-simulation.shOnce the simulation has loaded, wait for the following two lines to appear:
AP: EKF3 IMU0 is using GPS
AP: EKF3 IMU1 is using GPS
Then issue the following commands in the terminal (one at a time):
For Rover:
mode guided
arm throttle
Each command should produce an acknowledgment in the console (e.g., Got COMMAND_ACK: DO_SET_MODE: ACCEPTED after mode guided). A successful run will produce profiling output in the profiles directory and simulation logs confirming mission completion.
- (C1): RVDebloater effectively identifies required functions through combined static and dynamic analysis and reduces the firmware's attack surface at runtime (Section 6.2 in paper).
- (C2): RVDebloater supports multiple RV types (ArduCopter, ArduPlane, ArduRover, and PX4) and operates correctly in both profiling and monitoring modes.
Estimated time: 15 human-minutes + 1 compute-hour
This experiment demonstrates that RVDebloater correctly identifies required functions using profiling-based analysis for each RV type.
Step 1 — Select RV type. Edit scripts/run-simulation.sh and uncomment the appropriate mission line (keep only one uncommented):
# For Copter:
AUTO_MISSION="${AUTOTEST_BASE}/run_mission.py"
# For Plane:
AUTO_MISSION="${AUTOTEST_BASE}/run_missionPlane.py"
# For Rover:
AUTO_MISSION="${AUTOTEST_BASE}/run_missionRover.py"Step 2 — Configure vehicle type. In the same file, uncomment the vehicle and frame configuration (keep only one uncommented):
# For Copter:
# export VEHICLE="copter"
# FRAME_ARG=""
# For Plane:
# export VEHICLE="plane"
# FRAME_ARG="-f quadplane"
# For Rover:
export VEHICLE="rover"
FRAME_ARG=""Also uncomment one of lines 168, 169, or 170 based on your vehicle type:
# For Copter:
# cp ${RVD_PATH}/scripts/run_mission.py ${AUTOTEST_BASE}
# For Plane:
# cp ${RVD_PATH}/scripts/run_missionPlane.py ${AUTOTEST_BASE}
# For Rover:
cp ${RVD_PATH}/scripts/run_missionRover.py ${AUTOTEST_BASE}And one of lines 172, 173, or 174:
# For Copter:
# cd ${AP_PATH}/ArduCopter
# For Plane:
# cd ${AP_PATH}/ArduPlane
# For Rover:
cd ${AP_PATH}/RoverStep 3 — Set analysis mode to profiling. Edit scripts/dependent/instrument-ap.sh and uncomment the profiling passes (ensure monitoring passes are commented out):
opt -load ./lib/AddDPFuncs.so -dp-funcs \
ardu${VEHICLE}-uninstr-linked.bc \
-o ardu${VEHICLE}-instr-linked.bc
opt -load ./lib/AddTrack.so -track-funcs \
ardu${VEHICLE}-instr-linked.bc \
-o ardu${VEHICLE}-instr-linked.bcAlso uncomment the appropriate llvm-link line based on vehicle type:
# For Copter:
# llvm-link ardu${VEHICLE}-uninstr.bc req_funcs.bc -o ardu${VEHICLE}-uninstr-linked.bc
# For Plane:
# llvm-link ardu${VEHICLE}-uninstr.bc req_funcs_plane.bc -o ardu${VEHICLE}-uninstr-linked.bc
# For Rover:
llvm-link ardu${VEHICLE}-uninstr.bc req_funcs_rover.bc -o ardu${VEHICLE}-uninstr-linked.bcSub-Step 3 — Set Vehicle Type. Edit Instrumentation/AddTrack.cpp and uncomment the vehicle type (ensure the others are commented out):
// For Copter:
// if (demangledName == "Copter::set_mode(Mode::Number, ModeReason)")
// For Plane:
// if (demangledName == "Plane::set_mode_by_number(Mode::Number, ModeReason)")
// For Rover:
if (demangledName == "Rover::set_mode(Mode::Number, ModeReason)")Also uncomment the corresponding lines in Instrumentation/AddTrack.cpp:
- Copter: Lines 128–170
- Plane or Rover: Lines 176–218
Execution:
cd ${RVD_PROJ}
RVDebloater/scripts/run-simulation.shResults: The experiment generates a file called mode_profile in the profiles directory. Run the following to produce per-mode files listing required functions for each mode:
cd ${RVD_PROJ}/RVDebloater/profiles
python3 FunctionsName_to_Mode.pyCompare the number of identified required functions against Tables 2 and 3 in the paper.
Estimated time: 15 human-minutes + 1 compute-hour
This experiment demonstrates RVDebloater's runtime debloating in monitoring mode.
Preparation: Follow Steps 1 and 2 from (E1) to select the RV type.
Step 3 — Set analysis mode to monitoring. Edit scripts/dependent/instrument-ap.sh and uncomment the monitoring passes (ensure profiling passes are commented out; only one pair of passes should be active at a time):
opt -load ./lib/CallOverwrite.so -overwrite-call \
ardu${VEHICLE}-uninstr-linked.bc \
-o ardu${VEHICLE}-instr-linked.bc
opt -load ./lib/AddEnforce.so -enforce-funcs \
ardu${VEHICLE}-instr-linked.bc \
-o ardu${VEHICLE}-instr-linked.bcSub-Step 3 — Set Vehicle Type. Edit Instrumentation/CallOverwrite.cpp and uncomment the vehicle type (ensure the others are commented out):
// For Copter:
// std::set<string> modeNames = {"AUTO", "CIRCLE", "STABILIZE", "GUIDED", "RTL", "LOITER"};
// For Plane:
// std::set<string> modeNames = {"AUTO", "CIRCLE", "GUIDED", "RTL", "QLOITER", "MANUAL", "QHOVER"};
// For Rover:
// std::set<string> modeNames = {"AUTO", "CIRCLE", "GUIDED", "RTL", "LOITER", "MANUAL"};Also edit Instrumentation/AddEnforce.cpp and uncomment the vehicle type:
// For Copter:
// if (demangledName == "Copter::set_mode(Mode::Number, ModeReason)")
// For Plane:
// if (demangledName == "Plane::set_mode_by_number(Mode::Number, ModeReason)")
// For Rover:
if (demangledName == "Rover::set_mode(Mode::Number, ModeReason)")Also uncomment the corresponding lines in Instrumentation/AddEnforce.cpp:
- Copter: Lines 96–138
- Plane or Rover: Lines 142–185
Execution: Before running, comment out the following block in scripts/run-simulation.sh:
echo "--- Extraction Script for Profiles ---"
cd ${RVD_PROJ}/RVDebloater/profiles
python3 identifyAddress.py
cd ${AP_PATH}
echo "--- Finished Extraction Script ---"Then run:
cd ${RVD_PROJ}
RVDebloater/scripts/run-simulation.shResults: A successful monitoring run will complete the mission without errors and produce simulation logs confirming that RVDebloater's runtime monitor enforces the debloated function set throughout the mission. Verify that the vehicle completes its mission correctly, confirming that the monitor does not incorrectly block required functions.
Note on hardware overhead: To measure overhead on a real device, deploy the firmware (with or without RVDebloater) using the manufacturer's recommended software and standard procedure, then compare measured overhead between the two configurations.
Beyond the contributions of RVDebloater discussed in the paper, this artifact addresses a fundamental gap in the RV firmware ecosystem: the lack of an automated technique for generating LLVM bitcode (.bc) files, which are essential for leveraging analysis frameworks such as LLVM.
To overcome this limitation, we modified the infrastructure of gllvm and its underlying Go implementation, enabling automated generation of LLVM bitcode during the firmware build process. The artifact supports complex, real-world firmware systems such as ArduPilot and PX4 — two of the most widely used RV firmware platforms.
With this capability, developers can seamlessly apply LLVM-based analyses, including custom LLVM passes and third-party tools such as DataFlowSanitizer (DFSan). Because our changes extend the core infrastructure of gllvm and Go, the approach generalizes beyond ArduPilot and PX4 and can support a broader range of firmware.