~ubuntu-branches/ubuntu/karmic/valgrind/karmic

« back to all changes in this revision

Viewing changes to coregrind/m_errormgr.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-05 18:27:01 UTC
  • mfrom: (1.1.9 upstream) (2.1.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090305182701-yag747u3f33y9g8y
Tags: 1:3.4.1-1ubuntu1
* Merge with Debian; remaining changes:
  - Add 91_build_with_fno_stack_protector.dpatch.
  - Add lpia to Architecture.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
   This file is part of Valgrind, a dynamic binary instrumentation
8
8
   framework.
9
9
 
10
 
   Copyright (C) 2000-2007 Julian Seward 
 
10
   Copyright (C) 2000-2008 Julian Seward 
11
11
      jseward@acm.org
12
12
 
13
13
   This program is free software; you can redistribute it and/or
40
40
#include "pub_core_libcfile.h"
41
41
#include "pub_core_libcprint.h"
42
42
#include "pub_core_libcproc.h"         // For VG_(getpid)()
 
43
#include "pub_core_seqmatch.h"
43
44
#include "pub_core_mallocfree.h"
44
45
#include "pub_core_options.h"
45
46
#include "pub_core_stacktrace.h"
119
120
   // NULL if unsuppressed; or ptr to suppression record.
120
121
   Supp* supp;
121
122
   Int count;
122
 
   ThreadId tid;
123
123
 
124
124
   // The tool-specific part
 
125
   ThreadId tid;           // Initialised by core
125
126
   ExeContext* where;      // Initialised by core
126
127
   ErrorKind ekind;        // Used by ALL.  Must be in the range (0..)
127
128
   Addr addr;              // Used frequently
129
130
   void* extra;            // For any tool-specific extras
130
131
};
131
132
 
 
133
 
132
134
ExeContext* VG_(get_error_where) ( Error* err )
133
135
{
134
136
   return err->where;
183
185
   enum { 
184
186
      NoName,     /* Error case */
185
187
      ObjName,    /* Name is of an shared object file. */
186
 
      FunName     /* Name is of a function. */
 
188
      FunName,    /* Name is of a function. */
 
189
      DotDotDot   /* Frame-level wildcard */
187
190
   }
188
191
   SuppLocTy;
189
192
 
190
193
typedef
191
194
   struct {
192
195
      SuppLocTy ty;
193
 
      Char*     name;
 
196
      Char*     name; /* NULL for NoName and DotDotDot */
194
197
   }
195
198
   SuppLoc;
196
199
 
441
444
   }
442
445
 
443
446
   // Print stack trace elements
444
 
   VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
 
447
   VG_(apply_StackTrace)(printSuppForIp,
 
448
                         VG_(get_ExeContext_StackTrace)(ec), stop_at);
445
449
 
446
450
   VG_(printf)("}\n");
447
451
}
598
602
   */
599
603
 
600
604
   /* copy main part */
601
 
   p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
 
605
   p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
602
606
   *p = err;
603
607
 
604
608
   /* update 'extra' */
616
620
 
617
621
   /* copy block pointed to by 'extra', if there is one */
618
622
   if (NULL != p->extra && 0 != extra_size) { 
619
 
      void* new_extra = VG_(malloc)(extra_size);
 
623
      void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
620
624
      VG_(memcpy)(new_extra, p->extra, extra_size);
621
625
      p->extra = new_extra;
622
626
   }
707
711
         continue;
708
712
      any_supp = True;
709
713
      if (VG_(clo_xml)) {
710
 
         VG_(message)(Vg_DebugMsg, 
711
 
                      "  <pair>\n"
712
 
                      "    <count>%d</count>\n"
713
 
                      "    <name>%t</name>\n"
714
 
                      "  </pair>", 
715
 
                      su->count, su->sname);
 
714
         VG_(message_no_f_c)(Vg_DebugMsg,
 
715
                             "  <pair>\n"
 
716
                             "    <count>%d</count>\n"
 
717
                             "    <name>%t</name>\n"
 
718
                             "  </pair>",
 
719
                             su->count, su->sname);
716
720
      } else {
717
721
         VG_(message)(Vg_DebugMsg, "supp: %6d %s", su->count, su->sname);
718
722
      }
