IRC channel logs

2022-10-25.log

back to list of logs

<stikonas>oriansj: https://paste.debian.net/1258158/
<stikonas>oriansj: fputc on line 166 handles \r
<stikonas>(I meant branches are easier than pastebin if you want to reproduce issue)
<stikonas>pushed it here too (https://github.com/stikonas/M2libc/tree/wip)
<rekado_>this DEBUG_LoadSymbols stuff is useless. The segfault in hsc happens much too early for any of this debug stuff to contain useful info.
<rekado_>I’ll try building binutils < 2.22
<rekado_>got a build of 2.11 but “as” segfaults :-/
<stikonas>rekado_: but about 2.14, would that work?
<rekado_>I tried 2.14a, but I also get a segfault in “as’
<rekado_>2.11 is from around the same time as GHC 4, so I tried it first
<stikonas>as itself segfaults?
<stikonas>when compiling GHC sources?
<rekado_>just by itself
<rekado_>gdb doesn’t tell me anything
<rekado_>0x00000000 in ?? ()
<rekado_>‘as’ is not stripped
<stikonas>hmm, if you are up for it, you can try static musl build from live-bootstrap (I even have a it saved here https://stikonas.eu/files/bootstrap/binutils-2.14_0.tar.bz2)
<rekado_>I probably have something too modern in my build environment
<stikonas>possibly, hence my suggestion to try some other build
<oriansj>my bet is an off-by-one stack error in one of the asm blocks
<stikonas>oriansj: could very well be
<stikonas>my bet is on some kind of memory error too...
<oriansj>is it supposed to be "sub_rsp, %16" or "sub_rsp, %24"?
<stikonas>oriansj: depends on the number of arguments
<stikonas>if UEFI function has one argument, then we need to allocate 8
<stikonas>4 arguments is 32
<stikonas>after that arguments are only pushed onto stack by value and not written to registers
<stikonas>so arguments 1 to 4 is rcx, rdx, r8, r9 but you need to reserve 8, 16, 24, 32 bytes of stack space, anything further is just pushed onto stack
<stikonas>which complicates things a bit, because when we push stuff onto stack, those stack offsets change...
<oriansj>just more proof of your brillance in working around all the UEFI damage.
<stikonas>some of "damage" is just us being not used to windows calling convention
<stikonas>though linux seems more sensible to me
<stikonas>and hopefully, once M2.efi works, full M2libc can be a bit neater, we'll have access to &variable, etc...
<muurkha>the libc calling convention on i386 is kind of shitty. the Linux system call interface seems fairly sane, as is the amd64 ABI
<muurkha>I mean if you're going to have caller-saved registers you might as well use them for arguments, the occasional variadic function can suck it up
<oriansj>the only issue I have with the Linux calling convention is that more than the register with the return value is being altered.
<stikonas>it might be that offsets in _open are wrong
<oriansj>and a minor disagreement with the choice the ARM syscall changed from doing SYSCALL WRITE to setting the syscall number in a register then calling a syscall zero
<stikonas>let me double check, but I thing 40 is too much there
<stikonas>should be 32
<stikonas>let me try to fix it and we'll see if it helps
<stikonas>strange, it makes it even worse (always gets stuck on first run) but maybe there is another similar bug somewhere
<stikonas>oh I had 5 arguments in _open calls but only 4 in function definition
<stikonas>a stupid mistake, but probably explains stack offset confusion
<stikonas>hmm, back to original behaviour, so there must be another bug
<stikonas>oriansj: I found the bug
<stikonas>it's a memory handling error but in C code and not in assembly blocks
<stikonas>- char* wide_filename = string2wide(filename, strlen(filename));
<stikonas>+ char* wide_filename = string2wide(filename, strlen(filename) + 1);
<stikonas>strlen returns length of the string without terminating 0
<stikonas>and I guess sometimes that memory area had other garbage
<oriansj>that would do it
<oriansj>and because UEFI lacks proper memory initialization, random garbage certainly can appear
<stikonas>indeed
<stikonas>and probably I was opening not my file but some non existent file due to lack of wide 0
<stikonas>which resulted in that function returning 0 for file descriptor
<stikonas>so now it makes sense...
<stikonas>still M2.efi is not working yet :(. That one is still getting stuck on anything more than "M2.efi --help" or "M2.efi --version"
<stikonas>still, it's getting closer... One bug at a time
<stikonas>hmm, this last bug reminds me a bit of a similar issue I saw earlier (I think in M0) which was buggy until I zeroed the whole allocated memory area at the beginning of the program
<muurkha>oriansj: I know you prefer all registers to be callee-saved, but I'm not really comfortable working that way
<oriansj>muurkha: is it because the architecture doesn't change out the stack pointer on syscalls to the kernel stack and it could be used to do some serious damage?
<oriansj>or because of some performance based reason?
<muurkha>it's a combination of performance and convenience (talking about regular function calls here rather than system calls)
<muurkha>in the standard RISC-V ABI, ignoring floating point, you have 15 call-clobbered ("caller-saved") registers, 8 of which are argument registers
<oriansj>muurkha: I find just doing a couple push instructions at the start and a couple matching pop instructions at the end of a function quite convenient when writing assembly
<muurkha>if you're writing a leaf function, you can just use those registers for anything you want, without having to pray to the stack frame gods before and after dinner
<muurkha>and even if you're writing a non-leaf function, you can use them for anything you want with no worries in between calls to other functions, though you'll certainly want a stack frame in that case
<oriansj>muurkha: granted when you have 26+ spare registers to work with.
<muurkha>RISC-V is maybe more of a pain on this point than ARM because there's no LDM/STM
<stikonas>well, even on risc-v M2-Planet does not use RISC-V ABI, we use own calling convention
<muurkha>oh, of course
<stikonas>and same on UEFI, we only use that window calling convention to call UEFI functions
<muurkha>I'm just talking about designing calling conventions in the abstract, with reference to things that I've found good or bad
<muurkha>not attempting to assert anything about M2-Planet
<stikonas>yeah, it's a bit different for more powerful compilers
<stikonas>M2-Planet is just what was simplest for oriansj
<muurkha>I was just thinking for writing code by hand
<stikonas>indeed
<oriansj>muurkha: which we most certainly did
<stikonas>oriansj: typo fix https://github.com/oriansj/M2-Planet/pull/42
<muurkha>oriansj's preference is clearly for not having to remember which registers are call-clobbered, and I'm not saying his preference is wrong
<muurkha>just that I have a different one
<oriansj>stikonas: thank you, merged
<muurkha>non-leaf functions always need stack frames but I still find it convenient to have a little "slack space" or "headroom" I know I can use for temp values that won't survive a call
<oriansj>muurkha: well mine was formed from the pain of trying to debug hex2 when I was trying to be "clever" with register usage to reduce the total number of instructions.
<muurkha>yeah, and I respect that ;)
<oriansj>when you don't know where the mistake is or even if it is an encoding bug; you learn to value simplicity and easy to reason about assembly.
<muurkha>yeah
<muurkha>but I don't prefer to go to such an extreme
<oriansj>as certainly is your choice muurkha
<oriansj>but not having to learn the hardway that the register you were using to store something important was wiped because of a calling convention detail you didn't expect; is a worthwhile thing.
<oriansj>If the documentation says pass arguments in eax, ebx, ecx, edx and returns result in eax; it is hard to know that edi was going to get wiped out too
<muurkha>yep
<muurkha>been there, cried the bitter tears
<oriansj>vs on knight, the syscall spec says arguments in r0, r1, r2 and result is written in r0. well you can take it to the bank that r4 isn't going to be altered along the way.
<muurkha>:)
<oriansj>heck r1 and r2 are going to be in the exact same state, so you don't have to worry about having to reload that string pointer the second time around the loop
<oriansj>match("+", mystring); => r0 is the pointer to "+" and r1 is the pointer to mystring. If it is false we can just load "-" and do that match next and so on.
<oriansj>which is just the sort of logic you expect to see in an Assembler or Compiler
<rekado_>I’ve built binutils 2.14, glibc 2.2.5, and used those with gcc 2.95.3 to build ghc 4. Unfortunately, I still see the exact same segfault in hsc.
<janus>are all those libraries a lot newer than what the ghc devs used at the time? i see the 4.06 version page mentions glibc 2.1
<janus>looks like there are 3 years of development between glibc 2.2.5 (2002-01-20) and glibc 2.1 (1999-02-03)
***dongcarl is now known as Guest1624
***dongcarl8 is now known as dongcarl
***ChanServ sets mode: +o oriansj
<efraim>when was the glibc ABI change from 5 to 6? could that have something to do with it?
<stikonas>efraim: never
<stikonas>there was glibc 1 with ABI 1
<stikonas>then glibc 2 with ABI 6
<stikonas>there was another fork that used ABI 2 to 5 but it was not upstream glibc
<efraim>oh
<stikonas>good progress on stage0-uefi, now I've got M2-Planet working
<stikonas>used it to build M1-0.efi
<stikonas>I guess I still need to do a bit of cleanup in bootstrap M2libc but should be easier now
<stikonas>oriansj: should I add new UEFI defines to amd64/amd64_defs.M1 ?
<rekado_>no more segfault
<rekado_>turns out there’s even more evidence that I’m prone to looking in all the wrong places for errors
<rekado_>I used the wrong C ‘source’ tarball.
<rekado_>used the ‘unreg’ tarball instead of the x86 variant
<rekado_>since I actually linked for x86 and not the ‘unregisterized’ variant *of course* there was a segfault
<stikonas>sounds like you are making good progress too
<stikonas>hmm, I think one simplification I can do in M2libc embedded asm blocks is to use rbp rather than rsp, that should make argument offset easier to read
<oriansj>stikonas: sure, probably makes the transistion to making your new DEFINEs the new AMD64 default easier.