751 return ret_info.return_range_list;
752 }
753
754 static void match_call_marker(struct expression *expr)
755 {
756 struct symbol *type;
757
758 type = get_type(expr->fn);
759 if (type && type->type == SYM_PTR)
760 type = get_real_base_type(type);
761
762 /*
763 * we just want to record something in the database so that if we have
764 * two calls like: frob(4); frob(some_unkown); then on the receiving
765 * side we know that sometimes frob is called with unknown parameters.
766 */
767
768 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
769 }
770
771 static char *show_offset(int offset)
772 {
773 static char buf[64];
774
775 buf[0] = '\0';
776 if (offset != -1)
777 snprintf(buf, sizeof(buf), "(-%d)", offset);
778 return buf;
779 }
780
781 int is_recursive_member(const char *name)
782 {
783 char buf[256];
784 const char *p, *next;
785 int size;
786
787 p = strchr(name, '>');
788 if (!p)
789 return 0;
790 p++;
791 while (true) {
792 next = strchr(p, '>');
793 if (!next)
794 return 0;
795 next++;
796
797 size = next - p;
798 if (size >= sizeof(buf))
799 return 0;
800 memcpy(buf, p, size);
843 goto free;
844 if (sm_name[len] == '\0') {
845 snprintf(buf, sizeof(buf), "%s%s$",
846 add_star ? "*" : "", is_address ? "*" : "");
847 } else {
848 if (sm_name[len] != '.' && sm_name[len] != '-')
849 goto free;
850 if (sm_name[len] == '-')
851 len++;
852 // FIXME does is_address really imply that sm_name[len] == '-'
853 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
854 sm_name + len);
855 }
856
857 ret = alloc_sname(buf);
858 free:
859 free_string(name);
860 return ret;
861 }
862
863 static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, struct stree *stree,
864 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
865 {
866 struct sm_state *sm;
867 const char *sm_name;
868 char *name;
869 struct symbol *sym;
870 int len;
871 char printed_name[256];
872 int is_address = 0;
873 bool add_star;
874 struct symbol *type;
875
876 expr = strip_expr(expr);
877 if (!expr)
878 return;
879 type = get_type(expr);
880 if (type && type_bits(type) < type_bits(&ulong_ctype))
881 return;
882
883 if (expr->type == EXPR_PREOP && expr->op == '&') {
885 is_address = 1;
886 }
887
888 name = expr_to_var_sym(expr, &sym);
889 if (!name || !sym)
890 goto free;
891
892 len = strlen(name);
893 FOR_EACH_SM(stree, sm) {
894 if (sm->sym != sym)
895 continue;
896 sm_name = sm->name;
897 add_star = false;
898 if (sm_name[0] == '*') {
899 add_star = true;
900 sm_name++;
901 }
902 // FIXME: simplify?
903 if (!add_star && strcmp(name, sm_name) == 0) {
904 if (is_address)
905 snprintf(printed_name, sizeof(printed_name), "*$%s", show_offset(offset));
906 else /* these are already handled. fixme: handle them here */
907 continue;
908 } else if (add_star && strcmp(name, sm_name) == 0) {
909 snprintf(printed_name, sizeof(printed_name), "%s*$%s",
910 is_address ? "*" : "", show_offset(offset));
911 } else if (strncmp(name, sm_name, len) == 0) {
912 if (sm_name[len] != '.' && sm_name[len] != '-')
913 continue;
914 if (is_address)
915 snprintf(printed_name, sizeof(printed_name),
916 "%s$%s->%s", add_star ? "*" : "",
917 show_offset(offset), sm_name + len + 1);
918 else
919 snprintf(printed_name, sizeof(printed_name),
920 "%s$%s%s", add_star ? "*" : "",
921 show_offset(offset), sm_name + len);
922 } else {
923 continue;
924 }
925 if (is_recursive_member(printed_name))
926 continue;
927 callback(call, param, printed_name, sm);
928 } END_FOR_EACH_SM(sm);
929 free:
930 free_string(name);
931 }
932
933 static int param_used_callback(void *_container, int argc, char **argv, char **azColName)
934 {
935 char **container = _container;
936 static char buf[256];
937
938 snprintf(buf, sizeof(buf), "%s", argv[0]);
939 *container = buf;
940 return 0;
941 }
942
943 static void print_container_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
944 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
945 {
946 struct expression *tmp;
947 char *container = NULL;
948 int offset;
949 int holder_offset;
950 char *p;
951
952 if (!call->fn || call->fn->type != EXPR_SYMBOL || !call->fn->symbol)
953 return;
954
955 /*
956 * We can't use the in-mem DB because we have to parse the function
957 * first, then we know if it takes a container, then we know to pass it
958 * the container data.
959 *
960 */
961 run_sql(¶m_used_callback, &container,
962 "select key from return_implies where %s and type = %d and key like '%%$(%%' and parameter = %d limit 1;",
963 get_static_filter(call->fn->symbol), CONTAINER, param);
964 if (!container)
965 return;
966
967 p = strchr(container, '-');
968 if (!p)
969 return;
970 offset = atoi(p);
971 p = strchr(p, ')');
972 if (!p)
973 return;
974 p++;
975
976 tmp = get_assigned_expr(expr);
977 if (tmp)
978 expr = tmp;
979
980 if (expr->type != EXPR_PREOP || expr->op != '&')
981 return;
982 expr = strip_expr(expr->unop);
983 holder_offset = get_member_offset_from_deref(expr);
984 if (-holder_offset != offset)
985 return;
986
987 expr = strip_expr(expr->deref);
988 if (expr->type == EXPR_PREOP && expr->op == '*')
989 expr = strip_expr(expr->unop);
990
991 print_struct_members(call, expr, param, holder_offset, stree, callback);
992 }
993
994 static void match_call_info(struct expression *call)
995 {
996 struct member_info_callback *cb;
997 struct expression *arg;
998 struct stree *stree;
999 char *name;
1000 int i;
1001
1002 name = get_fnptr_name(call->fn);
1003 if (!name)
1004 return;
1005
1006 FOR_EACH_PTR(member_callbacks, cb) {
1007 stree = get_all_states_stree(cb->owner);
1008 i = 0;
1009 FOR_EACH_PTR(call->args, arg) {
1010 print_struct_members(call, arg, i, -1, stree, cb->callback);
1011 print_container_struct_members(call, arg, i, stree, cb->callback);
1012 i++;
1013 } END_FOR_EACH_PTR(arg);
1014 free_stree(&stree);
1015 } END_FOR_EACH_PTR(cb);
1016
1017 free_string(name);
1018 }
1019
1020 static int get_param(int param, char **name, struct symbol **sym)
1021 {
1022 struct symbol *arg;
1023 int i;
1024
1025 i = 0;
1026 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
1027 /*
1028 * this is a temporary hack to work around a bug (I think in sparse?)
1029 * 2.6.37-rc1:fs/reiserfs/journal.o
1030 * If there is a function definition without parameter name found
1031 * after a function implementation then it causes a crash.
|
751 return ret_info.return_range_list;
752 }
753
754 static void match_call_marker(struct expression *expr)
755 {
756 struct symbol *type;
757
758 type = get_type(expr->fn);
759 if (type && type->type == SYM_PTR)
760 type = get_real_base_type(type);
761
762 /*
763 * we just want to record something in the database so that if we have
764 * two calls like: frob(4); frob(some_unkown); then on the receiving
765 * side we know that sometimes frob is called with unknown parameters.
766 */
767
768 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
769 }
770
771 int is_recursive_member(const char *name)
772 {
773 char buf[256];
774 const char *p, *next;
775 int size;
776
777 p = strchr(name, '>');
778 if (!p)
779 return 0;
780 p++;
781 while (true) {
782 next = strchr(p, '>');
783 if (!next)
784 return 0;
785 next++;
786
787 size = next - p;
788 if (size >= sizeof(buf))
789 return 0;
790 memcpy(buf, p, size);
833 goto free;
834 if (sm_name[len] == '\0') {
835 snprintf(buf, sizeof(buf), "%s%s$",
836 add_star ? "*" : "", is_address ? "*" : "");
837 } else {
838 if (sm_name[len] != '.' && sm_name[len] != '-')
839 goto free;
840 if (sm_name[len] == '-')
841 len++;
842 // FIXME does is_address really imply that sm_name[len] == '-'
843 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
844 sm_name + len);
845 }
846
847 ret = alloc_sname(buf);
848 free:
849 free_string(name);
850 return ret;
851 }
852
853 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
854 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
855 {
856 struct sm_state *sm;
857 const char *sm_name;
858 char *name;
859 struct symbol *sym;
860 int len;
861 char printed_name[256];
862 int is_address = 0;
863 bool add_star;
864 struct symbol *type;
865
866 expr = strip_expr(expr);
867 if (!expr)
868 return;
869 type = get_type(expr);
870 if (type && type_bits(type) < type_bits(&ulong_ctype))
871 return;
872
873 if (expr->type == EXPR_PREOP && expr->op == '&') {
875 is_address = 1;
876 }
877
878 name = expr_to_var_sym(expr, &sym);
879 if (!name || !sym)
880 goto free;
881
882 len = strlen(name);
883 FOR_EACH_SM(stree, sm) {
884 if (sm->sym != sym)
885 continue;
886 sm_name = sm->name;
887 add_star = false;
888 if (sm_name[0] == '*') {
889 add_star = true;
890 sm_name++;
891 }
892 // FIXME: simplify?
893 if (!add_star && strcmp(name, sm_name) == 0) {
894 if (is_address)
895 snprintf(printed_name, sizeof(printed_name), "*$");
896 else /* these are already handled. fixme: handle them here */
897 continue;
898 } else if (add_star && strcmp(name, sm_name) == 0) {
899 snprintf(printed_name, sizeof(printed_name), "%s*$",
900 is_address ? "*" : "");
901 } else if (strncmp(name, sm_name, len) == 0) {
902 if (sm_name[len] != '.' && sm_name[len] != '-')
903 continue;
904 if (is_address)
905 snprintf(printed_name, sizeof(printed_name),
906 "%s$->%s", add_star ? "*" : "",
907 sm_name + len + 1);
908 else
909 snprintf(printed_name, sizeof(printed_name),
910 "%s$%s", add_star ? "*" : "",
911 sm_name + len);
912 } else {
913 continue;
914 }
915 if (is_recursive_member(printed_name))
916 continue;
917 callback(call, param, printed_name, sm);
918 } END_FOR_EACH_SM(sm);
919 free:
920 free_string(name);
921 }
922
923 static void match_call_info(struct expression *call)
924 {
925 struct member_info_callback *cb;
926 struct expression *arg;
927 struct stree *stree;
928 char *name;
929 int i;
930
931 name = get_fnptr_name(call->fn);
932 if (!name)
933 return;
934
935 FOR_EACH_PTR(member_callbacks, cb) {
936 stree = get_all_states_stree(cb->owner);
937 i = 0;
938 FOR_EACH_PTR(call->args, arg) {
939 print_struct_members(call, arg, i, stree, cb->callback);
940 i++;
941 } END_FOR_EACH_PTR(arg);
942 free_stree(&stree);
943 } END_FOR_EACH_PTR(cb);
944
945 free_string(name);
946 }
947
948 static int get_param(int param, char **name, struct symbol **sym)
949 {
950 struct symbol *arg;
951 int i;
952
953 i = 0;
954 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
955 /*
956 * this is a temporary hack to work around a bug (I think in sparse?)
957 * 2.6.37-rc1:fs/reiserfs/journal.o
958 * If there is a function definition without parameter name found
959 * after a function implementation then it causes a crash.
|