Same as the previous patch, with kernel's kallsyms and btf ready, we can locate and iterate all kernel modules' btf data.
Signed-off-by: Tao Liu <[email protected]> --- btf_info.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ btf_info.h | 2 ++ 2 files changed, 76 insertions(+) diff --git a/btf_info.c b/btf_info.c index e7f8d9a..752661c 100644 --- a/btf_info.c +++ b/btf_info.c @@ -184,3 +184,77 @@ out: free(buf); return ret; } + +#define MEMBER_OFF(S, M) \ + GET_STRUCT_MEMBER_MOFF(S, M) / 8 + +bool init_module_btf(void) +{ + struct btf *btf_mod; + uint64_t btf_modules, list; + struct struct_member_info smi; + uint64_t btf = 0, data = 0, module = 0; + int data_size = 0; + bool ret = false; + char *btf_buf = NULL; + char *modname = NULL; + + btf_modules = get_kallsyms_value_by_name("btf_modules"); + if (!btf_modules) + /* Maybe module is not enabled, this is not an error */ + return true; + + INIT_STRUCT_MEMBER(btf_module, list); + INIT_STRUCT_MEMBER(btf_module, btf); + INIT_STRUCT_MEMBER(btf_module, module); + INIT_STRUCT_MEMBER(module, name); + INIT_STRUCT_MEMBER(btf, data); + INIT_STRUCT_MEMBER(btf, data_size); + modname = (char *)malloc(GET_STRUCT_MEMBER_MSIZE(module, name)); + if (!modname) + goto no_mem; + + for (list = next_list(btf_modules); list != btf_modules; list = next_list(list)) { + readmem(VADDR, list - MEMBER_OFF(btf_module, list) + + MEMBER_OFF(btf_module, btf), + &btf, GET_STRUCT_MEMBER_MSIZE(btf_module, btf)); + readmem(VADDR, list - MEMBER_OFF(btf_module, list) + + MEMBER_OFF(btf_module, module), + &module, GET_STRUCT_MEMBER_MSIZE(btf_module, module)); + readmem(VADDR, module + MEMBER_OFF(module, name), + modname, GET_STRUCT_MEMBER_MSIZE(module, name)); + readmem(VADDR, btf + MEMBER_OFF(btf, data), + &data, GET_STRUCT_MEMBER_MSIZE(btf, data)); + readmem(VADDR, btf + MEMBER_OFF(btf, data_size), + &data_size, GET_STRUCT_MEMBER_MSIZE(btf, data_size)); + btf_buf = (char *)malloc(data_size); + if (!btf_buf) + goto no_mem; + readmem(VADDR, data, btf_buf, data_size); + btf_mod = btf__new_split(btf_buf, data_size, btf_arr[0].btf); + free(btf_buf); + if (libbpf_get_error(btf_mod) != 0 || + add_to_btf_arr(btf_mod, strdup(modname)) == false) { + fprintf(stderr, "%s: init %s btf fail\n", __func__, modname); + goto out; + } + } + ret = true; + goto out; + +no_mem: + fprintf(stderr, "%s: Not enough memory!\n", __func__); +out: + if (modname) + free(modname); + return ret; +} + +void cleanup_btf(void) +{ + for (int i = 0; i < btf_arr_len; i++) { + free(btf_arr[i].module); + btf__free(btf_arr[i].btf); + } + free(btf_arr); +} diff --git a/btf_info.h b/btf_info.h index 1fc6829..d4408c3 100644 --- a/btf_info.h +++ b/btf_info.h @@ -16,7 +16,9 @@ struct struct_member_info { }; bool init_kernel_btf(void); +bool init_module_btf(void); bool get_struct_member_by_name(struct struct_member_info *smi); +void cleanup_btf(void); struct member_off_size { int m_off; -- 2.47.0
