@@ -611,6 +611,158 @@ func (e *Emitter) generateTextSegment() []byte {
611611 }
612612 code = append (code , readStrHelper ... )
613613
614+ // Append net_listen helper
615+ labelPCs ["net_listen" ] = len (code )
616+ netListenHelperParts := [][]byte {
617+ /* 0: entry & socket call */
618+ {0x50 }, // push rax (save port)
619+ {0x48 , 0xc7 , 0xc7 , 0x02 , 0x00 , 0x00 , 0x00 }, // mov rdi, 2 (AF_INET)
620+ {0x48 , 0xc7 , 0xc6 , 0x01 , 0x00 , 0x00 , 0x00 }, // mov rsi, 1 (SOCK_STREAM)
621+ {0x48 , 0xc7 , 0xc2 , 0x00 , 0x00 , 0x00 , 0x00 }, // mov rdx, 0 (IPPROTO_IP)
622+ {0x48 , 0xc7 , 0xc0 , 0x29 , 0x00 , 0x00 , 0x00 }, // mov rax, 41 (sys_socket)
623+ {0x0f , 0x05 }, // syscall
624+ {0x48 , 0x85 , 0xc0 }, // test rax, rax
625+ {0x78 , 0x00 }, // js socket_error (placeholder offset at idx 7)
626+
627+ /* 8: bind preparation */
628+ {0x50 }, // push rax (save socket fd)
629+ {0x48 , 0x8b , 0x44 , 0x24 , 0x08 }, // mov rax, [rsp + 8] (get port)
630+ {0x66 , 0xc1 , 0xc0 , 0x08 }, // rol ax, 8
631+ {0x48 , 0xc1 , 0xe0 , 0x10 }, // shl rax, 16
632+ {0x48 , 0x83 , 0xc8 , 0x02 }, // or rax, 2
633+ {0x48 , 0x31 , 0xd2 }, // xor rdx, rdx
634+ {0x52 }, // push rdx (sin_zero)
635+ {0x50 }, // push rax (family, port, addr)
636+
637+ /* 16: bind call */
638+ {0x48 , 0x8b , 0x7c , 0x24 , 0x10 }, // mov rdi, [rsp + 16] (socket fd)
639+ {0x48 , 0x89 , 0xe6 }, // mov rsi, rsp
640+ {0x48 , 0xc7 , 0xc2 , 0x10 , 0x00 , 0x00 , 0x00 }, // mov rdx, 16
641+ {0x48 , 0xc7 , 0xc0 , 0x31 , 0x00 , 0x00 , 0x00 }, // mov rax, 49 (sys_bind)
642+ {0x0f , 0x05 }, // syscall
643+ {0x48 , 0x85 , 0xc0 }, // test rax, rax
644+ {0x78 , 0x00 }, // js bind_error (placeholder offset at idx 22)
645+
646+ /* 23: listen preparation */
647+ {0x48 , 0x83 , 0xc4 , 0x10 }, // add rsp, 16
648+ {0x48 , 0x8b , 0x3c , 0x24 }, // mov rdi, [rsp]
649+ {0x48 , 0xc7 , 0xc6 , 0x80 , 0x00 , 0x00 , 0x00 }, // mov rsi, 128
650+ {0x48 , 0xc7 , 0xc0 , 0x32 , 0x00 , 0x00 , 0x00 }, // mov rax, 50 (sys_listen)
651+ {0x0f , 0x05 }, // syscall
652+ {0x48 , 0x85 , 0xc0 }, // test rax, rax
653+ {0x78 , 0x00 }, // js listen_error (placeholder offset at idx 29)
654+
655+ /* 30: listen success */
656+ {0x58 }, // pop rax (return fd)
657+ {0x5e }, // pop rsi (clean port)
658+ {0xc3 }, // ret
659+
660+ /* 33: bind_error block */
661+ {0x48 , 0x83 , 0xc4 , 0x10 }, // add rsp, 16 (bind_error target)
662+
663+ /* 34: listen_error block */
664+ {0x5f }, // pop rdi (listen_error target)
665+ {0x5e }, // pop rsi
666+ {0x57 }, // push rdi
667+ {0x48 , 0xc7 , 0xc0 , 0x03 , 0x00 , 0x00 , 0x00 }, // mov rax, 3
668+ {0x0f , 0x05 }, // syscall
669+ {0x58 }, // pop rax
670+ {0x48 , 0xc7 , 0xc0 , 0xff , 0xff , 0xff , 0xff }, // mov rax, -1
671+ {0xc3 }, // ret
672+
673+ /* 42: socket_error block */
674+ {0x5e }, // pop rsi (socket_error target)
675+ {0x48 , 0xc7 , 0xc0 , 0xff , 0xff , 0xff , 0xff }, // mov rax, -1
676+ {0xc3 }, // ret
677+ }
678+ listenOffsets := make ([]int , len (netListenHelperParts ))
679+ currentListenOffset := 0
680+ for i , part := range netListenHelperParts {
681+ listenOffsets [i ] = currentListenOffset
682+ currentListenOffset += len (part )
683+ }
684+ netListenHelperParts [7 ][1 ] = byte (listenOffsets [42 ] - listenOffsets [8 ])
685+ netListenHelperParts [22 ][1 ] = byte (listenOffsets [33 ] - listenOffsets [23 ])
686+ netListenHelperParts [29 ][1 ] = byte (listenOffsets [34 ] - listenOffsets [30 ])
687+ for _ , part := range netListenHelperParts {
688+ code = append (code , part ... )
689+ }
690+
691+ // Append net_accept helper
692+ labelPCs ["net_accept" ] = len (code )
693+ netAcceptHelper := []byte {
694+ 0x48 , 0x89 , 0xc7 , // mov rdi, rax
695+ 0x48 , 0x31 , 0xf6 , // xor rsi, rsi
696+ 0x48 , 0x31 , 0xd2 , // xor rdx, rdx
697+ 0x48 , 0xc7 , 0xc0 , 0x2b , 0x00 , 0x00 , 0x00 , // mov rax, 43 (sys_accept)
698+ 0x0f , 0x05 , // syscall
699+ 0xc3 , // ret
700+ }
701+ code = append (code , netAcceptHelper ... )
702+
703+ // Append net_read helper
704+ labelPCs ["net_read" ] = len (code )
705+ netReadStart := len (code )
706+ netReadHelperParts := [][]byte {
707+ /* 0: read syscall */
708+ {0x48 , 0x89 , 0xc7 }, // mov rdi, rax
709+ {0x48 , 0x8d , 0x35 , 0x00 , 0x00 , 0x00 , 0x00 }, // lea rsi, [rip + __net_buf] (placeholder)
710+ {0x48 , 0xc7 , 0xc2 , 0x00 , 0x10 , 0x00 , 0x00 }, // mov rdx, 4096
711+ {0x48 , 0xc7 , 0xc0 , 0x00 , 0x00 , 0x00 , 0x00 }, // mov rax, 0
712+ {0x0f , 0x05 }, // syscall
713+ {0x48 , 0x85 , 0xc0 }, // test rax, rax
714+ {0x7e , 0x00 }, // jle net_read_empty (placeholder offset at idx 6)
715+
716+ /* 7: success path */
717+ {0xc6 , 0x04 , 0x06 , 0x00 }, // mov byte ptr [rsi + rax], 0
718+ {0x48 , 0x89 , 0xf0 }, // mov rax, rsi
719+ {0xc3 }, // ret
720+
721+ /* 10: empty path */
722+ {0x48 , 0x8d , 0x05 , 0x00 , 0x00 , 0x00 , 0x00 }, // lea rax, [rip + __empty_str] (placeholder)
723+ {0xc3 }, // ret
724+ }
725+ readOffsets := make ([]int , len (netReadHelperParts ))
726+ currentReadOffset := 0
727+ for i , part := range netReadHelperParts {
728+ readOffsets [i ] = currentReadOffset
729+ currentReadOffset += len (part )
730+ }
731+ netReadHelperParts [6 ][1 ] = byte (readOffsets [10 ] - readOffsets [7 ])
732+ for _ , part := range netReadHelperParts {
733+ code = append (code , part ... )
734+ }
735+
736+ // Append net_write helper
737+ labelPCs ["net_write" ] = len (code )
738+ netWriteHelper := []byte {
739+ 0x57 , // push rdi
740+ 0x56 , // push rsi
741+ 0x48 , 0x31 , 0xd2 , // xor rdx, rdx
742+ // net_write_len_loop:
743+ 0x80 , 0x3c , 0x16 , 0x00 , // cmp byte ptr [rsi + rdx], 0
744+ 0x74 , 0x05 , // je net_write_len_done
745+ 0x48 , 0xff , 0xc2 , // inc rdx
746+ 0xeb , 0xf5 , // jmp net_write_len_loop
747+ // net_write_len_done:
748+ 0x5e , // pop rsi
749+ 0x5f , // pop rdi
750+ 0x48 , 0xc7 , 0xc0 , 0x01 , 0x00 , 0x00 , 0x00 , // mov rax, 1 (sys_write)
751+ 0x0f , 0x05 , // syscall
752+ 0xc3 , // ret
753+ }
754+ code = append (code , netWriteHelper ... )
755+
756+ // Append net_close helper
757+ labelPCs ["net_close" ] = len (code )
758+ netCloseHelper := []byte {
759+ 0x48 , 0x89 , 0xc7 , // mov rdi, rax
760+ 0x48 , 0xc7 , 0xc0 , 0x03 , 0x00 , 0x00 , 0x00 , // mov rax, 3 (sys_close)
761+ 0x0f , 0x05 , // syscall
762+ 0xc3 , // ret
763+ }
764+ code = append (code , netCloseHelper ... )
765+
614766 // Append static data buffers
615767 emptyStrPC := len (code )
616768 code = append (code , 0x00 )
@@ -623,6 +775,10 @@ func (e *Emitter) generateTextSegment() []byte {
623775 readFileBufBytes := make ([]byte , 65536 )
624776 code = append (code , readFileBufBytes ... )
625777
778+ netBufPC := len (code )
779+ netBufBytes := make ([]byte , 4096 )
780+ code = append (code , netBufBytes ... )
781+
626782 // Relocate readFileHelper placeholders
627783 binary .LittleEndian .PutUint32 (code [readFileStart + 34 :readFileStart + 38 ], uint32 (readFileBufPC - (readFileStart + 38 )))
628784 binary .LittleEndian .PutUint32 (code [readFileStart + 65 :readFileStart + 69 ], uint32 (readFileBufPC - (readFileStart + 69 )))
@@ -635,6 +791,12 @@ func (e *Emitter) generateTextSegment() []byte {
635791 binary .LittleEndian .PutUint32 (code [readStrStart + 82 :readStrStart + 86 ], uint32 (inputBufPC - (readStrStart + 86 )))
636792 binary .LittleEndian .PutUint32 (code [readStrStart + 90 :readStrStart + 94 ], uint32 (emptyStrPC - (readStrStart + 94 )))
637793
794+ // Relocate net_read placeholders
795+ // lea rsi, [rip + __net_buf] at netReadStart + readOffsets[1]
796+ binary .LittleEndian .PutUint32 (code [netReadStart + readOffsets [1 ]+ 3 :netReadStart + readOffsets [1 ]+ 7 ], uint32 (netBufPC - (netReadStart + readOffsets [2 ])))
797+ // lea rax, [rip + __empty_str] at netReadStart + readOffsets[10]
798+ binary .LittleEndian .PutUint32 (code [netReadStart + readOffsets [10 ]+ 3 :netReadStart + readOffsets [10 ]+ 7 ], uint32 (emptyStrPC - (netReadStart + readOffsets [11 ])))
799+
638800 // Pass 2: label offsets resolution
639801 for _ , ref := range refs {
640802 targetPC , ok := labelPCs [ref .targetLabel ]
0 commit comments