refactor: Fix build on i386
Some checks failed
CodeQL Advanced / Analyze (${{ matrix.language }}) (manual, c-cpp) (push) Has been cancelled
Deploy Documentation / Deploy Documentation to GitHub Pages (push) Has been cancelled
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Build OS / Build amd64 (push) Has been cancelled
Build OS / Build i386 (push) Has been cancelled
Build OS / Build aarch64 (push) Has been cancelled

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-01-07 17:49:37 +02:00
parent 463d16f8bc
commit 2bb997597e
57 changed files with 1489 additions and 923 deletions

View File

@ -33,10 +33,16 @@
static inline scarg syscall0(scarg syscall)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall)
static inline scarg syscall1(scarg syscall, scarg arg1)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -93,10 +111,16 @@ static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -115,11 +139,17 @@ static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -139,12 +169,18 @@ static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}
@ -165,6 +201,7 @@ static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6;
@ -172,6 +209,11 @@ static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret;
}

View File

@ -14,7 +14,7 @@ OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(OBJECT_NAME)

View File

@ -124,6 +124,7 @@ ElfInfo *SearchLib(char *Path)
__attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
{
#if defined(__amd64__)
__asm__(
"pop %r11\n" /* Pop lazy resolve arguments */
"pop %r10\n"
@ -148,6 +149,11 @@ __attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
"pop %rdi\n"
"jmp *%r11\n"); /* Jump to the return value */
#elif defined(__i386__)
#warning "i386 _dl_runtime_resolve not implemented"
#else
#error "Unsupported architecture"
#endif
}
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated);
@ -561,7 +567,7 @@ int CheckElfEhdr(Elf_Ehdr *ehdr, char *Path)
if (ehdr->e_ident[EI_CLASS] != elfClass)
{
printf("dl: %s is not a %s-bit ELF file\n",
Path, __LP64__ ? "64" : "32");
Path, elfClass == ELFCLASS64 ? "64" : "32");
return -EINVAL;
}
@ -804,6 +810,7 @@ int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
addAddend = 1;
break;
}
#if __LP64__
case R_DTPMOD64:
{
printf("dl: i don't know what to do with DTPMOD64\n");
@ -822,6 +829,7 @@ int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
reloc = symAddress + Rela->r_addend;
break;
}
#endif // __LP64__
default:
{
printf("dl: Unsupported relocation type %d\n", relType);

View File

@ -99,6 +99,7 @@ void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
#if defined(__amd64__)
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
@ -125,14 +126,21 @@ __attribute__((naked, used, no_stack_protector)) void _start()
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
/* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n");
#endif
__builtin_unreachable();
}

View File

@ -39,6 +39,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#if defined(__amd64__)
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
@ -65,6 +66,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n"
"call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
/* These are declared in GNU ld */

View File

@ -39,6 +39,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#if defined(__amd64__)
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
@ -65,6 +66,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n"
"call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
/* These are declared in GNU ld */

View File

@ -15,7 +15,7 @@ OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -0,0 +1,290 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#if defined(__amd64__) || defined(__i386__)
// GCC 32/64-bit integer arithmetic support for 32-bit systems that can't link
// to libgcc.
// Function prototypes and descriptions are taken from
// https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html.
// This file may be #include'd by another file, so we try not to pollute the
// namespace and we don't import any headers.
// All functions must be resolvable by the linker and therefore can't be inline
// or static, even if they're #included into the file where they'll be used.
// For best performance we try to avoid branching. This makes the code a little
// weird in places.
// See https://github.com/glitchub/arith64 for more information.
// This software is released as-is into the public domain, as described at
// https://unlicense.org. Do whatever you like with it.
#define arith64_u64 unsigned long long int
#define arith64_s64 signed long long int
#define arith64_u32 unsigned int
#define arith64_s32 int
typedef union
{
arith64_u64 u64;
arith64_s64 s64;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_u32 hi; arith64_u32 lo;
#else
arith64_u32 lo; arith64_u32 hi;
#endif
} u32;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_s32 hi; arith64_s32 lo;
#else
arith64_s32 lo; arith64_s32 hi;
#endif
} s32;
} arith64_word;
// extract hi and lo 32-bit words from 64-bit value
#define arith64_hi(n) (arith64_word){.u64=n}.u32.hi
#define arith64_lo(n) (arith64_word){.u64=n}.u32.lo
// Negate a if b is negative, via invert and increment.
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
#define arith64_abs(a) arith64_neg(a, a)
// Return the absolute value of a.
// Note LLINT_MIN cannot be negated.
arith64_s64 __absvdi2(arith64_s64 a)
{
return arith64_abs(a);
}
// Return the result of shifting a left by b bits.
arith64_s64 __ashldi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.u32.hi = w.u32.lo << (b - 32);
w.u32.lo = 0;
} else if (b)
{
w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
w.u32.lo <<= b;
}
return w.s64;
}
// Return the result of arithmetically shifting a right by b bits.
arith64_s64 __ashrdi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.s32.lo = w.s32.hi >> (b - 32);
w.s32.hi >>= 31; // 0xFFFFFFFF or 0
} else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.s32.hi >>= b;
}
return w.s64;
}
// These functions return the number of leading 0-bits in a, starting at the
// most significant bit position. If a is zero, the result is undefined.
int __clzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0xffff0000) << 4; n += b; a <<= b;
b = !(a & 0xff000000) << 3; n += b; a <<= b;
b = !(a & 0xf0000000) << 2; n += b; a <<= b;
b = !(a & 0xc0000000) << 1; n += b; a <<= b;
return n + !(a & 0x80000000);
}
int __clzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0xffffffff00000000ULL) << 5; n += b; a <<= b;
b = !(a & 0xffff000000000000ULL) << 4; n += b; a <<= b;
b = !(a & 0xff00000000000000ULL) << 3; n += b; a <<= b;
b = !(a & 0xf000000000000000ULL) << 2; n += b; a <<= b;
b = !(a & 0xc000000000000000ULL) << 1; n += b; a <<= b;
return n + !(a & 0x8000000000000000ULL);
}
// These functions return the number of trailing 0-bits in a, starting at the
// least significant bit position. If a is zero, the result is undefined.
int __ctzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0x0000ffff) << 4; n += b; a >>= b;
b = !(a & 0x000000ff) << 3; n += b; a >>= b;
b = !(a & 0x0000000f) << 2; n += b; a >>= b;
b = !(a & 0x00000003) << 1; n += b; a >>= b;
return n + !(a & 0x00000001);
}
int __ctzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0x00000000ffffffffULL) << 5; n += b; a >>= b;
b = !(a & 0x000000000000ffffULL) << 4; n += b; a >>= b;
b = !(a & 0x00000000000000ffULL) << 3; n += b; a >>= b;
b = !(a & 0x000000000000000fULL) << 2; n += b; a >>= b;
b = !(a & 0x0000000000000003ULL) << 1; n += b; a >>= b;
return n + !(a & 0x0000000000000001ULL);
}
// Calculate both the quotient and remainder of the unsigned division of a by
// b. The return value is the quotient, and the remainder is placed in variable
// pointed to by c (if it's not NULL).
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
if (b > a) // divisor > numerator?
{
if (c) *c = a; // remainder = numerator
return 0; // quotient = 0
}
if (!arith64_hi(b)) // divisor is 32-bit
{
if (b == 0) // divide by 0
{
volatile char x = 0; x = 1 / x; // force an exception
}
if (b == 1) // divide by 1
{
if (c) *c = 0; // remainder = 0
return a; // quotient = numerator
}
if (!arith64_hi(a)) // numerator is also 32-bit
{
if (c) // use generic 32-bit operators
*c = arith64_lo(a) % arith64_lo(b);
return arith64_lo(a) / arith64_lo(b);
}
}
// let's do long division
char bits = __clzdi2(b) - __clzdi2(a) + 1; // number of bits to iterate (a and b are non-zero)
arith64_u64 rem = a >> bits; // init remainder
a <<= 64 - bits; // shift numerator to the high bit
arith64_u64 wrap = 0; // start with wrap = 0
while (bits-- > 0) // for each bit
{
rem = (rem << 1) | (a >> 63); // shift numerator MSB to remainder LSB
a = (a << 1) | (wrap & 1); // shift out the numerator, shift in wrap
wrap = ((arith64_s64)(b - rem - 1) >> 63); // wrap = (b > rem) ? 0 : 0xffffffffffffffff (via sign extension)
rem -= b & wrap; // if (wrap) rem -= b
}
if (c) *c = rem; // maybe set remainder
return (a << 1) | (wrap & 1); // return the quotient
}
// Return the quotient of the signed division of a by b.
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
return arith64_neg(q, a^b); // negate q if a and b signs are different
}
// Return the index of the least significant 1-bit in a, or the value zero if a
// is zero. The least significant bit is index one.
int __ffsdi2(arith64_u64 a)
{
return a ? __ctzdi2(a) + 1 : 0;
}
// Return the result of logically shifting a right by b bits.
arith64_u64 __lshrdi3(arith64_u64 a, int b)
{
arith64_word w = {.u64 = a};
b &= 63;
if (b >= 32)
{
w.u32.lo = w.u32.hi >> (b - 32);
w.u32.hi = 0;
} else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.u32.hi >>= b;
}
return w.u64;
}
// Return the remainder of the signed division of a by b.
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 r;
__divmoddi4(arith64_abs(a), arith64_abs(b), &r);
return arith64_neg(r, a); // negate remainder if numerator is negative
}
// Return the number of bits set in a.
int __popcountsi2(arith64_u32 a)
{
// collect sums into two low bytes
a = a - ((a >> 1) & 0x55555555);
a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
a = (a + (a >> 4)) & 0x0F0F0F0F;
a = (a + (a >> 16));
// add the bytes, return bottom 6 bits
return (a + (a >> 8)) & 63;
}
// Return the number of bits set in a.
int __popcountdi2(arith64_u64 a)
{
// collect sums into two low bytes
a = a - ((a >> 1) & 0x5555555555555555ULL);
a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
a = (a + (a >> 32));
a = (a + (a >> 16));
// add the bytes, return bottom 7 bits
return (a + (a >> 8)) & 127;
}
// Return the quotient of the unsigned division of a by b.
arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b)
{
return __divmoddi4(a, b, (void *)0);
}
// Return the remainder of the unsigned division of a by b.
arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
{
arith64_u64 r;
__divmoddi4(a, b, &r);
return r;
}
#endif

View File

@ -114,6 +114,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#if defined(__amd64__)
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
@ -140,6 +141,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n"
"call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#warning "unknown architecture"
#endif
}
int main(int argc, char *argv[], char *envp[])