示例#1
0
def test_g7x():
    infomsg(0, 'running g7x 100d tests\n')
    do_before_push_list(before_push_g7x_100d_data)
    do_after_pop_list(after_pop_g7x_100d_data)
    do_likely_func_start_list(likely_func_start_g7x_100d_data)
    do_likely_tail_call_list(likely_tail_call_g7x_100d_data)
    infomsg(0, 'done\n')
示例#2
0
def test_a540():
    infomsg(0, 'running a540 100b tests\n')
    do_before_push_list(before_push_a540_100b_data)
    do_after_pop_list(after_pop_a540_100b_data)
    do_likely_func_start_list(likely_func_start_a540_100b_data)
    do_likely_tail_call_list(likely_tail_call_a540_100b_data)
    infomsg(0, 'done\n')
示例#3
0
    def merge_blocks(self):
        '''merge adjacent blocks to reduce CHDK core data'''
        blocks = []
        pb = None
        for b in sorted(self.blocks, key=lambda b: b['offset']):
            if pb:
                infomsg(
                    2, '%s %s %x\n' % (pb['name'], b['name'], b['offset'] -
                                       (pb['offset'] + pb['size'])))
                pb_end = pb['offset'] + pb['size']
                # should be handled correctly, but may indicate incorrect block detection
                if pb_end > b['offset']:
                    warn('overlapping blocks %s %s\n' %
                         (pb['name'], b['name']))

                # allow a modest fudge, assuming Canon wouldn't put a varying chunk in a small space
                if b['offset'] <= pb['offset'] + pb['size'] + 32:
                    nb = pb
                    nb['name'] += ', ' + b['name']
                    nb['size'] += b['size'] + b['offset'] - (pb['offset'] +
                                                             pb['size'])
                    pb = nb
                    continue
            pb = b
            blocks.append(b)

        self.blocks = blocks
示例#4
0
    def create_bytemap(self, mbdef):
        addr = toAddr(mbdef['start'])
        src_addr = toAddr(mbdef['src'])
        mb_src = getMemoryBlock(src_addr)
        if not mb_src:
            warn("mblock %s bytemap no source block found" % (mbdef['name']))
            return

        infomsg(
            0, "Create bytemap mblock %s 0x%s 0x%x (%d) from %s %s\n" %
            (mbdef['name'], addr, mbdef['size'], mbdef['size'],
             mb_src.getName(), src_addr))
        if g_options['pretend']:
            return

        mem = getCurrentProgram().getMemory()
        # API changed in 9.2, added "overlay" bool
        if ghidra.framework.ApplicationVersion(getGhidraVersion(
        )) >= ghidra.framework.ApplicationVersion('9.2'):
            mem.createByteMappedBlock(mbdef['name'], addr, src_addr,
                                      mbdef['size'], False)
        else:
            mem.createByteMappedBlock(mbdef['name'], addr, src_addr,
                                      mbdef['size'])
        mb_new = getMemoryBlock(addr)
        self.set_attrs(mbdef, mb_new)
示例#5
0
def init_levent_table():
    addr = toAddr('levent_table')
    if addr is None:
        raise ValueError('levent_table not found, check stubs or run ImportCHDKStubs.py')

    cnt = 0
    while True:
        try:
            pname = get_valid_pointer_at(addr)
            if pname is None or getInt(addr.add(4)) == -1:
                infomsg(0,'break\n')
                break

            clearListing(addr, addr.add(11))

            b = getByte(pname)
            # if it looks like a string
            if is_print_char(b):
                # if preceding is null, and address isn't already inside data, make string
                if getByte(pname.add(-1)) == 0 and getDataContaining(pname) == None:
                    createAsciiString(pname)

            createData(addr, Pointer32DataType())

            createDwords(addr.add(4),2)
            addr = addr.add(12)
            cnt += 1

        except(ghidra.program.model.mem.MemoryAccessException):
            warn("Memory access exception at %s"%(addr))
            break

    infomsg(0,'levent_table %s %d entries\n'%(toAddr('levent_table'),cnt))
