Repository: cilium/ebpf
Pull request #1739 (2025-04-01 14:25:36)

build(deps): bump golangci/golangci-lint-action from 6.5.0 to 7.0.0
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.5.0 to 7.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/golangci/golangci-lint-action/releases">golangci/golangci-lint-action's releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<!-- raw HTML omitted -->
<p>⚠️ <strong>The GitHub Action v7 supports golangci-lint v2 only.</strong> ⚠️</p>
<h2>What's Changed</h2>
<h3>Changes</h3>
<ul>
<li>feat: golangci-lint v2 support by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1198">golangci/golangci-lint-action#1198</a></li>
</ul>
<h3>Documentation</h3>
<ul>
<li>docs: update annotation permissions by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1203">golangci/golangci-lint-action#1203</a></li>
<li>docs: fix checks permissions for annotations by <a href="https://github.com/kema-dev"><code>@​kema-dev</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1204">golangci/golangci-lint-action#1204</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1207">golangci/golangci-lint-action#1207</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/kema-dev"><code>@​kema-dev</code></a> made their first contribution in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1204">golangci/golangci-lint-action#1204</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/golangci/golangci-lint-action/compare/v6.5.2...v7.0.0">https://github.com/golangci/golangci-lint-action/compare/v6.5.2...v7.0.0</a></p>
<h2>v6.5.2</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changes</h3>
<ul>
<li>fix: update max version by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1201">golangci/golangci-lint-action#1201</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>build(deps-dev): bump the dev-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1199">golangci/golangci-lint-action#1199</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/golangci/golangci-lint-action/compare/v6.5.1...v6.5.2">https://github.com/golangci/golangci-lint-action/compare/v6.5.1...v6.5.2</a></p>
<h2>v6.5.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changes</h3>
<ul>
<li>fix: octokit retry by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1193">golangci/golangci-lint-action#1193</a></li>
<li>feat: restrict action v6 on golangci-lint v1 by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1194">golangci/golangci-lint-action#1194</a></li>
</ul>
<h3>Documentation</h3>
<ul>
<li>docs: add notes for annotation config by <a href="https://github.com/dveeden"><code>@​dveeden</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1173">golangci/golangci-lint-action#1173</a></li>
<li>docs: improve verify option explanation by <a href="https://github.com/ldez"><code>@​ldez</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1175">golangci/golangci-lint-action#1175</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1177">golangci/golangci-lint-action#1177</a></li>
<li>build(deps): bump the dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1178">golangci/golangci-lint-action#1178</a></li>
<li>build(deps): bump <code>@​octokit/request</code> from 8.4.0 to 8.4.1 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1181">golangci/golangci-lint-action#1181</a></li>
<li>build(deps-dev): bump the dev-dependencies group with 3 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1185">golangci/golangci-lint-action#1185</a></li>
<li>build(deps): bump <code>@​types/node</code> from 22.13.4 to 22.13.5 in the dependencies group by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1186">golangci/golangci-lint-action#1186</a></li>
<li>build(deps): bump <code>@​octokit/plugin-paginate-rest</code> from 9.2.1 to 9.2.2 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1187">golangci/golangci-lint-action#1187</a></li>
<li>build(deps): bump the dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1189">golangci/golangci-lint-action#1189</a></li>
<li>build(deps-dev): bump the dev-dependencies group across 1 directory with 5 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/golangci/golangci-lint-action/pull/1190">golangci/golangci-lint-action#1190</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/1481404843c368bc19ca9406f87d6e0fc97bdcfd"><code>1481404</code></a> 7.0.0</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/dec74fa03096ff515422f71d18d41307cacde373"><code>dec74fa</code></a> feat: golangci-lint v2 support (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1198">#1198</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/1f07148fa0c704709f56ae92884ec7fc9d19a413"><code>1f07148</code></a> build(deps-dev): bump the dev-dependencies group with 3 updates (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1207">#1207</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/9938e103f8065deff3f289d9e975270d5541b866"><code>9938e10</code></a> docs: fix checks permissions for annotations (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1204">#1204</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/b91d580160cdcb5498a14265c2b329fdc9d62f0a"><code>b91d580</code></a> docs: update annotation permissions (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1203">#1203</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/55c2c1448f86e01eaae002a5a3a9624417608d84"><code>55c2c14</code></a> 6.5.2</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/911ec56a221f2cb0322fe7e8a32026fafba0056f"><code>911ec56</code></a> fix: update max version (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1201">#1201</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/eb5c0cc4890366046baa605fa7592d303dea28e9"><code>eb5c0cc</code></a> build(deps-dev): bump the dev-dependencies group with 2 updates (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1199">#1199</a>)</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/4696ba8babb6127d732c3c6dde519db15edab9ea"><code>4696ba8</code></a> 6.5.1</li>
<li><a href="https://github.com/golangci/golangci-lint-action/commit/2ee514f1f31dd3d5f0ae6e6546082968a4b5e342"><code>2ee514f</code></a> feat: restrict action v6 on golangci-lint v1 (<a href="https://redirect.github.com/golangci/golangci-lint-action/issues/1194">#1194</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/golangci/golangci-lint-action/compare/v6.5.0...v7.0.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golangci/golangci-lint-action&package-manager=github_actions&previous-version=6.5.0&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ae435f3..06d6c09 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,9 +34,7 @@ jobs:
           go-version: '${{ env.go_version }}'
 
       - name: Run golangci-lint
-        uses: golangci/golangci-lint-action@v6.5.0
-        with:
-          args: "--out-format colored-line-number"
+        uses: golangci/golangci-lint-action@v7.0.0
 
       - name: Generate and format code
         run: |
diff --git a/.golangci.yaml b/.golangci.yaml
index 8298e59..cb17a6e 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -1,31 +1,38 @@
----
+version: "2"
 linters:
-  disable-all: true
+  default: none
   enable:
-    - goimports
-    - gosimple
+    - depguard
     - govet
     - ineffassign
     - misspell
     - staticcheck
-    - typecheck
     - unused
+  settings:
+    staticcheck:
+      checks:
+        [
+          # Defaults
+          "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022",
+          # Convert slice of bytes to string when printing it.
+          "-QF1010",
+        ]
+    depguard:
+      rules:
+        no-x-sys-unix:
+          files:
+            - '!**/internal/unix/*.go'
+            - '!**/examples/**/*.go'
+            - '!**/docs/**/*.go'
+          deny:
+            - pkg: golang.org/x/sys/unix
+              desc: use internal/unix instead
+
+formatters:
+  enable:
     - gofmt
-    - depguard
-linters-settings:
-  goimports:
-    # A comma-separated list of prefixes, which, if set, checks import paths
-    # with the given prefixes are grouped after 3rd-party packages.
-    # Default: ""
-    local-prefixes: github.com/cilium/ebpf
-  depguard:
-    rules:
-      no-x-sys-unix:
-        files:
-          # Filenames are matched against absolute paths, include **/ at the start.
-          - '!**/internal/unix/*.go'
-          - '!**/examples/**/*.go'
-          - '!**/docs/**/*.go'
-        deny:
-          - pkg: golang.org/x/sys/unix
-            desc: use internal/unix instead
+    - goimports
+  settings:
+    goimports:
+      local-prefixes:
+        - github.com/cilium/ebpf
diff --git a/Makefile b/Makefile
index e0fe974..18e9bb0 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,10 @@ UIDGID := $(shell stat -c '%u:%g' ${REPODIR})
 # Prefer podman if installed, otherwise use docker.
 # Note: Setting the var at runtime will always override.
 CONTAINER_ENGINE ?= $(if $(shell command -v podman), podman, docker)
-CONTAINER_RUN_ARGS ?= $(if $(filter ${CONTAINER_ENGINE}, podman), --log-driver=none, --user "${UIDGID}")
+CONTAINER_RUN_ARGS ?= $(if $(filter ${CONTAINER_ENGINE}, podman), \
+		--log-driver=none \
+		-v "$(shell go env GOCACHE)":/root/.cache/go-build \
+		-v "$(shell go env GOMODCACHE)":/go/pkg/mod, --user "${UIDGID}")
 
 IMAGE := $(shell cat ${REPODIR}/testdata/docker/IMAGE)
 VERSION := $(shell cat ${REPODIR}/testdata/docker/VERSION)
@@ -70,7 +73,7 @@ container-all:
 # (debug) Drop the user into a shell inside the container as root.
 # Set BPF2GO_ envs to make 'make generate' just work.
 container-shell:
-	${CONTAINER_ENGINE} run --rm -ti \
+	${CONTAINER_ENGINE} run --rm -ti ${CONTAINER_RUN_ARGS} \
 		-v "${REPODIR}":/ebpf -w /ebpf \
 		--env BPF2GO_CC="$(CLANG)" \
 		--env BPF2GO_FLAGS="-fdebug-prefix-map=/ebpf=. $(CFLAGS)" \
diff --git a/btf/btf.go b/btf/btf.go
index e8f80c1..eb5a23c 100644
--- a/btf/btf.go
+++ b/btf/btf.go
@@ -537,7 +537,7 @@ func (s *Spec) Copy() *Spec {
 	}
 
 	return &Spec{
-		s.mutableTypes.copy(),
+		s.copy(),
 		s.strings,
 	}
 }
