Search logs:

channel logs for 2004 - 2010 are archived at http://tunes.org/~nef/logs/old/ ·· can't be searched

#osdev2 = #osdev @ Libera from 23may2021 to present

#osdev @ OPN/FreeNode from 3apr2001 to 23may2021

all other channels are on OPN/FreeNode from 2004 to present


http://bespin.org/~qz/search/?view=1&c=osdev&y=19&m=8&d=20

Tuesday, 20 August 2019

09:22:07 <azonenberg> https://www.antikernel.net/temp/startup.png
09:22:10 <azonenberg> something about this feels wrong :p
09:23:09 <j`ey> is it the hardcoded mangled name?
09:29:56 <azonenberg> j`ey: partially, yes
09:30:11 <azonenberg> but also the fact that i am using the hardcoded mangled name to get around the fact that C++ doesn't allow you to take the address of a constructor
09:30:26 <azonenberg> And i'm calling a constructor explicitly on a global variable whose constructor wasn't automatically called
09:30:29 <j`ey> cant you make a function that calls it?
09:30:36 <azonenberg> In a C++ program with no libc and no main() function
09:30:44 <azonenberg> You cannot explicitly call a constructor
09:30:52 <azonenberg> it's called automagically when the object is created
09:30:52 <j`ey> for a global
09:31:06 <j`ey> oh duh, yeah i see
09:31:07 <azonenberg> there's no way to just call a constructor on a random pointer afaik
09:31:17 <azonenberg> the reason i'm doing this is because somethign in .init_array is hosed
09:31:30 <azonenberg> and my program segfaults between the "copy .data to ram" block and the start of where i would normally call main(
09:31:30 <j`ey> ok I was just about to mention .init_array P
09:31:32 <azonenberg> main()
09:31:42 <azonenberg> so i'm manually calling each of the init functions one by one
09:31:47 <azonenberg> in hopes of narrowing down the cause
09:31:54 <azonenberg> for annoying reasons i dont have single-step capability on the target right now
09:32:05 <azonenberg> or this would be a lot simpler
09:32:37 <azonenberg> oooook so now i am even more confused
09:32:39 <j`ey> cant you just iterate from 0..init_array-N ?
09:32:52 <j`ey> (I guess you wont know which function that was in the end)
09:33:13 <azonenberg> Working system:
09:33:13 <azonenberg> * call ctor for the single global object
09:33:13 <azonenberg> * call __aeabi_atexit to register the destructor for that variable
09:33:29 <azonenberg> the atexit is an empty stub because my system never terminates, so global destructors are never called
09:33:35 <azonenberg> the only way it can be shut down is by a hard system reset
09:34:43 <azonenberg> Non-working system:
09:34:45 <azonenberg> for(uint32_t ctor = __ctor_start; ctor != __ctor_end; ctor ++)
09:34:45 <azonenberg>        reinterpret_cast<fnptr>(ctor)();
09:34:54 <azonenberg> where __ctor_start/end are the boundaries of .init_array
09:35:16 <azonenberg> the "non working" fails in a really confusing fashion though
09:35:45 <azonenberg> so first off, init_array doesn't directly point to those two functions
09:36:13 <azonenberg> it points to __static_initialization_and_destruction_0 which for some reason i am unable to call either by mangled or unmangled name despite seeing it in the .o files
09:37:02 <azonenberg> actually i tak that back, it points to GLOBAL__sub_I_g_platform() which then calls that
09:37:25 <azonenberg> anyway, when i call that chain via init_array the global'
09:37:43 <azonenberg> the global's ctor fires, then i see the call to __aeabi_atexit
09:37:56 <azonenberg> then a hard fault prior to the init_array pass completing
09:40:54 <azonenberg> Looking at the ARM exception frame in my fault handler, the pc is pointing to the beginning of GLOBAL__sub_I_g_platform(), prior to the call to __static_initialization_and_destruction_0, which makes zero sense because i have uart logs showing that the constructors were invoked
09:42:30 <azonenberg> even more confusing, the instruction that the exception pc indicates is a "sub" instruction which is completely nonsensical, how can that fault?
09:43:10 <azonenberg> So i'm a little skeptical that i'm walking the stack frame right, even though manual testing with deliberate segfaults indicates i'm doing it right
09:46:18 <azonenberg> oh and it seems i can't link to GLOBAL__sub_I_g_platform explicitly because it's not a global symbol
09:48:13 <azonenberg> it's marked local in the .o file
09:48:25 <azonenberg> i'm somewhat tempted to see if i can hex edit the .o just for debugging to invoke it explicitly :p
10:08:37 <azonenberg> DERP
10:09:02 <azonenberg> __ctor_start is the first table entry, not a pointer to it
10:09:23 <azonenberg> so i was calling the first init function, then calling 4 bytes into it...
10:09:45 <j`ey> azonenberg: :)))
21:30:27 <geist> azonenberg: did you get that constructor biz sorted out?
21:30:39 <geist> as far as calling a constructor manually, that's what a placement new is basically
21:32:02 <zid> geist: he was derefing the pointers
21:32:11 <geist> yah
21:32:14 <geist> that'll do it
21:32:25 <geist> note i've had a teensy bit of problems with clang and that sequence of code
21:32:43 <geist> tere's some edge case interpretation of the language that says no two global variables shall have the same address
21:33:18 <geist> so the logicthat tests that __ctor_begin and __ctor_end are not the same can be elided in case they actually are the same (no constructors)
21:33:22 <geist> and then the code just runs open loop
21:33:52 <geist> ie, i've had that for loop turned into a do while loop in assembly, assuming that the first iteration always happens
21:33:55 <geist> only via clang
21:37:15 <Shockk> I have a quick question; what would the advantages be of going from my 32-bit OS to a purely 64-bit OS? for context, right now I have paging, user mode, basic task switching, and a partial C library
21:40:46 <geist> the most obvious answer is its much easier to deal with large amounts of memory
21:41:08 <geist> physical memory that is. the kernel has much more access to virtual space inside the kernel, which also helps you access physical memory
21:41:36 <Shockk> right
21:41:57 <geist> you can switch to just using syscall instead of needing to fiddle with int/sysenter/syscall
21:42:27 <Shockk> hmm syscall is always supported on 64-bit procs?
21:42:32 <geist> you can now boot from 64bit UEFI implementations
21:42:54 <geist> yep. syscall was AMDs invention but they're mandatory to x86-64 so they're the defacto syscall mechanism that works on all 64bit cores
21:43:07 <geist> sysenter is the wideest supported on x86-32
21:43:14 <Shockk> ahh interesting okay
21:43:42 <Shockk> and it's faster than int iirc right?
21:43:42 <geist> lets see.. also x86-64 implies at least SSE2, so you can compile float that way and assume as much
21:43:47 <geist> yes
21:44:10 <geist> the GDT/IDT/LDT stuff is a little simpler, but for the most part they removed stuff in 64bit mode that you probably weren't using anyway
21:44:13 <geist> so it's kind of a wash
21:44:57 <Shockk> huh, maybe I'll go ahead and do this then
21:44:58 <Brnocrist> it's kind of legacy
21:45:11 <geist> plus there's the whole thing that x86-64 is clearly the future
21:45:20 <geist> it's a little cleaner, a little more complex, a little simpler in places
21:45:35 <geist> so it's about the same level of complexity, but i think the additional address space is a nice advantage
21:46:35 <geist> and if you're doing a new kernel without any backwards compatibility there's very little reason to allow <64bit user space at all
21:46:51 <Shockk> someone mentioned to me earlier that the calling convention also doesn't use frame pointers by default, instead it just uses rsp - n and is done by the compiler or something?
21:46:56 <geist> only reason is if you were thinking of trying to do some compatibility with other OSes binaries
21:47:16 <geist> that's correct, the x86-64 unix abi passes the first 6 args via register
21:47:38 <Shockk> interesting
21:47:40 <geist> and yes, the frame pointer isn't necessarily there by default
21:48:13 <geist> i think there's a general trend towards not relying on frame pointers in modern arches/toolchains
21:48:26 <geist> and instead using DWARF or whatnot to know how to unwind stuff
21:48:34 <Shockk> ah that makes sense
21:48:54 <geist> but since x86-64 has twice as many registers it's not nearly as register starved as x86-32 so the cost of a frame pointer isn't as bad
21:49:14 <Shockk> oh right it has r8 to r15 right
21:49:53 <geist> yah also why they can afford to pass args via registers
21:50:12 <Shockk> in fact why not even more than 6?
21:51:10 <geist> well, arg passing registers are callee trashed, and in as much as you want some callee saved you cant use up all of them
21:51:30 <Shockk> ahr ight
21:51:33 <geist> usually some percentage of registers in any ABI are callee saved
21:51:55 <geist> but the x86-64 unix abi is a little weird. MSFT has a different ABI that makes a little more sense, honestly
21:52:07 <geist> but it's mostly just hard to follow, you always need a cheat sheet
21:54:38 <azonenberg> geist: yeah i like x86-64 much more than i386 because of the extra regs
22:06:11 <zid> geist: windows abi sucks shit, wtf
22:06:17 <zid> shadow space, no redzone, etc
22:06:26 <zid> and the regs it uses aren't as useful
22:14:21 <zid> no struct optimizations either afaik
22:37:23 <geist> zid: perhaps
22:37:37 <geist> i thought it at least looked at little more sane on paper, but maybe in practice it's garbage