4
4
module native
5
5
6
6
import os
7
+ import ast
7
8
8
9
const elf_class32 = 1
9
10
const elf_class64 = 2
300
301
size i64 // Symbol size.
301
302
}
302
303
304
+ // see for more details: https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779
305
+ // https://www.etherington.xyz/elfguide#symtab-section-entries
303
306
fn (mut g Gen) create_symbol_table_section (str_name string , info u8 , bind u8 , other i8 , value i64 , size i64 ,
304
307
shndx i16 ) SymbolTableSection {
305
308
return SymbolTableSection{
@@ -615,7 +618,6 @@ fn (mut g Gen) gen_section_data(sections []Section) {
615
618
for rela in data {
616
619
g.write64 (rela.offset)
617
620
g.fn_addr[rela.name] = rela.offset // that's wierd it's the call offset, not the fn
618
- g.fn_names << rela.name
619
621
g.write64 (rela.info)
620
622
g.write64 (rela.addend)
621
623
g.println ('; SHT_RELA `${rela.name} ` (${rela.offset} , ${rela.info} , ${rela.addend} )' )
@@ -711,6 +713,23 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
711
713
elf_stv_default, 0 , 0 , 0 ),
712
714
]
713
715
716
+ mut sym_data_offset := 0 // offset from the beggining of the data section
717
+ for f in g.files {
718
+ for s in f.stmts {
719
+ if s is ast.GlobalDecl {
720
+ for fi in s.fields {
721
+ size := g.get_type_size (fi.typ)
722
+ if size > 0 {
723
+ g.symbol_table << g.create_symbol_table_section (fi.name, elf_stt_object,
724
+ elf_stb_global, elf_stv_default, sym_data_offset, size, i16 (g.find_section_header ('.data' ,
725
+ sections)))
726
+ }
727
+ sym_data_offset + = size
728
+ }
729
+ }
730
+ }
731
+ }
732
+
714
733
for symbol in g.extern_symbols {
715
734
g.symbol_table << g.create_symbol_table_section (symbol[2 ..], elf_stt_notype, elf_stb_global,
716
735
elf_stv_default, 0 , 0 , 0 )
@@ -742,6 +761,37 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
742
761
743
762
g.elf_rela_section = sections[g.find_section_header ('.rela.text' , sections)]
744
763
764
+ // Init data section
765
+ // TODO: use .bss for uninitialized data or generate the data
766
+ data_section := sections[g.find_section_header ('.data' , sections)]
767
+ g.elf_data_header_addr = data_section.header.offset
768
+
769
+ data_pos := g.pos ()
770
+ g.println ('\n data_start_pos = ${data_pos.hex()} ' )
771
+ g.write64_at (g.elf_data_header_addr + 24 , data_pos)
772
+ for f in g.files {
773
+ for s in f.stmts {
774
+ if s is ast.GlobalDecl {
775
+ for fi in s.fields {
776
+ size := g.get_type_size (fi.typ)
777
+ match size {
778
+ 1 { g.write8 (0xF ) }
779
+ 2 { g.write16 (0xF ) }
780
+ 4 { g.write32 (0xF ) }
781
+ 8 { g.write64 (i64 (0xF )) }
782
+ else { println ('${@LOCATION} unsupported size ${size} for global ${fi} ' ) }
783
+ }
784
+ g.println ('; global ${fi.name} , size: ${size} ' )
785
+ }
786
+ }
787
+ }
788
+ }
789
+ g.write64_at (g.elf_data_header_addr + 32 , g.pos () - data_pos)
790
+ // TODO: pre-calculate .data instead of genetating it at runtime
791
+
792
+ // It is wierd, the init section has something in it but I did not find
793
+ // where does it come from
794
+
745
795
// user code starts here
746
796
if g.pref.is_verbose {
747
797
eprintln ('code_start_pos = ${g.buf.len.hex()} ' )
@@ -752,11 +802,29 @@ pub fn (mut g Gen) generate_linkable_elf_header() {
752
802
// if g.start_symbol_addr > 0 {
753
803
// g.write64_at(g.start_symbol_addr + native.elf_symtab_size - 16, g.code_start_pos)
754
804
// }
755
-
756
805
text_section := sections[g.find_section_header ('.text' , sections)]
757
806
g.elf_text_header_addr = text_section.header.offset
758
807
g.write64_at (g.elf_text_header_addr + 24 , g.pos ()) // write the code start pos to the text section
759
808
809
+ g.println ('; fill .data' )
810
+ for f in g.files {
811
+ for s in f.stmts {
812
+ if s is ast.GlobalDecl {
813
+ for fi in s.fields {
814
+ size := g.get_type_size (fi.typ)
815
+ if size > 8 || size < = 0 {
816
+ println ('${@LOCATION} unsupported size ${size} for global ${fi} ' )
817
+ } else if fi.expr ! is ast.EmptyExpr {
818
+ g.expr (fi.expr)
819
+ g.code_gen.mov_reg_to_var (GlobalVar{fi.name, fi.typ}, g.code_gen.main_reg ())
820
+ g.println ('; global ${fi.name} , size: ${size} ' )
821
+ }
822
+ }
823
+ }
824
+ }
825
+ }
826
+
827
+ g.elf_main_call_pos = g.pos ()
760
828
g.code_gen.call (placeholder)
761
829
g.println ('; call main.main' )
762
830
g.code_gen.mov64 (g.code_gen.main_reg (), i64 (0 ))
@@ -848,9 +916,13 @@ pub fn (mut g Gen) gen_rela_section() {
848
916
g.symtab_get_index (g.symbol_table, symbol[2 ..]), elf_r_amd64_ gotpcrelx, - 4 )
849
917
}
850
918
for var_pos, symbol in g.extern_vars {
851
- relocations << g.create_rela_section (symbol, var_pos - g.code_start_pos + 2 , g.symtab_get_index (g.symbol_table,
919
+ relocations << g.create_rela_section (symbol, var_pos - g.code_start_pos, g.symtab_get_index (g.symbol_table,
852
920
symbol[2 ..]), elf_r_amd64_64 , 0 )
853
921
}
922
+ for var_pos, symbol in g.global_vars {
923
+ relocations << g.create_rela_section (symbol, var_pos - g.code_start_pos, g.symtab_get_index (g.symbol_table,
924
+ symbol), elf_r_amd64_64 , 0 )
925
+ }
854
926
g.elf_rela_section.data = relocations
855
927
g.gen_section_data ([g.elf_rela_section])
856
928
}
@@ -872,15 +944,15 @@ pub fn (mut g Gen) generate_elf_footer() {
872
944
g.write64_at (g.file_size_pos + 8 , file_size)
873
945
if g.pref.arch == .arm64 {
874
946
bl_next := u32 (0x94000001 )
875
- g.write32_at (g.code_start_pos , i32 (bl_next))
947
+ g.write32_at (g.elf_main_call_pos , i32 (bl_next))
876
948
} else {
877
949
// amd64
878
950
// call main function, it's not guaranteed to be the first
879
951
// we generated call(0) ("e8 0")
880
952
// now need to replace "0" with a relative address of the main function
881
953
// +1 is for "e8"
882
954
// -5 is for "e8 00 00 00 00"
883
- g.write32_at (g.code_start_pos + 1 , i32 (g.main_fn_addr - g.code_start_pos ) - 5 )
955
+ g.write32_at (g.elf_main_call_pos + 1 , i32 (g.main_fn_addr - g.elf_main_call_pos ) - 5 )
884
956
}
885
957
g.create_executable ()
886
958
}
0 commit comments