示例#6
0
def extract_thumb2_blobs_main():
    argparser = argparse.ArgumentParser(description='''\
Extract firmware blobs for cores other than the main CPU from
Digic 6 and later firmware, using CHDK stubs_entry.S info
''',
    formatter_class=argparse.RawDescriptionHelpFormatter)
    argparser.add_argument('platform', help='CHDK platform name, like g7x')
    argparser.add_argument('sub', help='Firmware sub name, like 100d')
    argparser.add_argument("-s", "--source",
        help="CHDK source root, default current tree", action='store',
        default=os.path.abspath(os.path.join(self_dir,'..')))
    argparser.add_argument("-d", "--dumps", help="CHDK dumps root, default PRIMARY_ROOT or source platform dir",action='store')
    argparser.add_argument("-o", "--out", help="Output directory, default dump directory",action='store')
    argparser.add_argument('-v','--verbose',help="Increase verbosity", action='count',default=0)
    argparser.add_argument("--dumpfile", help="specify dump file directly instead of inferring from platform/sub",action='store')

    args = argparser.parse_args()

    chdklib.logutil.verbosity = args.verbose

    stubs_data = StubsData(warnfunc=warn) # only warnings, no info

    plat = args.platform
    platsub = args.sub
    chdk_root = args.source
    if args.dumps:
        dump_root = args.dumps
    else:
        dump_root = os.environ.get('PRIMARY_ROOT',os.path.join(chdk_root,'platform'))

    stubsub = platsub

    stubplat = plat

    plat_dir = os.path.join(chdk_root,'platform',stubplat,'sub',stubsub)
    if args.dumpfile:
        dump_name = args.dumpfile
    else:
        dump_name = os.path.join(dump_root,plat,'sub',platsub,'PRIMARY.BIN')

    if args.out:
        out_dir = args.out
    else:
        out_dir = os.path.dirname(dump_name)
        if out_dir == '':
            out_dir = './'

    stubs_entry_name = os.path.join(plat_dir,'stubs_entry.S')

    infomsg(1,'Loading stubs %s %s %s\n'%(stubplat,stubsub,stubs_entry_name))

    if not os.path.isfile(stubs_entry_name):
        sys.stderr.write("ERROR: missing %s\n"%(stubs_entry_name))
        sys.exit(1)

    stubs_data.load_stubs_s(stubs_entry_name,process_comments=True)
    stubs_data.guess_platform_vals()

    process_dump(dump_name,out_dir,stubs_data)
示例#7
0
    def create_uninit(self, mbdef):
        infomsg(
            0, "Create uninit mblock %s 0x%08x 0x%x (%d)\n" %
            (mbdef['name'], mbdef['start'], mbdef['size'], mbdef['size']))
        if g_options['pretend']:
            return

        mb_new = createMemoryBlock(mbdef['name'], toAddr(mbdef['start']), None,
                                   mbdef['size'], False)
        self.set_attrs(mbdef, mb_new)
示例#8
0
def labels_to_funcs_main():
    t0 = datetime.datetime.now()
    is_thumb2 = str(currentProgram.getLanguageID())[-2:] == 'v7'
    symbol_count = 0
    found_count = 0
    create_count = 0
    # LAB_ labels are "dynamic" labels, no obvious way to iterate over them
    # without iterating over everything
    st = currentProgram.getSymbolTable()
    mem = currentProgram.getMemory()
    # getNumSymbols doesn't return dynamic, so not really accurate
    prog_max = long(st.getNumSymbols() * 2.5)
    monitor.initialize(prog_max)
    for s in st.getAllSymbols(True):
        symbol_count += 1
        monitor.incrementProgress(1)
        monitor.checkCanceled()

        # already a function, skip
        if s.getSymbolType() == SymbolType.FUNCTION:
            continue

        # ignore non-global symbols like switch cases
        if s.getParentNamespace().getID() != GLOBAL_NAMESPACE_ID:
            continue

        addr = s.getAddress()

        # skip bad addresses and non-exec blocks
        mb = mem.getBlock(addr)
        if not mb or not mb.isExecute():
            continue

        found_count += 1
        if is_thumb2 and (addr.offset & 1):
            monitor.setMessage(s.getName())
            if process_thumb_label(s):
                create_count += 1
        else:
            # already defined as code
            if getInstructionAt(addr):
                monitor.setMessage(s.getName())
                if process_insn_label(s):
                    create_count += 1

        # creating functions appears to reset monitor state
        if monitor.getMaximum() != prog_max:
            monitor.setMaximum(prog_max)
            monitor.setProgress(symbol_count)

    infomsg(
        0, "symbols %d checked %d created %d in %0.1f sec\n" %
        (symbol_count, found_count, create_count,
         (datetime.datetime.now() - t0).total_seconds()))
示例#9
0
    def describe(self, regvals):
        for rname in sorted(list(regvals)):
            reg = regvals[rname]
            if reg is None:
                rval = "Unknown"
            elif reg.isRegisterRelativeValue():
                rval = str(
                    reg.getRelativeRegister()) + ' %#x' % (reg.getValue())
            else:
                rval = '%#x' % (reg.getValue())

            infomsg(-1, '%s %s\n' % (rname, rval))
