13a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#!/usr/bin/env python
23a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#
33a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# Copyright 2011 the V8 project authors. All rights reserved.
43a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# Redistribution and use in source and binary forms, with or without
53a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# modification, are permitted provided that the following conditions are
63a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# met:
73a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#
83a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#     * Redistributions of source code must retain the above copyright
93a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       notice, this list of conditions and the following disclaimer.
103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#     * Redistributions in binary form must reproduce the above
113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       copyright notice, this list of conditions and the following
123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       disclaimer in the documentation and/or other materials provided
133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       with the distribution.
143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#     * Neither the name of Google Inc. nor the names of its
153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       contributors may be used to endorse or promote products derived
163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#       from this software without specific prior written permission.
173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org#
183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgimport os
313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgimport re
323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgimport subprocess
333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgimport tempfile
343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# Avoid using the slow (google-specific) wrapper around objdump.
373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgOBJDUMP_BIN = "/usr/bin/objdump"
383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgif not os.path.exists(OBJDUMP_BIN):
393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  OBJDUMP_BIN = "objdump"
403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org_COMMON_DISASM_OPTIONS = ["-M", "intel-mnemonic", "-C"]
433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org_DISASM_HEADER_RE = re.compile(r"[a-f0-9]+\s+<.*:$")
453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org_DISASM_LINE_RE = re.compile(r"\s*([a-f0-9]+):\s*(\S.*)")
463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org# Keys must match constants in Logger::LogCodeInfo.
483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org_ARCH_MAP = {
493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  "ia32": "-m i386",
503a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  "x64": "-m i386 -M x86-64",
5156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  "arm": "-m arm",  # Not supported by our objdump build.
5208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  "mips": "-m mips",  # Not supported by our objdump build.
5308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  "arm64": "-m aarch64"
543a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
563a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
5759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgdef GetDisasmLines(filename, offset, size, arch, inplace, arch_flags=""):
583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  tmp_name = None
593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if not inplace:
603a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    # Create a temporary file containing a copy of the code.
613a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    assert arch in _ARCH_MAP, "Unsupported architecture '%s'" % arch
6259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    arch_flags = arch_flags + " " +  _ARCH_MAP[arch]
633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    tmp_name = tempfile.mktemp(".v8code")
643a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    command = "dd if=%s of=%s bs=1 count=%d skip=%d && " \
653a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org              "%s %s -D -b binary %s %s" % (
663a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      filename, tmp_name, size, offset,
673a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags,
683a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      tmp_name)
693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  else:
7059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    command = "%s %s %s --start-address=%d --stop-address=%d -d %s " % (
7159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      OBJDUMP_BIN, ' '.join(_COMMON_DISASM_OPTIONS), arch_flags,
723a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      offset,
733a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      offset + size,
743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      filename)
753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  process = subprocess.Popen(command,
763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                             shell=True,
773a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                             stdout=subprocess.PIPE,
783a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                             stderr=subprocess.STDOUT)
793a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  out, err = process.communicate()
803a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  lines = out.split("\n")
813a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  header_line = 0
823a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  for i, line in enumerate(lines):
833a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if _DISASM_HEADER_RE.match(line):
843a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      header_line = i
853a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      break
863a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if tmp_name:
873a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    os.unlink(tmp_name)
883a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  split_lines = []
893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  for line in lines[header_line + 1:]:
903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    match = _DISASM_LINE_RE.match(line)
913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    if match:
923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      line_address = int(match.group(1), 16)
933a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      split_lines.append((line_address, match.group(2)))
943a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  return split_lines
95