#!/usr/bin/env python
# Merge or print the coverage data collected by asan's coverage.
# Input files are sequences of 4-byte integers.
# We need to merge these integers into a set and then
# either print them (as hex) or dump them into another file.
import array
import bisect
import glob
import os.path
import struct
import subprocess
import sys

prog_name = ""

def Usage():
  sys.stderr.write(
    "Usage: \n" + \
    " " + prog_name + " merge FILE [FILE...] > OUTPUT\n" \
    " " + prog_name + " print FILE [FILE...]\n" \
    " " + prog_name + " unpack FILE [FILE...]\n" \
    " " + prog_name + " rawunpack FILE [FILE ...]\n" \
    " " + prog_name + " missing BINARY < LIST_OF_PCS\n" \
    "\n")
  exit(1)

def CheckBits(bits):
  if bits != 32 and bits != 64:
    raise Exception("Wrong bitness: %d" % bits)

def TypeCodeForBits(bits):
  CheckBits(bits)
  return 'L' if bits == 64 else 'I'

def TypeCodeForStruct(bits):
  CheckBits(bits)
  return 'Q' if bits == 64 else 'I'

kMagic32SecondHalf = 0xFFFFFF32;
kMagic64SecondHalf = 0xFFFFFF64;
kMagicFirstHalf    = 0xC0BFFFFF;

def MagicForBits(bits):
  CheckBits(bits)
  if sys.byteorder == 'little':
    return [kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf, kMagicFirstHalf]
  else:
    return [kMagicFirstHalf, kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf]

def ReadMagicAndReturnBitness(f, path):
  magic_bytes = f.read(8)
  magic_words = struct.unpack('II', magic_bytes);
  bits = 0
  idx = 1 if sys.byteorder == 'little' else 0
  if magic_words[idx] == kMagicFirstHalf:
    if magic_words[1-idx] == kMagic64SecondHalf:
      bits = 64
    elif magic_words[1-idx] == kMagic32SecondHalf:
      bits = 32
  if bits == 0:
    raise Exception('Bad magic word in %s' % path)
  return bits

def ReadOneFile(path):
  with open(path, mode="rb") as f:
    f.seek(0, 2)
    size = f.tell()
    f.seek(0, 0)
    if size < 8:
      raise Exception('File %s is short (< 8 bytes)' % path)
    bits = ReadMagicAndReturnBitness(f, path)
    size -= 8
    w = size * 8 // bits
    s = struct.unpack_from(TypeCodeForStruct(bits) * (w), f.read(size))
  sys.stderr.write(
    "%s: read %d %d-bit PCs from %s\n" % (prog_name, w, bits, path))
  return s

def Merge(files):
  s = set()
  for f in files:
    s = s.union(set(ReadOneFile(f)))
  sys.stderr.write(
    "%s: %d files merged; %d PCs total\n" % (prog_name, len(files), len(s))
  )
  return sorted(s)

def PrintFiles(files):
  if len(files) > 1:
    s = Merge(files)
  else:  # If there is just on file, print the PCs in order.
    s = ReadOneFile(files[0])
    sys.stderr.write("%s: 1 file merged; %d PCs total\n" % (prog_name, len(s)))
  for i in s:
    print("0x%x" % i)

def MergeAndPrint(files):
  if sys.stdout.isatty():
    Usage()
  s = Merge(files)
  bits = 32
  if max(s) > 0xFFFFFFFF:
    bits = 64
  stdout_buf = getattr(sys.stdout, 'buffer', sys.stdout)
  array.array('I', MagicForBits(bits)).tofile(stdout_buf)
  a = struct.pack(TypeCodeForStruct(bits) * len(s), *s)
  stdout_buf.write(a)


def UnpackOneFile(path):
  with open(path, mode="rb") as f:
    sys.stderr.write("%s: unpacking %s\n" % (prog_name, path))
    while True:
      header = f.read(12)
      if not header: return
      if len(header) < 12:
        break
      pid, module_length, blob_size = struct.unpack('iII', header)
      module = f.read(module_length).decode('utf-8')
      blob = f.read(blob_size)
      assert(len(module) == module_length)
      assert(len(blob) == blob_size)
      extracted_file = "%s.%d.sancov" % (module, pid)
      sys.stderr.write("%s: extracting %s\n" % (prog_name, extracted_file))
      # The packed file may contain multiple blobs for the same pid/module
      # pair. Append to the end of the file instead of overwriting.
      with open(extracted_file, 'ab') as f2:
        f2.write(blob)
    # fail
    raise Exception('Error reading file %s' % path)


def Unpack(files):
  for f in files:
    UnpackOneFile(f)

