~oriansj/M2libc

400ddd7836d3cb01e817c914e02930d3af42d2d9 — Andrius Štikonas 1 year, 11 months ago 0bd0f97
Implement getenv for x86, amd64, aarch64, riscv32 and riscv64.

knight-posix and armv7l do not support it yet.
M aarch64/libc-full.M1 => aarch64/libc-full.M1 +9 -0
@@ 28,6 28,12 @@
	ADD_X0_BP_X0
	PUSH_X0

	;; Setup for _envp
	LOAD_W1_AHEAD
	SKIP_32_DATA
	&GLOBAL__envp
	STR_X0_[X1]

	;; Setup for malloc
	LOAD_W16_AHEAD
	SKIP_32_DATA


@@ 65,3 71,6 @@
	DEREF_X0
	SET_X8_TO_SYS_EXIT
	SYSCALL

:GLOBAL__envp
	NULL

M amd64/amd64_defs.M1 => amd64/amd64_defs.M1 +1 -0
@@ 33,6 33,7 @@ DEFINE je 0F84
DEFINE jne 0F85
DEFINE lea_rax,[rbp+DWORD] 488D85
DEFINE lea_rax,[rip+DWORD] 488D05
DEFINE lea_rbx,[rip+DWORD] 488D1D
DEFINE lea_rcx,[rbp+DWORD] 488D8D
DEFINE lea_rdi,[rsp+DWORD] 488DBC24
DEFINE lea_rdx,[rip+DWORD] 488D15

M amd64/libc-full.M1 => amd64/libc-full.M1 +5 -0
@@ 29,6 29,8 @@
	sal_rax, !3                 ; OFFSET = OFFSET * WORDSIZE
	add_rax,rbp                 ; ENVP_address = RSP + OFFSET
	push_rax                    ; Put envp on the stack
	lea_rbx,[rip+DWORD] %GLOBAL__envp ; Get _envp global
	mov_[rbx],rax               ; Save environment to _envp

	;; Stack offset
	add_rbp, %8                 ; Fix rbp


@@ 52,3 54,6 @@
	pop_rdi
	mov_rax, %0x3C
	syscall

:GLOBAL__envp
	NULL

M armv7l/libc-full.M1 => armv7l/libc-full.M1 +3 -0
@@ 144,3 144,6 @@
	'0' R1 R0 NO_SHIFT MOVE_ALWAYS  ; MOV R0,R1
	{LR} POP_ALWAYS                 ; Prepare for return
	'1' LR RETURN

:GLOBAL__envp
	NULL

M knight/libc-full.M1 => knight/libc-full.M1 +3 -0
@@ 53,3 53,6 @@
:FUNCTION__exit
	LOAD R0 R14 0
	SYS_EXIT

:GLOBAL__envp
	NULL

M riscv32/libc-full.M1 => riscv32/libc-full.M1 +12 -6
@@ 23,13 23,16 @@
    RS1_SP RS2_A0 SW       ; Put argv on the stack

    ; Prepare envp
    RD_A0 RS1_FP MV        ; Address we need to load from
    RD_A0 RS1_A0 LW        ; Get ARGC
    RD_A0 RS1_A0 !2 ADDI   ; OFFSET = ARGC + 2
    RD_A0 RS1_A0 RS2_X2 SLLI ; OFFSET = OFFSET * WORDSIZE
    RD_A0 RS1_FP RS2_A0 ADD ; ENVP_address = RSP + OFFSET
    RD_A0 RS1_FP MV           ; Address we need to load from
    RD_A0 RS1_A0 LW           ; Get ARGC
    RD_A0 RS1_A0 !2 ADDI      ; OFFSET = ARGC + 2
    RD_A0 RS1_A0 RS2_X2 SLLI  ; OFFSET = OFFSET * WORDSIZE
    RD_A0 RS1_FP RS2_A0 ADD   ; ENVP_address = RSP + OFFSET
    RD_SP RS1_SP !-4 ADDI
    RS1_SP RS2_A0 SW       ; Put envp on the stack
    RS1_SP RS2_A0 SW          ; Put envp on the stack
    RD_A1 ~GLOBAL__envp AUIPC ; Get _envp global
    RD_A1 RS1_A1 !GLOBAL__envp ADDI
    RS1_A1 RS2_A0 SW          ; Save environment to _envp

    ; Stack offset
    RD_FP RS1_FP !4 ADDI


