import os, subprocess, re, sys, struct
import binascii

debug_log = True
tool_chain_prefix = ''

def log(stuff):
  if not debug_log:
    return
  print(stuff)
   
print(sys.argv)

if len(sys.argv) < 5:
  print("Usage: %s [Output file] [Toolchain prefix] [C file] [ELF file] (gcc option file ~inc_def.tmp)"%(sys.argv[0]))
  exit(0)

elf_file = sys.argv[4]
cmd_list = []
if len(sys.argv) >= 6:
  cmd_list = ['@'+sys.argv[5]]
  
tool_chain_prefix = sys.argv[2]
step1o_fname = os.path.join(os.path.dirname(sys.argv[1]),'~mdmp_step1.o')
step2o_fname = os.path.join(os.path.dirname(sys.argv[1]),'~mdmp_step2.o')
if subprocess.call([tool_chain_prefix + 'gcc', '-G0', '-EL', '-c', '-o' + step1o_fname] + cmd_list + [sys.argv[3]]) != 0:
  exit(1)

if subprocess.call([tool_chain_prefix + 'ld', '-EL', '--entry=mdmp_profile_list', '--just-symbols=' + elf_file, '-o' + step2o_fname, step1o_fname]) != 0:
  exit(2)

def readSymbolTableV2(objFile, prefix = False):
	global tool_chain_prefix

	sec_tbl = []
	r = re.compile(br'\[\s?(\d+)\](.*)')
	proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-WS', objFile], stdout=subprocess.PIPE)
	for line in proc.stdout:
		m = r.search(line.rstrip())
		if m is None:
			continue
			
		s = m.group(2).split()
		sec_tbl.append({'addr':int(s[2], 16), 'offset':int(s[3], 16), 'size':int(s[4], 16)})

	symDict = {}
	r = re.compile(br'\d+: (\w*)\s+(\d+).+ (\w+) ([^\s]+)$')

	proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-Ws', objFile], stdout=subprocess.PIPE)
	for line in proc.stdout:
		m = r.search(line)
		if m is None: continue
		s = m.group(4)
		if prefix is not False and not s.startswith(prefix): continue
		
		v = int(m.group(1), 16)
		if m.group(3).isdigit():
			t = sec_tbl[int(m.group(3))]
			v = (v - t['addr']) + t['offset']
		symDict.update({s:{'val':v, 'size':int(m.group(2))}})

	return symDict

def readFromFileV2(objFile, offset, size, isNullTerminated = False):
	fd = open(objFile, 'rb')
	fd.seek(offset)
	d = fd.read(size)
	if (isNullTerminated):
		b = d.find(b'\x00')
		if b is not False: d=d[:b]
	return d
	
_sec_info = None
def getDataSectionInfo():
  global _sec_info
  if _sec_info == None:
    proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-S', step2o_fname], stdout=subprocess.PIPE)
    r = re.compile(br'\[\s?(\d+)\](.*)')
    for line in proc.stdout:
      m = r.search(line.rstrip())
      if m is None:
        continue
      s = m.group(2).split()
      if s[0] != b'.data':
        continue
      _sec_info = {'idx':m.group(1), 'addr':int(s[2], 16), 'offset':int(s[3], 16), 'size':int(s[4], 16)}
  return _sec_info

_sym_table = None
def getSymbolTable():
  global _sym_table
  if _sym_table is None:
    _sym_table = []
    proc = subprocess.Popen([tool_chain_prefix + 'readelf', '--syms', '--wide', step2o_fname], stdout=subprocess.PIPE)
    for line in proc.stdout:
      s = line.split()
      if len(s) != 8 or s[3] != b'OBJECT' or not s[6].isdigit():
        continue
      _sym_table.append({'symbol': s[7], 'addr':int(s[1], 16), 'size':int(s[2])})
    log('==== Symbol Table ====')
    log(_sym_table)
    log('======================')
  return _sym_table

def getAddrOffsetSizeByAddr(address):
  sec_info = getDataSectionInfo()  
  if address < sec_info['addr'] or address >= sec_info['addr'] + sec_info['size']:
    raise ValueError('Address not in range.')
  offset = address-sec_info['addr']+sec_info['offset']
  
  sym_table = getSymbolTable()
  for e in sym_table:
    if e['addr'] == address:
      return {'addr': address, 'offset': offset, 'size':e['size']}
  raise IndexError('Address not found in symbol list.')      
  return None  
  
def getAddrBySymbol(symbol):
  sym_table = getSymbolTable()
  for e in sym_table:
    if e['symbol'] == symbol:
      return e['addr']
  raise IndexError('Symbol not found.')
  return None
  

