{"record":{"id":"786ee57081638dc2","repo":"cilium/cilium","slug":"instrumenting-s-w","errorCode":null,"errorMessage":"instrumenting %s: %w","messagePattern":"instrumenting (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/datapath/loader/plugins.go","lineNumber":698,"sourceCode":"\thooks := make(map[string]*datapathplugins.InstrumentCollectionRequest)\n\tprogramPatches := make(map[string]func(asm.Instructions) (asm.Instructions, error))\n\n\tfor hookTarget, hookTypes := range hs.hooks {\n\t\tpre, sortErr := hookTypes[datapathplugins.HookType_PRE].sort()\n\t\tif sortErr != nil {\n\t\t\terr = errors.Join(err, fmt.Errorf(\"%s/%s: %w\", hookTarget, datapathplugins.HookType_PRE, sortErr))\n\n\t\t\tcontinue\n\t\t}\n\t\tpost, sortErr := hookTypes[datapathplugins.HookType_POST].sort()\n\t\tif sortErr != nil {\n\t\t\terr = errors.Join(err, fmt.Errorf(\"%s/%s: %w\", hookTarget, datapathplugins.HookType_POST, sortErr))\n\n\t\t\tcontinue\n\t\t}\n\t\tpatch, patchErr := hs.instrumentProgram(cs.Programs[hookTarget], pre, post, hooks)\n\t\tif patchErr != nil {\n\t\t\terr = errors.Join(err, fmt.Errorf(\"instrumenting %s: %w\", hookTarget, patchErr))\n\n\t\t\tcontinue\n\t\t}\n\t\tprogramPatches[hookTarget] = patch\n\t}\n\n\treturn hooks, programPatches, err\n}\n\n// instrumentProgram generates a program patcher that prepends a dispatcher that\n// invokes pre-program hooks, then invokes the original program, and finally\n// invokes post-program hooks. Something like this:\n//\n//\tint dispatch(void *ctx) {\n//\t    int orig_ret, ret;\n//\n//\t    ret = __pre_hook_plugin_a__(ctx);\n//\t    if (ret != RET_PROCEED)","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/datapath/loader/plugins.go#L680-L716","documentation":"After both hook lists sort successfully, instrumentCollection calls hs.instrumentProgram on the target program's spec to generate the patched instructions; any failure is wrapped as \"instrumenting <hookTarget>\". This covers BTF metadata extraction, prologue/epilogue generation, and assembling hook calls for that target. Failures here are aggregated via errors.Join and abort Load.","triggerScenarios":"instrumentProgram fails when the target program lacks function BTF metadata (see 2519), the instructions cannot be rewritten for the requested pre/post hooks, the hook count/context layout mismatches, or the target program is nil/not found in the collection.","commonSituations":"Kernel/clang compiled the target without BTF (no -g / BTF stripped), so FuncMetadata fails; hook attached to a program type that instrumentation doesn't support; plugin requests hooks on a program that was not loaded (name mismatch).","solutions":["Check the wrapped inner error from instrumentProgram — most often 'unable to extract function BTF info for target program'.","Ensure the target ELF was built with BTF (compile with -g, do not strip .BTF section).","Verify the hook target name matches a program present in the loaded collection spec.","Confirm the target program type is supported for freplace instrumentation.","Exclude the hook/plugin for that target if instrumentation isn't supported there."],"exampleFix":"// before\npatch, patchErr := hs.instrumentProgram(cs.Programs[hookTarget], pre, post, hooks)\n// after: guard against missing target\nprog := cs.Programs[hookTarget]\nif prog == nil {\n    return nil, fmt.Errorf(\"hook target %s not found in collection\", hookTarget)\n}\npatch, patchErr := hs.instrumentProgram(prog, pre, post, hooks)","handlingStrategy":"validation","validationCode":"// pre-flight: target exists and has BTF func metadata\nprog, ok := cs.Programs[hookTarget]\nif !ok || prog == nil {\n    return fmt.Errorf(\"hook target %q missing from collection\", hookTarget)\n}\nif btf.FuncMetadata(&prog.Instructions[0]) == nil {\n    return fmt.Errorf(\"target %q lacks BTF func metadata; rebuild ELF with -g\", hookTarget)\n}","typeGuard":"func instrumentable(spec *ebpf.ProgramSpec) bool {\n    if spec == nil || len(spec.Instructions) == 0 { return false }\n    meta := btf.FuncMetadata(&spec.Instructions[0])\n    if meta == nil { return false }\n    _, ok := meta.Type.(*btf.FuncProto)\n    return ok\n}","tryCatchPattern":"if err := load(); err != nil {\n    if strings.Contains(err.Error(), \"instrumenting \") {\n        target := extractTarget(err) // parse wrapped message\n        disableHookFor(target)\n        return load()\n    }\n    return err\n}","preventionTips":["Always build BPF objects with clang -g and never strip BTF","Validate hook target names against the collection spec before Load","Check target program types are supported for instrumentation","Run instrumentable() checks in CI against shipped ELFs"],"tags":["bpf","ebtf","btf","instrumentation","datapath"],"backgroundTag":"bpf-program-instrumentation-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}