From 7a6849e19ab100e275d066d529cd88b07d6c623d Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 09:45:14 +0530 Subject: [PATCH 1/8] X86Assembler: Fix elf comment --- src/libasr/codegen/x86_assembler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libasr/codegen/x86_assembler.cpp b/src/libasr/codegen/x86_assembler.cpp index eadff7b7ba..45fb27acc5 100644 --- a/src/libasr/codegen/x86_assembler.cpp +++ b/src/libasr/codegen/x86_assembler.cpp @@ -282,7 +282,7 @@ void emit_print_float(X86Assembler &a, const std::string &name) { /************************* 64-bit functions **************************/ void emit_elf64_header(X86Assembler &a, uint32_t p_flags) { - /* Elf32_Ehdr */ + /* Elf64_Ehdr */ a.add_label("ehdr"); // e_ident a.asm_db_imm8(0x7F); @@ -320,7 +320,7 @@ void emit_elf64_header(X86Assembler &a, uint32_t p_flags) { a.add_var("ehdrsize", a.pos()-a.get_defined_symbol("ehdr").value); - /* Elf32_Phdr */ + /* Elf64_Phdr */ a.add_label("phdr"); a.asm_dd_imm32(1); // p_type a.asm_dd_imm32(p_flags); // p_flags From da045298924f72a2ba5d158ee904fd762136635b Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 09:58:16 +0530 Subject: [PATCH 2/8] WASM_X64: Support text and data segments --- src/libasr/codegen/wasm_to_x64.cpp | 14 ++++++--- src/libasr/codegen/x86_assembler.cpp | 44 +++++++++++++++++++++------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index 76074eff4c..50b3a7f305 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -589,6 +589,8 @@ class X64Visitor : public WASMDecoder, label_to_str["base_memory"] = base_memory; NO_OF_IMPORTS = imports.size(); + + m_a.add_label("text_segment_start"); for (uint32_t idx = 0; idx < type_indices.size(); idx++) { m_a.add_label(exports[idx + 1].name); { @@ -607,14 +609,17 @@ class X64Visitor : public WASMDecoder, } - for (auto &s : label_to_str) { - emit_data_string(m_a, s.first, s.second); - } - for (auto &d : double_consts) { emit_double_const(m_a, d.first, d.second); } + m_a.add_label("text_segment_end"); + + m_a.add_label("data_segment_start"); + for (auto &s : label_to_str) { + emit_data_string(m_a, s.first, s.second); + } + for (size_t i = 0; i < globals.size(); i++) { uint32_t tmp_offset = globals[i].insts_start_idx; wasm::read_b8(wasm_bytes, tmp_offset); // read byte for i32/i64/f32/f64.const @@ -644,6 +649,7 @@ class X64Visitor : public WASMDecoder, default: throw CodeGenError("decode_global_section: Unsupport global type"); break; } } + m_a.add_label("data_segment_end"); emit_elf64_footer(m_a); } diff --git a/src/libasr/codegen/x86_assembler.cpp b/src/libasr/codegen/x86_assembler.cpp index 45fb27acc5..cc35defd4a 100644 --- a/src/libasr/codegen/x86_assembler.cpp +++ b/src/libasr/codegen/x86_assembler.cpp @@ -313,30 +313,54 @@ void emit_elf64_header(X86Assembler &a, uint32_t p_flags) { a.asm_dd_imm32(0); // e_flags a.asm_dw_label("ehdrsize"); // e_ehsize a.asm_dw_label("phdrsize"); // e_phentsize - a.asm_dw_imm16(1); // e_phnum + a.asm_dw_imm16(3); // e_phnum a.asm_dw_imm16(0); // e_shentsize a.asm_dw_imm16(0); // e_shnum a.asm_dw_imm16(0); // e_shstrndx - a.add_var("ehdrsize", a.pos()-a.get_defined_symbol("ehdr").value); - /* Elf64_Phdr */ a.add_label("phdr"); - a.asm_dd_imm32(1); // p_type - a.asm_dd_imm32(p_flags); // p_flags + a.asm_dd_imm32(1); // p_type + a.asm_dd_imm32(4); // p_flags (permission to read only) a.asm_dq_imm64(0); // p_offset a.asm_dq_imm64(a.origin()); // p_vaddr a.asm_dq_imm64(a.origin()); // p_paddr - a.asm_dq_label("filesize"); // p_filesz - a.asm_dq_label("filesize"); // p_memsz + a.asm_dq_label("phdr_size"); // p_filesz + a.asm_dq_label("phdr_size"); // p_memsz a.asm_dq_imm64(0x1000); // p_align - a.add_var("phdrsize", a.pos()-a.get_defined_symbol("phdr").value); - a.add_var64("e_phoff", a.get_defined_symbol("phdr").value-a.origin()); + /* text_segment_phdr */ + a.add_label("text_phdr"); + a.asm_dd_imm32(1); // p_type + a.asm_dd_imm32(5); // p_flags (permission to read and execute) + a.asm_dq_label("text_segment_offset"); // p_offset + a.asm_dq_label("text_segment_start"); // p_vaddr + a.asm_dq_label("text_segment_start"); // p_paddr + a.asm_dq_label("text_segment_size"); // p_filesz + a.asm_dq_label("text_segment_size"); // p_memsz + a.asm_dq_imm64(0x1000); // p_align + + /* data_segment_phdr */ + a.add_label("data_phdr"); + a.asm_dd_imm32(1); // p_type + a.asm_dd_imm32(6); // p_flags (permission to read and write) + a.asm_dq_label("data_segment_offset"); // p_offset + a.asm_dq_label("data_segment_start"); // p_vaddr + a.asm_dq_label("data_segment_start"); // p_paddr + a.asm_dq_label("data_segment_size"); // p_filesz + a.asm_dq_label("data_segment_size"); // p_memsz + a.asm_dq_imm64(0x1000); // p_align } void emit_elf64_footer(X86Assembler &a) { - a.add_var_size("filesize"); + a.add_var("ehdrsize", "ehdr", "phdr"); + a.add_var("phdrsize", "phdr", "text_phdr"); + a.add_var64("e_phoff", "ehdr", "phdr"); + a.add_var64("phdr_size", "ehdr", "text_segment_start"); + a.add_var64("text_segment_offset", "ehdr", "text_segment_start"); + a.add_var64("text_segment_size", "text_segment_start", "text_segment_end"); + a.add_var64("data_segment_offset", "ehdr", "data_segment_start"); + a.add_var64("data_segment_size", "data_segment_start", "data_segment_end"); } void emit_exit_64(X86Assembler &a, std::string name, int exit_code) { From cd769ef5f1bd88b146bdbd43d745166ed44f51c4 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 10:01:03 +0530 Subject: [PATCH 3/8] X86Assembler: Update add_var() and add_var64() to use labels --- src/libasr/codegen/x86_assembler.cpp | 7 ++++--- src/libasr/codegen/x86_assembler.h | 12 +++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libasr/codegen/x86_assembler.cpp b/src/libasr/codegen/x86_assembler.cpp index cc35defd4a..38d080c1be 100644 --- a/src/libasr/codegen/x86_assembler.cpp +++ b/src/libasr/codegen/x86_assembler.cpp @@ -62,7 +62,6 @@ void emit_elf32_header(X86Assembler &a, uint32_t p_flags) { a.asm_dw_imm16(0); // e_shnum a.asm_dw_imm16(0); // e_shstrndx - a.add_var("ehdrsize", a.pos()-a.get_defined_symbol("ehdr").value); /* Elf32_Phdr */ a.add_label("phdr"); @@ -74,9 +73,11 @@ void emit_elf32_header(X86Assembler &a, uint32_t p_flags) { a.asm_dd_label("filesize"); // p_memsz a.asm_dd_imm32(p_flags); // p_flags a.asm_dd_imm32(0x1000); // p_align + a.add_label("phdr_end"); - a.add_var("phdrsize", a.pos()-a.get_defined_symbol("phdr").value); - a.add_var("e_phoff", a.get_defined_symbol("phdr").value-a.origin()); + a.add_var("ehdrsize", "ehdr", "phdr"); + a.add_var("phdrsize", "phdr", "phdr_end"); + a.add_var("e_phoff", "ehdr", "phdr"); } void emit_elf32_footer(X86Assembler &a) { diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 8cf73a4b09..658fbe089f 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -40,7 +40,7 @@ Old Link: https://www.systutorials.com/go/intel-x86-64-reference-manual/ #ifdef LFORTRAN_ASM_PRINT # define EMIT(s) emit(" ", s) # define EMIT_LABEL(s) emit("", s) -# define EMIT_VAR(a, b) emit("\n", a + " equ " + i2s(b) + "\n") +# define EMIT_VAR(a, b, c) emit(" ", a + " equ " + c + " - " + b) # define EMIT_VAR_SIZE(a) emit("\n", a + " equ $ - $$\n") // $ is current addr, $$ is start addr #else # define EMIT(s) @@ -555,15 +555,17 @@ class X86Assembler { EMIT_VAR_SIZE(var); } - void add_var64(const std::string &var, uint64_t val) { + void add_var64(const std::string &var, const std::string &start, const std::string &end) { // TODO: Support 64-bit or 8 byte parameter val in define_symbol() + uint64_t val = get_defined_symbol(end).value - get_defined_symbol(start).value; define_symbol(var, val); - EMIT_VAR(var, val); + EMIT_VAR(var, start, end); } - void add_var(const std::string &var, uint32_t val) { + void add_var(const std::string &var, const std::string &start, const std::string &end) { + uint32_t val = get_defined_symbol(end).value - get_defined_symbol(start).value; define_symbol(var, val); - EMIT_VAR(var, val); + EMIT_VAR(var, start, end); } uint32_t pos() { From 7e48c492e7181224b3469ce863efbc2f993e3b67 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 10:05:40 +0530 Subject: [PATCH 4/8] WASM_X64: Align segments by alignment byte --- src/libasr/codegen/wasm_to_x64.cpp | 2 ++ src/libasr/codegen/x86_assembler.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index 50b3a7f305..d58eae0301 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -590,6 +590,7 @@ class X64Visitor : public WASMDecoder, NO_OF_IMPORTS = imports.size(); + m_a.align_by_byte(0x1000); m_a.add_label("text_segment_start"); for (uint32_t idx = 0; idx < type_indices.size(); idx++) { m_a.add_label(exports[idx + 1].name); @@ -615,6 +616,7 @@ class X64Visitor : public WASMDecoder, m_a.add_label("text_segment_end"); + m_a.align_by_byte(0x1000); m_a.add_label("data_segment_start"); for (auto &s : label_to_str) { emit_data_string(m_a, s.first, s.second); diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 658fbe089f..3f713c6c36 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -30,6 +30,7 @@ Old Link: https://www.systutorials.com/go/intel-x86-64-reference-manual/ #include #include #include +#include #include #include @@ -465,6 +466,15 @@ class X86Assembler { return m_code; } + void align_by_byte(uint64_t alignment) { + uint64_t code_size = m_code.size() ; + uint64_t padding_size = (alignment * ceil(code_size / (double)alignment)) - code_size; + for (size_t i = 0; i < padding_size; i++) { + m_code.push_back(m_al, 0); + } + EMIT("times " + std::to_string(padding_size) + " db 0"); + } + void define_symbol(const std::string &name, uint32_t value) { if (m_symbols.find(name) == m_symbols.end()) { Symbol s; From aa6c67f4fde12a3174a26961be58c2fdb1d66775 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 10:12:04 +0530 Subject: [PATCH 5/8] WASM_X64: Remove use of add_var_size() --- src/libasr/codegen/x86_assembler.cpp | 3 ++- src/libasr/codegen/x86_assembler.h | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/libasr/codegen/x86_assembler.cpp b/src/libasr/codegen/x86_assembler.cpp index 38d080c1be..0ae4a356fc 100644 --- a/src/libasr/codegen/x86_assembler.cpp +++ b/src/libasr/codegen/x86_assembler.cpp @@ -81,7 +81,8 @@ void emit_elf32_header(X86Assembler &a, uint32_t p_flags) { } void emit_elf32_footer(X86Assembler &a) { - a.add_var_size("filesize"); + a.add_label("footer"); + a.add_var("filesize", "ehdr", "footer"); } void emit_exit(X86Assembler &a, const std::string &name, diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 3f713c6c36..7007c356ac 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -42,12 +42,10 @@ Old Link: https://www.systutorials.com/go/intel-x86-64-reference-manual/ # define EMIT(s) emit(" ", s) # define EMIT_LABEL(s) emit("", s) # define EMIT_VAR(a, b, c) emit(" ", a + " equ " + c + " - " + b) -# define EMIT_VAR_SIZE(a) emit("\n", a + " equ $ - $$\n") // $ is current addr, $$ is start addr #else # define EMIT(s) # define EMIT_LABEL(s) # define EMIT_VAR(a, b) -# define EMIT_VAR_SIZE(a) #endif namespace LCompilers { @@ -558,13 +556,6 @@ class X86Assembler { EMIT_LABEL(label + ":"); } - void add_var_size(const std::string &var) { - uint64_t val = pos() - origin(); - // TODO: Support 64-bit or 8 byte parameter val in define_symbol() - define_symbol(var, val); - EMIT_VAR_SIZE(var); - } - void add_var64(const std::string &var, const std::string &start, const std::string &end) { // TODO: Support 64-bit or 8 byte parameter val in define_symbol() uint64_t val = get_defined_symbol(end).value - get_defined_symbol(start).value; From ba1da0f5103e4ce438355a7e816b3363f1460f16 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Thu, 23 Mar 2023 10:14:42 +0530 Subject: [PATCH 6/8] X86Assembler: Remove unused parameter --- src/libasr/codegen/wasm_to_x64.cpp | 2 +- src/libasr/codegen/x86_assembler.cpp | 2 +- src/libasr/codegen/x86_assembler.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index d58eae0301..dd5fb4711b 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -579,7 +579,7 @@ class X64Visitor : public WASMDecoder, void visit_F32Sqrt() { visit_F64Sqrt(); } void gen_x64_bytes() { - emit_elf64_header(m_a, 7U); + emit_elf64_header(m_a); // declare compile-time strings std::string base_memory = " "; /* in wasm backend, memory starts after 4 bytes*/ diff --git a/src/libasr/codegen/x86_assembler.cpp b/src/libasr/codegen/x86_assembler.cpp index 0ae4a356fc..600239d2d8 100644 --- a/src/libasr/codegen/x86_assembler.cpp +++ b/src/libasr/codegen/x86_assembler.cpp @@ -283,7 +283,7 @@ void emit_print_float(X86Assembler &a, const std::string &name) { /************************* 64-bit functions **************************/ -void emit_elf64_header(X86Assembler &a, uint32_t p_flags) { +void emit_elf64_header(X86Assembler &a) { /* Elf64_Ehdr */ a.add_label("ehdr"); // e_ident diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 7007c356ac..c6d2fdb53c 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -1542,7 +1542,7 @@ void emit_print_float(X86Assembler &a, const std::string &name); // Generate an ELF 64 bit header and footer // With these two functions, one only must generate a `_start` assembly // function to have a working binary on Linux. -void emit_elf64_header(X86Assembler &a, uint32_t p_flags=5); +void emit_elf64_header(X86Assembler &a); void emit_elf64_footer(X86Assembler &a); void emit_exit_64(X86Assembler &a, std::string label, int exit_code); From 7357202656efbd4d5333b08056e23243f99656f3 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Fri, 24 Mar 2023 11:18:07 +0530 Subject: [PATCH 7/8] X86Assembler: Use align macro for assembly text format --- src/libasr/codegen/x86_assembler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index c6d2fdb53c..8f21f3a7f2 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -470,7 +470,7 @@ class X86Assembler { for (size_t i = 0; i < padding_size; i++) { m_code.push_back(m_al, 0); } - EMIT("times " + std::to_string(padding_size) + " db 0"); + EMIT("\n\talign " + std::to_string(alignment) + ", db 0"); } void define_symbol(const std::string &name, uint32_t value) { From 1b62e6b04ac3c11a08107ff5248b561184c5f60e Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Fri, 24 Mar 2023 11:43:25 +0530 Subject: [PATCH 8/8] CTEST: Update reference test for x86 asm --- src/lpython/tests/test_asm.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/lpython/tests/test_asm.cpp b/src/lpython/tests/test_asm.cpp index a65010f256..1f1b5601dd 100644 --- a/src/lpython/tests/test_asm.cpp +++ b/src/lpython/tests/test_asm.cpp @@ -403,9 +403,6 @@ BITS 32 dw 0x0000 dw 0x0000 dw 0x0000 - -ehdrsize equ 0x00000034 - phdr: dd 0x00000001 dd 0x00000000 @@ -415,12 +412,10 @@ ehdrsize equ 0x00000034 dd filesize dd 0x00000005 dd 0x00001000 - -phdrsize equ 0x00000020 - - -e_phoff equ 0x00000034 - +phdr_end: + ehdrsize equ phdr - ehdr + phdrsize equ phdr_end - phdr + e_phoff equ phdr - ehdr msg: db 0x48 db 0x65 @@ -446,9 +441,8 @@ e_phoff equ 0x00000034 mov eax, 0x00000001 mov ebx, 0x00000000 int 0x80 - -filesize equ $ - $$ - +footer: + filesize equ footer - ehdr )"""); CHECK(asm_code == ref); #endif