@@ -579,7 +579,7 @@ func (s *Spec) TypeByID(id TypeID) (Type, error) {
 //
 // Returns an error wrapping [ErrNotFound] if the type isn't part of the Spec.
 func (s *Spec) TypeID(typ Type) (TypeID, error) {
-	return s.mutableTypes.typeID(typ)
+	return s.typeID(typ)
 }
 
 // AnyTypesByName returns a list of BTF Types with the given name.
@@ -590,7 +590,7 @@ func (s *Spec) TypeID(typ Type) (TypeID, error) {
 //
 // Returns an error wrapping ErrNotFound if no matching Type exists in the Spec.
 func (s *Spec) AnyTypesByName(name string) ([]Type, error) {
-	return s.mutableTypes.anyTypesByName(name)
+	return s.anyTypesByName(name)
 }
 
 // AnyTypeByName returns a Type with the given name.
diff --git a/cmd/bpf2go/main.go b/cmd/bpf2go/main.go
index 9408be1..3732333 100644
--- a/cmd/bpf2go/main.go
+++ b/cmd/bpf2go/main.go
@@ -13,6 +13,7 @@ import (
 	"regexp"
 	"slices"
 	"sort"
+	"strconv"
 	"strings"
 
 	"github.com/cilium/ebpf"
@@ -57,7 +58,8 @@ func run(stdout io.Writer, args []string) (err error) {
 }
 
 type bpf2go struct {
-	stdout io.Writer
+	stdout  io.Writer
+	verbose bool
 	// Absolute path to a .c file.
 	sourceFile string
 	// Absolute path to a directory where .go are written
@@ -89,12 +91,19 @@ type bpf2go struct {
 	makeBase string
 }
 
+func (b2g *bpf2go) Debugln(a ...any) {
+	if b2g.verbose {
+		fmt.Fprintln(b2g.stdout, a...)
+	}
+}
+
 func newB2G(stdout io.Writer, args []string) (*bpf2go, error) {
 	b2g := &bpf2go{
 		stdout: stdout,
 	}
 
 	fs := flag.NewFlagSet("bpf2go", flag.ContinueOnError)
+	fs.BoolVar(&b2g.verbose, "verbose", getBool("V", false), "Enable verbose logging ($V)")
 	fs.StringVar(&b2g.cc, "cc", getEnv("BPF2GO_CC", "clang"),
 		"`binary` used to compile C to BPF ($BPF2GO_CC)")
 	fs.StringVar(&b2g.strip, "strip", getEnv("BPF2GO_STRIP", ""),
@@ -117,6 +126,7 @@ func newB2G(stdout io.Writer, args []string) (*bpf2go, error) {
 		"suffix in generated file names such as _test (default based on $GOFILE)")
 	outDir := fs.String("output-dir", "", "target directory of generated files (defaults to current directory)")
 	outPkg := fs.String("go-package", "", "package for output go file (default as ENV GOPACKAGE)")
+
 	fs.SetOutput(b2g.stdout)
 	fs.Usage = func() {
 		fmt.Fprintf(fs.Output(), helpText, fs.Name())
@@ -273,6 +283,20 @@ func getEnv(key, defaultVal string) string {
 	return defaultVal
 }
 
+func getBool(key string, defaultVal bool) bool {
+	val, ok := os.LookupEnv(key)
+	if !ok {
+		return defaultVal
+	}
+
+	b, err := strconv.ParseBool(val)
+	if err != nil {
+		return defaultVal
+	}
+
+	return b
+}
+
 func (b2g *bpf2go) convertAll() (err error) {
 	if _, err := os.Stat(b2g.sourceFile); os.IsNotExist(err) {
 		return fmt.Errorf("file %s doesn't exist", b2g.sourceFile)
@@ -365,10 +389,10 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
 		return fmt.Errorf("compile: %w", err)
 	}
 
-	fmt.Fprintln(b2g.stdout, "Compiled", objFileName)
-
-	if !b2g.disableStripping {
-		fmt.Fprintln(b2g.stdout, "Stripped", objFileName)
+	if b2g.disableStripping {
+		b2g.Debugln("Compiled object", "file", objFileName)
+	} else {
+		b2g.Debugln("Compiled and stripped object", "file", objFileName)
 	}
 
 	spec, err := ebpf.LoadCollectionSpec(objFileName)
@@ -426,7 +450,7 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
 		return fmt.Errorf("can't write %s: %s", goFileName, err)
 	}
 
-	fmt.Fprintln(b2g.stdout, "Wrote", goFileName)
+	b2g.Debugln("Generated bpf2go binding", "file", goFileName)
 
 	if b2g.makeBase == "" {
 		return
@@ -450,7 +474,8 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
 		return fmt.Errorf("can't adjust dependency information: %s", err)
 	}
 
-	fmt.Fprintln(b2g.stdout, "Wrote", depFileName)
+	b2g.Debugln("Wrote dependency", "file", depFileName)
+
 	return nil
 }
 
@@ -474,7 +499,7 @@ func (b2g *bpf2go) removeOldOutputFiles(outputStem string, tgt gen.Target) error
 			return err
 		}
 
-		fmt.Fprintln(b2g.stdout, "Removed obsolete", filename)
+		b2g.Debugln("Removed obsolete output file", "file", filename)
 	}
 
 	return nil
diff --git a/elf_reader.go b/elf_reader.go
index 92076aa..f83033c 100644
--- a/elf_reader.go
+++ b/elf_reader.go
@@ -80,8 +80,8 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
 
 	// Checks if the ELF file is for BPF data.
 	// Old LLVM versions set e_machine to EM_NONE.
-	if f.File.Machine != elf.EM_NONE && f.File.Machine != elf.EM_BPF {
-		return nil, fmt.Errorf("unexpected machine type for BPF ELF: %s", f.File.Machine)
+	if f.Machine != elf.EM_NONE && f.Machine != elf.EM_BPF {
+		return nil, fmt.Errorf("unexpected machine type for BPF ELF: %s", f.Machine)
 	}
 
 	var (
@@ -742,7 +742,7 @@ func (ec *elfCode) loadMaps() error {
 			lr := io.LimitReader(r, int64(size))
 
 			spec := MapSpec{
-				Name: SanitizeName(mapName, -1),
+				Name: sanitizeName(mapName, -1),
 			}
 			switch {
 			case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
@@ -1029,7 +1029,7 @@ func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *b
 	}
 
 	return &MapSpec{
-		Name:       SanitizeName(name, -1),
+		Name:       sanitizeName(name, -1),
 		Type:       MapType(mapType),
 		KeySize:    keySize,
 		ValueSize:  valueSize,
@@ -1095,7 +1095,7 @@ func resolveBTFValuesContents(es *elfSection, vs *btf.VarSecinfo, member btf.Mem
 	end := vs.Size + vs.Offset
 	// The size of an address in this section. This determines the width of
 	// an index in the array.
-	align := uint32(es.SectionHeader.Addralign)
+	align := uint32(es.Addralign)
 
 	// Check if variable-length section is aligned.
 	if (end-start)%align != 0 {
@@ -1156,7 +1156,7 @@ func (ec *elfCode) loadDataSections() error {
 		}
 
 		mapSpec := &MapSpec{
-			Name:       SanitizeName(sec.Name, -1),
+			Name:       sanitizeName(sec.Name, -1),
 			Type:       Array,
 			KeySize:    4,
 			ValueSize:  uint32(sec.Size),
diff --git a/examples/fentry/main.go b/examples/fentry/main.go
index 3d5670c..3726a0e 100644
--- a/examples/fentry/main.go
+++ b/examples/fentry/main.go
@@ -48,14 +48,14 @@ func main() {
 	defer objs.Close()
 
 	link, err := link.AttachTracing(link.TracingOptions{
-		Program: objs.bpfPrograms.TcpConnect,
+		Program: objs.TcpConnect,
 	})
 	if err != nil {
 		log.Fatal(err)
 	}
 	defer link.Close()
 
-	rd, err := ringbuf.NewReader(objs.bpfMaps.Events)
+	rd, err := ringbuf.NewReader(objs.Events)
 	if err != nil {
 		log.Fatalf("opening ringbuf reader: %s", err)
 	}
diff --git a/examples/tcprtt/main.go b/examples/tcprtt/main.go
index 926400f..15f42d2 100644
--- a/examples/tcprtt/main.go
+++ b/examples/tcprtt/main.go
@@ -49,14 +49,14 @@ func main() {
 	defer objs.Close()
 
 	link, err := link.AttachTracing(link.TracingOptions{
-		Program: objs.bpfPrograms.TcpClose,
+		Program: objs.TcpClose,
 	})
 	if err != nil {
 		log.Fatal(err)
 	}
 	defer link.Close()
 
-	rd, err := ringbuf.NewReader(objs.bpfMaps.Events)
+	rd, err := ringbuf.NewReader(objs.Events)
 	if err != nil {
 		log.Fatalf("opening ringbuf reader: %s", err)
 	}
diff --git a/examples/tcprtt_sockops/main.go b/examples/tcprtt_sockops/main.go
index 56bf5c2..8f7b158 100644
--- a/examples/tcprtt_sockops/main.go
+++ b/examples/tcprtt_sockops/main.go
@@ -66,7 +66,7 @@ func main() {
 	// Attach ebpf program to a cgroupv2
 	link, err := link.AttachCgroup(link.CgroupOptions{
 		Path:    cgroupPath,
-		Program: objs.bpfPrograms.BpfSockopsCb,
+		Program: objs.BpfSockopsCb,
 		Attach:  ebpf.AttachCGroupSockOps,
 	})
 	if err != nil {
@@ -76,7 +76,7 @@ func main() {
 
 	log.Printf("eBPF program loaded and attached on cgroup %s\n", cgroupPath)
 
-	rd, err := ringbuf.NewReader(objs.bpfMaps.RttEvents)
+	rd, err := ringbuf.NewReader(objs.RttEvents)
 	if err != nil {
 		log.Fatalf("opening ringbuf reader: %s", err)
 	}
diff --git a/internal/cmd/gentypes/main.go b/internal/cmd/gentypes/main.go
index 10047b2..08fde8a 100644
--- a/internal/cmd/gentypes/main.go
+++ b/internal/cmd/gentypes/main.go
@@ -7,10 +7,12 @@ package main
 import (
 	"bytes"
 	"errors"
+	"flag"
 	"fmt"
 	"os"
 	"slices"
 	"sort"
+	"strconv"
 	"strings"
 
 	"github.com/cilium/ebpf/btf"
@@ -25,8 +27,40 @@ const (
 	retFd
 )
 
+var (
+	verbose bool
+)
+
+func debugln(a ...any) {
+	if verbose {
+		fmt.Println(a...)
+	}
+}
+
+func getBool(key string, defaultVal bool) bool {
+	val, ok := os.LookupEnv(key)
+	if !ok {
+		return defaultVal
+	}
+
+	b, err := strconv.ParseBool(val)
+	if err != nil {
+		return defaultVal
+	}
+
+	return b
+}
+
 func main() {
-	if err := run(os.Args[1:]); err != nil {
+	fs := flag.NewFlagSet("gentypes", flag.ContinueOnError)
+	fs.BoolVar(&verbose, "verbose", getBool("V", false), "Enable verbose logging ($V)")
+
+	if err := fs.Parse(os.Args[1:]); err != nil {
+		fmt.Fprintln(os.Stderr, "Error:", err)
+		os.Exit(1)
+	}
+
+	if err := run(fs.Args()); err != nil {
 		fmt.Fprintln(os.Stderr, "Error:", err)
 		os.Exit(1)
 	}
@@ -154,12 +188,15 @@ import (
 		return consts[i].Name < consts[j].Name
 	})
 
+	var nconsts uint32
 	w.WriteString("const (\n")
 	for _, c := range consts {
-		fmt.Println("const", c.Name)
+		debugln("const", c.Name)
 		fmt.Fprintf(w, "\t%s = %v\n", c.Name, c.Value)
+		nconsts++
 	}
 	w.WriteString(")\n")
+	fmt.Printf("Generated %d constants\n", nconsts)
 
 	// Typed constants (aka named enums)
 	enums := []struct {
@@ -188,9 +225,10 @@ import (
 		return enums[i].goType < enums[j].goType
 	})
 
+	var nenums uint32
 	enumTypes := make(map[string]btf.Type)
 	for _, o := range enums {
-		fmt.Println("enum", o.goType)
+		debugln("enum", o.goType)
 
 		var t *btf.Enum
 		if err := spec.TypeByName(o.cType, &t); err != nil {
@@ -212,7 +250,10 @@ import (
 
 		w.WriteString(decl)
 		w.WriteRune('\n')
+
+		nenums++
 	}
+	fmt.Printf("Generated %d enums\n", nenums)
 
 	// Assorted structs
 
@@ -277,8 +318,9 @@ import (
 		return structs[i].goType < structs[j].goType
 	})
 
+	var nstructs uint32
 	for _, s := range structs {
-		fmt.Println("struct", s.goType)
+		debugln("struct", s.goType)
 
 		var t *btf.Struct
 		if err := spec.TypeByName(s.cType, &t); err != nil {
@@ -288,7 +330,9 @@ import (
 		if err := outputPatchedStruct(gf, w, s.goType, t, s.patches); err != nil {
 			return nil, fmt.Errorf("output %q: %w", s.goType, err)
 		}
+		nstructs++
 	}
+	fmt.Printf("Generated %d structs\n", nstructs)
 
 	// Attrs
 
@@ -620,8 +664,9 @@ import (
 		return nil, fmt.Errorf("split bpf_attr: %w", err)
 	}
 
+	var nattrs uint32
 	for _, s := range attrs {
-		fmt.Println("attr", s.goType)
+		debugln("attr", s.goType)
 
 		t := attrTypes[s.cType]
 		if t == nil {
@@ -639,7 +684,9 @@ import (
 		case retFd:
 			fmt.Fprintf(w, "func %s(attr *%s) (*FD, error) { fd, err := BPF(%s, unsafe.Pointer(attr), unsafe.Sizeof(*attr)); if err != nil { return nil, err }; return NewFD(int(fd)) }\n\n", s.goType, goAttrType, s.cmd)
 		}
+		nattrs++
 	}
+	fmt.Printf("Generated %d attrs\n", nattrs)
 
 	// Link info type specific
 	linkInfoExtraTypes := []struct {
diff --git a/internal/kallsyms/kallsyms.go b/internal/kallsyms/kallsyms.go
index f5451e2..c7b12c4 100644
--- a/internal/kallsyms/kallsyms.go
+++ b/internal/kallsyms/kallsyms.go
@@ -282,7 +282,7 @@ func parseSymbol(r *reader, types []rune) (s ksym, err error, skip bool) {
 			s.mod = strings.Trim(r.Text(), "[]")
 		// Ignore any future fields.
 		default:
-			break
+			return
 		}
 	}
 
diff --git a/link/kprobe_multi.go b/link/kprobe_multi.go
index 5a4832c..3a2b06a 100644
--- a/link/kprobe_multi.go
+++ b/link/kprobe_multi.go
@@ -85,10 +85,10 @@ func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Lin
 		return nil, fmt.Errorf("one of Symbols or Addresses is required: %w", errInvalidInput)
 	}
 	if syms != 0 && addrs != 0 {
-		return nil, fmt.Errorf("Symbols and Addresses are mutually exclusive: %w", errInvalidInput)
+		return nil, fmt.Errorf("fields Symbols and Addresses are mutually exclusive: %w", errInvalidInput)
 	}
 	if cookies > 0 && cookies != syms && cookies != addrs {
-		return nil, fmt.Errorf("Cookies must be exactly Symbols or Addresses in length: %w", errInvalidInput)
+		return nil, fmt.Errorf("field Cookies must be exactly Symbols or Addresses in length: %w", errInvalidInput)
 	}
 
 	attachType := sys.BPF_TRACE_KPROBE_MULTI
diff --git a/link/uprobe_multi.go b/link/uprobe_multi.go
index eb8b233..e34ad71 100644
--- a/link/uprobe_multi.go
+++ b/link/uprobe_multi.go
@@ -70,13 +70,13 @@ func (ex *Executable) uprobeMulti(symbols []string, prog *ebpf.Program, opts *Up
 	refCtrOffsets := len(opts.RefCtrOffsets)
 
 	if addrs == 0 {
-		return nil, fmt.Errorf("Addresses are required: %w", errInvalidInput)
+		return nil, fmt.Errorf("field Addresses is required: %w", errInvalidInput)
 	}
 	if refCtrOffsets > 0 && refCtrOffsets != addrs {
-		return nil, fmt.Errorf("RefCtrOffsets must be exactly Addresses in length: %w", errInvalidInput)
+		return nil, fmt.Errorf("field RefCtrOffsets must be exactly Addresses in length: %w", errInvalidInput)
 	}
 	if cookies > 0 && cookies != addrs {
-		return nil, fmt.Errorf("Cookies must be exactly Addresses in length: %w", errInvalidInput)
+		return nil, fmt.Errorf("field Cookies must be exactly Addresses in length: %w", errInvalidInput)
 	}
 
 	attr := &sys.LinkCreateUprobeMultiAttr{
diff --git a/map.go b/map.go
index f288966..b2da9f6 100644
--- a/map.go
+++ b/map.go
@@ -50,8 +50,9 @@ type MapID = sys.MapID
 
 // MapSpec defines a Map.
 type MapSpec struct {
-	// Name is passed to the kernel as a debug aid. Must only contain
-	// alpha numeric and '_' characters.
+	// Name is passed to the kernel as a debug aid.
+	//
+	// Unsupported characters will be stripped.
 	Name       string
 	Type       MapType
 	KeySize    uint32
diff --git a/prog.go b/prog.go
index d1f4908..ebad9cf 100644
--- a/prog.go
+++ b/prog.go
@@ -106,8 +106,9 @@ type ProgramOptions struct {
 
 // ProgramSpec defines a Program.
 type ProgramSpec struct {
-	// Name is passed to the kernel as a debug aid. Must only contain
-	// alpha numeric and '_' characters.
+	// Name is passed to the kernel as a debug aid.
+	//
+	// Unsupported characters will be stripped.
 	Name string
 
 	// Type determines at which hook in the kernel a program will run.
diff --git a/syscalls.go b/syscalls.go
index e6f5f69..f03bed0 100644
--- a/syscalls.go
+++ b/syscalls.go
@@ -27,12 +27,12 @@ var (
 	sysErrNotSupported = sys.Error(ErrNotSupported, sys.ENOTSUPP)
 )
 
-// SanitizeName replaces all invalid characters in name with replacement.
+// sanitizeName replaces all invalid characters in name with replacement.
 // Passing a negative value for replacement will delete characters instead
 // of replacing them.
 //
 // The set of allowed characters may change over time.
-func SanitizeName(name string, replacement rune) string {
+func sanitizeName(name string, replacement rune) string {
 	return strings.Map(func(char rune) rune {
 		switch {
 		case char >= 'A' && char <= 'Z':
@@ -56,6 +56,7 @@ func maybeFillObjName(name string) sys.ObjName {
 		return sys.ObjName{}
 	}
 
+	name = sanitizeName(name, -1)
 	if errors.Is(objNameAllowsDot(), ErrNotSupported) {
 		name = strings.ReplaceAll(name, ".", "")
 	}


Test patch:
diff --git a/btf/types_test.go b/btf/types_test.go
index b7e325b..9382568 100644
--- a/btf/types_test.go
+++ b/btf/types_test.go
@@ -435,7 +435,7 @@ func TestInflateLegacyBitfield(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			types, err := readAndInflateTypes(test.reader, binary.LittleEndian, 2, emptyStrings, nil)
 			if err != nil {
-				fmt.Println(before.Bytes())
+				t.Log(before.Bytes())
 				t.Fatal(err)
 			}
 
diff --git a/docs/examples/rlimit_test.go b/docs/examples/rlimit_test.go
index 5eb52ea..1b62fd2 100644
--- a/docs/examples/rlimit_test.go
+++ b/docs/examples/rlimit_test.go
@@ -5,7 +5,7 @@ package examples
 // DocRlimit {
 import "github.com/cilium/ebpf/rlimit"
 
-func main() {
+func init() {
 	if err := rlimit.RemoveMemlock(); err != nil {
 		panic(err)
 	}
diff --git a/link/kprobe_test.go b/link/kprobe_test.go
index 6284a90..5975b49 100644
--- a/link/kprobe_test.go
+++ b/link/kprobe_test.go
@@ -103,7 +103,7 @@ func TestKretprobe(t *testing.T) {
 	}
 
 	k, err := Kretprobe("bogus", prog, nil)
-	if !(errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL)) {
+	if !errors.Is(err, os.ErrNotExist) && !errors.Is(err, unix.EINVAL) {
 		t.Fatal(err)
 	}
 	if k != nil {
diff --git a/map_test.go b/map_test.go
index 9bb7c02..021c8d7 100644
--- a/map_test.go
+++ b/map_test.go
@@ -1362,20 +1362,23 @@ func TestMapMarshalUnsafe(t *testing.T) {
 }
 
 func TestMapName(t *testing.T) {
-	if err := haveObjName(); err != nil {
-		t.Skip(err)
-	}
+	testutils.SkipIfNotSupported(t, haveObjName())
 
-	m := createMap(t, Array, 1)
+	m := mustNewMap(t, &MapSpec{
+		Name:       "test!123",
+		Type:       Array,
+		KeySize:    4,
+		ValueSize:  4,
+		MaxEntries: 1,
+	}, nil)
 
 	var info sys.MapInfo
 	if err := sys.ObjInfo(m.fd, &info); err != nil {
 		t.Fatal(err)
 	}
 
-	if name := unix.ByteSliceToString(info.Name[:]); name != "test" {
-		t.Error("Expected name to be test, got", name)
-	}
+	name := unix.ByteSliceToString(info.Name[:])
+	qt.Assert(t, qt.Equals(name, "test123"))
 }
 
 func TestMapFromFD(t *testing.T) {
diff --git a/prog_test.go b/prog_test.go
index ab5929b..7f15ef0 100644
--- a/prog_test.go
+++ b/prog_test.go
@@ -479,20 +479,25 @@ func TestProgramWithUnsatisfiedMap(t *testing.T) {
 }
 
 func TestProgramName(t *testing.T) {
-	if err := haveObjName(); err != nil {
-		t.Skip(err)
-	}
+	testutils.SkipIfNotSupported(t, haveObjName())
 
-	prog := createBasicProgram(t)
+	prog := mustNewProgram(t, &ProgramSpec{
+		Name: "test*123",
+		Type: SocketFilter,
+		Instructions: asm.Instructions{
+			asm.LoadImm(asm.R0, 1, asm.DWord),
+			asm.Return(),
+		},
+		License: "MIT",
+	}, nil)
 
 	var info sys.ProgInfo
 	if err := sys.ObjInfo(prog.fd, &info); err != nil {
 		t.Fatal(err)
 	}
 
-	if name := unix.ByteSliceToString(info.Name[:]); name != "test" {
-		t.Errorf("Name is not test, got '%s'", name)
-	}
+	name := unix.ByteSliceToString(info.Name[:])
+	qt.Assert(t, qt.Equals(name, "test123"))
 }
 
 func TestProgramCloneNil(t *testing.T) {
diff --git a/syscalls_test.go b/syscalls_test.go
index 1642bce..f85f382 100644
--- a/syscalls_test.go
+++ b/syscalls_test.go
@@ -19,7 +19,7 @@ func TestSanitizeName(t *testing.T) {
 		"t_est":    "t_est",
 		"hörnchen": "hrnchen",
 	} {
-		qt.Assert(t, qt.Equals(SanitizeName(input, -1), want), qt.Commentf("input: %s", input))
+		qt.Assert(t, qt.Equals(sanitizeName(input, -1), want), qt.Commentf("input: %s", input))
 	}
 }