def getElementListByAddr(address, fd, fmt):
  r = []
  if address != 0:
    aos = getAddrOffsetSizeByAddr(address)
    # log(['getElementListByAddr',aos])
    fd.seek(aos['offset'])
    bytes_remain = aos['size']
    size = struct.calcsize(fmt)
    while bytes_remain > 0:
      r.append(struct.unpack(fmt, fd.read(size)))
      bytes_remain -= size
  return r


bin_obj = {}

def genBinObj(addr, build_function, *args):
  global bin_obj
  if addr == 0: 
    return
  if addr in bin_obj:
    log('Bin addr {:08X} already exists'.format(addr))
    return
  bin_obj[addr] = build_function(*args)
  log('Bin addr {:08X} created'.format(addr))

  
def buildSelectiveTable(selective_tbl):
  r = struct.pack('<I', len(selective_tbl))
  for s in selective_tbl:
    r = r + struct.pack('<IIBBxx', s[0], s[1], s[2], s[3])

  return r


def buildRegionTable(num_mem_type, num_option, region_tbl):
  # Handle region table
  option_size = (num_option+7)//8
  mem = [bytearray(option_size) for y in range(num_mem_type)] 
  for r in region_tbl:
    mem_type = r[0]
    for x in r[1:]:
      if x == 0:
        break
      x=x-1
      mem[mem_type][x//8] = mem[mem_type][x//8] ^ (1<<(x%8))
      
    # log(['Config:', r])
    # log(['Mem:', mem])
  
  log(['num_mem_type:',num_mem_type])
  log(['option_byte:', option_size])

  r = struct.pack('<HH', num_mem_type, option_size)
  for x in mem:
    r = r + x
    
  return r


# open object file  
fd=open(step2o_fname, 'rb')

# get information from object
num_mem_type = getElementListByAddr(getAddrBySymbol(b'_mdmp_num_mem_type'), fd, '=I')[0][0]
num_region_option = getElementListByAddr(getAddrBySymbol(b'_mdmp_num_region_option'), fd, '=I')[0][0]

profile = []
pid = 0
for p in getElementListByAddr(getAddrBySymbol(b'mdmp_profile_list'), fd, '=III'):
  log('Profile #{}: +0x{:X} -0x{:X}'.format(pid, p[0], p[1]))
  genBinObj(p[0], buildRegionTable, num_mem_type, num_region_option, getElementListByAddr(p[0], fd, '=I'+'I'*num_region_option))
  genBinObj(p[1], buildSelectiveTable, getElementListByAddr(p[1], fd, '=IIII'))
  profile.append((p[0],p[1],p[2]))
  pid = pid+1

fd.close()

# Write to binary file  
fd_bin = open(sys.argv[1], 'wb+')

profile_info_size = 8 + len(profile)*8
fd_bin.seek(profile_info_size)

bin_obj_offset = {0:0}
for b in bin_obj:
  bin_obj_offset[b] = fd_bin.tell()
  fd_bin.write(bin_obj[b])

# write eof pattern
fd_bin.write(b'\x99\x17\x71\xCB')

# Read build info
try:
	sym = readSymbolTableV2(elf_file, (b'RELEASE_VERNO_RW', b'BUILD_TIME_RW'))
	build_verno = readFromFileV2(elf_file, sym[b'RELEASE_VERNO_RW$$Base']['val'], sym[b'RELEASE_VERNO_RW$$Length']['val'], isNullTerminated = True)
	build_time = readFromFileV2(elf_file, sym[b'BUILD_TIME_RW$$Base']['val'], sym[b'BUILD_TIME_RW$$Length']['val'], isNullTerminated = True)
	signature = bytearray(build_verno + b'_' + build_time)
except Exception as err:
	print("Cannot read build information!", err)

signature_pos = fd_bin.tell()
fd_bin.write(struct.pack('<H', len(signature)))
fd_bin.write(signature)

# from the end of binary
fd_bin.write(struct.pack('<I', signature_pos))
fd_bin.seek(0)

profile_binary_magic = 0x1A424650
fd_bin.write(struct.pack('<II', profile_binary_magic, len(profile)))
for p in profile:
  fd_bin.write(struct.pack('<HHI', bin_obj_offset[p[0]], bin_obj_offset[p[1]], p[2]))

# add crc32 at file end
fd_bin.seek(0)
buf = fd_bin.read()
crc32 = binascii.crc32(buf, profile_binary_magic) & 0xFFFFFFFF
fd_bin.write(struct.pack('<I', crc32))
output_size = fd_bin.tell()
fd_bin.close()

os.remove(step1o_fname)
os.remove(step2o_fname)
print ("Memory dump profile %s created. File size %d. CRC32 0x%08X"%(sys.argv[1], output_size, crc32))
