www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.ldc - Solaris/x86 port - how to get the TLS section?

reply "Kai Nacke" <kai redstar.de> writes:
Hi!

GitHub master contains a close-to-working port of LDC to 
Solaris/x86. The only missing piece is getting a pointer to the 
TLS section. I tried the following:

1) Solaris uses the ELF file format. Unfortunately, it does not 
support the dl_phdr_info.dlpi_tls_modid field which is used on 
FreeBSD to get the module id of the TLS section.

2) On glibc-based systems, the function dlinfo(RTLD_SELF, 
RTLD_DI_TLS_MODID, &modid) can be used to get the module id. 
Again, this is not supported on Solaris.

Does somebody else know a way to get a pointer to or the module 
id of the TLS section? Maybe a linkmap or a /proc/<pid>/map based 
solution? Every suggestion is welcome!

Regards,
Kai
Nov 25 2014
next sibling parent reply "Joakim" <dlang joakim.fea.st> writes:
On Tuesday, 25 November 2014 at 17:59:48 UTC, Kai Nacke wrote:
 Hi!

 GitHub master contains a close-to-working port of LDC to 
 Solaris/x86. The only missing piece is getting a pointer to the 
 TLS section. I tried the following:

 1) Solaris uses the ELF file format. Unfortunately, it does not 
 support the dl_phdr_info.dlpi_tls_modid field which is used on 
 FreeBSD to get the module id of the TLS section.

 2) On glibc-based systems, the function dlinfo(RTLD_SELF, 
 RTLD_DI_TLS_MODID, &modid) can be used to get the module id. 
 Again, this is not supported on Solaris.

 Does somebody else know a way to get a pointer to or the module 
 id of the TLS section? Maybe a linkmap or a /proc/<pid>/map 
 based solution? Every suggestion is welcome!

 Regards,
 Kai
Take a look at Drepper's TLS reference, if you haven't already: http://www.akkadia.org/drepper/tls.pdf He talks a lot about how Solaris is different in there.
Nov 25 2014
parent reply "Joakim" <dlang joakim.fea.st> writes:
On Tuesday, 25 November 2014 at 19:35:36 UTC, Joakim wrote:
 On Tuesday, 25 November 2014 at 17:59:48 UTC, Kai Nacke wrote:
 Hi!

 GitHub master contains a close-to-working port of LDC to 
 Solaris/x86. The only missing piece is getting a pointer to 
 the TLS section. I tried the following:

 1) Solaris uses the ELF file format. Unfortunately, it does 
 not support the dl_phdr_info.dlpi_tls_modid field which is 
 used on FreeBSD to get the module id of the TLS section.

 2) On glibc-based systems, the function dlinfo(RTLD_SELF, 
 RTLD_DI_TLS_MODID, &modid) can be used to get the module id. 
 Again, this is not supported on Solaris.

 Does somebody else know a way to get a pointer to or the 
 module id of the TLS section? Maybe a linkmap or a 
 /proc/<pid>/map based solution? Every suggestion is welcome!

 Regards,
 Kai
Take a look at Drepper's TLS reference, if you haven't already: http://www.akkadia.org/drepper/tls.pdf He talks a lot about how Solaris is different in there.
Hmm, I don't see it in there. btw, isn't the TLS module id for the executable itself usually 1? If you don't plan on supporting shared libraries, maybe you can just hard-code it for now?
Nov 25 2014
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-11-26 03:11, Joakim wrote:

 Hmm, I don't see it in there.
Yeah, I couldn't find any information specific for a given operating system. Only information for a given architecture. -- /Jacob Carlborg
Nov 25 2014
parent "Joakim" <dlang joakim.fea.st> writes:
On Wednesday, 26 November 2014 at 06:59:42 UTC, Jacob Carlborg 
wrote:
 On 2014-11-26 03:11, Joakim wrote:

 Hmm, I don't see it in there.
Yeah, I couldn't find any information specific for a given operating system. Only information for a given architecture.
Do a search for Sun: there are a lot of specifics about how the Sun x86 ABI is different for the various thread models. But it doesn't go into what OS APIs, ie structs and functions, to use to access the TLS data.
Nov 26 2014
prev sibling parent "Kai Nacke" <kai redstar.de> writes:
On Wednesday, 26 November 2014 at 02:11:10 UTC, Joakim wrote:
 On Tuesday, 25 November 2014 at 19:35:36 UTC, Joakim wrote:
 On Tuesday, 25 November 2014 at 17:59:48 UTC, Kai Nacke wrote:
 Hi!

 GitHub master contains a close-to-working port of LDC to 
 Solaris/x86. The only missing piece is getting a pointer to 
 the TLS section. I tried the following:

 1) Solaris uses the ELF file format. Unfortunately, it does 
 not support the dl_phdr_info.dlpi_tls_modid field which is 
 used on FreeBSD to get the module id of the TLS section.

 2) On glibc-based systems, the function dlinfo(RTLD_SELF, 
 RTLD_DI_TLS_MODID, &modid) can be used to get the module id. 
 Again, this is not supported on Solaris.

 Does somebody else know a way to get a pointer to or the 
 module id of the TLS section? Maybe a linkmap or a 
 /proc/<pid>/map based solution? Every suggestion is welcome!

 Regards,
 Kai