787
791
      pp_Error( p_min );
788
792
 
789
793
      if ((i+1 == VG_(clo_dump_error))) {
790
 
         StackTrace ips = VG_(extract_StackTrace)(p_min->where);
 
794
         StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
791
795
         VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
792
796
                          ips[0], /*debugging*/True, 0xFE/*verbosity*/,
793
797
                          /*bbs_done*/0,
837
841
 
838
842
 
839
843
/*------------------------------------------------------------*/
840
 
/*--- Standard suppressions                                ---*/
 
844
/*--- Suppression parsing                                  ---*/
841
845
/*------------------------------------------------------------*/
842
846
 
843
847
/* Get the next char from fd into *out_buf.  Returns 1 if success,
846
850
static Int get_char ( Int fd, Char* out_buf )
847
851
{
848
852
   Int r;
849
 
   static Char buf[64];
 
853
   static Char buf[256];
850
854
   static Int buf_size = 0;
851
855
   static Int buf_used = 0;
852
 
   vg_assert(buf_size >= 0 && buf_size <= 64);
 
856
   vg_assert(buf_size >= 0 && buf_size <= 256);
853
857
   vg_assert(buf_used >= 0 && buf_used <= buf_size);
854
858
   if (buf_used == buf_size) {
855
 
      r = VG_(read)(fd, buf, 64);
 
859
      r = VG_(read)(fd, buf, 256);
856
860
      if (r < 0) return r; /* read failed */
857
 
      vg_assert(r >= 0 && r <= 64);
 
861
      vg_assert(r >= 0 && r <= 256);
858
862
      buf_size = r;
859
863
      buf_used = 0;
860
864
   }
861
865
   if (buf_size == 0)
862
866
     return 0; /* eof */
863
 
   vg_assert(buf_size >= 0 && buf_size <= 64);
 
867
   vg_assert(buf_size >= 0 && buf_size <= 256);
864
868
   vg_assert(buf_used >= 0 && buf_used < buf_size);
865
869
   *out_buf = buf[buf_used];
866
870
   buf_used++;
924
928
      p->ty = ObjName;
925
929
      return True;
926
930
   }
927
 
   VG_(printf)("location should start with fun: or obj:\n");
 
931
   if (VG_(strcmp)(p->name, "...") == 0) {
 
932
      p->name = NULL;
 
933
      p->ty = DotDotDot;
 
934
      return True;
 
935
   }
 
936
   VG_(printf)("location should be \"...\", or should start "
 
937
               "with \"fun:\" or \"obj:\"\n");
928
938
   return False;
929
939
}
930
940
 
931
941
 
932
942
/* Look for "tool" in a string like "tool1,tool2,tool3" */
933
 
static __inline__
934
 
Bool tool_name_present(Char *name, Char *names)
 
943
static Bool tool_name_present(Char *name, Char *names)
935
944
{
936
945
   Bool  found;
937
946
   Char *s = NULL;   /* Shut gcc up */
953
962
{
954
963
#  define N_BUF 200
955
964
   SysRes sres;
956
 
   Int    fd, i;
 
965
   Int    fd, i, j, lineno = 0;
957
966
   Bool   eof;
958
967
   Char   buf[N_BUF+1];
959
968
   Char*  tool_names;
966
975
   if (sres.isError) {
967
976
      if (VG_(clo_xml))
968
977
         VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
969
 
      VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file '%s'", 
 
978
      VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file \"%s\"", 
970
979
                   filename );
971
980
      VG_(exit)(1);
972
981
   }
977
986
   while (True) {
978
987
      /* Assign and initialise the two suppression halves (core and tool) */
979
988
      Supp* supp;
980
 
      supp        = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
 
989
      supp        = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
 
990
                                      sizeof(Supp));
981
991
      supp->count = 0;
982
992
 
983
993
      // Initialise temporary reading-in buffer.
989
999
      supp->string = supp->extra = NULL;
990
1000
 
991
1001
      eof = VG_(get_line) ( fd, buf, N_BUF );
 
1002
      lineno++;
992
1003
      if (eof) break;
993
1004
 
994
1005
      if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
995
1006
      
996
1007
      eof = VG_(get_line) ( fd, buf, N_BUF );
 
1008
      lineno++;
997
1009
 
998
1010
      if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
999
1011
 
1000
 
      supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
 
1012
      supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
1001
1013
 
1002
1014
      eof = VG_(get_line) ( fd, buf, N_BUF );
 
1015
      lineno++;
1003
1016
 
1004
1017
      if (eof) BOMB("unexpected end-of-file");
1005
1018
 
1038
1051
         // Ignore rest of suppression
1039
1052
         while (True) {
1040
1053
            eof = VG_(get_line) ( fd, buf, N_BUF );
 
1054
            lineno++;
1041
1055
            if (eof) BOMB("unexpected end-of-file");
1042
1056
            if (VG_STREQ(buf, "}"))
1043
1057
               break;
1046
1060
      }
1047
1061
 
1048
1062
      if (VG_(needs).tool_errors && 
1049
 
          !VG_TDICT_CALL(tool_read_extra_suppression_info, fd, buf, N_BUF, supp))
 
1063
          !VG_TDICT_CALL(tool_read_extra_suppression_info,
 
1064
                         fd, buf, N_BUF, supp))
1050
1065
      {
1051
1066
         BOMB("bad or missing extra suppression info");
1052
1067
      }
1053
1068
 
 
1069
      /* the main frame-descriptor reading loop */
1054
1070
      i = 0;
1055
1071
      while (True) {
1056
1072
         eof = VG_(get_line) ( fd, buf, N_BUF );
 
1073
         lineno++;
1057
1074
         if (eof)
1058
1075
            BOMB("unexpected end-of-file");
1059
1076
         if (VG_STREQ(buf, "}")) {
1067
1084
            BOMB("too many callers in stack trace");
1068
1085
         if (i > 0 && i >= VG_(clo_backtrace_size)) 
1069
1086
            break;
1070
 
         tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf);
 
1087
         tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE,
 
1088
                                                 "errormgr.losf.3", buf);
1071
1089
         if (!setLocationTy(&(tmp_callers[i])))
1072
 
            BOMB("location should start with 'fun:' or 'obj:'");
 
1090
            BOMB("location should be \"...\", or should start "
 
1091
                 "with \"fun:\" or \"obj:\"");
1073
1092
         i++;
1074
1093
      }
1075
1094
 
1078
1097
      if (!VG_STREQ(buf, "}")) {
1079
1098
         do {
1080
1099
            eof = VG_(get_line) ( fd, buf, N_BUF );
 
1100
            lineno++;
1081
1101
         } while (!eof && !VG_STREQ(buf, "}"));
1082
1102
      }
1083
1103
 
 
1104
      // Reject entries which are entirely composed of frame
 
1105
      // level wildcards.
 
1106
      vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
 
1107
      for (j = 0; j < i; j++) {
 
1108
         if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
 
1109
            break;
 
1110
         vg_assert(tmp_callers[j].ty == DotDotDot);
 
1111
      }
 
1112
      vg_assert(j >= 0 && j <= i);
 
1113
      if (j == i) {
 
1114
         // we didn't find any non-"..." entries
 
1115
         BOMB("suppression must contain at least one location "
 
1116
              "line which is not \"...\"");
 
1117
      } 
 
1118
 
1084
1119
      // Copy tmp_callers[] into supp->callers[]
1085
1120
      supp->n_callers = i;
1086
 
      supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc));
 
1121
      supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
 
1122
                                        i*sizeof(SuppLoc));
1087
1123
      for (i = 0; i < supp->n_callers; i++) {
1088
1124
         supp->callers[i] = tmp_callers[i];
1089
1125
      }
1098
1134
   if (VG_(clo_xml))
1099
1135
      VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
1100
1136
   VG_(message)(Vg_UserMsg, 
1101
 
                "FATAL: in suppressions file '%s': %s", filename, err_str );
 
1137
                "FATAL: in suppressions file \"%s\" near line %d:",
 
1138
                filename, lineno );
 
1139
   VG_(message)(Vg_UserMsg, 
 
1140
                "   %s", err_str );
1102
1141
   
1103
1142
   VG_(close)(fd);
1104
1143
   VG_(message)(Vg_UserMsg, "exiting now.");
1122
1161
   }
1123
1162
}
1124
1163
 
 
1164
 
 
1165
/*------------------------------------------------------------*/
 
1166
/*--- Matching errors to suppressions                      ---*/
 
1167
/*------------------------------------------------------------*/
 
1168
 
 
1169
/* Parameterising functions for the use of VG_(generic_match) in
 
1170
   suppression-vs-error matching.  The suppression frames (SuppLoc)
 
1171
   play the role of 'pattern'-element, and the error frames (IPs,
 
1172
   hence simply Addrs) play the role of 'input'.  In short then, we're
 
1173
   matching a sequence of Addrs against a pattern composed of a
 
1174
   sequence of SuppLocs.
 
1175
*/
 
1176
static Bool supploc_IsStar ( void* supplocV )
 
1177
{
 
1178
   SuppLoc* supploc = (SuppLoc*)supplocV;
 
1179
   return supploc->ty == DotDotDot;
 
1180
}
 
1181
 
 
1182
static Bool supploc_IsQuery ( void* supplocV )
 
1183
{
 
1184
   return False; /* there's no '?' equivalent in the supp syntax */
 
1185
}
 
1186
 
 
1187
static Bool supp_pattEQinp ( void* supplocV, void* addrV )
 
1188
{
 
1189
   SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
 
1190
   Addr     ip      = *(Addr*)addrV; /* INPUT */
 
1191
 
 
1192
   Char caller_name[ERRTXT_LEN];
 
1193
   caller_name[0] = 0;
 
1194
 
 
1195
   /* So, does this IP address match this suppression-line? */
 
1196
   switch (supploc->ty) {
 
1197
      case DotDotDot:
 
1198
         /* supp_pattEQinp is a callback from VG_(generic_match).  As
 
1199
            per the spec thereof (see include/pub_tool_seqmatch.h), we
 
1200
            should never get called with a pattern value for which the
 
1201
            _IsStar or _IsQuery function would return True.  Hence
 
1202
            this can't happen. */
 
1203
         vg_assert(0);
 
1204
      case ObjName:
 
1205
         /* Get the object name into 'caller_name', or "???"
 
1206
            if unknown. */
 
1207
         if (!VG_(get_objname)(ip, caller_name, ERRTXT_LEN))
 
1208
            VG_(strcpy)(caller_name, "???");
 
1209
         break; 
 
1210
      case FunName: 
 
1211
         /* Get the function name into 'caller_name', or "???"
 
1212
            if unknown. */
 
1213
         // Nb: mangled names used in suppressions.  Do, though,
 
1214
         // Z-demangle them, since otherwise it's possible to wind
 
1215
         // up comparing "malloc" in the suppression against
 
1216
         // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
 
1217
         // two of them need to be made to match.
 
1218
         if (!VG_(get_fnname_Z_demangle_only)(ip, caller_name, ERRTXT_LEN))
 
1219
            VG_(strcpy)(caller_name, "???");
 
1220
         break;
 
1221
      default:
 
1222
        vg_assert(0);
 
1223
   }
 
1224
 
 
1225
   /* So now we have the function or object name in caller_name, and
 
1226
      the pattern (at the character level) to match against is in
 
1227
      supploc->name.  Hence (and leading to a re-entrant call of
 
1228
      VG_(generic_match)): */
 
1229
   return VG_(string_match)(supploc->name, caller_name);
 
1230
}
 
1231
 
 
1232
/////////////////////////////////////////////////////
 
1233
 
 
1234
static Bool supp_matches_callers(Error* err, Supp* su)
 
