Skip to content

Commit

Permalink
More info/demo on environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
xarantolus committed Jan 7, 2023
1 parent 5e53cca commit c771963
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 24 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ let ax = Axecutor.from_binary(/* elf file content as Uint8Array */);
// and writes the stack pointer to RSP
ax.init_stack_program_start(
8n * 1024n, // Stack size
["/bin/my_binary", "arg1", "arg2"],
[ /* environment variables */ ]
["/bin/my_binary", "arg1", "arg2"], // argv
["COLORTERM=truecolor", "TERM=xterm-256color" ] // environment variables
);


Expand Down
64 changes: 51 additions & 13 deletions examples/programs/args/args.S
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
.intel_syntax noprefix

.section .rodata
.Largv: .asciz "argv values:\n"
.Largv_len: .quad 13
.Largv: .ascii "--------------------------------------------------\nargv values:\n--------------------------------------------------\n"
.Largv_len: .quad .Largv_len - .Largv

.Lenvp: .ascii "--------------------------------------------------\nenvp values:\n--------------------------------------------------\n"
.Lenvp_len: .quad .Lenvp_len - .Lenvp

.Lnewline: .asciz "\n"
.Lnewline_len: .quad 1
Expand Down Expand Up @@ -30,17 +33,7 @@ _start:
je .Lend_argv

pop rsi # pointer to string, argv[i]
# strlen:
xor rax, rax
push rbx
.Lstrlen_loop:
mov bl, [rsi+rax]
cmp bl, 0
je .Lstrlen_end
inc rax
jmp .Lstrlen_loop
.Lstrlen_end:
pop rbx
call strlen

mov rdx, rax # number of bytes to write
mov rax, 1 # write system call
Expand All @@ -53,6 +46,37 @@ _start:
JMP .Lstart_argv

.Lend_argv:

# after argv values, we have 8 zero bytes on the stack
pop rsi

# now we can write "envp values:\n"
mov rax, 1 # write system call
mov rdi, 1 # Stdout
lea rsi, [rip+.Lenvp] # pointer to string, argv[i]
mov rdx, [rip+.Lenvp_len] # Number of bytes to write
syscall

# envp, just like argv, is a null-terminated array of string pointers
# unlike argv, we don't have a count, so we just iterate until we find null
.Lstart_envp:
pop rsi # pointer to string, envp[i]
cmp rsi, 0
je .Lend_envp

call strlen

mov rdx, rax # number of bytes to write
mov rax, 1 # write system call
mov rdi, 1 # Stdout
# rsi already points to envp[i]
syscall

call newline

JMP .Lstart_envp
.Lend_envp:

mov rdi, Vargc
mov rax, 0x3c
syscall
Expand Down Expand Up @@ -80,3 +104,17 @@ newline:
pop rax

ret

# strlen(char *rsi) -> rax
strlen:
xor rax, rax
push rbx
.Lstrlen_loop:
mov bl, [rsi+rax]
cmp bl, 0
je .Lstrlen_end
inc rax
jmp .Lstrlen_loop
.Lstrlen_end:
pop rbx
ret
30 changes: 21 additions & 9 deletions examples/web/src/components/Demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@
<br />
<p>
Please select an ELF binary compiled with <code>-m64 -nostdlib -static</code> that only interacts with std{in,out,err}.
Some binaries (especially the ones that use libc) will not work due to the ELF loader being very basic right now.
Some binaries, especially the ones that use libc, might not work.
</p>
<div>
<input type="file" ref="file">
<button @click="runFile">Run!</button>
</div>
<br />
<div v-if="programs.length > 0">
You can also load one of the following binaries:
Click to load one of the following binaries:
<ul>
<li v-for="program in programs" :key="program.name">
<a :href="'/programs/' + program.binary" @click.prevent="setBinary(program.binary)">{{ program.name }}</a> (<a :href="program_source_prefix + program.source_name" target="_blank">Source</a>)
<a :href="'/programs/' + program.binary" @click.prevent="setBinary(program.binary)">{{ program.name }}</a>: {{ program.description }} (<a :href="program_source_prefix + program.source_name" target="_blank">Source</a>)
</li>
</ul>
<br />
You can also download these binaries and run them on Linux. This of course shows that the emulator can run some real binaries without any modifications.
</div>
<br />
Expand Down Expand Up @@ -58,40 +59,47 @@ export default defineComponent({
};
const programs = [
{
name: "Exit Code",
binary: "exit_code.bin",
source_name: "exit/exit_code.s",
description: "Exits with exit code 13",
},
{
name: "Hello World",
binary: "hello_world.bin",
source_name: "hello_world/hello_world.s",
description: "Prints \"Hello World!\" to stdout",
},
{
name: "Alphabet",
binary: "alphabet.bin",
source_name: "alphabet/alphabet.s",
},
{
name: "Exit Code",
binary: "exit_code.bin",
source_name: "exit/exit_code.s",
description: "Prints the alphabet to stdout",
},
{
name: "Input to uppercase",
binary: "uppercase_naive.bin",
source_name: "uppercase/uppercase_naive.s",
description: "Repeatedly reads a single character from stdin and prints the uppercase representation",
},
{
name: "Byte to hex",
binary: "hex_naive.bin",
source_name: "hex/hex_naive.s",
description: "Repeatedly reads a single byte from stdin and prints the hex representation",
},
{
name: "String length",
binary: "strlen.bin",
source_name: "strlen/strlen.s",
description: "Reads a string from stdin and prints its length",
},
{
name: "Print command-line arguments",
binary: "args.bin",
source_name: "args/args.S",
description: "Prints all command-line arguments and environment variables",
},
/*
{
Expand Down Expand Up @@ -309,7 +317,11 @@ export default defineComponent({
return;
}
try {
ax.init_stack_program_start(8n * 1024n, ["/bin/my_binary", "arg1", "arg2"], []);
ax.init_stack_program_start(8n * 1024n, ["/bin/my_binary", "arg1", "arg2"], [
"USER=demo-user",
"COLORTERM=truecolor",
"TERM=xterm-256color",
]);
ax.hook_before_mnemonic(Mnemonic.Syscall, this.syscallHandler);
}
catch (e) {
Expand Down

0 comments on commit c771963

Please sign in to comment.