Take a look at Drepper's TLS reference, if you haven't already: http://www.akkadia.org/drepper/tls.pdf He talks a lot about how Solaris is different in there.
Hmm, I don't see it in there. btw, isn't the TLS module id for the executable itself usually 1? If you don't plan on supporting shared libraries, maybe you can just hard-code it for now?
That's a good hint. I try this. Regards, Kai
Nov 26 2014
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-11-25 18:59, Kai Nacke wrote:

 Does somebody else know a way to get a pointer to or the module id of
 the TLS section? Maybe a linkmap or a /proc/<pid>/map based solution?
 Every suggestion is welcome!
How about manually iterating the sections, would that be possible? I found this link that might be of help: https://docs.oracle.com/cd/E26502_01/html/E26507/chapter8-1.html#scrolltoc -- /Jacob Carlborg
Nov 25 2014
parent reply "Kai Nacke" <kai redstar.de> writes:
On Tuesday, 25 November 2014 at 20:27:40 UTC, Jacob Carlborg 
wrote:
 On 2014-11-25 18:59, Kai Nacke wrote:

 Does somebody else know a way to get a pointer to or the 
 module id of
 the TLS section? Maybe a linkmap or a /proc/<pid>/map based 
 solution?
 Every suggestion is welcome!
How about manually iterating the sections, would that be possible?
That is no problem. The trouble starts because the TLS section is allocated for every thread (at least if the thread touches a variable in this section). I need to find the start of the section at runtime for a thread. The module id helps her because __tls_get_addr() can then be used.
 I found this link that might be of help: 
 https://docs.oracle.com/cd/E26502_01/html/E26507/chapter8-1.html#scrolltoc
That's a nice summary of the Drepper paper only for Solaris. Unfortunately all the OS stuff is missing. Regards, Kai
Nov 26 2014
parent reply Jacob Carlborg <doob me.com> writes:
On 2014-11-26 18:33, Kai Nacke wrote:

 That is no problem. The trouble starts because the TLS section is
 allocated for every thread (at least if the thread touches a variable in
 this section). I need to find the start of the section at runtime for a
 thread. The module id helps her because __tls_get_addr() can then be used.
Are you referring what you're supposed to pass to __tls_get_addr when generating a call to __tls_get_addr in the compiler? Or is it in the runtime where you need to access the TLS data to get the roots for the GC? -- /Jacob Carlborg
Nov 27 2014
parent reply "Kai Nacke" <kai redstar.de> writes:
On Thursday, 27 November 2014 at 12:23:18 UTC, Jacob Carlborg 
wrote:
 On 2014-11-26 18:33, Kai Nacke wrote:

 That is no problem. The trouble starts because the TLS section 
 is
 allocated for every thread (at least if the thread touches a 
 variable in
 this section). I need to find the start of the section at 
 runtime for a
 thread. The module id helps her because __tls_get_addr() can 
 then be used.
Are you referring what you're supposed to pass to __tls_get_addr when generating a call to __tls_get_addr in the compiler? Or is it in the runtime where you need to access the TLS data to get the roots for the GC?
Here are the dirty details: On Linux and FreeBSD, the module id and size of the TLS section is found in the ELF structure dl_phdr_info. The module id is converted to a pointer to the first byte of the TLS section for every thread: auto ti = tls_index(moduleId, 0); return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz]; (sz is the size) Solaris does not have the dl_phdr_info.dlpi_tls_modid field therefore this methods breaks. But I think I found the solution. After reading the link you posted the tenth time I realized the following sentence: "The static TLS arena associated with the calculated TLS size tlssizeS, is placed immediately preceding the thread pointer tpt. Accesses to this TLS data is based off of subtractions from tpt." The thread pointer is fs:0 or gs:0 on Intel and r7 on Sparc. The size of the TLS data is found in the ELF header as before. I simply need to do the rounding as documented in the chapter and then I can calculate the required pointer. Great!!! Regards, Kai
Nov 27 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-11-27 18:39, Kai Nacke wrote:

 Here are the dirty details:

 On Linux and FreeBSD, the module id and size of the TLS section is found
 in the ELF structure dl_phdr_info. The module id is converted to a
 pointer to the first byte of the TLS section for every thread:

      auto ti = tls_index(moduleId, 0);
      return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];

 (sz is the size)

 Solaris does not have the dl_phdr_info.dlpi_tls_modid field therefore
 this methods breaks.

 But I think I found the solution. After reading the link you posted the
 tenth time I realized the following sentence:

 "The static TLS arena associated with the calculated TLS size tlssizeS,
 is placed immediately preceding the thread pointer tpt. Accesses to this
 TLS data is based off of subtractions from tpt."

 The thread pointer is fs:0 or gs:0 on Intel and r7 on Sparc. The size of
 the TLS data is found in the ELF header as before. I simply need to do
 the rounding as documented in the chapter and then I can calculate the
 required pointer.

 Great!!!
I don't really understand this but it's great if you found a solution. -- /Jacob Carlborg
Nov 27 2014