1235
{
 
1236
   /* Unwrap the args and set up the correct parameterisation of
 
1237
      VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
 
1238
      supp_pattEQinp. */
 
1239
   /* note, StackTrace === Addr* */
 
1240
   StackTrace ips      = VG_(get_ExeContext_StackTrace)(err->where);
 
1241
   UWord      n_ips    = VG_(get_ExeContext_n_ips)(err->where);
 
1242
   SuppLoc*   supps    = su->callers;
 
1243
   UWord      n_supps  = su->n_callers;
 
1244
   UWord      szbPatt  = sizeof(SuppLoc);
 
1245
   UWord      szbInput = sizeof(Addr);
 
1246
   Bool       matchAll = False; /* we just want to match a prefix */
 
1247
   return
 
1248
      VG_(generic_match)(
 
1249
         matchAll,
 
1250
         /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
 
1251
         /*INPUT*/ips, szbInput, n_ips,  0/*initial Ix*/,
 
1252
         supploc_IsStar, supploc_IsQuery, supp_pattEQinp
 
1253
      );
 
1254
}
 
1255
 
 
1256
/////////////////////////////////////////////////////
 
1257
 
1125
1258
static
1126
1259
Bool supp_matches_error(Supp* su, Error* err)
1127
1260
{
1142
1275
   }
1143
1276
}
1144
1277
 
1145
 
static
1146
 
Bool supp_matches_callers(Error* err, Supp* su)
1147
 
{
1148
 
   Int i;
1149
 
   Char caller_name[ERRTXT_LEN];
1150
 
   StackTrace ips = VG_(extract_StackTrace)(err->where);
1151
 
 
1152
 
   for (i = 0; i < su->n_callers; i++) {
1153
 
      Addr a = ips[i];
1154
 
      vg_assert(su->callers[i].name != NULL);
1155
 
      // The string to be used in the unknown case ("???") can be anything
1156
 
      // that couldn't be a valid function or objname.  --gen-suppressions
1157
 
      // prints 'obj:*' for such an entry, which will match any string we
1158
 
      // use.
1159
 
      switch (su->callers[i].ty) {
1160
 
         case ObjName: 
1161
 
            if (!VG_(get_objname)(a, caller_name, ERRTXT_LEN))
1162
 
               VG_(strcpy)(caller_name, "???");
1163
 
            break; 
1164
 
 
1165
 
         case FunName: 
1166
 
            // Nb: mangled names used in suppressions.  Do, though,
1167
 
            // Z-demangle them, since otherwise it's possible to wind
1168
 
            // up comparing "malloc" in the suppression against
1169
 
            // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1170
 
            // two of them need to be made to match.
1171
 
            if (!VG_(get_fnname_Z_demangle_only)(a, caller_name, ERRTXT_LEN))
1172
 
               VG_(strcpy)(caller_name, "???");
1173
 
            break;
1174
 
         default: VG_(tool_panic)("supp_matches_callers");
1175
 
      }
1176
 
      if (0) VG_(printf)("cmp %s %s\n", su->callers[i].name, caller_name);
1177
 
      if (!VG_(string_match)(su->callers[i].name, caller_name))
1178
 
         return False;
1179
 
   }
1180
 
 
1181
 
   /* If we reach here, it's a match */
1182
 
   return True;
1183
 
}
 
1278
/////////////////////////////////////////////////////
1184
1279
 
1185
1280
/* Does an error context match a suppression?  ie is this a suppressible
1186
1281
   error?  If so, return a pointer to the Supp record, otherwise NULL.
1219
1314
void VG_(print_errormgr_stats) ( void )
1220
1315
{
1221
1316
   VG_(message)(Vg_DebugMsg, 
1222
 
      " errormgr: %,lu supplist searches, %,lu comparisons during search",
 
1317
      " errormgr: %'lu supplist searches, %'lu comparisons during search",
1223
1318
      em_supplist_searches, em_supplist_cmps
1224
1319
   );
1225
1320
   VG_(message)(Vg_DebugMsg, 
1226
 
      " errormgr: %,lu errlist searches, %,lu comparisons during search",
 
1321
      " errormgr: %'lu errlist searches, %'lu comparisons during search",
1227
1322
      em_errlist_searches, em_errlist_cmps
1228
1323
   );
1229
1324
}