Skip to content

build: strip kernel modules with --strip-unneeded, not --strip-debug - #2502

Merged
openipc-ai merged 1 commit into
masterfrom
strip-kernel-modules
Sep 30, 2026
Merged

openipc-ai merged 1 commit into
masterfrom
strip-kernel-modules

Conversation

@openipc-ai

Copy link
Copy Markdown
Collaborator

Problem

The lite boards keep going over their 5120 KB squashfs cap (#2500 was the latest rescue), and every image ships kernel modules that are only half stripped.

Buildroot's linux.mk installs modules with INSTALL_MOD_STRIP=1, which the kernel's Makefile turns into strip --strip-debug. That leaves each module's full .symtab/.strtab in place. For any other value, the kernel passes the value to strip as its options. --strip-unneeded keeps exactly the symbols the module loader needs (those referenced by relocations, and the __ksymtab exports) and drops the rest. #2447 already strips the opensdk modules this way on hi3516cv6xx and runs them on hardware.

This appends INSTALL_MOD_STRIP=--strip-unneeded to LINUX_MAKE_FLAGS in general/external.mk. It uses the same include-order mechanism as the wpa_supplicant line above it: the last assignment on the make command line wins. pkg-kernel-module.mk installs with the same LINUX_MAKE_FLAGS, so out-of-tree module packages (wireguard, the Wi-Fi drivers) are covered too. Prebuilt vendor blobs are not touched.

The cost: an oops inside a module prints offsets instead of the names of its static functions. Exported and global symbols stay.

Hardware tested on

hi3516ev300_lite, IMX335, lab camera 10.216.128.76, running nightly-20260922-ca38928.

To match the running kernel exactly, I tested the camera's own modules. I copied all 26 in-tree modules plus wireguard.ko off the camera, stripped them here with the board's toolchain, served them back over NFS, and loaded them with insmod. Nothing was flashed. I then unloaded them and restored the camera's original module set. majestic kept streaming throughout. The vendor media stack was loaded and in use, so it was not touched.

One difference from what the build does: the test copies were stripped with --strip-unneeded --remove-section=.comment --remove-section=.note, while this change passes only --strip-unneeded, which removes strictly less.

Evidence

Size, clean builds of hi3516ev300_lite on master:

Before:

- uImage: [2005KB/2048KB]
- rootfs.squashfs: [5096KB/5120KB]
cfg80211.ko 560108   mac80211.ko 596048   option.ko 139164   mt7601u.ko 97268   wireguard.ko 125024

After:

- uImage: [2005KB/2048KB]
- rootfs.squashfs: [5052KB/5120KB]
cfg80211.ko 500472   mac80211.ko 543948   option.ko 92556    mt7601u.ko 88972   wireguard.ko 122020

That is 44 KB of squashfs back, with no kernel cost. (The "before" is master prior to #2501; the CA bundle adds another 8 KB on top.)

On the camera, the camera's own modules, stripped: 1,827,288 → 1,624,584 B across the 26. Every one loaded with nothing in dmesg about unknown symbols, relocations or taint:

unloaded stock vfat fat
insmod ok=25 fail=0
mt7601u 65521 0 - Live 0xbf000000
usbcore: registered new interface driver mt7601u

Then each one was exercised:

--- vfat: mount, write, read back          (FAT image on NFS through /dev/loop0)
stripped-vfat-ok
/dev/loop0 on /mnt/nfs/ai-ko-test/m type vfat (ro,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
--- tun
crw-rw----    1 root     root       10, 200 Sep 30 04:18 /dev/net/tun
--- wireguard
3: wgtest: <POINTOPOINT,NOARP> mtu 1420 qdisc noop state DOWN qlen 1
--- crypto templates registered
name         : crc32
name         : ghash
name         : jitterentropy_rng
--- drivers registered
cdc_ether option rndis_host usbserial_generic
tun: Universal TUN/TAP device driver, 1.6
wireguard: WireGuard 1.0.20220627 loaded. See www.wireguard.com for information.

There was no USB device attached, so mt7601u, option, cdc_ether and rndis_host were proven to load and register, not to drive hardware.

Local checks: ci-matrix.py --self-test ok. general/external.mk selects the full matrix.

Scope

  • No kernel patches under general/package/all-patches/linux/ (those go to OpenIPC/linux)
  • No files specific to a single retail camera model (those go to OpenIPC/builder)
  • No probing or bring-up tooling (that goes to OpenIPC/ipctool)
  • Nothing under general/overlay/ or in a shared load_<vendor> script hardcodes a value specific to my board
  • Package sources come from an OpenIPC repository, and any version bump keeps at least the specificity of the pin it replaces (a new package should pin a full 40-character SHA)
  • No LD_PRELOAD, and no binaries that cannot be rebuilt from source
  • New code is selected by a defconfig, so CI actually builds it

Buildroot installs modules with INSTALL_MOD_STRIP=1, which the kernel
turns into `strip --strip-debug`, so every module still ships its full
.symtab and .strtab. Any other value is passed to strip as its options;
--strip-unneeded keeps the symbols relocation and __ksymtab need and
drops the rest. pkg-kernel-module.mk uses the same LINUX_MAKE_FLAGS, so
out-of-tree modules are covered too.

hi3516ev300_lite: rootfs.squashfs 5096 -> 5052 KB on a clean build.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Strip installed kernel modules with --strip-unneeded

✨ Enhancement ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Use --strip-unneeded for Buildroot-installed kernel modules to reduce image size.
• Apply the setting to in-tree and out-of-tree modules without changing prebuilt vendor blobs.
• Recover 44 KB of squashfs space on the tested lite board.
Diagram

graph TD
  A["general/external.mk"] --> B["LINUX_MAKE_FLAGS"] --> C["In-tree install"] --> E["strip-unneeded"] --> F[("Squashfs image")]
  B --> D["Out-of-tree install"] --> E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Strip modules during target finalization
  • ➕ Could cover modules installed outside Buildroot's kernel-module paths.
  • ➖ Would need exclusions for prebuilt vendor blobs and could change modules that require their existing symbols.

Recommendation: Prefer the shared LINUX_MAKE_FLAGS setting: it covers both intended install paths while leaving vendor blobs alone. Confirm the documented include-order dependency remains valid when Buildroot is upgraded.

Files changed (1) +12 / -0

Other (1) +12 / -0
external.mkSelect --strip-unneeded for installed kernel modules +12/-0

Select --strip-unneeded for installed kernel modules

• Appends INSTALL_MOD_STRIP=--strip-unneeded to LINUX_MAKE_FLAGS, covering in-tree and Buildroot kernel-module package installs. Comments explain the include-order dependency, size benefit, and loss of static function names in module oops output.

general/external.mk

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can route each severity your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@openipc-ai
openipc-ai enabled auto-merge (squash) September 30, 2026 04:43
@openipc-ai
openipc-ai merged commit e484a42 into master Sep 30, 2026
121 of 122 checks passed
@openipc-ai
openipc-ai deleted the strip-kernel-modules branch September 30, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant