Lines Matching full:linker
3 * BPF static linker
158 static int init_output_elf(struct bpf_linker *linker, const char *file);
160 static int linker_load_obj_file(struct bpf_linker *linker, const char *filename,
169 static int linker_append_sec_data(struct bpf_linker *linker, struct src_obj *obj);
170 static int linker_append_elf_syms(struct bpf_linker *linker, struct src_obj *obj);
171 static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj,
173 static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *obj);
174 static int linker_append_btf(struct bpf_linker *linker, struct src_obj *obj);
175 static int linker_append_btf_ext(struct bpf_linker *linker, struct src_obj *obj);
177 static int finalize_btf(struct bpf_linker *linker);
178 static int finalize_btf_ext(struct bpf_linker *linker);
180 void bpf_linker__free(struct bpf_linker *linker) in bpf_linker__free() argument
184 if (!linker) in bpf_linker__free()
187 free(linker->filename); in bpf_linker__free()
189 if (linker->elf) in bpf_linker__free()
190 elf_end(linker->elf); in bpf_linker__free()
192 if (linker->fd >= 0) in bpf_linker__free()
193 close(linker->fd); in bpf_linker__free()
195 strset__free(linker->strtab_strs); in bpf_linker__free()
197 btf__free(linker->btf); in bpf_linker__free()
198 btf_ext__free(linker->btf_ext); in bpf_linker__free()
200 for (i = 1; i < linker->sec_cnt; i++) { in bpf_linker__free()
201 struct dst_sec *sec = &linker->secs[i]; in bpf_linker__free()
211 free(linker->secs); in bpf_linker__free()
213 free(linker->glob_syms); in bpf_linker__free()
214 free(linker); in bpf_linker__free()
219 struct bpf_linker *linker; in bpf_linker__new() local
230 linker = calloc(1, sizeof(*linker)); in bpf_linker__new()
231 if (!linker) in bpf_linker__new()
234 linker->fd = -1; in bpf_linker__new()
236 err = init_output_elf(linker, filename); in bpf_linker__new()
240 return linker; in bpf_linker__new()
243 bpf_linker__free(linker); in bpf_linker__new()
247 static struct dst_sec *add_dst_sec(struct bpf_linker *linker, const char *sec_name) in add_dst_sec() argument
249 struct dst_sec *secs = linker->secs, *sec; in add_dst_sec()
250 size_t new_cnt = linker->sec_cnt ? linker->sec_cnt + 1 : 2; in add_dst_sec()
257 memset(secs + linker->sec_cnt, 0, (new_cnt - linker->sec_cnt) * sizeof(*secs)); in add_dst_sec()
259 linker->secs = secs; in add_dst_sec()
260 linker->sec_cnt = new_cnt; in add_dst_sec()
262 sec = &linker->secs[new_cnt - 1]; in add_dst_sec()
271 static Elf64_Sym *add_new_sym(struct bpf_linker *linker, size_t *sym_idx) in add_new_sym() argument
273 struct dst_sec *symtab = &linker->secs[linker->symtab_sec_idx]; in add_new_sym()
295 static int init_output_elf(struct bpf_linker *linker, const char *file) in init_output_elf() argument
301 linker->filename = strdup(file); in init_output_elf()
302 if (!linker->filename) in init_output_elf()
305 linker->fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); in init_output_elf()
306 if (linker->fd < 0) { in init_output_elf()
312 linker->elf = elf_begin(linker->fd, ELF_C_WRITE, NULL); in init_output_elf()
313 if (!linker->elf) { in init_output_elf()
319 linker->elf_hdr = elf64_newehdr(linker->elf); in init_output_elf()
320 if (!linker->elf_hdr) { in init_output_elf()
325 linker->elf_hdr->e_machine = EM_BPF; in init_output_elf()
326 linker->elf_hdr->e_type = ET_REL; in init_output_elf()
328 linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2LSB; in init_output_elf()
330 linker->elf_hdr->e_ident[EI_DATA] = ELFDATA2MSB; in init_output_elf()
337 linker->strtab_strs = strset__new(INT_MAX, "", sizeof("")); in init_output_elf()
338 if (libbpf_get_error(linker->strtab_strs)) in init_output_elf()
339 return libbpf_get_error(linker->strtab_strs); in init_output_elf()
341 sec = add_dst_sec(linker, ".strtab"); in init_output_elf()
345 sec->scn = elf_newscn(linker->elf); in init_output_elf()
361 str_off = strset__add_str(linker->strtab_strs, sec->sec_name); in init_output_elf()
366 linker->elf_hdr->e_shstrndx = sec->sec_idx; in init_output_elf()
367 linker->strtab_sec_idx = sec->sec_idx; in init_output_elf()
380 sec = add_dst_sec(linker, ".symtab"); in init_output_elf()
384 sec->scn = elf_newscn(linker->elf); in init_output_elf()
400 str_off = strset__add_str(linker->strtab_strs, sec->sec_name); in init_output_elf()
405 linker->symtab_sec_idx = sec->sec_idx; in init_output_elf()
411 sec->shdr->sh_link = linker->strtab_sec_idx; in init_output_elf()
420 linker->btf = btf__new_empty(); in init_output_elf()
421 err = libbpf_get_error(linker->btf); in init_output_elf()
426 init_sym = add_new_sym(linker, NULL); in init_output_elf()
440 int bpf_linker__add_file(struct bpf_linker *linker, const char *filename, in bpf_linker__add_file() argument
449 if (!linker->elf) in bpf_linker__add_file()
452 err = err ?: linker_load_obj_file(linker, filename, opts, &obj); in bpf_linker__add_file()
453 err = err ?: linker_append_sec_data(linker, &obj); in bpf_linker__add_file()
454 err = err ?: linker_append_elf_syms(linker, &obj); in bpf_linker__add_file()
455 err = err ?: linker_append_elf_relos(linker, &obj); in bpf_linker__add_file()
456 err = err ?: linker_append_btf(linker, &obj); in bpf_linker__add_file()
457 err = err ?: linker_append_btf_ext(linker, &obj); in bpf_linker__add_file()
538 static int linker_load_obj_file(struct bpf_linker *linker, const char *filename, in linker_load_obj_file() argument
556 pr_debug("linker: adding object file '%s'...\n", filename); in linker_load_obj_file()
978 static int init_sec(struct bpf_linker *linker, struct dst_sec *dst_sec, struct src_sec *src_sec) in init_sec() argument
993 scn = elf_newscn(linker->elf); in init_sec()
1008 name_off = strset__add_str(linker->strtab_strs, src_sec->sec_name); in init_sec()
1034 static struct dst_sec *find_dst_sec_by_name(struct bpf_linker *linker, const char *sec_name) in find_dst_sec_by_name() argument
1039 for (i = 1; i < linker->sec_cnt; i++) { in find_dst_sec_by_name()
1040 sec = &linker->secs[i]; in find_dst_sec_by_name()
1079 static int extend_sec(struct bpf_linker *linker, struct dst_sec *dst, struct src_sec *src) in extend_sec() argument
1099 err = init_sec(linker, dst, src); in extend_sec()
1169 static int linker_append_sec_data(struct bpf_linker *linker, struct src_obj *obj) in linker_append_sec_data() argument
1181 dst_sec = find_dst_sec_by_name(linker, src_sec->sec_name); in linker_append_sec_data()
1183 dst_sec = add_dst_sec(linker, src_sec->sec_name); in linker_append_sec_data()
1186 err = init_sec(linker, dst_sec, src_sec); in linker_append_sec_data()
1213 err = extend_sec(linker, dst_sec, src_sec); in linker_append_sec_data()
1221 static int linker_append_elf_syms(struct bpf_linker *linker, struct src_obj *obj) in linker_append_elf_syms() argument
1246 err = linker_append_elf_sym(linker, obj, sym, sym_name, i); in linker_append_elf_syms()
1254 static Elf64_Sym *get_sym_by_idx(struct bpf_linker *linker, size_t sym_idx) in get_sym_by_idx() argument
1256 struct dst_sec *symtab = &linker->secs[linker->symtab_sec_idx]; in get_sym_by_idx()
1262 static struct glob_sym *find_glob_sym(struct bpf_linker *linker, const char *sym_name) in find_glob_sym() argument
1268 for (i = 0; i < linker->glob_sym_cnt; i++) { in find_glob_sym()
1269 glob_sym = &linker->glob_syms[i]; in find_glob_sym()
1270 name = strset__data(linker->strtab_strs) + glob_sym->name_off; in find_glob_sym()
1279 static struct glob_sym *add_glob_sym(struct bpf_linker *linker) in add_glob_sym() argument
1283 syms = libbpf_reallocarray(linker->glob_syms, linker->glob_sym_cnt + 1, in add_glob_sym()
1284 sizeof(*linker->glob_syms)); in add_glob_sym()
1288 sym = &syms[linker->glob_sym_cnt]; in add_glob_sym()
1292 linker->glob_syms = syms; in add_glob_sym()
1293 linker->glob_sym_cnt++; in add_glob_sym()
1581 struct bpf_linker *linker, struct glob_sym *glob_sym, in glob_map_defs_match() argument
1603 t = btf__type_by_id(linker->btf, glob_sym->btf_id); in glob_map_defs_match()
1604 t = skip_mods_and_typedefs(linker->btf, t->type, NULL); in glob_map_defs_match()
1605 err = parse_btf_map_def(sym_name, linker->btf, t, true /*strict*/, &dst_def, &dst_inner_def); in glob_map_defs_match()
1616 return map_defs_match(sym_name, linker->btf, &dst_def, &dst_inner_def, in glob_map_defs_match()
1621 struct bpf_linker *linker, struct glob_sym *glob_sym, in glob_syms_match() argument
1642 if (glob_sym->sec_id && strcmp(linker->secs[glob_sym->sec_id].sec_name, MAPS_ELF_SEC) == 0) in glob_syms_match()
1643 return glob_map_defs_match(sym_name, linker, glob_sym, obj, sym, btf_id); in glob_syms_match()
1646 linker->btf, glob_sym->btf_id, obj->btf, btf_id)) in glob_syms_match()
1811 static int linker_append_elf_sym(struct bpf_linker *linker, struct src_obj *obj, in linker_append_elf_sym() argument
1837 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_elf_sym()
1873 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_elf_sym()
1877 glob_sym = find_glob_sym(linker, sym_name); in linker_append_elf_sym()
1896 if (!glob_syms_match(sym_name, linker, glob_sym, obj, sym, src_sym_idx, btf_id)) in linker_append_elf_sym()
1899 dst_sym = get_sym_by_idx(linker, glob_sym->sym_idx); in linker_append_elf_sym()
1952 if (complete_extern_btf_info(linker->btf, glob_sym->btf_id, in linker_append_elf_sym()
1964 name_off = strset__add_str(linker->strtab_strs, sym_name); in linker_append_elf_sym()
1968 dst_sym = add_new_sym(linker, &dst_sym_idx); in linker_append_elf_sym()
1987 glob_sym = add_glob_sym(linker); in linker_append_elf_sym()
2009 static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *obj) in linker_append_elf_relos() argument
2029 dst_sec = find_dst_sec_by_name(linker, src_sec->sec_name); in linker_append_elf_relos()
2031 dst_sec = add_dst_sec(linker, src_sec->sec_name); in linker_append_elf_relos()
2034 err = init_sec(linker, dst_sec, src_sec); in linker_append_elf_relos()
2045 dst_sec->shdr->sh_link = linker->symtab_sec_idx; in linker_append_elf_relos()
2048 dst_linked_sec = &linker->secs[src_linked_sec->dst_id]; in linker_append_elf_relos()
2052 err = extend_sec(linker, dst_sec, src_sec); in linker_append_elf_relos()
2166 * by static linker, not libbpf and kernel. When such in linker_fixup_btf()
2234 static int linker_append_btf(struct bpf_linker *linker, struct src_obj *obj) in linker_append_btf() argument
2243 start_id = btf__type_cnt(linker->btf); in linker_append_btf()
2262 glob_sym = find_glob_sym(linker, name); in linker_append_btf()
2289 id = btf__add_type(linker->btf, obj->btf, t); in linker_append_btf()
2305 n = btf__type_cnt(linker->btf); in linker_append_btf()
2307 struct btf_type *dst_t = btf_type_by_id(linker->btf, i); in linker_append_btf()
2316 for (i = 0; i < linker->glob_sym_cnt; i++) { in linker_append_btf()
2317 struct glob_sym *glob_sym = &linker->glob_syms[i]; in linker_append_btf()
2325 glob_t = btf_type_by_id(linker->btf, glob_sym->btf_id); in linker_append_btf()
2339 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_btf()
2359 t = btf_type_by_id(linker->btf, new_id); in linker_append_btf()
2361 name = btf__str_by_offset(linker->btf, t->name_off); in linker_append_btf()
2362 glob_sym = find_glob_sym(linker, name); in linker_append_btf()
2383 sz = btf__resolve_size(linker->btf, glob_sym->underlying_btf_id); in linker_append_btf()
2432 static int linker_append_btf_ext(struct bpf_linker *linker, struct src_obj *obj) in linker_append_btf_ext() argument
2453 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_btf_ext()
2482 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_btf_ext()
2499 str_off = btf__add_str(linker->btf, s); in linker_append_btf_ext()
2505 str_off = btf__add_str(linker->btf, s); in linker_append_btf_ext()
2524 dst_sec = &linker->secs[src_sec->dst_id]; in linker_append_btf_ext()
2542 str_off = btf__add_str(linker->btf, s); in linker_append_btf_ext()
2554 int bpf_linker__finalize(struct bpf_linker *linker) in bpf_linker__finalize() argument
2561 if (!linker->elf) in bpf_linker__finalize()
2564 err = finalize_btf(linker); in bpf_linker__finalize()
2569 strs_sz = strset__data_size(linker->strtab_strs); in bpf_linker__finalize()
2570 strs = strset__data(linker->strtab_strs); in bpf_linker__finalize()
2572 sec = &linker->secs[linker->strtab_sec_idx]; in bpf_linker__finalize()
2580 for (i = 1; i < linker->sec_cnt; i++) { in bpf_linker__finalize()
2581 sec = &linker->secs[i]; in bpf_linker__finalize()
2584 if (sec->sec_idx == linker->strtab_sec_idx) in bpf_linker__finalize()
2595 if (elf_update(linker->elf, ELF_C_NULL) < 0) { in bpf_linker__finalize()
2602 if (elf_update(linker->elf, ELF_C_WRITE) < 0) { in bpf_linker__finalize()
2608 elf_end(linker->elf); in bpf_linker__finalize()
2609 close(linker->fd); in bpf_linker__finalize()
2611 linker->elf = NULL; in bpf_linker__finalize()
2612 linker->fd = -1; in bpf_linker__finalize()
2617 static int emit_elf_data_sec(struct bpf_linker *linker, const char *sec_name, in emit_elf_data_sec() argument
2625 name_off = strset__add_str(linker->strtab_strs, sec_name); in emit_elf_data_sec()
2629 scn = elf_newscn(linker->elf); in emit_elf_data_sec()
2657 static int finalize_btf(struct bpf_linker *linker) in finalize_btf() argument
2660 struct btf *btf = linker->btf; in finalize_btf()
2666 if (btf__type_cnt(linker->btf) == 1) in finalize_btf()
2669 for (i = 1; i < linker->sec_cnt; i++) { in finalize_btf()
2670 struct dst_sec *sec = &linker->secs[i]; in finalize_btf()
2690 err = finalize_btf_ext(linker); in finalize_btf()
2696 opts.btf_ext = linker->btf_ext; in finalize_btf()
2697 err = btf__dedup(linker->btf, &opts); in finalize_btf()
2704 raw_data = btf__raw_data(linker->btf, &raw_sz); in finalize_btf()
2708 err = emit_elf_data_sec(linker, BTF_ELF_SEC, 8, raw_data, raw_sz); in finalize_btf()
2715 if (linker->btf_ext) { in finalize_btf()
2716 raw_data = btf_ext__get_raw_data(linker->btf_ext, &raw_sz); in finalize_btf()
2720 err = emit_elf_data_sec(linker, BTF_EXT_ELF_SEC, 8, raw_data, raw_sz); in finalize_btf()
2730 static int emit_btf_ext_data(struct bpf_linker *linker, void *output, in emit_btf_ext_data() argument
2741 str_off = btf__add_str(linker->btf, sec_name); in emit_btf_ext_data()
2757 static int finalize_btf_ext(struct bpf_linker *linker) in finalize_btf_ext() argument
2769 for (i = 1; i < linker->sec_cnt; i++) { in finalize_btf_ext()
2770 struct dst_sec *sec = &linker->secs[i]; in finalize_btf_ext()
2847 for (i = 1; i < linker->sec_cnt; i++) { in finalize_btf_ext()
2848 struct dst_sec *sec = &linker->secs[i]; in finalize_btf_ext()
2850 sz = emit_btf_ext_data(linker, cur, sec->sec_name, &sec->func_info); in finalize_btf_ext()
2864 for (i = 1; i < linker->sec_cnt; i++) { in finalize_btf_ext()
2865 struct dst_sec *sec = &linker->secs[i]; in finalize_btf_ext()
2867 sz = emit_btf_ext_data(linker, cur, sec->sec_name, &sec->line_info); in finalize_btf_ext()
2881 for (i = 1; i < linker->sec_cnt; i++) { in finalize_btf_ext()
2882 struct dst_sec *sec = &linker->secs[i]; in finalize_btf_ext()
2884 sz = emit_btf_ext_data(linker, cur, sec->sec_name, &sec->core_relo_info); in finalize_btf_ext()
2894 linker->btf_ext = btf_ext__new(data, total_sz); in finalize_btf_ext()
2895 err = libbpf_get_error(linker->btf_ext); in finalize_btf_ext()
2897 linker->btf_ext = NULL; in finalize_btf_ext()