summaryrefslogtreecommitdiff
path: root/tools/libdol2asm/binary.py
blob: be40360fb1cf63e857d04b5f8535f42903118ca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import pickle
from pathlib import Path
from typing import Dict

from . import util
from .disassemble import AccessCollector, Access
from .context import Context
from .data.section import ExecutableSection

def analyze(context: Context,
            module_id: int,
            sections: Dict[str, ExecutableSection],
            cache: bool = True) -> Dict[int, Access]:
    """

    Each code segment provided by the sections will be search through 
    to find accesses to possible labels. These accesses are necessary as the linker
    map not may include all symbols. For exampel, there are symbols in '.init' section 
    which is missing from the linker map.

    By default this data is cached in 'build/generate/analyze_cache_X.dump' where the X is the
    module id passed in. This behaviour can be changed by providing the 'cache'
    argument.

    """

    cache_path = Path(f"build/generate/analyze_cache_{module_id}.dump")
    if cache and cache_path.exists():
        with cache_path.open('rb') as input:
            access, highLink = pickle.load(input)
            return access, highLink

    accesses = dict()
    highLink = dict()
    for section in sections:
        for start, stop in section.code_segments:
            size = stop - start
            data = section.data[start:stop]

            collector = AccessCollector(sections)
            for i, addr in collector.execute_generator(start + section.addr, data, size):
                pass

            accesses.update(collector.accesses)
            highLink.update(collector.highLink)
    if cache:
        util._create_dirs_for_file(cache_path)
        with cache_path.open('wb') as output:
            pickle.dump((accesses,highLink,), output)

    return accesses, highLink