#!/usr/bin/python

# usage examples:

# python itrace -o i -m m ...
# python itrace-decode1.py m < i

# python itrace -o i -m m -b ...
# od -v -t x4 -w4 i | cut -d' ' -f2 | python itrace-decode1.py m
# od -v -t x8 -w8 i | cut -d' ' -f2 | python itrace-decode1.py m

import sys, bisect, popen2
objdump_cache = {}

def objdump_cache_generate(file):
    cmd = "objdump -d %s" % file
    o, i = popen2.popen2(cmd)
    i.close()
    ret = []
    for l in o.readlines():
        l = l.rstrip("\n")
        parts = l.split(" ")
        if len(parts) == 2 and parts[1].startswith("<") and parts[1].endswith(">:"):
            fun_addr = int(parts[0], 16)
            fun = parts[1].strip("<").rstrip(">:")
            ret += [ (fun_addr, fun) ]
    o.close()
    return ret

def add_symbols(m, start, end, file):
    global objdump_cache
    if file not in objdump_cache:
        objdump_cache[file] = objdump_cache_generate(file)
    for (addr, fun) in objdump_cache[file]:
        ok = addr <= end - start
        #print("%s: %08x + %08x = %08x = %s end %08x %s" % (file, start, addr, start+addr, fun, end, ok))
        if ok:
            m[start + addr] = fun
    return m

def map_rebuild(mapfd):
    m = {}
    map_expiry = -1
    
    while True:
        l = mapfd.readline()
        if not l or l.find("-") == -1:
            if l:
                map_expiry = int(l)
            break
        l = l.rstrip("\n")
        parts = l.split(" ")
        if len(parts) < 9:
            name = "anon"
        else:
            name = parts[-1]
            
        rangeparts = parts[0].split("-")
        start = int(rangeparts[0], 16)
        end = int(rangeparts[1], 16)
        

        m[start] = name
        if name.startswith("/"):
            m = add_symbols(m, start, end, name)

    map = {}
    map["sym"] = m
    map["list"] = m.keys()
    map["list"].sort()
    
    return (map_expiry, map)

def map_find(map, addr):
    i = bisect.bisect(map["list"], addr) - 1
    funaddr = map["list"][i]
    fun = map["sym"][funaddr]
    return "%s+%d" % (fun, addr - funaddr)

def main():
    steps = 0
    mapfd = open(sys.argv[1], "r")
    map_expiry = int(mapfd.readline())

    while True:
        if map_expiry != -1 and map_expiry <= steps:
            (map_expiry, map) = map_rebuild(mapfd)
            
        l = sys.stdin.readline()
        if not l:
            break
        addr = int(l, 16)
        
        sym = map_find(map, addr)
        print("%08x %s" % (addr, sym))
        steps += 1

main()
