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 }