# Copyright (c) 2017 Trail of Bits, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import hashlib
import os
import shutil
import stat
import subprocess
import tempfile

def binary_info(binary):
  res = subprocess.check_output(['file', binary])
  is_pie = 'LSB shared object' in res
  address_size = 64

  if 'aarch64' in res:
    arch = 'aarch64'
  elif 'x86-64' in res:
    arch = 'amd64_avx'
  elif 'x86' in res:
    arch = 'x86_avx'
    address_size = 32
  else:
    raise Exception("Unknown architecture for file type {}".format(res))

  return address_size, arch, is_pie

def binary_libraries(binary):
  try:
    res = subprocess.check_output(['ldd', binary])
  except:
    return
  for line in res.split("\n"):
    if "=>" not in line:
      continue
    name, path_and_addr = line.split(" => ")
    path_and_addr = path_and_addr.strip(" ")
    if not path_and_addr.startswith("/"):
      continue
    
    lib = " ".join(path_and_addr.split(" ")[:-1])
    lib = os.path.realpath(lib)

    if os.path.isfile(lib):
      yield name.strip(), lib

def make_executable(path):
  st = os.stat(path)
  os.chmod(path, st.st_mode | stat.S_IEXEC)

def hash_file(path):
  hash = hashlib.md5()
  with open(path, "rb") as f:
    for block in iter(lambda: f.read(65536), b""):
      hash.update(block)
  return hash.hexdigest()

def make_directory(path):
  try:
    os.makedirs(path)
  except:
    pass

def main():
  arg_parser = argparse.ArgumentParser()

  arg_parser.add_argument(
      '--libraries_dir',
      help='Path to directory in which the cxx-common libraries are unpacked',
      required=True)

  arg_parser.add_argument(
      '--llvm_version',
      help='Version number MAJOR.MINOR of the LLVM toolchain',
      required=True)

  arg_parser.add_argument(
      '--ida_dir',
      help='Directory containing IDA binaries.',
      required=True)

  arg_parser.add_argument(
      '--workspace_dir',
      help='Directory in which intermediate and final files are placed',
      required=True)

  arg_parser.add_argument(
      '--binary',
      help='Path to the binary to be lifted',
      required=True)

  arg_parser.add_argument(
      '--dry_run',
      help='Should the actual commands be executed?',