linkmap.py 3.15 KB
Newer Older
PoroCYon's avatar
PoroCYon committed
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

# stolen from the contrib folder in https://github.com/blackle/LZMA-Vizualizer
# (i.e. I'm stealing it from myself)

import re
from typing import *

class CommonSym(NamedTuple):
    name: str
    size: int
    file: str
class Discard(NamedTuple):
    name: str
    size: int
    file: str
class MemCfg(NamedTuple):
    name: str
    org : int
    size: int
class MMap(NamedTuple):
    sect: str
    org : int
    #size: int
    sym : str
    file: str
class XRef(NamedTuple):
    name: str
    deff: str
    reff: Sequence[str]

class LinkMap(NamedTuple):
    common : Sequence[CommonSym]
    discard: Sequence[Discard]
    memcfg : Sequence[MemCfg]
    mmap   : Sequence[MMap]
    xref   : Sequence[XRef]

def parse_common( ls: Sequence[str]) -> Sequence[CommonSym]: return [] # TODO
def parse_discard(ls: Sequence[str]) -> Sequence[Discard  ]: return [] # TODO
def parse_memcfg( ls: Sequence[str]) -> Sequence[MemCfg   ]: return [] # TODO
def parse_xref(   ls: Sequence[str]) -> Sequence[XRef     ]: return [] # TODO

def parse_mmap(ls: Sequence[str]) -> Sequence[MMap]:
    rrr = []

    bigsect = None
    section = None
    curfile = None
    #size = -1

    for l in ls:
        def matcher(mobj):
            return mobj.group(0).replace(' ', '_')
        l = re.sub(r"\*\(.*\)", matcher, l)
        #print(repr(l))
        s = l.strip(); w = s.split()

        if s.startswith('LOAD ') or s.startswith('OUTPUT('): continue#break

        if l[0] != ' ':
            bigsect = w[0]
            del w[0]
        elif l[1] != ' ':
            section = w[0]
            del w[0]

        if len(w) == 0 or w[0] == "[!provide]":
            continue # addr placed on next line for prettyprinting reasons

        #print(repr(l), w[0])
        assert w[0].startswith("0x"), "welp, bad symbol addr"

        addr = int(w[0], 16)

        size = -1
        symn = ""
        if w[1].startswith("0x"): # filename will prolly follow
            size = int(w[1], 16)
            curfile = w[2] if len(w) > 2 else ""
        else: symn = w[1]

        if len(symn) > 0:
            rrr.append(MMap(section, addr, symn, curfile))

PoroCYon's avatar
PoroCYon committed
85
    return sorted(rrr, key=lambda m: m.org)
PoroCYon's avatar
PoroCYon committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

def parse(s: str) -> LinkMap:
    COMMON  = 0
    DISCARD = 1
    MEMCFG  = 2
    MMAP    = 3
    XREF    = 4

    curpt = -1

    commonl, discardl, memcfgl, mmapl, xrefl = [], [], [], [], []

    for l in s.split('\n'):
        if len(l.strip()) == 0: continue

        ls = l.strip()
        if ls == "Allocating common symbols": curpt = COMMON
        elif ls == "Discarded input sections": curpt = DISCARD
        elif ls == "Memory Configuration": curpt = MEMCFG
        elif ls == "Linker script and memory map": curpt = MMAP
        elif ls == 'Cross Reference Table': curpt = XREF
        elif curpt == COMMON :  commonl.append(l)
        elif curpt == DISCARD: discardl.append(l)
        elif curpt == MEMCFG :  memcfgl.append(l)
        elif curpt == MMAP   :    mmapl.append(l)
        elif curpt == XREF   :    xrefl.append(l)
        else:
            assert False, "bad line %s" % ls

    return LinkMap(parse_common(commonl), parse_discard(discardl), \
                   parse_memcfg(memcfgl), parse_mmap(mmapl), parse_xref(xrefl))