4
4
import com .compilerprogramming .ezlang .compiler .nodes .*;
5
5
import com .compilerprogramming .ezlang .compiler .sontypes .*;
6
6
7
- import java .util . Map ;
8
- import java . util . HashMap ;
7
+ import java .io .* ;
8
+
9
9
import java .nio .ByteBuffer ;
10
10
import java .nio .ByteOrder ;
11
- import java .io .IOException ;
12
- import java .io .FileOutputStream ;
13
- import java .io .ByteArrayOutputStream ;
14
- import java .io .BufferedOutputStream ;
11
+ import java .util .HashMap ;
12
+ import java .util .Map ;
15
13
16
14
public class ElfFile {
17
15
@@ -69,6 +67,10 @@ public static class Symbol {
69
67
// top 4bits are the "bind", bottom 4 are "type"
70
68
int _info ;
71
69
70
+ // bind 1011
71
+ // 00001111
72
+ // 10110000
73
+
72
74
Symbol (String name , int parent , int bind , int type ) {
73
75
_name = name ;
74
76
_parent = parent ;
@@ -78,6 +80,7 @@ public static class Symbol {
78
80
void writeHeader (ByteBuffer out ) {
79
81
out .putInt (_name_pos ); // name
80
82
out .put ((byte ) _info ); // info
83
+ // default visibility
81
84
out .put ((byte ) 0 ); // other
82
85
out .putShort ((short ) _parent ); // shndx
83
86
out .putLong (_value ); // value
@@ -117,7 +120,7 @@ void writeHeader(ByteBuffer out) {
117
120
out .putLong (size ()); // size
118
121
out .putInt (_link ); // link
119
122
out .putInt (_info ); // info
120
- out .putLong (1 ); // addralign
123
+ out .putLong (16 ); // addralign
121
124
if (_type == 2 ) {
122
125
out .putLong (SYMBOL_SIZE );// entsize
123
126
} else if (_type == 4 ) {
@@ -140,7 +143,7 @@ public static class SymbolSection extends Section {
140
143
}
141
144
142
145
@ Override
143
- void writeHeader (ByteBuffer out ) {
146
+ void writeHeader (ByteBuffer out ) {
144
147
// points to string table section
145
148
_link = 1 ;
146
149
@@ -159,23 +162,22 @@ void push(Symbol s) {
159
162
}
160
163
161
164
@ Override
162
- void write (ByteBuffer out ) {
165
+ void write (ByteBuffer out ) {
166
+ // Index 0 both designates the first entry in the table and serves as the undefined symbol index
163
167
for ( int i = 0 ; i < SYMBOL_SIZE /4 ; i ++ ) {
164
168
out .putInt (0 );
165
169
}
166
- int num = 1 ;
170
+ // index is already set
167
171
for ( Symbol s : _loc ) {
168
- s ._index = num ++;
169
172
s .writeHeader (out );
170
173
}
171
174
for ( Symbol s : _symbols ) {
172
- s ._index = num ++;
173
175
s .writeHeader (out );
174
176
}
175
177
}
176
178
177
179
@ Override
178
- int size () {
180
+ int size () {
179
181
return (1 + _symbols .len () + _loc .len ()) * SYMBOL_SIZE ;
180
182
}
181
183
}
@@ -210,54 +212,21 @@ private void pushSection(Section s) {
210
212
s ._index = _sections ._len ;
211
213
}
212
214
215
+ /* creates function and stores where it starts*/
213
216
private final HashMap <SONTypeFunPtr ,Symbol > _funcs = new HashMap <>();
214
217
private void encodeFunctions (SymbolSection symbols , DataSection text ) {
215
- int func_start = 0 ;
216
218
for ( int i =0 ; i <_code ._cfg ._len ; i ++ ) {
217
- Node bb = _code ._cfg .at (i );
218
- if ( bb instanceof FunNode f ) {
219
- // skip until the function ends
220
- while ( !(_code ._cfg .at (i ) instanceof ReturnNode ) ) {
221
- i ++;
222
- }
223
-
224
- Node r = _code ._cfg .at (i );
225
- int end = _code ._encoding ._opStart [r ._nid ] + _code ._encoding ._opLen [r ._nid ];
226
-
227
- Symbol func = new Symbol (f ._name , text ._index , SYM_BIND_GLOBAL , SYM_TYPE_FUNC );
228
- func ._size = end - func_start ;
229
- func ._value = func_start ;
230
- symbols .push (func );
231
- _funcs .put (f .sig (), func );
232
-
233
- // next function starts where the last one ends
234
- func_start = end ;
235
- }
236
- }
237
- }
238
-
239
- public final HashMap <SONType ,Symbol > _bigCons = new HashMap <>();
240
- private void encodeConstants (SymbolSection symbols , DataSection rdata ) {
241
- int cnt = 0 ;
242
- for (Map .Entry <Node ,SONType > e : _code ._encoding ._bigCons .entrySet ()) {
243
- if (_bigCons .get (e .getValue ()) != null ) {
244
- continue ;
245
- }
246
-
247
- Symbol glob = new Symbol ("GLOB$" +cnt , rdata ._index , SYM_BIND_GLOBAL , SYM_TYPE_FUNC );
248
- glob ._value = rdata ._contents .size ();
249
- symbols .push (glob );
250
-
251
- SONType t = e .getValue ();
252
- if ( t instanceof SONTypeFloat tf ) {
253
- write8 (rdata ._contents , Double .doubleToLongBits (tf ._con ));
254
- } else {
255
- throw Utils .TODO ();
256
- }
257
-
258
- glob ._size = rdata ._contents .size () - glob ._value ;
259
- _bigCons .put (e .getValue (), glob );
260
- cnt ++;
219
+ if ( !(_code ._cfg .at (i ) instanceof FunNode fun ) ) continue ;
220
+ // skip until the function ends
221
+ while ( !(_code ._cfg .at (i ) instanceof ReturnNode ret ) )
222
+ i ++;
223
+ int end = _code ._encoding ._opStart [ret ._nid ] + _code ._encoding ._opLen [ret ._nid ];
224
+
225
+ Symbol func = new Symbol (fun ._name , text ._index , SYM_BIND_GLOBAL , SYM_TYPE_FUNC );
226
+ func ._value = _code ._encoding ._opStart [fun ._nid ];
227
+ func ._size = end - func ._value ;
228
+ symbols .push (func );
229
+ _funcs .put (fun .sig (), func );
261
230
}
262
231
}
263
232
@@ -271,67 +240,90 @@ public void export(String fname) throws IOException {
271
240
SymbolSection symbols = new SymbolSection (".symtab" , 2 /* SHT_STRTAB */ );
272
241
pushSection (symbols );
273
242
243
+ // zero flag by default
274
244
// we've already constructed this entire section in the encoding phase
275
245
DataSection text = new DataSection (".text" , 1 /* SHT_PROGBITS */ , _code ._encoding ._bits );
276
246
text ._flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR ;
277
247
pushSection (text );
278
248
279
- DataSection rdata = new DataSection (".rodata" , 1 /* SHT_PROGBITS */ );
249
+ // Build and write constant pool
250
+ Encoding .BAOS cpool = new Encoding .BAOS ();
251
+ Encoding enc = _code ._encoding ;
252
+ enc .writeConstantPool (cpool ,false );
253
+ DataSection rdata = new DataSection (".rodata" , 1 /* SHT_PROGBITS */ , cpool );
280
254
rdata ._flags = SHF_ALLOC ;
281
255
pushSection (rdata );
282
256
283
257
// populate function symbols
284
258
encodeFunctions (symbols , text );
285
- // populate big constants
286
- // encodeConstants(symbols, rdata);
259
+
260
+ int idx = 1 ;
261
+ for ( Section s : _sections ) {
262
+ Symbol sym = new Symbol (s ._name , idx ++, SYM_BIND_LOCAL , SYM_TYPE_SECTION );
263
+ // we can reuse the same name pos from the actual section
264
+ sym ._name_pos = s ._name_pos ;
265
+ sym ._size = s .size ();
266
+ symbols .push (sym );
267
+ }
268
+
269
+ // calculate local index
270
+ int num = 1 ;
271
+ for ( Symbol s : symbols ._loc )
272
+ s ._index = num ++;
273
+ // extra space for .rela.text
274
+ int start_global = num +1 ; // Add one to skip the final .rela.text local symbol
275
+ for ( Symbol a : symbols ._symbols )
276
+ a ._index = start_global ++;
277
+ int bigConIdx = start_global ;
278
+ start_global += enc ._bigCons .size ();
287
279
288
280
// create .text relocations
289
281
DataSection text_rela = new DataSection (".rela.text" , 4 /* SHT_RELA */ );
290
- for ( Node n : _code . _encoding ._externals .keySet ()) {
282
+ for ( Node n : enc ._externals .keySet ()) {
291
283
int nid = n ._nid ;
292
- String extern = _code ._encoding ._externals .get (n );
293
- int sym_id = _funcs .get (extern )._index ;
294
- int offset = _code ._encoding ._opStart [nid ] + _code ._encoding ._opLen [nid ] - 4 ;
284
+ String extern = enc ._externals .get (n );
285
+
286
+ Symbol sym = new Symbol (extern , 0 , SYM_BIND_GLOBAL , SYM_TYPE_NOTYPE );
287
+ sym ._index = start_global ++;
288
+ symbols .push (sym );
289
+
290
+ int offset = enc ._opStart [nid ] + enc ._opLen [nid ] - 4 ;
295
291
296
292
// u64 offset
297
293
write8 (text_rela ._contents , offset );
298
294
// u64 info
299
- write8 (text_rela ._contents , ((long )sym_id << 32L ) | 4L /* PLT32 */ );
295
+ write8 (text_rela ._contents , ((long )sym . _index << 32L ) | 4L /* PLT32 */ );
300
296
// i64 addend
301
297
write8 (text_rela ._contents , -4 );
302
298
}
303
- // relocations to constants
304
- if (false ) for (Map .Entry <Node ,SONType > e : _code ._encoding ._bigCons .entrySet ()) {
305
- int nid = e .getKey ()._nid ;
306
- int sym_id = _bigCons .get (e .getValue ())._index ;
307
- int offset = _code ._encoding ._opStart [nid ] + _code ._encoding ._opLen [nid ] - 4 ;
308
299
309
- // u64 offset
310
- write8 (text_rela ._contents , offset );
311
- // u64 info
312
- write8 (text_rela ._contents , ((long )sym_id << 32L ) | 1L /* PC32 */ );
313
- // i64 addend
300
+ // Write relocations for the constant pool
301
+ for ( Encoding .Relo relo : enc ._bigCons .values () ) {
302
+ Symbol glob = new Symbol ("GLOB$" +bigConIdx , rdata ._index , SYM_BIND_GLOBAL , SYM_TYPE_FUNC );
303
+ glob ._value = relo ._target ;
304
+ glob ._size = 1 << relo ._t .log_size ();
305
+ glob ._index = bigConIdx ++;
306
+ symbols .push (glob );
307
+ write8 (text_rela ._contents , relo ._opStart +relo ._off );
308
+ write8 (text_rela ._contents , ((long )glob ._index << 32L ) | relo ._elf );
314
309
write8 (text_rela ._contents , -4 );
315
310
}
311
+
316
312
text_rela ._flags = SHF_INFO_LINK ;
317
313
text_rela ._link = 2 ;
318
314
text_rela ._info = text ._index ;
319
315
pushSection (text_rela );
320
316
317
+ Symbol sym = new Symbol (text_rela ._name , num ++, SYM_BIND_LOCAL , SYM_TYPE_SECTION );
318
+ sym ._name_pos = text_rela ._name_pos ;
319
+ sym ._size = text_rela .size ();
320
+ symbols .push (sym );
321
+
321
322
// populate string table
322
323
for ( Section s : _sections ) { s ._name_pos = writeCString (strtab , s ._name ); }
323
324
for ( Symbol s : symbols ._symbols ) { s ._name_pos = writeCString (strtab , s ._name ); }
324
325
for ( Symbol s : symbols ._loc ) { s ._name_pos = writeCString (strtab , s ._name ); }
325
326
326
- int idx = 1 ;
327
- for ( Section s : _sections ) {
328
- Symbol sym = new Symbol (s ._name , idx ++, SYM_BIND_LOCAL , SYM_TYPE_SECTION );
329
- // we can reuse the same name pos from the actual section
330
- sym ._name_pos = s ._name_pos ;
331
- sym ._size = s .size ();
332
- symbols .push (sym );
333
- }
334
-
335
327
int size = 64 ; // ELF header
336
328
// size of all section data
337
329
for ( Section s : _sections ) {
@@ -379,7 +371,10 @@ public void export(String fname) throws IOException {
379
371
}
380
372
assert out .position () == size ;
381
373
382
- BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream (fname ));
374
+ File file = new File (fname );
375
+ if ( file .getParentFile ()!=null )
376
+ file .getParentFile ().mkdirs ();
377
+ BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream (file ));
383
378
bos .write (out .array ());
384
379
bos .close ();
385
380
}
0 commit comments