2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2006 Mandriva Conectiva S.A.
5 Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
18 #include <sys/types.h>
22 #include "dwarves_reorganize.h"
23 #include "dwarves_emit.h"
26 #include "elf_symtab.h"
31 static char *class_name
;
34 * List of compilation units being looked for functions with
35 * pointers to the specified struct.
37 static struct cus
*methods_cus
;
40 * Mini class, the subset of the traced class that is collected at the probes
43 static struct class *mini_class
;
46 * Directory where to generate source files
48 static const char *src_dir
= ".";
51 * Where to print the ctracer_methods.stp file
53 static FILE *fp_methods
;
56 * Where to print the ctracer_collector.c file
58 static FILE *fp_collector
;
61 * Where to print the ctracer_classes.h file
63 static FILE *fp_classes
;
66 * blacklist __init marked functions, i.e. functions that are
67 * in the ".init.text" ELF section and are thus discarded after
70 static struct strlist
*init_blacklist
;
73 * List of definitions and forward declarations already emitted for
74 * methods_cus, to avoid duplication.
76 static struct type_emissions emissions
;
79 * CU blacklist: if a "blacklist.cu" file is present, don't consider the
80 * CUs listed. Use a default of blacklist.cu.
82 static const char *cu_blacklist_filename
= "blacklist.cu";
84 static struct strlist
*cu_blacklist
;
86 static struct cu
*cu_filter(struct cu
*cu
)
88 if (strlist__has_entry(cu_blacklist
, cu
->name
))
94 * List of probes and kretprobes already emitted, this is a hack to cope with
95 * name space collisions, a better solution would be to in these cases to use the
96 * compilation unit name (net/ipv4/tcp.o, for instance) as a prefix when a
97 * static function has the same name in multiple compilation units (aka object
100 static void *probes_emitted
;
103 struct list_head node
;
108 static struct structure
*structure__new(struct tag
*class, struct cu
*cu
)
110 struct structure
*st
= malloc(sizeof(*st
));
121 * structs that can be casted to the target class, e.g. i.e. that has the target
122 * class at its first member.
124 static LIST_HEAD(aliases
);
127 * structs have pointers to the target class.
129 static LIST_HEAD(pointers
);
131 static const char *structure__name(const struct structure
*st
)
133 return class__name(tag__class(st
->class));
136 static struct structure
*structures__find(struct list_head
*list
, const char *name
)
138 struct structure
*pos
;
143 list_for_each_entry(pos
, list
, node
)
144 if (strcmp(structure__name(pos
), name
) == 0)
150 static void structures__add(struct list_head
*list
, struct tag
*class, struct cu
*cu
)
152 struct structure
*str
= structure__new(class, cu
);
155 list_add(&str
->node
, list
);
158 static int methods__compare(const void *a
, const void *b
)
163 static int methods__add(void **table
, const char *str
)
165 char **s
= tsearch(str
, table
, methods__compare
);
169 char *dup
= strdup(str
);
173 tdelete(str
, table
, methods__compare
);
184 static void method__add(struct cu
*cu
, struct function
*function
, uint32_t id
)
186 list_add(&function
->tool_node
, &cu
->tool_list
);
187 function
->priv
= (void *)(long)id
;
191 * We want just the function tags that have as one of its parameters
192 * a pointer to the specified "class" (a struct, unions can be added later).
194 static struct function
*function__filter(struct function
*function
,
195 struct cu
*cu
, type_id_t target_type_id
)
197 if (function__inlined(function
) ||
198 function
->abstract_origin
!= 0 ||
199 !list_empty(&function
->tool_node
) ||
200 !ftype__has_parm_of_type(&function
->proto
, target_type_id
, cu
) ||
201 strlist__has_entry(init_blacklist
, function__name(function
))) {
209 * Iterate thru all the tags in the compilation unit, looking just for the
210 * function tags that have as one of its parameters a pointer to
211 * the specified "class" (struct).
213 static int cu_find_methods_iterator(struct cu
*cu
, void *cookie
)
215 type_id_t target_type_id
;
216 uint32_t function_id
;
217 struct function
*function
;
218 struct tag
*target
= cu__find_struct_by_name(cu
, cookie
, 0,
221 INIT_LIST_HEAD(&cu
->tool_list
);
226 cu__for_each_function(cu
, function_id
, function
)
227 if (function__filter(function
, cu
, target_type_id
))
228 method__add(cu
, function
, function_id
);
233 static struct class_member
*class_member__bitfield_tail(struct class_member
*head
,
236 struct class_member
*tail
= head
,
237 *member
= list_prepare_entry(head
,
240 list_for_each_entry_continue(member
, class__tags(class), tag
.node
)
241 if (member
->byte_offset
== head
->byte_offset
)
250 * Bitfields are removed as one for simplification right now.
252 static struct class_member
*class__remove_member(struct class *class, const struct cu
*cu
,
253 struct class_member
*member
)
255 size_t size
= member
->byte_size
;
256 struct class_member
*bitfield_tail
= NULL
;
257 struct list_head
*next
;
258 uint16_t member_hole
= member
->hole
;
260 if (member
->bitfield_size
!= 0) {
261 bitfield_tail
= class_member__bitfield_tail(member
, class);
262 member_hole
= bitfield_tail
->hole
;
265 * Is this the first member?
267 if (member
->tag
.node
.prev
== class__tags(class)) {
268 class->type
.size
-= size
+ member_hole
;
269 class__subtract_offsets_from(class, bitfield_tail
?: member
,
272 * Is this the last member?
274 } else if (member
->tag
.node
.next
== class__tags(class)) {
275 if (size
+ class->padding
>= cu
->addr_size
) {
276 class->type
.size
-= size
+ class->padding
;
279 class->padding
+= size
;
281 if (size
+ member_hole
>= cu
->addr_size
) {
282 class->type
.size
-= size
+ member_hole
;
283 class__subtract_offsets_from(class,
284 bitfield_tail
?: member
,
287 struct class_member
*from_prev
=
288 list_entry(member
->tag
.node
.prev
,
291 if (from_prev
->hole
== 0)
293 from_prev
->hole
+= size
+ member_hole
;
296 if (member_hole
!= 0)
299 if (bitfield_tail
!= NULL
) {
300 next
= bitfield_tail
->tag
.node
.next
;
301 list_del_range(&member
->tag
.node
, &bitfield_tail
->tag
.node
);
302 if (bitfield_tail
->bit_hole
!= 0)
303 class->nr_bit_holes
--;
305 next
= member
->tag
.node
.next
;
306 list_del(&member
->tag
.node
);
309 return list_entry(next
, struct class_member
, tag
.node
);
312 static size_t class__find_biggest_member_name(const struct class *class)
314 struct class_member
*pos
;
315 size_t biggest_name_len
= 0;
317 type__for_each_data_member(&class->type
, pos
) {
318 const size_t len
= pos
->name
?
319 strlen(class_member__name(pos
)) : 0;
321 if (len
> biggest_name_len
)
322 biggest_name_len
= len
;
325 return biggest_name_len
;
328 static void class__emit_class_state_collector(struct class *class, struct class *clone
)
330 struct class_member
*pos
;
331 int len
= class__find_biggest_member_name(clone
);
333 fprintf(fp_collector
,
334 "void ctracer__class_state(const void *from, void *to)\n"
336 "\tconst struct %s *obj = from;\n"
337 "\tstruct %s *mini_obj = to;\n\n",
338 class__name(class), class__name(clone
));
339 type__for_each_data_member(&clone
->type
, pos
)
340 fprintf(fp_collector
, "\tmini_obj->%-*s = obj->%s;\n", len
,
341 class_member__name(pos
),
342 class_member__name(pos
));
343 fputs("}\n\n", fp_collector
);
346 static struct class *class__clone_base_types(const struct tag
*tag
,
348 const char *new_class_name
)
350 struct class *class = tag__class(tag
);
351 struct class_member
*pos
, *next
;
352 struct class *clone
= class__clone(class, new_class_name
, cu
);
357 type__for_each_data_member_safe(&clone
->type
, pos
, next
) {
358 struct tag
*member_type
= cu__type(cu
, pos
->tag
.type
);
360 tag__assert_search_result(member_type
, pos
->tag
.tag
, class_member__name(pos
));
361 if (!tag__is_base_type(member_type
, cu
)) {
362 next
= class__remove_member(clone
, cu
, pos
);
363 class_member__delete(pos
, cu
);
366 class__fixup_alignment(clone
, cu
);
367 class__reorganize(clone
, cu
, 0, NULL
);
372 * Converter to the legacy ostra tables, will be much improved in the future.
374 static void emit_struct_member_table_entry(FILE *fp
,
375 int field
, const char *name
,
376 int traced
, const char *hooks
)
378 fprintf(fp
, "%u:%s:", field
, name
);
380 fprintf(fp
, "yes:%%object->%s:u:%s:none\n", name
, hooks
);
382 fprintf(fp
, "no:None:None:%s:dev_null\n", hooks
);
386 * Generates a converter to the ostra lebacy tables format, needef by
387 * ostra-cg to preprocess the raw data collected from the debugfs/relay
390 static int class__emit_ostra_converter(struct tag
*tag
)
392 struct class *class = tag__class(tag
);
393 struct class_member
*pos
;
394 struct type
*type
= &mini_class
->type
;
395 int field
= 0, first
= 1;
397 char parm_list
[1024] = "";
400 size_t plen
= sizeof(parm_list
);
401 FILE *fp_fields
, *fp_converter
;
402 const char *name
= class__name(class);
404 snprintf(filename
, sizeof(filename
), "%s/%s.fields", src_dir
, name
);
405 fp_fields
= fopen(filename
, "w");
406 if (fp_fields
== NULL
) {
407 fprintf(stderr
, "ctracer: couldn't create %s\n", filename
);
411 snprintf(filename
, sizeof(filename
), "%s/ctracer2ostra.c", src_dir
);
413 fp_converter
= fopen(filename
, "w");
414 if (fp_converter
== NULL
) {
415 fprintf(stderr
, "ctracer: couldn't create %s\n", filename
);
419 fputs("#include \"ctracer_classes.h\"\n"
420 "#include <stdio.h>\n"
421 "#include <string.h>\n"
422 "#include \"ctracer_relay.h\"\n\n", fp_converter
);
423 emit_struct_member_table_entry(fp_fields
, field
++, "action", 0,
425 emit_struct_member_table_entry(fp_fields
, field
++, "function_id", 0,
427 emit_struct_member_table_entry(fp_fields
, field
++, "object", 1,
430 fprintf(fp_converter
, "\n"
434 "\t\tstruct trace_entry hdr;\n"
435 "\t\tstruct ctracer__mini_%s obj;\n"
437 "\t\tif (read(0, &hdr, sizeof(hdr)) != sizeof(hdr))\n"
440 "\t\tfprintf(stdout, \"%%llu %%c:%%llu:%%p\",\n"
442 "\t\t\thdr.probe_type ? 'o' : 'i',\n"
443 "\t\t\thdr.function_id,\n"
444 "\t\t\thdr.object);\n"
446 "\t\tif (read(0, &obj, sizeof(obj)) != sizeof(obj))\n"
448 "\t\tfprintf(stdout,\n"
451 type__for_each_data_member(type
, pos
) {
455 fputc(':', fp_converter
);
456 n
= snprintf(p
, plen
, ",\n\t\t\t ");
459 fprintf(fp_converter
, "%%u");
460 n
= snprintf(p
, plen
, "obj.%s", class_member__name(pos
));
462 emit_struct_member_table_entry(fp_fields
, field
++,
463 class_member__name(pos
),
466 fprintf(fp_converter
,
467 "\\n\",\n\t\t\t %s);\n"
472 fclose(fp_converter
);
477 * We want just the DW_TAG_structure_type tags that have a member that is a pointer
478 * to the target class.
480 static struct tag
*pointer_filter(struct tag
*tag
, struct cu
*cu
,
481 type_id_t target_type_id
)
484 struct class_member
*pos
;
485 const char *class_name
;
487 if (!tag__is_struct(tag
))
490 type
= tag__type(tag
);
491 if (type
->nr_members
== 0)
494 class_name
= class__name(tag__class(tag
));
495 if (class_name
== NULL
|| structures__find(&pointers
, class_name
))
498 type__for_each_member(type
, pos
) {
499 struct tag
*ctype
= cu__type(cu
, pos
->tag
.type
);
501 tag__assert_search_result(ctype
, pos
->tag
.tag
, class_member__name(pos
));
502 if (tag__is_pointer_to(ctype
, target_type_id
))
510 * Iterate thru all the tags in the compilation unit, looking for classes
511 * that have as one member that is a pointer to the target type.
513 static int cu_find_pointers_iterator(struct cu
*cu
, void *class_name
)
515 type_id_t target_type_id
, id
;
516 struct tag
*target
= cu__find_struct_by_name(cu
, class_name
, 0,
517 &target_type_id
), *pos
;
522 cu__for_each_type(cu
, id
, pos
)
523 if (pointer_filter(pos
, cu
, target_type_id
))
524 structures__add(&pointers
, pos
, cu
);
529 static void class__find_pointers(const char *class_name
)
531 cus__for_each_cu(methods_cus
, cu_find_pointers_iterator
, (void *)class_name
, cu_filter
);
535 * We want just the DW_TAG_structure_type tags that have as its first member
536 * a struct of type target.
538 static struct tag
*alias_filter(struct tag
*tag
, type_id_t target_type_id
)
541 struct class_member
*first_member
;
543 if (!tag__is_struct(tag
))
546 type
= tag__type(tag
);
547 if (type
->nr_members
== 0)
550 first_member
= list_first_entry(&type
->namespace.tags
,
551 struct class_member
, tag
.node
);
552 if (first_member
->tag
.type
!= target_type_id
)
555 if (structures__find(&aliases
, class__name(tag__class(tag
))))
561 static void class__find_aliases(const char *class_name
);
564 * Iterate thru all the tags in the compilation unit, looking for classes
565 * that have as its first member the specified "class" (struct).
567 static int cu_find_aliases_iterator(struct cu
*cu
, void *class_name
)
569 type_id_t target_type_id
, id
;
570 struct tag
*target
= cu__find_struct_by_name(cu
, class_name
, 0,
571 &target_type_id
), *pos
;
575 cu__for_each_type(cu
, id
, pos
) {
576 if (alias_filter(pos
, target_type_id
)) {
577 const char *alias_name
= class__name(tag__class(pos
));
579 structures__add(&aliases
, pos
, cu
);
582 * Now find aliases to this alias, e.g.:
585 * struct inet_connection_sock {
593 class__find_aliases(alias_name
);
600 static void class__find_aliases(const char *class_name
)
602 cus__for_each_cu(methods_cus
, cu_find_aliases_iterator
, (void *)class_name
, cu_filter
);
605 static void emit_list_of_types(struct list_head
*list
)
607 struct structure
*pos
;
609 list_for_each_entry(pos
, list
, node
) {
610 struct type
*type
= tag__type(pos
->class);
612 * Lets look at the other CUs, perhaps we have already
615 if (type_emissions__find_definition(&emissions
, type__tag(type
)->tag
, structure__name(pos
))) {
616 type
->definition_emitted
= 1;
619 type__emit_definitions(pos
->class, pos
->cu
, &emissions
,
621 type
->definition_emitted
= 1;
622 type__emit(pos
->class, pos
->cu
, NULL
, NULL
, fp_classes
);
623 tag__type(pos
->class)->definition_emitted
= 1;
624 fputc('\n', fp_classes
);
628 static int class__emit_classes(struct tag
*tag
, struct cu
*cu
)
630 struct class *class = tag__class(tag
);
632 char mini_class_name
[128];
634 snprintf(mini_class_name
, sizeof(mini_class_name
), "ctracer__mini_%s",
637 mini_class
= class__clone_base_types(tag
, cu
, mini_class_name
);
638 if (mini_class
== NULL
)
641 type__emit_definitions(tag
, cu
, &emissions
, fp_classes
);
643 type__emit(tag
, cu
, NULL
, NULL
, fp_classes
);
644 fputs("\n/* class aliases */\n\n", fp_classes
);
646 emit_list_of_types(&aliases
);
648 fputs("\n/* class with pointers */\n\n", fp_classes
);
650 emit_list_of_types(&pointers
);
652 class__fprintf(mini_class
, cu
, fp_classes
);
653 fputs(";\n\n", fp_classes
);
654 class__emit_class_state_collector(class, mini_class
);
661 * Emit the kprobes routine for one of the selected "methods", later we'll
662 * put this into the 'kprobes' table, in cu_emit_kprobes_table_iterator.
664 * This marks the function entry, function__emit_kretprobes will emit the
665 * probe for the function exit.
667 static int function__emit_probes(struct function
*func
, uint32_t function_id
,
669 const type_id_t target_type_id
, int probe_type
,
672 struct parameter
*pos
;
673 const char *name
= function__name(func
);
675 fprintf(fp_methods
, "probe %s%s = kernel.function(\"%s@%s\")%s\n"
680 probe_type
== 0 ? "" : "__return",
683 probe_type
== 0 ? "" : ".return",
685 probe_type
== 0 ? "" : "__return");
687 list_for_each_entry(pos
, &func
->proto
.parms
, tag
.node
) {
688 struct tag
*type
= cu__type(cu
, pos
->tag
.type
);
690 tag__assert_search_result(type
, pos
->tag
.tag
, parameter__name(pos
));
691 if (!tag__is_pointer_to(type
, target_type_id
))
695 fprintf(fp_methods
, "\tif ($%s)\n\t", parameter__name(pos
));
698 "\tctracer__method_hook(%d, %d, $%s%s%s, %d);\n",
701 parameter__name(pos
),
702 member
? "->" : "", member
?: "",
703 class__size(mini_class
));
707 fputs("}\n\n", fp_methods
);
714 * Iterate thru the list of methods previously collected by
715 * cu_find_methods_iterator, emitting the probes for function entry.
717 static int cu_emit_probes_iterator(struct cu
*cu
, void *cookie
)
719 type_id_t target_type_id
;
720 struct tag
*target
= cu__find_struct_by_name(cu
, cookie
, 0, &target_type_id
);
721 struct function
*pos
;
723 /* OK, this type is not present in this compile unit */
727 list_for_each_entry(pos
, &cu
->tool_list
, tool_node
) {
728 uint32_t function_id
= (long)pos
->priv
;
730 if (methods__add(&probes_emitted
, function__name(pos
)) != 0)
732 function__emit_probes(pos
, function_id
, cu
, target_type_id
, 0, NULL
); /* entry */
733 function__emit_probes(pos
, function_id
, cu
, target_type_id
, 1, NULL
); /* exit */
740 * Iterate thru the list of methods previously collected by
741 * cu_find_methods_iterator, emitting the probes for function entry.
743 static int cu_emit_pointer_probes_iterator(struct cu
*cu
, void *cookie
)
745 type_id_t target_type_id
, pointer_id
;
746 struct tag
*target
, *pointer
;
747 struct function
*pos_tag
;
748 struct class_member
*pos_member
;
750 /* This CU doesn't have our classes */
751 if (list_empty(&cu
->tool_list
))
754 target
= cu__find_struct_by_name(cu
, class_name
, 1, &target_type_id
);
755 pointer
= cu__find_struct_by_name(cu
, cookie
, 0, &pointer_id
);
757 /* OK, this type is not present in this compile unit */
758 if (target
== NULL
|| pointer
== NULL
)
761 /* for now just for the first member that is a pointer */
762 type__for_each_member(tag__type(pointer
), pos_member
) {
763 struct tag
*ctype
= cu__type(cu
, pos_member
->tag
.type
);
765 tag__assert_search_result(ctype
, pos_member
->tag
.tag
, class_member__name(pos_member
));
766 if (tag__is_pointer_to(ctype
, target_type_id
))
770 list_for_each_entry(pos_tag
, &cu
->tool_list
, tool_node
) {
771 uint32_t function_id
= (long)pos_tag
->priv
;
773 if (methods__add(&probes_emitted
, function__name(pos_tag
)) != 0)
776 function__emit_probes(pos_tag
, function_id
, cu
, target_type_id
, 0,
777 class_member__name(pos_member
)); /* entry */
778 function__emit_probes(pos_tag
, function_id
, cu
, target_type_id
, 1,
779 class_member__name(pos_member
)); /* exit */
786 * Iterate thru the list of methods previously collected by
787 * cu_find_methods_iterator, creating the functions table that will
788 * be used by ostra-cg
790 static int cu_emit_functions_table(struct cu
*cu
, void *fp
)
792 struct function
*pos
;
794 list_for_each_entry(pos
, &cu
->tool_list
, tool_node
)
795 if (pos
->priv
!= NULL
) {
796 uint32_t function_id
= (long)pos
->priv
;
797 fprintf(fp
, "%d:%s\n", function_id
, function__name(pos
));
804 static int elf__open(const char *filename
)
806 int fd
= open(filename
, O_RDONLY
);
813 if (elf_version(EV_CURRENT
) == EV_NONE
) {
814 fprintf(stderr
, "%s: cannot set libelf version.\n", __func__
);
818 Elf
*elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
820 fprintf(stderr
, "%s: cannot read %s ELF file.\n",
827 Elf_Scn
*init
= elf_section_by_name(elf
, &shdr
, ".init.text", &init_index
);
831 struct elf_symtab
*symtab
= elf_symtab__new(".symtab", elf
);
835 init_blacklist
= strlist__new(true);
836 if (init_blacklist
== NULL
)
837 goto out_elf_symtab_delete
;
841 elf_symtab__for_each_symbol(symtab
, index
, sym
) {
842 if (!elf_sym__is_local_function(&sym
))
844 if (elf_sym__section(&sym
) != init_index
)
846 err
= strlist__add(init_blacklist
, elf_sym__name(&sym
, symtab
));
847 if (err
== -ENOMEM
) {
848 fprintf(stderr
, "failed for %s(%d,%zd)\n", elf_sym__name(&sym
, symtab
),elf_sym__section(&sym
),init_index
);
849 goto out_delete_blacklist
;
854 out_elf_symtab_delete
:
855 elf_symtab__delete(symtab
);
861 out_delete_blacklist
:
862 strlist__delete(init_blacklist
);
863 goto out_elf_symtab_delete
;
866 /* Name and version of program. */
867 ARGP_PROGRAM_VERSION_HOOK_DEF
= dwarves_print_version
;
869 static const struct argp_option ctracer__options
[] = {
874 .doc
= "generate source files in this directory",
878 .name
= "cu_blacklist",
880 .doc
= "Blacklist the CUs in FILE",
886 .doc
= "load files in this directory",
892 .doc
= "file mask to load",
897 .doc
= "recursively load files",
904 static const char *dirname
, *glob
;
905 static int recursive
;
907 static error_t
ctracer__options_parser(int key
, char *arg
,
908 struct argp_state
*state __maybe_unused
)
911 case 'd': src_dir
= arg
; break;
912 case 'C': cu_blacklist_filename
= arg
; break;
913 case 'D': dirname
= arg
; break;
914 case 'g': glob
= arg
; break;
915 case 'r': recursive
= 1; break;
916 default: return ARGP_ERR_UNKNOWN
;
921 static const char ctracer__args_doc
[] = "FILE CLASS";
923 static struct argp ctracer__argp
= {
924 .options
= ctracer__options
,
925 .parser
= ctracer__options_parser
,
926 .args_doc
= ctracer__args_doc
,
929 int main(int argc
, char *argv
[])
935 char functions_filename
[PATH_MAX
];
936 char methods_filename
[PATH_MAX
];
937 char collector_filename
[PATH_MAX
];
938 char classes_filename
[PATH_MAX
];
939 struct structure
*pos
;
941 int rc
= EXIT_FAILURE
;
943 if (dwarves__init()) {
944 fputs("ctracer: insufficient memory\n", stderr
);
947 dwarves__resolve_cacheline_size(NULL
, 0);
949 if (argp_parse(&ctracer__argp
, argc
, argv
, 0, &remaining
, NULL
) ||
951 switch (argc
- remaining
) {
952 case 1: goto failure
;
953 case 2: filename
= argv
[remaining
++];
954 class_name
= argv
[remaining
++]; break;
955 default: goto failure
;
959 argp_help(&ctracer__argp
, stderr
, ARGP_HELP_SEE
, argv
[0]);
963 type_emissions__init(&emissions
, NULL
);
966 * Create the methods_cus (Compilation Units) object where we will
967 * load the objects where we'll look for functions pointers to the
968 * specified class, i.e. to find its "methods", where we'll insert
969 * the entry and exit hooks.
971 methods_cus
= cus__new();
972 if (methods_cus
== NULL
) {
973 fputs("ctracer: insufficient memory\n", stderr
);
978 * if --dir/-D was specified, recursively traverse the path looking for
979 * object files (compilation units) that match the glob specified (*.ko)
980 * for kernel modules, but could be "*.o" in the future when we support
981 * uprobes for user space tracing.
983 if (dirname
!= NULL
&& cus__load_dir(methods_cus
, NULL
, dirname
, glob
,
985 fprintf(stderr
, "ctracer: couldn't load DWARF info "
986 "from %s dir with glob %s\n",
992 * If a filename was specified, for instance "vmlinux", load it too.
994 if (filename
!= NULL
) {
995 if (elf__open(filename
)) {
996 fprintf(stderr
, "ctracer: couldn't load ELF symtab "
997 "info from %s\n", filename
);
1000 err
= cus__load_file(methods_cus
, NULL
, filename
);
1002 cus__print_error_msg("ctracer", methods_cus
, filename
, err
);
1008 * See if the specified struct exists:
1010 class = cus__find_struct_by_name(methods_cus
, &cu
, class_name
, 0, NULL
);
1011 if (class == NULL
) {
1012 fprintf(stderr
, "ctracer: struct %s not found!\n", class_name
);
1016 snprintf(functions_filename
, sizeof(functions_filename
),
1017 "%s/%s.functions", src_dir
, class__name(tag__class(class)));
1018 fp_functions
= fopen(functions_filename
, "w");
1019 if (fp_functions
== NULL
) {
1020 fprintf(stderr
, "ctracer: couldn't create %s\n",
1021 functions_filename
);
1025 snprintf(methods_filename
, sizeof(methods_filename
),
1026 "%s/ctracer_methods.stp", src_dir
);
1027 fp_methods
= fopen(methods_filename
, "w");
1028 if (fp_methods
== NULL
) {
1029 fprintf(stderr
, "ctracer: couldn't create %s\n",
1034 snprintf(collector_filename
, sizeof(collector_filename
),
1035 "%s/ctracer_collector.c", src_dir
);
1036 fp_collector
= fopen(collector_filename
, "w");
1037 if (fp_collector
== NULL
) {
1038 fprintf(stderr
, "ctracer: couldn't create %s\n",
1039 collector_filename
);
1043 snprintf(classes_filename
, sizeof(classes_filename
),
1044 "%s/ctracer_classes.h", src_dir
);
1045 fp_classes
= fopen(classes_filename
, "w");
1046 if (fp_classes
== NULL
) {
1047 fprintf(stderr
, "ctracer: couldn't create %s\n",
1053 "#include </home/acme/git/pahole/lib/ctracer_relay.h>\n"
1055 "function ctracer__method_hook(probe_type, func, object, state_len)\n"
1057 "\tctracer__method_hook(_stp_gettimeofday_ns(), "
1058 "THIS->probe_type, THIS->func, "
1059 "(void *)(long)THIS->object, "
1060 "THIS->state_len);\n"
1061 "%}\n\n", fp_methods
);
1063 fputs("\n#include \"ctracer_classes.h\"\n\n", fp_collector
);
1064 class__find_aliases(class_name
);
1065 class__find_pointers(class_name
);
1067 class__emit_classes(class, cu
);
1068 fputc('\n', fp_collector
);
1070 class__emit_ostra_converter(class);
1072 cu_blacklist
= strlist__new(true);
1073 if (cu_blacklist
!= NULL
)
1074 strlist__load(cu_blacklist
, cu_blacklist_filename
);
1076 cus__for_each_cu(methods_cus
, cu_find_methods_iterator
,
1077 class_name
, cu_filter
);
1078 cus__for_each_cu(methods_cus
, cu_emit_probes_iterator
,
1079 class_name
, cu_filter
);
1080 cus__for_each_cu(methods_cus
, cu_emit_functions_table
,
1081 fp_functions
, cu_filter
);
1083 list_for_each_entry(pos
, &aliases
, node
) {
1084 const char *alias_name
= structure__name(pos
);
1086 cus__for_each_cu(methods_cus
, cu_find_methods_iterator
,
1087 (void *)alias_name
, cu_filter
);
1088 cus__for_each_cu(methods_cus
, cu_emit_probes_iterator
,
1089 (void *)alias_name
, cu_filter
);
1090 cus__for_each_cu(methods_cus
, cu_emit_functions_table
,
1091 fp_functions
, cu_filter
);
1094 list_for_each_entry(pos
, &pointers
, node
) {
1095 const char *pointer_name
= structure__name(pos
);
1096 cus__for_each_cu(methods_cus
, cu_find_methods_iterator
,
1097 (void *)pointer_name
, cu_filter
);
1098 cus__for_each_cu(methods_cus
, cu_emit_pointer_probes_iterator
,
1099 (void *)pointer_name
, cu_filter
);
1100 cus__for_each_cu(methods_cus
, cu_emit_functions_table
, fp_functions
,
1105 fclose(fp_collector
);
1106 fclose(fp_functions
);
1108 strlist__delete(cu_blacklist
);
1112 cus__delete(methods_cus
);