def UnpackOneRawFile(path, map_path):
  mem_map = []
  with open(map_path, mode="rt") as f_map:
    sys.stderr.write("%s: reading map %s\n" % (prog_name, map_path))
    bits = int(f_map.readline())
    if bits != 32 and bits != 64:
      raise Exception('Wrong bits size in the map')
    for line in f_map:
      parts = line.rstrip().split()
      mem_map.append((int(parts[0], 16),
                  int(parts[1], 16),
                  int(parts[2], 16),
                  ' '.join(parts[3:])))
  mem_map.sort(key=lambda m : m[0])
  mem_map_keys = [m[0] for m in mem_map]

  with open(path, mode="rb") as f:
    sys.stderr.write("%s: unpacking %s\n" % (prog_name, path))

    f.seek(0, 2)
    size = f.tell()
    f.seek(0, 0)
    pcs = struct.unpack_from(TypeCodeForStruct(bits) * (size * 8 // bits), f.read(size))
    mem_map_pcs = [[] for i in range(0, len(mem_map))]

    for pc in pcs:
      if pc == 0: continue
      map_idx = bisect.bisect(mem_map_keys, pc) - 1
      (start, end, base, module_path) = mem_map[map_idx]
      assert pc >= start
      if pc >= end:
        sys.stderr.write("warning: %s: pc %x outside of any known mapping\n" % (prog_name, pc))
        continue
      mem_map_pcs[map_idx].append(pc - base)

    for ((start, end, base, module_path), pc_list) in zip(mem_map, mem_map_pcs):
      if len(pc_list) == 0: continue
      assert path.endswith('.sancov.raw')
      dst_path = module_path + '.' + os.path.basename(path)[:-4]
      sys.stderr.write("%s: writing %d PCs to %s\n" % (prog_name, len(pc_list), dst_path))
      sorted_pc_list = sorted(pc_list)
      pc_buffer = struct.pack(TypeCodeForStruct(bits) * len(pc_list), *sorted_pc_list)
      with open(dst_path, 'ab+') as f2:
        array.array('I', MagicForBits(bits)).tofile(f2)
        f2.seek(0, 2)
        f2.write(pc_buffer)

def RawUnpack(files):
  for f in files:
    if not f.endswith('.sancov.raw'):
      raise Exception('Unexpected raw file name %s' % f)
    f_map = f[:-3] + 'map'
    UnpackOneRawFile(f, f_map)

def GetInstrumentedPCs(binary):
  # This looks scary, but all it does is extract all offsets where we call:
  # - __sanitizer_cov() or __sanitizer_cov_with_check(),
  # - with call or callq,
  # - directly or via PLT.
  cmd = "objdump -d %s | " \
        "grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\|_trace_pc_guard\)\(@plt\|\)>' | " \
        "grep '^\s\+[0-9a-f]\+' -o" % binary
  proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                          shell=True)
  proc.stdin.close()
  # The PCs we get from objdump are off by 4 bytes, as they point to the
  # beginning of the callq instruction. Empirically this is true on x86 and
  # x86_64.
  return set(int(line.strip(), 16) + 4 for line in proc.stdout)

def PrintMissing(binary):
  if not os.path.isfile(binary):
    raise Exception('File not found: %s' % binary)
  instrumented = GetInstrumentedPCs(binary)
  sys.stderr.write("%s: found %d instrumented PCs in %s\n" % (prog_name,
                                                              len(instrumented),
                                                              binary))
  covered = set(int(line, 16) for line in sys.stdin)
  sys.stderr.write("%s: read %d PCs from stdin\n" % (prog_name, len(covered)))
  missing = instrumented - covered
  sys.stderr.write("%s: %d PCs missing from coverage\n" % (prog_name, len(missing)))
  if (len(missing) > len(instrumented) - len(covered)):
    sys.stderr.write(
      "%s: WARNING: stdin contains PCs not found in binary\n" % prog_name
    )
  for pc in sorted(missing):
    print("0x%x" % pc)

if __name__ == '__main__':
  prog_name = sys.argv[0]
  if len(sys.argv) <= 2:
    Usage();

  if sys.argv[1] == "missing":
    if len(sys.argv) != 3:
      Usage()
    PrintMissing(sys.argv[2])
    exit(0)

  file_list = []
  for f in sys.argv[2:]:
    file_list += glob.glob(f)
  if not file_list:
    Usage()

  if sys.argv[1] == "print":
    PrintFiles(file_list)
  elif sys.argv[1] == "merge":
    MergeAndPrint(file_list)
  elif sys.argv[1] == "unpack":
    Unpack(file_list)
  elif sys.argv[1] == "rawunpack":
    RawUnpack(file_list)
  else:
    Usage()
