001    package daikon;
002    
003    import plume.Option;
004    import plume.Options;
005    import plume.SimpleLog;
006    
007    import java.util.*;
008    import java.io.*;
009    
010    public class StackOffsets {
011    
012      public static class OffsetInfo {
013        int offset;
014        int cnt;
015        public OffsetInfo (int offset) {
016          this.offset = offset;
017          cnt = 1;
018        }
019      }
020    
021      public static class StackInfo {
022    
023        PptTopLevel ppt;
024        Stack<Integer> entry_esp = new Stack<Integer>();
025        int entry_cnt = 0;
026        Map<VarInfo,OffsetInfo> offset_map
027          = new LinkedHashMap<VarInfo,OffsetInfo>();
028    
029        public StackInfo (PptTopLevel ppt) {
030          this.ppt = ppt;
031        }
032    
033        public void sample (PptTopLevel func_ppt, PptTopLevel ppt, ValueTuple vt) {
034    
035          String enter_esp_name = String.format ("bv:0x%x:esp", ppt.bb_offset());
036    
037          // Loop through each variable
038          for (VarInfo vi : ppt.var_infos) {
039    
040            // Skip non stack pointer variables
041            if (!vi.name().endsWith (":esp"))
042              continue;
043    
044            // If this is the function entry esp
045            if ((ppt == func_ppt) && (enter_esp_name.equals (vi.name()))) {
046              entry_cnt++;
047              // if (entry_esp.size() > 0)
048                // System.out.printf ("Entry stack for %s is size %d\n",
049                //                    func_ppt.name(), entry_esp.size());
050              @SuppressWarnings("nullness") // application invariant
051              /*@NonNull*/ Integer entry = int_val (vi, vt);
052              assert entry != null : "function entry esp should not be nonsense";
053              entry_esp.push (entry);
054              // System.out.printf ("Enter function %s\n", ppt.name);
055            } else {
056              if (entry_esp.size() == 0) {
057                System.out.printf ("No function entry for ppt %s (func %s) "
058                                   + "(line %d)\n", ppt.name(), ppt.function_id,
059                                   FileIO.get_linenum());
060                return;
061              }
062              OffsetInfo past_offset = offset_map.get(vi);
063              Integer cur_offset = int_val(vi, vt);
064              if (cur_offset == null) {
065                System.out.printf ("unexpected nonsense val for ppt %s (func %s) "
066                                   + "(line %d)\n", ppt.name(), ppt.function_id,
067                                   FileIO.get_linenum());
068              } else if (past_offset == null) {
069                cur_offset -= entry_esp.peek();
070                offset_map.put (vi, new OffsetInfo (cur_offset));
071              } else {
072                cur_offset -= entry_esp.peek();
073                if (cur_offset != past_offset.offset) {
074                  System.out.printf ("Mismatch at %s: %d - %d [%d]\n", vi.name(),
075                                 cur_offset, past_offset.offset, past_offset.cnt);
076                } else {
077                  past_offset.cnt++;
078                }
079              }
080    
081            }
082          }
083    
084          // pop off the entry if this is a return
085          if (ppt.flags.contains (PptTopLevel.PptFlags.RETURN)) {
086            // System.out.printf ("Return from %s (function %s)\n", ppt.name(),
087            //                   ppt.function_id);
088            entry_esp.pop();
089          }
090    
091        }
092    
093        public static /*@Nullable*/ Integer int_val (VarInfo vi, ValueTuple vt) {
094          Object o = vt.getValue(vi);
095          if (o == null)
096            return null;
097          return new Integer (((Long) o).intValue());
098        }
099    
100        public void dump() {
101    
102          System.out.printf ("Ppt %s [stack=%d/%d]\n", ppt.name(),
103                             entry_esp.size(), entry_cnt);
104          for (VarInfo vi : offset_map.keySet()) {
105            OffsetInfo oi = offset_map.get (vi);
106            System.out.printf ("  var %s: %d [%d]\n", vi.name(), oi.offset, oi.cnt);
107          }
108        }
109    
110      }
111      public static class Processor extends FileIO.Processor {
112    
113        Map<PptTopLevel,StackInfo> stack_info_map
114          = new LinkedHashMap<PptTopLevel,StackInfo>();
115    
116        public void process_sample (PptMap all_ppts, PptTopLevel ppt, ValueTuple vt,
117                                    /*@Nullable*/ Integer nonce) {
118    
119          // System.out.printf ("Processing sample for ppt %s [%d]\n", ppt.name(),
120          //                   nonce);
121    
122          // Find the StackInfo for this function
123          String function_id = ppt.function_id;
124          @SuppressWarnings("nullness") // Map.get: ppt.function_id is a key in all_ppts
125          /*@NonNull*/ PptTopLevel func_ppt = all_ppts.get(function_id);
126          StackInfo si = stack_info_map.get (func_ppt);
127          if (si == null) {
128            si = new StackInfo (func_ppt);
129            stack_info_map.put (func_ppt, si);
130          }
131          si.sample (func_ppt, ppt, vt);
132        }
133    
134      }
135    
136      public static PptMap all_ppts = new PptMap();
137    
138      public static Processor processor = new Processor();
139    
140      public static void main (String args[]) throws IOException {
141    
142        String dtrace_file = args[0];
143    
144        FileIO.read_data_trace_file (dtrace_file, all_ppts, processor, false, true);
145    
146        // build function information
147        Map<PptTopLevel,List<PptTopLevel>> func_map
148          = new LinkedHashMap<PptTopLevel,List<PptTopLevel>>();
149        for (Iterator<PptTopLevel> ii = all_ppts.pptIterator(); ii.hasNext(); ) {
150          PptTopLevel ppt = ii.next();
151          @SuppressWarnings("nullness") // Map.get: ppt.function_id is a key in all_ppts
152          /*@NonNull*/ PptTopLevel func = all_ppts.get(ppt.function_id);
153          List<PptTopLevel> bbs = func_map.get (func);
154          if (bbs == null) {
155            bbs = new ArrayList<PptTopLevel>();
156            func_map.put (func, bbs);
157          }
158          bbs.add (ppt);
159        }
160    
161        // Dump function info
162        for (PptTopLevel ppt : func_map.keySet()) {
163          System.out.printf ("function %s\n", ppt.name());
164          List<PptTopLevel> bbs = func_map.get (ppt);
165          PptTopLevel prev = null;
166          for (PptTopLevel bb : bbs) {
167            System.out.printf ("  %04X+%02d: ", bb.bb_offset() & 0xFFFF,
168                               bb.bb_length);
169            assert (prev == null) ||
170              ((prev.bb_offset() + prev.bb_length) == bb.bb_offset())
171              : prev.name() + "  not adjacent to " + bb.name();
172            if (bb.ppt_successors != null) {
173              for (String succ : bb.ppt_successors) {
174                @SuppressWarnings("nullness") // Map.get: successor is a Ppt
175                /*@NonNull*/ PptTopLevel ppt_succ = all_ppts.get (succ);
176                System.out.printf ("%04X ", ppt_succ.bb_offset() & 0xFFFF);
177                assert ppt_succ.function_id != null && ppt_succ.function_id.equals (ppt.function_id);
178              }
179            }
180            if (bb.flags.contains(PptTopLevel.PptFlags.RETURN))
181              System.out.printf ("[ret]");
182            System.out.printf ("\n");
183          }
184        }
185    
186        // Dump stack info for each function
187        for (PptTopLevel ppt : processor.stack_info_map.keySet()) {
188          StackInfo si = processor.stack_info_map.get (ppt);
189          si.dump();
190        }
191      }
192    
193    }