From: Matthias Kruk Date: Sun, 26 Jul 2020 08:09:52 +0000 (+0900) Subject: libc, kernel/klibc: Fix bug in memcpy() where quantities less than 4 byte wouldn... X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=0a5eb7fd51eb70745b738b6b7db545b873a5f04c;p=corax libc, kernel/klibc: Fix bug in memcpy() where quantities less than 4 byte wouldn't be copied correctly (replacing the implementation with an assembly one) --- diff --git a/kernel/klibc/Makefile b/kernel/klibc/Makefile index 40a2c94..ff21f07 100644 --- a/kernel/klibc/Makefile +++ b/kernel/klibc/Makefile @@ -1,6 +1,6 @@ OUTPUT = klibc.a OBJECTS = string.o spinlock.o mutex.o posixcall.o coraxcall.o heap.o stdio.o signal.o \ - kq.o sem.o + kq.o sem.o string_ia32.o PHONY = clean INCLUDES = -I../include -I../../include -I../.. CFLAGS = -m32 -Wall -nostdlib -nodefaultlibs -nostartfiles -ffreestanding $(INCLUDES) diff --git a/kernel/klibc/string.c b/kernel/klibc/string.c index 657d746..aa56af3 100644 --- a/kernel/klibc/string.c +++ b/kernel/klibc/string.c @@ -10,33 +10,6 @@ size_t strlen(const char *s) return(ret_val); } -void* memcpy(void *dst, const void *src, size_t n) -{ - u32_t *d; - const u32_t *s; - - d = (u32_t*)dst; - s = (const u32_t*)src; - - while(n > 4) { - *d++ = *s++; - n -= 4; - } - - if(n >= 2) { - *((u16_t*)d) = *((u16_t*)s); - d = (u32_t*)(((void*)d) + 2); - s = (u32_t*)(((void*)s) + 2); - n -= 2; - } - - if(n >= 1) { - *((u8_t*)d) = *((u8_t*)s); - } - - return(dst); -} - void* memset(void *dst, int val, u32_t n) { char *ptr; diff --git a/kernel/klibc/string_ia32.S b/kernel/klibc/string_ia32.S new file mode 100644 index 0000000..b2fb623 --- /dev/null +++ b/kernel/klibc/string_ia32.S @@ -0,0 +1,44 @@ +#define __ASSEMBLY_SOURCE + +#include + +.section .text + +.global memcpy + +memcpy: + pushl %ebx + + movl 8(%esp), %eax + movl 12(%esp), %ebx + movl 16(%esp), %ecx + +0: testl $0xfffffffc, %ecx + jz 1f + + movl (%ebx), %edx + movl %edx, (%eax) + addl $4, %eax + addl $4, %ebx + subl $4, %ecx + jmp 0b + +1: testl $0x2, %ecx + jz 2f + + movw (%ebx), %dx + movw %dx, (%eax) + addl $2, %eax + addl $2, %ebx + subl $2, %ecx + +2: testl $0x1, %ecx + jz 3f + + movb (%ebx), %dl + movb %dl, (%eax) + +3: movl 8(%esp), %eax + + popl %ebx + ret diff --git a/libc/Makefile b/libc/Makefile index 2d4fc3d..2383060 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -1,7 +1,7 @@ OUTPUT = libc.a -OBJECTS = syscall.o string.o signal.o start.o stdio.o +OBJECTS = syscall.o string.o signal.o start.o stdio.o string_ia32.o PHONY = clean -INCLUDES = -I../include +INCLUDES = -I../include -I.. CFLAGS = -m32 -Wall -nostdlib -nodefaultlibs -nostartfiles -ffreestanding $(INCLUDES) ASFLAGS = $(CFLAGS) LIBGCC = /usr/lib/gcc-cross/i686-linux-gnu/8/libgcc.a diff --git a/libc/string.c b/libc/string.c index 5822776..a8e548a 100644 --- a/libc/string.c +++ b/libc/string.c @@ -22,30 +22,3 @@ void *memset(void *s, int c, size_t n) return(s); } - -void* memcpy(void *dst, const void *src, size_t n) -{ - u32_t *d; - const u32_t *s; - - d = (u32_t*)dst; - s = (const u32_t*)src; - - while(n > 4) { - *d++ = *s++; - n -= 4; - } - - if(n >= 2) { - *((u16_t*)d) = *((u16_t*)s); - d = (u32_t*)(((void*)d) + 2); - s = (u32_t*)(((void*)s) + 2); - n -= 2; - } - - if(n >= 1) { - *((u8_t*)d) = *((u8_t*)s); - } - - return(dst); -} diff --git a/libc/string_ia32.S b/libc/string_ia32.S new file mode 100644 index 0000000..b2fb623 --- /dev/null +++ b/libc/string_ia32.S @@ -0,0 +1,44 @@ +#define __ASSEMBLY_SOURCE + +#include + +.section .text + +.global memcpy + +memcpy: + pushl %ebx + + movl 8(%esp), %eax + movl 12(%esp), %ebx + movl 16(%esp), %ecx + +0: testl $0xfffffffc, %ecx + jz 1f + + movl (%ebx), %edx + movl %edx, (%eax) + addl $4, %eax + addl $4, %ebx + subl $4, %ecx + jmp 0b + +1: testl $0x2, %ecx + jz 2f + + movw (%ebx), %dx + movw %dx, (%eax) + addl $2, %eax + addl $2, %ebx + subl $2, %ecx + +2: testl $0x1, %ecx + jz 3f + + movb (%ebx), %dl + movb %dl, (%eax) + +3: movl 8(%esp), %eax + + popl %ebx + ret