Page 1 of 1

[x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 5:09 am
by AlfaOmega08
I'm porting my kernel to x64. In protected mode I used to use C++ features like constructors, virtual methods, exceptions. However in long mode I'm having a problem calling a constructor in the libsupc++.a library, particularly in the eh_alloc.o object file. All the others constructors are executed correctly. Disassembling the code which is going to be executed I found this in the first instructions of the constructor:

Code: Select all

ffffffff80235200 <_GLOBAL__I_eh_alloc.cc>:
ffffffff80235200:	48 83 ec 38          	sub    $0x38,%rsp
ffffffff80235204:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
ffffffff8023520b:	00 00 
ffffffff8023520d:	48 89 44 24 28       	mov    %rax,0x28(%rsp)
ffffffff80235212:	31 c0                	xor    %eax,%eax
ffffffff80235214:	48 83 3d 14 7f 05 00 	cmpq   $0x0,0x57f14(%rip)        # ffffffff8028d130 <AcpiRtypeNames+0x30>
ffffffff8023521b:	00 
...
Bochs stops at the second one (mov rax, fs:0x28). As far as I read on the wiki, the FS register can't be used in a legacy way, so I didn't bother initializing it among the other segment registers, and it still contains it's protected mode setup, pointing to a data segment from 0x00000000 to 0xffffffff. Why is this eh_alloc.o code using that register? Am I missing something? Should I initialize the register in a particular way?

Thanks...

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 5:11 am
by gerryg400
Which tool chain are you using ?

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 5:24 am
by AlfaOmega08
The standard gcc/g++ compiler which cames with my ubuntu 64bit distribution. I'm using the libsup++ libgcc libgcc_eh taken from the host too.

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:16 am
by Solar
AFAIK, GCC assumes all segment registers being initialized to flat memory mode. I don't know why this specific constructor uses the FS register, but with the above assumption I'd think the GCC maintainers felt safe in doing so.

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:26 am
by AlfaOmega08
So I should use the MSR to set FS base address to 0, and that would suffice to set FS as flat?

Edit:
Set fs and gs using the "legacy" way (mov fs, ax). Still not working. This is the bochs dump when executing that instruction:

Code: Select all

00052987808i[CPU0 ] CPU is in long mode (active)
00052987808i[CPU0 ] CS.d_b = 16 bit
00052987808i[CPU0 ] SS.d_b = 16 bit
00052987808i[CPU0 ] EFER   = 0x00000500
00052987808i[CPU0 ] | RAX=ffffffff802351f0  RBX=0000000000103000
00052987808i[CPU0 ] | RCX=0000000000000080  RDX=00000000000003d5
00052987808i[CPU0 ] | RSP=ffffffff8010ef88  RBP=ffffffff8010eff8
00052987808i[CPU0 ] | RSI=0000000000000080  RDI=ffffffff8029b004
00052987808i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00052987808i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00052987808i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00052987808i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00052987808i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf AF PF cf
00052987808i[CPU0 ] | SEG selector     base    limit G D
00052987808i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00052987808i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 00000fff 1 0
00052987808i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00052987808i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00052987808i[CPU0 ] | RIP=ffffffff802351f4 (ffffffff802351f4)
00052987808i[CPU0 ] | CR0=0xe0000013 CR2=0x0000000000000080
00052987808i[CPU0 ] | CR3=0x00291000 CR4=0x00000620
(0).[52987808] [0x00000000002351f4] 0008:ffffffff802351f4 (unk. ctxt): mov rax, qword ptr fs:0x0000000000000028 ; 64488b042528000000
00052987808e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:28 am
by Combuster
GCC only expects DS=ES=SS; FS/GS were the only segmentation registers kept in long mode for thread-local storage purposes. They even added a SWAPGS instruction for convenience.

Since the operand is [FS:low_number], use of TLS seems most likely here. (and setting it FS.base to zero will consequently crash anything that expects TLS to be implemented)

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:32 am
by AlfaOmega08
ehm... I've never used thread local storage in kernel development... any particular setup?

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:33 am
by Combuster
Just a reminder why you don't want to reuse host toolchains :wink:

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 7:35 am
by AlfaOmega08
I wasn't successful at compiling libsupc++ and I read that using the host one would have worked. So I end up using the whole toolchain, from compilers to linkers and libraries

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 9:05 am
by AlfaOmega08
This is how I solved:

Code: Select all

//Alloc a page
void *tls = valloc(4096);
WriteMsr(0xC0001000, (uint64_t) tls);
The constructor now works as fs is pointing to valid memory.

I don't know if this will cause me problems, but actually it seems to work. I still didn't test exceptions..

Edit:

Exceptions don't work. Exploring the disassembly I found that __cxa_throw_exceptions calls __cxa_get_globals which takes a 64bit pointer at fs:0x0, then decreases it by 16, and since it's 0 it becomes the invalid pointer 0xFFFFFFFFFFF0. Looking in the libsupc++ source code, which now I MUST get to compile, I see preprocessors instructions like "#if _GLIBCXX_HAVE_TLS". I think a compilation is needed unless someone is able to point out how TLS works...

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Tue Sep 13, 2011 1:04 pm
by Owen
...If the x86_64 SysV ABI doesn't say, the Thread Local Storage ELF supplement should

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Wed Sep 14, 2011 2:29 am
by AlfaOmega08
Well at this point I have three choices:
1) Remove libsupc++ and say godbye to exceptions
2) Compile or find a 64bit libsupc++ that won't use TLS (if someone is able to provide me one that would be great). But I have to say godbye to multithreading in the kernel
3) Add support for TLS in ELF in the Kernel loader and make everyone happy. Quite difficoult though...

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Wed Sep 14, 2011 3:57 am
by jnc100
For TLS in IA-32, there was need for a register which stored the location of a thread pointer which was specific to each thread. Various data is accessed at positive and negative indices from this pointer. Due to the limited number of GPRs in the IA32 architecture, the GS register was chosen. GS is loaded with a segment which has its base at the address of the thread pointer (so that gs:0x0 is the address of the thread pointer) and a limit of 0xffffffff so that you can access gs:-0x4 without problems.

In x86_64, the mechanism is essentially the same, except that FS is used instead of GS.

The entire mechanism for setting up the TLS structures is specified in the document 'ELF Handling For Thread-Local Storage' as previously mentioned.

Regards,
John.

Re: [x64] Constructor of libsupc++.a uses FS

Posted: Wed Sep 14, 2011 6:17 am
by AlfaOmega08
berkus wrote:4) use some other library to implement exceptions?
If you can give me some links... because I've never heard of other libraries except from libsupc++