44import com .compilerprogramming .ezlang .compiler .nodes .*;
55import com .compilerprogramming .ezlang .compiler .sontypes .*;
66
7- import java .util . Map ;
8- import java . util . HashMap ;
7+ import java .io .* ;
8+
99import java .nio .ByteBuffer ;
1010import 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 ;
1513
1614public class ElfFile {
1715
@@ -69,6 +67,10 @@ public static class Symbol {
6967 // top 4bits are the "bind", bottom 4 are "type"
7068 int _info ;
7169
70+ // bind 1011
71+ // 00001111
72+ // 10110000
73+
7274 Symbol (String name , int parent , int bind , int type ) {
7375 _name = name ;
7476 _parent = parent ;
@@ -78,6 +80,7 @@ public static class Symbol {
7880 void writeHeader (ByteBuffer out ) {
7981 out .putInt (_name_pos ); // name
8082 out .put ((byte ) _info ); // info
83+ // default visibility
8184 out .put ((byte ) 0 ); // other
8285 out .putShort ((short ) _parent ); // shndx
8386 out .putLong (_value ); // value
@@ -117,7 +120,7 @@ void writeHeader(ByteBuffer out) {
117120 out .putLong (size ()); // size
118121 out .putInt (_link ); // link
119122 out .putInt (_info ); // info
120- out .putLong (1 ); // addralign
123+ out .putLong (16 ); // addralign
121124 if (_type == 2 ) {
122125 out .putLong (SYMBOL_SIZE );// entsize
123126 } else if (_type == 4 ) {
@@ -140,7 +143,7 @@ public static class SymbolSection extends Section {
140143 }
141144
142145 @ Override
143- void writeHeader (ByteBuffer out ) {
146+ void writeHeader (ByteBuffer out ) {
144147 // points to string table section
145148 _link = 1 ;
146149
@@ -159,23 +162,22 @@ void push(Symbol s) {
159162 }
160163
161164 @ 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
163167 for ( int i = 0 ; i < SYMBOL_SIZE /4 ; i ++ ) {
164168 out .putInt (0 );
165169 }
166- int num = 1 ;
170+ // index is already set
167171 for ( Symbol s : _loc ) {
168- s ._index = num ++;
169172 s .writeHeader (out );
170173 }
171174 for ( Symbol s : _symbols ) {
172- s ._index = num ++;
173175 s .writeHeader (out );
174176 }
175177 }
176178
177179 @ Override
178- int size () {
180+ int size () {
179181 return (1 + _symbols .len () + _loc .len ()) * SYMBOL_SIZE ;
180182 }
181183 }
@@ -210,54 +212,21 @@ private void pushSection(Section s) {
210212 s ._index = _sections ._len ;
211213 }
212214
215+ /* creates function and stores where it starts*/
213216 private final HashMap <SONTypeFunPtr ,Symbol > _funcs = new HashMap <>();
214217 private void encodeFunctions (SymbolSection symbols , DataSection text ) {
215- int func_start = 0 ;
216218 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 );
261230 }
262231 }
263232
@@ -271,67 +240,90 @@ public void export(String fname) throws IOException {
271240 SymbolSection symbols = new SymbolSection (".symtab" , 2 /* SHT_STRTAB */ );
272241 pushSection (symbols );
273242
243+ // zero flag by default
274244 // we've already constructed this entire section in the encoding phase
275245 DataSection text = new DataSection (".text" , 1 /* SHT_PROGBITS */ , _code ._encoding ._bits );
276246 text ._flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR ;
277247 pushSection (text );
278248
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 );
280254 rdata ._flags = SHF_ALLOC ;
281255 pushSection (rdata );
282256
283257 // populate function symbols
284258 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 ();
287279
288280 // create .text relocations
289281 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 ()) {
291283 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 ;
295291
296292 // u64 offset
297293 write8 (text_rela ._contents , offset );
298294 // u64 info
299- write8 (text_rela ._contents , ((long )sym_id << 32L ) | 4L /* PLT32 */ );
295+ write8 (text_rela ._contents , ((long )sym . _index << 32L ) | 4L /* PLT32 */ );
300296 // i64 addend
301297 write8 (text_rela ._contents , -4 );
302298 }
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 ;
308299
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 );
314309 write8 (text_rela ._contents , -4 );
315310 }
311+
316312 text_rela ._flags = SHF_INFO_LINK ;
317313 text_rela ._link = 2 ;
318314 text_rela ._info = text ._index ;
319315 pushSection (text_rela );
320316
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+
321322 // populate string table
322323 for ( Section s : _sections ) { s ._name_pos = writeCString (strtab , s ._name ); }
323324 for ( Symbol s : symbols ._symbols ) { s ._name_pos = writeCString (strtab , s ._name ); }
324325 for ( Symbol s : symbols ._loc ) { s ._name_pos = writeCString (strtab , s ._name ); }
325326
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-
335327 int size = 64 ; // ELF header
336328 // size of all section data
337329 for ( Section s : _sections ) {
@@ -379,7 +371,10 @@ public void export(String fname) throws IOException {
379371 }
380372 assert out .position () == size ;
381373
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 ));
383378 bos .write (out .array ());
384379 bos .close ();
385380 }
0 commit comments