Subversion Repositories Kolibri OS

Rev

Rev 7696 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
7696 akron1 4
    Copyright (c) 2018-2019, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE KOS;
9
 
10
IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS;
11
 
12
 
13
CONST
14
 
15
    HEADER_SIZE = 36;
16
 
17
    SIZE_OF_DWORD = 4;
18
 
19
 
20
TYPE
21
 
22
    FILE = WR.FILE;
23
 
24
    HEADER = RECORD
25
 
26
        menuet01: ARRAY 9 OF CHAR;
27
        ver, start, size, mem, sp, param, path: INTEGER
28
 
29
    END;
30
 
31
 
32
PROCEDURE align (n, _align: INTEGER): INTEGER;
33
BEGIN
34
    IF n MOD _align # 0 THEN
35
        n := n + _align - (n MOD _align)
36
    END
37
 
38
    RETURN n
39
END align;
40
 
41
 
42
PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER);
43
VAR
44
    i:      INTEGER;
45
    import: BIN.IMPRT;
46
 
47
BEGIN
48
    libcount  := 0;
49
    import := program.imp_list.first(BIN.IMPRT);
50
    WHILE import # NIL DO
51
        IF import.label = 0 THEN
52
            INC(libcount)
53
        END;
54
        import := import.next(BIN.IMPRT)
55
    END;
56
 
57
    len  := libcount * 2 + 2;
58
    size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
59
 
60
    ImportTable := CHL.CreateIntList();
61
    FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
62
        CHL.PushInt(ImportTable, 0)
63
    END;
64
 
65
    i := 0;
66
    import := program.imp_list.first(BIN.IMPRT);
67
    WHILE import # NIL DO
68
 
69
        IF import.label = 0 THEN
70
            CHL.SetInt(ImportTable, len, 0);
71
            INC(len);
72
            CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
73
            INC(i);
74
            CHL.SetInt(ImportTable, i, import.nameoffs + size + idata);
75
            INC(i)
76
        ELSE
77
            CHL.SetInt(ImportTable, len, import.nameoffs + size + idata);
78
            import.label := len * SIZE_OF_DWORD;
79
            INC(len)
80
        END;
81
 
82
        import := import.next(BIN.IMPRT)
83
    END;
84
    CHL.SetInt(ImportTable, len, 0);
85
    CHL.SetInt(ImportTable, i, 0);
86
    CHL.SetInt(ImportTable, i + 1, 0);
87
    INC(len);
88
    size := size + CHL.Length(program.import)
89
END Import;
90
 
91
 
92
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR);
93
 
94
CONST
95
 
96
    PARAM_SIZE    = 2048;
97
    FileAlignment = 16;
98
 
99
 
100
VAR
101
    header: HEADER;
102
 
103
    base, text, data, idata, bss: INTEGER;
104
 
105
    reloc:   BIN.RELOC;
106
    iproc:   BIN.IMPRT;
107
    L:       INTEGER;
108
    delta:   INTEGER;
109
 
110
    i: INTEGER;
111
 
112
    File: FILE;
113
 
114
    ImportTable: CHL.INTLIST;
115
    ILen, libcount, isize: INTEGER;
116
 
117
    icount, dcount, ccount: INTEGER;
118
 
7983 leency 119
    code: CHL.BYTELIST;
7597 akron1 120
 
121
BEGIN
122
    base := 0;
123
 
124
    icount := CHL.Length(program.import);
125
    dcount := CHL.Length(program.data);
126
    ccount := CHL.Length(program.code);
127
 
128
    text  := base + HEADER_SIZE;
129
    data  := align(text + ccount, FileAlignment);
130
    idata := align(data + dcount, FileAlignment);
131
 
132
    Import(program, idata, ImportTable, ILen, libcount, isize);
133
 
134
    bss := align(idata + isize, FileAlignment);
135
 
136
    header.menuet01 := "MENUET01";
137
    header.ver      :=  1;
138
    header.start    :=  text;
139
    header.size     :=  idata + isize - base;
140
    header.mem      :=  align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
141
    header.sp       :=  base + header.mem - PARAM_SIZE * 2;
142
    header.param    :=  header.sp;
143
    header.path     :=  header.param + PARAM_SIZE;
144
 
7983 leency 145
    code := program.code;
7597 akron1 146
    reloc := program.rel_list.first(BIN.RELOC);
147
    WHILE reloc # NIL DO
148
 
7983 leency 149
        L := BIN.get32le(code, reloc.offset);
7597 akron1 150
        delta := 3 - reloc.offset - text;
151
 
152
        CASE reloc.opcode OF
153
 
154
        |BIN.RIMP:
155
              iproc := BIN.GetIProc(program, L);
7983 leency 156
              BIN.put32le(code, reloc.offset, idata + iproc.label)
7597 akron1 157
 
158
        |BIN.RBSS:
7983 leency 159
              BIN.put32le(code, reloc.offset, L + bss)
7597 akron1 160
 
161
        |BIN.RDATA:
7983 leency 162
              BIN.put32le(code, reloc.offset, L + data)
7597 akron1 163
 
164
        |BIN.RCODE:
7983 leency 165
              BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text)
7597 akron1 166
 
167
        |BIN.PICDATA:
7983 leency 168
              BIN.put32le(code, reloc.offset, L + data + delta)
7597 akron1 169
 
170
        |BIN.PICCODE:
7983 leency 171
              BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta)
7597 akron1 172
 
173
        |BIN.PICBSS:
7983 leency 174
              BIN.put32le(code, reloc.offset, L + bss + delta)
7597 akron1 175
 
176
        |BIN.PICIMP:
177
              iproc := BIN.GetIProc(program, L);
7983 leency 178
              BIN.put32le(code, reloc.offset, idata + iproc.label + delta)
7597 akron1 179
 
180
        |BIN.IMPTAB:
7983 leency 181
              BIN.put32le(code, reloc.offset, idata + delta)
7597 akron1 182
 
183
        END;
184
 
185
        reloc := reloc.next(BIN.RELOC)
186
    END;
187
 
188
    File := WR.Create(FileName);
189
 
190
    FOR i := 0 TO 7 DO
191
        WR.WriteByte(File, ORD(header.menuet01[i]))
192
    END;
193
 
194
    WR.Write32LE(File, header.ver);
195
    WR.Write32LE(File, header.start);
196
    WR.Write32LE(File, header.size);
197
    WR.Write32LE(File, header.mem);
198
    WR.Write32LE(File, header.sp);
199
    WR.Write32LE(File, header.param);
200
    WR.Write32LE(File, header.path);
7693 akron1 201
 
7983 leency 202
    CHL.WriteToFile(File, code);
7597 akron1 203
    WR.Padding(File, FileAlignment);
204
 
205
    CHL.WriteToFile(File, program.data);
206
    WR.Padding(File, FileAlignment);
207
 
208
    FOR i := 0 TO ILen - 1 DO
209
        WR.Write32LE(File, CHL.GetInt(ImportTable, i))
7693 akron1 210
    END;
211
 
7597 akron1 212
    CHL.WriteToFile(File, program.import);
213
 
214
    WR.Close(File)
215
 
216
END write;
217
 
218
 
7983 leency 219
END KOS.