@@ 54,3 57,6 @@
    RD_A0 RS1_SP LW
    RD_A7 !93 ADDI         ; Syscall for exit
    ECALL                  ; Exit with code in a0

:GLOBAL__envp
	NULL

M riscv64/libc-full.M1 => riscv64/libc-full.M1 +12 -6
@@ 23,13 23,16 @@
    RS1_SP RS2_A0 SD       ; Put argv on the stack

    ; Prepare envp
    RD_A0 RS1_FP MV        ; Address we need to load from
    RD_A0 RS1_A0 LD        ; Get ARGC
    RD_A0 RS1_A0 !2 ADDI   ; OFFSET = ARGC + 2
    RD_A0 RS1_A0 RS2_X3 SLLI ; OFFSET = OFFSET * WORDSIZE
    RD_A0 RS1_FP RS2_A0 ADD ; ENVP_address = RSP + OFFSET
    RD_A0 RS1_FP MV           ; Address we need to load from
    RD_A0 RS1_A0 LD           ; Get ARGC
    RD_A0 RS1_A0 !2 ADDI      ; OFFSET = ARGC + 2
    RD_A0 RS1_A0 RS2_X3 SLLI  ; OFFSET = OFFSET * WORDSIZE
    RD_A0 RS1_FP RS2_A0 ADD   ; ENVP_address = RSP + OFFSET
    RD_SP RS1_SP !-8 ADDI
    RS1_SP RS2_A0 SD       ; Put envp on the stack
    RS1_SP RS2_A0 SD          ; Put envp on the stack
    RD_A1 ~GLOBAL__envp AUIPC ; Get _envp global
    RD_A1 RS1_A1 !GLOBAL__envp ADDI
    RS1_A1 RS2_A0 SD          ; Save environment to _envp

    ; Stack offset
    RD_FP RS1_FP !8 ADDI


@@ 54,3 57,6 @@
    RD_A0 RS1_SP LD
    RD_A7 !93 ADDI         ; Syscall for exit
    ECALL                  ; Exit with code in a0

:GLOBAL__envp
	NULL

M stdlib.c => stdlib.c +42 -0
@@ 401,3 401,45 @@ size_t wcstombs(char* dest, char* src, size_t n)

	return i;
}

/************************************************************************
 * getenv - get an environmental variable                               *
 ************************************************************************/
size_t _strlen(char const* str)
{
	size_t i = 0;
	while(0 != str[i]) i = i + 1;
	return i;
}
int _strncmp(char const* lhs, char const* rhs, size_t count)
{
	size_t i = 0;
	while(count > i)
	{
		if(0 == lhs[i]) break;
		if(lhs[i] != rhs[i]) return lhs[i] - rhs[i];
		i = i + 1;
	}

	return 0;
}
char** _envp;
char* getenv (char const* name)
{
	char** p = _envp;
	char* q;
	int length = _strlen(name);

	while (p[0] != 0)
	{
		if(_strncmp(name, p[0], length) == 0)
		{
			q = p[0] + length;
			if(q[0] == '=')
				return q + 1;
		}
		p += sizeof(char**); /* M2 pointer arithemtic */
	}

	return 0;
}

M stdlib.h => stdlib.h +1 -0
@@ 36,6 36,7 @@ extern void free(void* l);
extern void* malloc(unsigned size);
extern void* memset(void* ptr, int value, int num);
extern void* calloc(int count, int size);
extern char *getenv(const char *name);

size_t wcstombs(char* dest, const wchar_t* src, size_t n);


M x86/libc-full.M1 => x86/libc-full.M1 +5 -0
@@ 29,6 29,8 @@
	sal_eax, !2                 ; OFFSET = OFFSET * WORDSIZE
	add_eax,ebp                 ; ENVP_address = ESP + OFFSET
	push_eax                    ; Put envp on the stack
	mov_ebx, &GLOBAL__envp      ; Get _envp global
	mov_[ebx],eax               ; Save environment to _envp

	;; Stack offset
	add_ebp, %4                 ; Fix ebp


@@ 51,3 53,6 @@
	pop_ebx
	mov_eax, %1
	int !0x80

:GLOBAL__envp
	NULL