}
 
 void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is_weak,
-                           int kind, int insn_idx)
+                           bool is_typeless, int kind, int insn_idx)
 {
        struct ksym_relo_desc *relo;
 
        relo += gen->relo_cnt;
        relo->name = name;
        relo->is_weak = is_weak;
+       relo->is_typeless = is_typeless;
        relo->kind = kind;
        relo->insn_idx = insn_idx;
        gen->relo_cnt++;
        debug_ret(gen, "find_by_name_kind(%s,%d)", relo->name, relo->kind);
 }
 
+/* Overwrites BPF_REG_{0, 1, 2, 3, 4, 7}
+ * Returns result in BPF_REG_7
+ * Returns u64 symbol addr in BPF_REG_9
+ */
+static void emit_bpf_kallsyms_lookup_name(struct bpf_gen *gen, struct ksym_relo_desc *relo)
+{
+       int name_off, len = strlen(relo->name) + 1, res_off;
+
+       name_off = add_data(gen, relo->name, len);
+       res_off = add_data(gen, NULL, 8); /* res is u64 */
+       emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
+                                        0, 0, 0, name_off));
+       emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
+       emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
+       emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_4, BPF_PSEUDO_MAP_IDX_VALUE,
+                                        0, 0, 0, res_off));
+       emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_4));
+       emit(gen, BPF_EMIT_CALL(BPF_FUNC_kallsyms_lookup_name));
+       emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0));
+       emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
+       debug_ret(gen, "kallsyms_lookup_name(%s,%d)", relo->name, relo->kind);
+}
+
 /* Expects:
  * BPF_REG_8 - pointer to instruction
  *
                   relo->name, kdesc->ref);
 }
 
+static void emit_ksym_relo_log(struct bpf_gen *gen, struct ksym_relo_desc *relo,
+                              int ref)
+{
+       if (!gen->log_level)
+               return;
+       emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
+                             offsetof(struct bpf_insn, imm)));
+       emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8, sizeof(struct bpf_insn) +
+                             offsetof(struct bpf_insn, imm)));
+       debug_regs(gen, BPF_REG_7, BPF_REG_9, " var t=%d w=%d (%s:count=%d): imm[0]: %%d, imm[1]: %%d",
+                  relo->is_typeless, relo->is_weak, relo->name, ref);
+       emit(gen, BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_8, offsetofend(struct bpf_insn, code)));
+       debug_regs(gen, BPF_REG_9, -1, " var t=%d w=%d (%s:count=%d): insn.reg",
+                  relo->is_typeless, relo->is_weak, relo->name, ref);
+}
+
+/* Expects:
+ * BPF_REG_8 - pointer to instruction
+ */
+static void emit_relo_ksym_typeless(struct bpf_gen *gen,
+                                   struct ksym_relo_desc *relo, int insn)
+{
+       struct ksym_desc *kdesc;
+
+       kdesc = get_ksym_desc(gen, relo);
+       if (!kdesc)
+               return;
+       /* try to copy from existing ldimm64 insn */
+       if (kdesc->ref > 1) {
+               move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
+                              kdesc->insn + offsetof(struct bpf_insn, imm));
+               move_blob2blob(gen, insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 4,
+                              kdesc->insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm));
+               goto log;
+       }
+       /* remember insn offset, so we can copy ksym addr later */
+       kdesc->insn = insn;
+       /* skip typeless ksym_desc in fd closing loop in cleanup_relos */
+       kdesc->typeless = true;
+       emit_bpf_kallsyms_lookup_name(gen, relo);
+       emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_7, -ENOENT, 1));
+       emit_check_err(gen);
+       /* store lower half of addr into insn[insn_idx].imm */
+       emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_9, offsetof(struct bpf_insn, imm)));
+       /* store upper half of addr into insn[insn_idx + 1].imm */
+       emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_9, 32));
+       emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_9,
+                     sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
+log:
+       emit_ksym_relo_log(gen, relo, kdesc->ref);
+}
+
 /* Expects:
  * BPF_REG_8 - pointer to instruction
  */
        emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7,
                              sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
 log:
-       if (!gen->log_level)
-               return;
-       emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
-                             offsetof(struct bpf_insn, imm)));
-       emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8, sizeof(struct bpf_insn) +
-                             offsetof(struct bpf_insn, imm)));
-       debug_regs(gen, BPF_REG_7, BPF_REG_9, " var (%s:count=%d): imm: %%d, fd: %%d",
-                  relo->name, kdesc->ref);
+       emit_ksym_relo_log(gen, relo, kdesc->ref);
 }
 
 static void emit_relo(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insns)
        emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_8, BPF_PSEUDO_MAP_IDX_VALUE, 0, 0, 0, insn));
        switch (relo->kind) {
        case BTF_KIND_VAR:
-               emit_relo_ksym_btf(gen, relo, insn);
+               if (relo->is_typeless)
+                       emit_relo_ksym_typeless(gen, relo, insn);
+               else
+                       emit_relo_ksym_btf(gen, relo, insn);
                break;
        case BTF_KIND_FUNC:
                emit_relo_kfunc_btf(gen, relo, insn);
        int i, insn;
 
        for (i = 0; i < gen->nr_ksyms; i++) {
-               if (gen->ksyms[i].kind == BTF_KIND_VAR) {
+               /* only close fds for typed ksyms and kfuncs */
+               if (gen->ksyms[i].kind == BTF_KIND_VAR && !gen->ksyms[i].typeless) {
                        /* close fd recorded in insn[insn_idx + 1].imm */
                        insn = gen->ksyms[i].insn;
                        insn += sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm);
                        emit_sys_close_blob(gen, insn);
-               } else { /* BTF_KIND_FUNC */
+               } else if (gen->ksyms[i].kind == BTF_KIND_FUNC) {
                        emit_sys_close_blob(gen, blob_fd_array_off(gen, gen->ksyms[i].off));
                        if (gen->ksyms[i].off < MAX_FD_ARRAY_SZ)
                                gen->nr_fd_array--;