示例#10
0
def list_levent_calls():
    cd = LeventCallDescriber()

    instr = str(askString("Event","Names, numbers or *")).upper()
    event_ids = []
    do_all = False

    for s in re.split('[ ,]+',instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$',s,re.I):
            event_ids.append(int(s,16))
        elif re.match('[0-9]+$',s):
            event_ids.append(int(s,10))
        else:
            event_id = cd.ld.by_name.get(s)
            if event_id is None:
                # iterate over list for case insensitive compare
                for evdef in cd.ld.list:
                    if evdef['name'].lower() == s.lower():
                        event_id = evdef['id']
                        break

            if event_id is None:
                warn('ignoring unknown event id %s'%(s))
            else:
                event_ids.append(event_id)

    if len(event_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0,"Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for event_id in event_ids:
        if event_id in cd.ld.by_id and cd.ld.by_id[event_id]['name'] !='':
            msg.append("%s (%d)"%(cd.ld.by_id[event_id]['name'],event_id))
        else:
            msg.append("%d"%(event_id))

    infomsg(0," %s\n"%(', '.join(msg)))

    for desc in cd.describe_all_calls():
        event_id = desc.args[0].val
        if (do_all and cd.ld.by_id.get(event_id)) or event_id in event_ids:
            infomsg(0,'%s %s(%s'%(desc.addr,desc.fname,desc.args[0].desc))
            if len(desc.args) == 2:
                infomsg(0,', %s'%(desc.args[1].desc))
            infomsg(0,')\n')
示例#11
0
def process_thumb_insn_label(addr):
    # already part of a function, done
    # TODO could check for incorrect inclusion from tail call
    if getFunctionContaining(addr):
        return False
    # normal function start, already disassembled
    # without push seems OK, switches excluded in main loop
    if is_likely_func_start(addr, require_push=False, disassemble=False):
        if g_options['verbose']:
            if not is_push_lr(getInstructionAt(addr)):
                infomsg(0, '%s thumb data notpush\n' % (addr))
            else:
                infomsg(0, '%s thumb data func\n' % (addr))
        return do_make_func(addr)

    return False
示例#12
0
def clean_empty_funcs_main():
    found_count = 0
    clean_count = 0
    fm = currentProgram.getFunctionManager()
    monitor.initialize(fm.getFunctionCount())
    for f in fm.getFunctions(True):
        b = f.getBody()
        if b.getMinAddress() == b.getMaxAddress():
            found_count += 1
            if clean_empty_func(f):
                clean_count += 1

        monitor.incrementProgress(1)
        monitor.checkCanceled()

    infomsg(0, "found %d cleaned %d\n" % (found_count, clean_count))
示例#13
0
def process_call(desc, mzrm_createmsg_addr):
    # should always have a function, since call describer won't find if not
    fn = currentProgram.getListing().getFunctionContaining(desc.addr)

    mzrm_name = desc.args[2].mzrm_name
    if mzrm_name == '':
        mzrm_name = 'mzrm_unk_%d' % (desc.args[2].val)

    # if the function already has a non-default name, leave it
    sym_source = fn.getSymbol().getSource()
    if not (sym_source == SourceType.ANALYSIS
            or sym_source == SourceType.DEFAULT):
        # TODO could add repeatable comment
        infomsg(
            0, "%s %s no-default source %s\n" %
            (fn.getEntryPoint(), fn.getName(), sym_source))
        return False

    n = 0
    for ref in get_refs_from_addrset(fn.getBody()):
        if ref.getToAddress() == mzrm_createmsg_addr:
            n += 1

    # only attempt to name if function has exactly one ref to mzrm_createmsg
    if n != 1:
        infomsg(
            0, '%s %s skip, has %d mzrm_createmsg calls\n' %
            (fn.getEntryPoint(), mzrm_name, n))
        return False

    # check for existing uses of this name
    mzrm_name_base = mzrm_name
    name_count = 0
    while True:
        n_syms = 0
        # could be multiple
        for sym in getSymbols(mzrm_name, None):
            # if already used with our address, done!
            if sym.getAddress() == fn.getEntryPoint():
                infomsg(0, '%s already %s\n' % (fn.getEntryPoint(), mzrm_name))
                return True
            n_syms += 1

        # if none, found a free name
        if n_syms == 0:
            break

        name_count += 1
        mzrm_name = '%s_%d' % (mzrm_name_base, name_count)

    infomsg(0, '%s %s\n' % (fn.getEntryPoint(), mzrm_name))
    if not g_options['pretend']:
        fn.setName(mzrm_name, SourceType.ANALYSIS)

    return True
示例#14
0
    def create_split(self, mbdef):
        addr = toAddr(mbdef['start'])
        mb_src = getMemoryBlock(addr)
        if not mb_src:
            warn("mblock %s split no source block found" % (mbdef['name']))
            return

        infomsg(
            0, "Create split mblock %s 0x%s from %s\n" %
            (mbdef['name'], addr, mb_src.getName()))
        if g_options['pretend']:
            return

        mem = getCurrentProgram().getMemory()
        mem.split(mb_src, addr)
        mb_new = getMemoryBlock(addr)
        mb_new.setName(mbdef['name'])
        self.set_attrs(mbdef, mb_new)
示例#15
0
def clean_code_from_opref(b):
    addr = b.getAddress()

    # opref on thumb code has thumb bit set
    tmode = get_tmode_reg_at(addr)
    if tmode and addr.getUnsignedOffset() & 1:
        addr = addr.add(-1)

    # check if function has already been created starting at this address
    sym = getSymbolAt(addr)
    if sym and sym.getSymbolType() == SymbolType.FUNCTION:
        infomsg(0,'already a function %s\n'%(addr));
        return True

    if is_likely_func_start(addr):
        return do_make_func(addr)

    return False
示例#16
0
def process_dump(dump_name,out_dir,stubs_data):
    if not os.path.isfile(dump_name):
        warn("missing %s"%(dump_name))
        return

    dumper = BlobDumper(dump_name)
    if dumper.filesize == 0:
        warn("zero size %s"%(dump_name))
        return

    dumper.process_stubs(stubs_data)

    with open(dump_name,'rb') as fh:
        for b in dumper.blocks:
            oname = os.path.join(out_dir,b['name']+'.bin')
            fh.seek(b['offset'])
            data = fh.read(b['size'])
            infomsg(0,'Write %s 0x%08x %s\n'%(oname,b['start_adr'],b['size']))
            with open(oname,'wb') as ofh:
                ofh.write(data)
示例#17
0
def write_options(secname, cfgfile, options_spec, options):
    # lets caller bypass
    if options['skip_create_config']:
        infomsg(0, "Skip writing config file %s\n" % (cfgfile))
        return

    infomsg(0, "Writing config file %s\n" % (cfgfile))
    try:
        fh = open(cfgfile, "w")
        fh.write('[' + secname + ']\n')
        for ospec in options_spec:
            k = ospec['name']
            fh.write('# {} {} default={}\n'.format(k, ospec['type'],
                                                   ospec['default']))
            fh.write(ospec['desc'])
            # this is g_options, to allow merging. Should always have been initialized from defaults, at least
            fh.write('{}={}\n\n'.format(k, options[k]))
        fh.close()

    except IOError:
        warn('saving default cfg failed')
def thumb_bookmark_cleanup_main():
    bmm = getCurrentProgram().getBookmarkManager()
    # cleanup triggers more disassembly, which can create more of the same kind of errors
    # try a few times or until nothing cleanable was found
    for clean_pass in range(1, 11):
        check_count = 0
        clean_count = 0
        for b in bmm.getBookmarksIterator("Error"):
            check_count += 1
            if check_bookmark(b):
                clean_count += 1
                if g_options['remove_resolved'] and not g_options['pretend']:
                    bmm.removeBookmark(b)

        infomsg(
            0, "pass %d checked %d cleaned %d\n" %
            (clean_pass, check_count, clean_count))
        if clean_count == 0:
            break
        # wait for analysis to complete before next pass
        analyzeChanges(getCurrentProgram())
示例#19
0
def func_bookmark_clean_main():
    bmm = getCurrentProgram().getBookmarkManager()
    check_count = 0
    clean_count = 0
    for b in bmm.getBookmarksIterator("Analysis"):
        if (b.getCategory() == 'Function Start Search delayed Overlap'
            and b.getComment() == 'Function exists at probable good function start'):
            check_count += 1
            status = clean_func_exists(b)
        elif (b.getCategory() ==  'Found Code'
            and b.getComment() == 'Found code from operand reference'):
            check_count += 1
            status = clean_code_from_opref(b)
        else:
            status = False

        if status:
            clean_count += 1
            if g_options['remove_resolved'] and not g_options['pretend']:
                bmm.removeBookmark(b)

    infomsg(0,"checked %d cleaned %d\n"%(check_count, clean_count))
示例#20
0
def clean_func_exists(b):
    jump_ref = False;
    addr = b.getAddress()

    # check if function has already been created starting at this address
    sym = getSymbolAt(addr)
    if sym and sym.getSymbolType() == SymbolType.FUNCTION:
        infomsg(0,'already a function %s\n'%(addr));
        return True

    # check references to address:
    for ref in getReferencesTo(addr):
        # if the reference is a call, assume this is a valid function start
        if ref.getReferenceType().isCall():
            return do_make_func(addr)
        if ref.getReferenceType().isJump():
            jump_ref = ref

    # if there's a jump, check if it looks like the start of a function (push et al)
    if jump_ref and is_likely_func_start(addr):
        return do_make_func(addr)

    return False
示例#21
0
def name_mzrm_functions():
    sym = getSymbol('mzrm_createmsg', None)
    if not sym:
        warnf('mzrm_createmsg not present')
        return

    mzrm_createmsg_addr = sym.getAddress()

    filename = str(askFile("mzrm id list", "select"))

    mzrmlist = MzrmMsgList(filename)

    cd = MzrmCallDescriber(mzrmlist)

    found_count = 0
    named_count = 0

    for desc in cd.describe_all_calls():
        if process_call(desc, mzrm_createmsg_addr):
            named_count += 1
        found_count += 1

    infomsg(0, "found %d named %d\n" % (found_count, named_count))
示例#22
0
def list_mzrm_create_calls():

    filename = str(askFile("mzrm id list", "select"))

    mzrmlist = MzrmMsgList(filename)

    cd = MzrmCallDescriber(mzrmlist)

    instr = str(askString("MZRM Messages", "Names, numbers or *")).upper()
    mzrm_ids = []
    do_all = False

    for s in re.split('[ ,]+', instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$', s, re.I):
            mzrm_ids.append(int(s, 16))
        elif re.match('[0-9]+$', s):
            mzrm_ids.append(int(s, 10))
        else:
            mzrm_msg = mzrmlist.by_name.get(s)
            if mzrm_msg is None:
                # iterate over list for case insensitive compare
                for mzrm_id in mzrmlist.by_id:
                    if mzrmlist.by_id[mzrm_id].name.lower() == s.lower():
                        mzrm_msg = mzrmlist.by_id[mzrm_id]
                        break

            if mzrm_msg is None:
                warn('ignoring unknown mesasge id %s' % (s))
            else:
                mzrm_ids.append(mzrm_msg.mid)

    if len(mzrm_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0, "Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for mzrm_id in mzrm_ids:
        if mzrm_id in mzrmlist.by_id and not mzrmlist.by_id[mzrm_id].unk:
            msg.append("%s (%d)" % (mzrmlist.by_id[mzrm_id].name, mzrm_id))
        else:
            msg.append("%d" % (mzrm_id))

    infomsg(0, " %s\n" % (', '.join(msg)))

    for desc in cd.describe_all_calls():
        mzrm_id = desc.args[2].val
        if (do_all and mzrmlist.by_id.get(mzrm_id)) or mzrm_id in mzrm_ids:
            infomsg(
                0, '%s %s(%s,%s,%s,%s)\n' %
                (desc.addr, desc.fname, desc.args[0].desc, desc.args[1].desc,
                 desc.args[2].desc, desc.args[3].desc))
示例#23
0
def process_thumb_notdis_label(addr, t_addr):
    # no instruction, look for possible code
    for ref in getReferencesTo(t_addr):
        idesc = get_insn_desc(ref.getFromAddress())
        if idesc is None:
            continue
        # tbb instructions create weird refs
        # also don't want anything ref'd by lrdb
        # mvn almost always constants that look like addresses
        # mov could be suspect, but also valid since ghidra tracks load + mov
        mne = idesc.get_mne()
        if mne == 'tbb' or mne == 'tbh' or mne == 'ldrb' or mne == 'mvn':
            # infomsg(0,"%s skip ref %s\n"%(addr,mne))
            return False

    if not is_likely_func_start(
            addr, require_push=False, disassemble=True, tmode=True):
        return False

    # infomsg(0,"%s dis thumb\n"%(addr))
    bad_data = getDataAt(t_addr)
    if bad_data:
        if g_options['verbose']:
            infomsg(0, '%s remove data %s\n' % (t_addr, bad_data))
        if not g_options['pretend']:
            removeData(bad_data)
    else:
        # check for data containing
        bad_data = getDataContaining(addr)
        # if it's also unaligned, assume bad
        # could check for other signs of validity, but already have valid func start
        if bad_data and (bad_data.getAddress().getOffset() & 1 == 1):
            if g_options['verbose']:
                infomsg(0,
                        '%s remove containing data %s\n' % (t_addr, bad_data))
            if not g_options['pretend']:
                removeData(bad_data)

    # if existing function without disassembled code, remove and try to recreate
    old_fn = getFunctionAt(addr)
    if old_fn:
        # infomsg(0,'%s remove func\n'%(addr))
        if not g_options['pretend']:
            removeFunction(old_fn)

    if not g_options['pretend']:
        # set thumb since this case is only used when address has thumb bit set
        set_tmode_reg_at(addr, 1)
        if not disassemble(addr):
            warn("%s dis fail" % (addr))
            return False

    if g_options['verbose']:
        infomsg(0, '%s thumb data dis func\n' % (addr))
    return do_make_func(addr)
def check_thumb_data_conflict(b):
    m = re.match(
        'Failed to disassemble at ([0-9a-fA-F]{8}) due to conflicting data at ([0-9a-fA-F]{8})',
        b.getComment())
    # Not this kind of bookmark
    if not m:
        return False

    # check if data conflict is at +1. i_addr should be the same as bookmark, but number
    i_addr = int(m.group(1), 16)
    d_addr = int(m.group(2), 16)
    if d_addr != i_addr + 1:
        return False

    b_addr = b.getAddress()

    # thumb instruction already there, assume resolved
    if getInstructionAt(b_addr):
        if get_tmode_reg_at(b_addr):
            infomsg(0, "%s looks resolved!\n" % (b_addr))
            return True
        else:
            # ARM instruction, likely a different problem
            return False

    bad_data = getDataAt(toAddr(d_addr))
    if bad_data:
        infomsg(0, 'remove data %s\n' % (bad_data))
        if not g_options['pretend']:
            removeData(bad_data)
    infomsg(0, "Dis thumb %s\n" % (b_addr))
    if not g_options['pretend']:
        # assume thumb if data was at +1
        set_tmode_reg_at(b_addr, 1)
        if disassemble(b_addr):
            return True
        else:
            infomsg(0, "Dis failed %s\n" % (b_addr))
            return False
示例#25
0
def list_prop_calls():
    filename = str(askFile("platform_camera.h or propsetN.h", "select"))
    instr = str(askString("Propcases", "Names, numbers or *")).upper()
    pd = PropsetData(filename)
    prop_ids = []
    do_all = False

    for s in re.split('[ ,]+', instr):
        if s == '*':
            do_all = True
        elif re.match('0x[0-9a-f]+$', s, re.I):
            prop_ids.append(int(s, 16))
        elif re.match('[0-9]+$', s):
            prop_ids.append(int(s, 10))
        else:
            if re.match('^PROPCASE_', s):
                prop_name = s
            else:
                prop_name = 'PROPCASE_' + s
            prop_id = pd.by_name.get(prop_name)
            if prop_id is None:
                warn('ignoring unknown propcase id %s' % (prop_name))
            else:
                prop_ids.append(prop_id)

    if len(prop_ids) == 0 and not do_all:
        warn('no valid IDs specified, exiting')
        return

    infomsg(0, "Searching for")
    msg = []
    if do_all:
        msg.append('all known')
    for prop_id in prop_ids:
        if prop_id in pd.by_id:
            msg.append("%s (%d)" % (pd.by_id[prop_id], prop_id))
        else:
            msg.append("%d" % (prop_id))

    infomsg(0, " %s from propset %d\n" % (', '.join(msg), pd.propset))

    cd = PropCallDescriber(filename)
    for desc in cd.describe_all_calls():
        prop_id = desc.args[0].val
        if (do_all and pd.by_id.get(prop_id)) or prop_id in prop_ids:
            infomsg(
                0, '%s %s(%s,%s,%s)\n' %
                (desc.addr, desc.fname, desc.args[0].desc, desc.args[1].desc,
                 desc.args[2].desc))
示例#26
0
def load_options(secname, cfgfile, options_spec, options):
    # initialize with default values
    for ospec in options_spec:
        options[ospec['name']] = ospec['default']

    if not os.path.isfile(cfgfile):
        infomsg(0, 'Config not found %s\n' % (cfgfile))
        return True

    missing = False
    # lets caller bypass
    if options['skip_load_config']:
        infomsg(0, 'Skip load config %s\n' % (cfgfile))
    else:
        config = ConfigParser.ConfigParser()
        infomsg(0, 'Load config %s\n' % (cfgfile))
        config.read(cfgfile)
        if config.has_section(secname):
            for ospec in options_spec:
                k = ospec['name']
                if not config.has_option(secname, k):
                    missing = True
                    continue

                vt = ospec['type']
                if vt == 'bool':
                    options[k] = config.getboolean(secname, k)
                elif vt == 'int':
                    options[k] = config.getint(secname, k)
                elif vt == 'enum':
                    cv = config.get(secname, k)
                    if cv in ospec['vals']:
                        options[k] = cv
                    else:
                        warn("unexpected cfg option %s %s" % (k, cv))
                else:
                    warn("unexpected option desc %s" % (k))

        else:
            missing = True
    return missing
示例#27
0
    def crc32_all(self):
        infomsg(
            1, '%-10s %-10s %-7s %-10s %s\n' %
            ('start_adr', 'offset', 'size', 'crc32', 'name'))

        with open(self.filepath, 'rb') as fh:
            for b in self.blocks:
                if b['size']:
                    fh.seek(b['offset'])
                    data = fh.read(b['size'])
                    b['crc32'] = zlib.crc32(data)
                else:
                    b['crc32'] = 0
                infomsg(
                    1, '0x%08x 0x%08x %7d 0x%08x %s\n' %
                    (b['start_adr'], b['offset'], b['size'], b['crc32'],
                     b['name']))

        infomsg(
            1, "%d blocks %d bytes %d%%\n" %
            (len(self.blocks), self.total_size,
             100 * self.total_size / self.filesize))
示例#28
0
def clean_empty_func(f):
    f_entry = f.getEntryPoint()
    infomsg(0, 'empty func %s\n' % (f_entry))
    if not g_options['pretend']:
        removeFunction(f)

    # if the function is inside data or non-code memory block
    # don't try to recreate
    if getDataContaining(f_entry):
        infomsg(0, 'entry inside data %s\n' % (f_entry))
        return True

    # if no instruction, don't re-create
    if not getInstructionAt(f_entry):
        infomsg(0, 'entry not code %s\n' % (f_entry))
        return True

    mb = getMemoryBlock(f_entry)
    if not mb:
        infomsg(0, 'entry not in memblock!? %s\n' % (f_entry))
        return True

    if not mb.isExecute():
        infomsg(0, 'entry in noexec block %s %s\n' % (f_entry, mb.getName()))
        return True

    if not mb.isInitialized() and not mb.isMapped():
        infomsg(0, 'entry in uninit block %s %s\n' % (f_entry, mb.getName()))
        return True

    # infomsg(0,'create %s'%(f_entry))
    if g_options['pretend']:
        return True

    f_new = createFunction(f_entry, None)
    if f_new:
        b = f_new.getBody()
        if b.getMinAddress() == b.getMaxAddress():
            infomsg(0, 'still zero size %s\n' % (f_entry))
            removeFunction(f)
            return False

        return True

    else:
        infomsg(0, 'create failed %s\n' % (f_entry))
        return False
示例#29
0
def init_chdk_mem_map_main():
    init_options()

    stubs_data = StubsData(warnfunc=warn, infofunc=infomsg)

    # whatever askDirectory returns isn't actually string
    sub_dir = str(askDirectory("CHDK platform sub", "select"))

    filepath = os.path.join(sub_dir, 'stubs_entry.S')
    if not os.path.isfile(filepath):
        infomsg(0, 'No stubs_entry.S, trying stubs_entry.S.err\n')
        filepath = os.path.join(sub_dir, 'stubs_entry.S.err')
        if not os.path.isfile(filepath):
            warn('No stubs_entry files found')
            return

    stubs_data.load_stubs_s(filepath, process_comments=True)

    stubs_data.guess_platform_vals()

    smisc = stubs_data.stubs_entry_misc

    if not 'ar_rom' in smisc:
        warn('No ROM region identified, giving up')
        return

    if not 'main_fw_code_end' in smisc:
        warn('Main firmware code end not identified, giving up')
        return

    if len(getMemoryBlocks()) > 1:
        warn('Program already has multiple memory blocks, giving up')

    mb_rom = getMemoryBlocks()[0]

    if mb_rom.getStart() != toAddr(smisc['ar_rom']['start_adr']):
        warn('Memory block start does not match ROM, giving up')
        return

    if not mb_rom.isInitialized():
        warn('ROM block not initialized, giving up')
        return

    if mb_rom.getEnd() <= toAddr(smisc['main_fw_code_end']):
        warn(
            'Already initialized? ROM block end <= main fw code end, giving up'
        )
        return

    mbops.add_split('ROMDATA', smisc['main_fw_code_end'] + 1, w=False, x=False)

    make_romstarter_mblock(smisc)

    # if main firmware doesn't start at rom start, split
    if 'main_fw_start' in smisc and smisc['main_fw_start'] > smisc['ar_rom'][
            'start_adr']:
        mbops.add_split('ROMCODE', smisc['main_fw_start'], w=False, x=True)

    # ignored if not present
    ar_ramcode = smisc.get('ar_ramcode')
    ar_btcmcode = smisc.get('ar_btcmcode')
    ar_ramdata = smisc.get('ar_ramdata')
    ar_evec = smisc.get('ar_evec')
    ar_atcm = smisc.get('ar_atcm')

    mbops.add_stubs_ar(ar_ramdata, 'RAMDATA')
    mbops.add_stubs_ar(ar_ramcode, 'RAMCODE', x=True)
    mbops.add_stubs_ar(ar_btcmcode, 'BTCMCODE', x=True)
    mbops.add_stubs_ar(smisc.get('ar_itcm'), 'ITCM')
    mbops.add_stubs_ar(smisc.get('ar_uncached'), 'UNCACHED')
    mbops.add_stubs_ar(smisc.get('ar_dtcm'), 'DTCM')
    mbops.add_stubs_ar(smisc.get('ar_mmio'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xd'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xc1'), 'MMIO', v=True)
    mbops.add_stubs_ar(smisc.get('ar_mmio_0xc8'), 'MMIO', v=True)

    if smisc['digic'] >= 60:
        # RAM between ATCM and copied data
        mbops.add_uninit('RAM', 0x4000, 0x4000)
        # detected exception vector at address 0, add as initialized
        if ar_evec and ar_evec['start_adr'] == 0:
            mbops.add_stubs_ar(smisc.get('ar_evec'), 'EVEC')
            if ar_atcm and ar_atcm['start_adr'] == 0:
                mbops.add_uninit('ATCM',
                                 ar_evec['last_adr'] + 1,
                                 last_adr=ar_atcm['last_adr'])
            else:
                mbops.add_stubs_ar(smisc.get('ar_atcm'), 'ATCM')
        else:
            mbops.add_stubs_ar(smisc.get('ar_atcm'), 'ATCM')
    else:
        # RAM between ITCM and copied data
        mbops.add_uninit('RAM', 0x1000, 0x900)

    if ar_ramcode:
        # RAM between ram data and code (assumes code after data!)
        mbops.add_uninit('RAM',
                         ar_ramdata['last_adr'] + 1,
                         last_adr=ar_ramcode['start_adr'] - 1)
        # RAM from end of code to end of RAM
        mbops.add_uninit('RAM',
                         ar_ramcode['last_adr'] + 1,
                         last_adr=smisc['max_ram_addr'])
    else:
        # RAM from end of ram data to end of RAM
        mbops.add_uninit('RAM',
                         ar_ramdata['last_adr'] + 1,
                         last_adr=smisc['max_ram_addr'])

    if smisc['digic'] == 60:
        if ar_btcmcode and ar_btcmcode['start_adr'] == 0xbfe10800:
            # 0x800 before code
            mbops.add_uninit('BTCM', 0xbfe10000, 0x800)
            # from code end to 64k
            mbops.add_uninit('BTCM',
                             ar_btcmcode['last_adr'] + 1,
                             last_adr=0xbfe20000 - 1)
    elif smisc['digic'] == 70:
        # per https://chdk.setepontos.com/index.php?topic=11316.msg142197#msg142197
        if ar_btcmcode and ar_btcmcode['start_adr'] == 0xdffc4900:
            # 0x4900 before code. TODO this is actually initialized, could create mapped
            mbops.add_uninit('BTCM', 0xdffc0000, 0x4900)
            # from code end to 256k
            mbops.add_uninit('BTCM',
                             ar_btcmcode['last_adr'] + 1,
                             last_adr=0xdfffffff)

    if g_options['include_zico']:
        for ardef in smisc['zico_blobs']:
            mbops.add_stubs_ar(ardef, 'ZICO')

    # set whole ROM read-only before splitting
    if not g_options['pretend']:
        mb_rom.setWrite(False)

    mbops.apply_ops()
示例#30
0
def make_romstarter_mblock(smisc):
    """check for romstarter and create execuable block if possible"""

    if smisc['digic'] < 60:
        rs_start = 0xffff0000
        rs_start_addr = toAddr(rs_start)
        # TODO size could be found by checking for run of 0xff
        rs_size = 0x4000
        rs_after = rs_start + rs_size
        rs_after_addr = rs_start_addr.add(rs_size)

    elif smisc['digic'] == 60:
        if not 'main_fw_start' in smisc:
            infomsg(0,
                    'make_romstarter_mblock: main fw start not identified\n')
            return

        rs_start = smisc['ar_rom']['start_adr']
        rs_start_addr = toAddr(rs_start)
        rs_size = 0x5000
        rs_after = rs_start + rs_size
        rs_after_addr = rs_start_addr.add(rs_size)

        main_fw_addr = toAddr(smisc['main_fw_start'])

        if smisc['main_fw_start'] < rs_after:
            infomsg(
                0,
                'make_romstarter_mblock: main fw start not too close to romstarter\n'
            )
            return

    # TODO d7 unclear
    else:
        return

    # get memory block containing start addr
    mb_src = getMemoryBlock(rs_start_addr)
    if not mb_src:
        infomsg(0, 'make_romstarter_mblock: no address containing %s\n',
                rs_start_addr)
        return

    if mb_src != getMemoryBlock(rs_after_addr):
        infomsg(
            0,
            'make_romstarter_mblock: multiple memory blocks in region or too small\n'
        )
        return

    if smisc['digic'] == 60:
        if mb_src != getMemoryBlock(main_fw_addr):
            infomsg(
                0,
                'make_romstarter_mblock: multiple memory blocks in region or too small\n'
            )

    # check if there's enough space
    if smisc['ar_rom']['last_adr'] < rs_after:
        infomsg(0, 'make_romstarter_mblock: too small\n')
        return

    if smisc['digic'] < 60:
        pi = get_pinsn_at(rs_start_addr)
        if not pi:
            infomsg(0, 'make_romstarter_mblock: no instruction found\n')
            return

        if pi.getMnemonicString() != 'b' and pi.getMnemonicString() != 'ldr':
            infomsg(
                0,
                'make_romstarter_mblock: unexpected instruction %s\n' % (pi))
            return

        mbops.add_split('ROMSTARTER', rs_start, w=False, x=True)
        mbops.add_split('ROMDATA', rs_after, w=False, x=False)

    elif smisc['digic'] == 60:
        # digic 6 romstarter code doesn't start exactly at rom start, can't do instruction check
        # TODO romstarter will end up with the original ROM name, should have a rename op
        mbops.add_split('ROMDATA', rs_after, w=False, x=False)