The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / disassembler.cc @ 40c0f755

History | View | Annotate | Download (10.8 KB)

1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include "v8.h"
29

    
30
#include "code-stubs.h"
31
#include "codegen-inl.h"
32
#include "debug.h"
33
#include "disasm.h"
34
#include "disassembler.h"
35
#include "macro-assembler.h"
36
#include "serialize.h"
37
#include "string-stream.h"
38

    
39
namespace v8 { namespace internal {
40

    
41
#ifdef ENABLE_DISASSEMBLER
42

    
43
void Disassembler::Dump(FILE* f, byte* begin, byte* end) {
44
  for (byte* pc = begin; pc < end; pc++) {
45
    if (f == NULL) {
46
      PrintF("%p  %4d  %02x\n", pc, pc - begin, *pc);
47
    } else {
48
      fprintf(f, "%p  %4d  %02x\n", pc, pc - begin, *pc);
49
    }
50
  }
51
}
52

    
53

    
54
class V8NameConverter: public disasm::NameConverter {
55
 public:
56
  explicit V8NameConverter(Code* code) : code_(code) {}
57
  virtual const char* NameOfAddress(byte* pc) const;
58
  virtual const char* NameInCode(byte* addr) const;
59
  Code* code() const { return code_; }
60
 private:
61
  Code* code_;
62
};
63

    
64

    
65
const char* V8NameConverter::NameOfAddress(byte* pc) const {
66
  static v8::internal::EmbeddedVector<char, 128> buffer;
67

    
68
  const char* name = Builtins::Lookup(pc);
69
  if (name != NULL) {
70
    OS::SNPrintF(buffer, "%s  (%p)", name, pc);
71
    return buffer.start();
72
  }
73

    
74
  if (code_ != NULL) {
75
    int offs = pc - code_->instruction_start();
76
    // print as code offset, if it seems reasonable
77
    if (0 <= offs && offs < code_->instruction_size()) {
78
      OS::SNPrintF(buffer, "%d  (%p)", offs, pc);
79
      return buffer.start();
80
    }
81
  }
82

    
83
  return disasm::NameConverter::NameOfAddress(pc);
84
}
85

    
86

    
87
const char* V8NameConverter::NameInCode(byte* addr) const {
88
  // The V8NameConverter is used for well known code, so we can "safely"
89
  // dereference pointers in generated code.
90
  return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : "";
91
}
92

    
93

    
94
static void DumpBuffer(FILE* f, char* buff) {
95
  if (f == NULL) {
96
    PrintF("%s", buff);
97
  } else {
98
    fprintf(f, "%s", buff);
99
  }
100
}
101

    
102
static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
103
static const int kRelocInfoPosition = 57;
104

    
105
static int DecodeIt(FILE* f,
106
                    const V8NameConverter& converter,
107
                    byte* begin,
108
                    byte* end) {
109
  NoHandleAllocation ha;
110
  AssertNoAllocation no_alloc;
111
  ExternalReferenceEncoder ref_encoder;
112

    
113
  v8::internal::EmbeddedVector<char, 128> decode_buffer;
114
  v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
115
  byte* pc = begin;
116
  disasm::Disassembler d(converter);
117
  RelocIterator* it = NULL;
118
  if (converter.code() != NULL) {
119
    it = new RelocIterator(converter.code());
120
  } else {
121
    // No relocation information when printing code stubs.
122
  }
123
  int constants = -1;  // no constants being decoded at the start
124

    
125
  while (pc < end) {
126
    // First decode instruction so that we know its length.
127
    byte* prev_pc = pc;
128
    if (constants > 0) {
129
      OS::SNPrintF(decode_buffer,
130
                   "%08x       constant",
131
                   *reinterpret_cast<int32_t*>(pc));
132
      constants--;
133
      pc += 4;
134
    } else {
135
      int num_const = d.ConstantPoolSizeAt(pc);
136
      if (num_const >= 0) {
137
        OS::SNPrintF(decode_buffer,
138
                     "%08x       constant pool begin",
139
                     *reinterpret_cast<int32_t*>(pc));
140
        constants = num_const;
141
        pc += 4;
142
      } else if (it != NULL && !it->done() && it->rinfo()->pc() == pc &&
143
          it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
144
        // raw pointer embedded in code stream, e.g., jump table
145
        byte* ptr = *reinterpret_cast<byte**>(pc);
146
        OS::SNPrintF(decode_buffer,
147
                     "%08x      jump table entry %4d",
148
                     reinterpret_cast<int32_t>(ptr),
149
                     ptr - begin);
150
        pc += 4;
151
      } else {
152
        decode_buffer[0] = '\0';
153
        pc += d.InstructionDecode(decode_buffer, pc);
154
      }
155
    }
156

    
157
    // Collect RelocInfo for this instruction (prev_pc .. pc-1)
158
    List<const char*> comments(4);
159
    List<byte*> pcs(1);
160
    List<RelocInfo::Mode> rmodes(1);
161
    List<intptr_t> datas(1);
162
    if (it != NULL) {
163
      while (!it->done() && it->rinfo()->pc() < pc) {
164
        if (RelocInfo::IsComment(it->rinfo()->rmode())) {
165
          // For comments just collect the text.
166
          comments.Add(reinterpret_cast<const char*>(it->rinfo()->data()));
167
        } else {
168
          // For other reloc info collect all data.
169
          pcs.Add(it->rinfo()->pc());
170
          rmodes.Add(it->rinfo()->rmode());
171
          datas.Add(it->rinfo()->data());
172
        }
173
        it->next();
174
      }
175
    }
176

    
177
    StringBuilder out(out_buffer.start(), out_buffer.length());
178

    
179
    // Comments.
180
    for (int i = 0; i < comments.length(); i++) {
181
      out.AddFormatted("                  %s\n", comments[i]);
182
    }
183

    
184
    // Write out comments, resets outp so that we can format the next line.
185
    DumpBuffer(f, out.Finalize());
186
    out.Reset();
187

    
188
    // Instruction address and instruction offset.
189
    out.AddFormatted("%p  %4d  ", prev_pc, prev_pc - begin);
190

    
191
    // Instruction.
192
    out.AddFormatted("%s", decode_buffer.start());
193

    
194
    // Print all the reloc info for this instruction which are not comments.
195
    for (int i = 0; i < pcs.length(); i++) {
196
      // Put together the reloc info
197
      RelocInfo relocinfo(pcs[i], rmodes[i], datas[i]);
198

    
199
      // Indent the printing of the reloc info.
200
      if (i == 0) {
201
        // The first reloc info is printed after the disassembled instruction.
202
        out.AddPadding(' ', kRelocInfoPosition - out.position());
203
      } else {
204
        // Additional reloc infos are printed on separate lines.
205
        out.AddFormatted("\n");
206
        out.AddPadding(' ', kRelocInfoPosition);
207
      }
208

    
209
      RelocInfo::Mode rmode = relocinfo.rmode();
210
      if (RelocInfo::IsPosition(rmode)) {
211
        if (RelocInfo::IsStatementPosition(rmode)) {
212
          out.AddFormatted("    ;; debug: statement %d", relocinfo.data());
213
        } else {
214
          out.AddFormatted("    ;; debug: position %d", relocinfo.data());
215
        }
216
      } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
217
        HeapStringAllocator allocator;
218
        StringStream accumulator(&allocator);
219
        relocinfo.target_object()->ShortPrint(&accumulator);
220
        SmartPointer<const char> obj_name = accumulator.ToCString();
221
        out.AddFormatted("    ;; object: %s", *obj_name);
222
      } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
223
        const char* reference_name =
224
            ref_encoder.NameOfAddress(*relocinfo.target_reference_address());
225
        out.AddFormatted("    ;; external reference (%s)", reference_name);
226
      } else if (RelocInfo::IsCodeTarget(rmode)) {
227
        out.AddFormatted("    ;; code:");
228
        if (rmode == RelocInfo::CONSTRUCT_CALL) {
229
          out.AddFormatted(" constructor,");
230
        }
231
        Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
232
        Code::Kind kind = code->kind();
233
        if (code->is_inline_cache_stub()) {
234
          if (rmode == RelocInfo::CODE_TARGET_CONTEXT) {
235
            out.AddFormatted(" contextual,");
236
          }
237
          InlineCacheState ic_state = code->ic_state();
238
          out.AddFormatted(" %s, %s", Code::Kind2String(kind),
239
              Code::ICState2String(ic_state));
240
          if (kind == Code::CALL_IC) {
241
            out.AddFormatted(", argc = %d", code->arguments_count());
242
          }
243
        } else if (kind == Code::STUB) {
244
          // Reverse lookup required as the minor key cannot be retrieved
245
          // from the code object.
246
          Object* obj = Heap::code_stubs()->SlowReverseLookup(code);
247
          if (obj != Heap::undefined_value()) {
248
            ASSERT(obj->IsSmi());
249
            // Get the STUB key and extract major and minor key.
250
            uint32_t key = Smi::cast(obj)->value();
251
            uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
252
            ASSERT(code->major_key() == CodeStub::MajorKeyFromKey(key));
253
            out.AddFormatted(" %s, %s, ",
254
                             Code::Kind2String(kind),
255
                             CodeStub::MajorName(code->major_key()));
256
            switch (code->major_key()) {
257
              case CodeStub::CallFunction:
258
                out.AddFormatted("argc = %d", minor_key);
259
                break;
260
              case CodeStub::Runtime: {
261
                const char* name =
262
                    RuntimeStub::GetNameFromMinorKey(minor_key);
263
                out.AddFormatted("%s", name);
264
                break;
265
              }
266
              default:
267
                out.AddFormatted("minor: %d", minor_key);
268
            }
269
          }
270
        } else {
271
          out.AddFormatted(" %s", Code::Kind2String(kind));
272
        }
273
      } else {
274
        out.AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
275
      }
276
    }
277
    out.AddString("\n");
278
    DumpBuffer(f, out.Finalize());
279
    out.Reset();
280
  }
281

    
282
  delete it;
283
  return pc - begin;
284
}
285

    
286

    
287
int Disassembler::Decode(FILE* f, byte* begin, byte* end) {
288
  V8NameConverter defaultConverter(NULL);
289
  return DecodeIt(f, defaultConverter, begin, end);
290
}
291

    
292

    
293
// Called by Code::CodePrint.
294
void Disassembler::Decode(FILE* f, Code* code) {
295
  byte* begin = Code::cast(code)->instruction_start();
296
  byte* end = begin + Code::cast(code)->instruction_size();
297
  V8NameConverter v8NameConverter(code);
298
  DecodeIt(f, v8NameConverter, begin, end);
299
}
300

    
301
#else  // ENABLE_DISASSEMBLER
302

    
303
void Disassembler::Dump(FILE* f, byte* begin, byte* end) {}
304
int Disassembler::Decode(FILE* f, byte* begin, byte* end) { return 0; }
305
void Disassembler::Decode(FILE* f, Code* code) {}
306

    
307
#endif  // ENABLE_DISASSEMBLER
308

    
309
} }  // namespace v8::internal