Text relocations in shared libs
7 answers - 2303 bytes -

[Thanks to Nick Hudson for discovering this]
For sh3 a few shared libraries in the base system has text
relocations. This means that ld.so needs to perform relocations
during startup. E.g.
nada# ktruss echo
600 1 echo open("/lib/libc.so.12", 0, 0xfffff804) = 3, 6214
600 1 echo __fstat30(0x3, 0x7fffd82c) = 0, 6214
600 1 echo mmap(0, 0x1000, 0x1, 0x1, 0x3, 0, 0, 0) = 0x20434000
600 1 echo munmap(0x20434000, 0x1000) = 0, 541254268
600 1 echo mmap(0, 0xdc000, 0x5, 0x10000002, 0x3, 0, 0, 0) = 0x20440000
600 1 echo mmap(0x20505000, 0x8000, 0x3, 0x12, 0x3, 0, 0xb5000, 0) = 0x20505000
600 1 echo mmap(0x2050d000, 0xf000, 0x3, 0x1012, 0xffffffff, 0, 0, 0) = 0x2050d000
600 1 echo mprotect(0x204f6000, 0xf000, 0) = 0
600 1 echo close(0x3) = 0, 831372
!->600 1 echo mprotect(0x20440000, 0xb6000, 0x7) = 0
!->600 1 echo mprotect(0x20440000, 0xb6000, 0x5) = 0
This also means that the pages are no longer shared.
libraries are libc, libposix, and libpthread. Text
relocations come from the handwritten asm files. libc and libposix
(that borrows SYS.h code from libc) has a lot of relocs for cerror:
#define _SYSCALL(x,y)\
.text;\
911:mov.l912f, r3;\
brafr3;\
nop;\
.align2;\
912:.longcerror-(911b+6);\
^^^^^^^^^^^^^^^^^^^^^^^
_SYSCALL_NERRR(x,y);\
bf911b;\
nop
A proper PIC call would be to set up r12 and do the call via plt, but
that raises a number of questions.
plt destroys r0, where syscall code passes errno, so that would either
cause a flag day, or we will need to introduce a flag or'ed into the
syscall number, that would tell the kernel to use a different return
convention.
The benefits of calling cerror via plt are not clear, b/c there's
little point in allowing cerror to be overridden, after all it's just
the error path factored out of all the syscalls. I'm really inclined
to think that making cerror .protected or even .hidden is the right
thing to do.
libposix will need a copy of cerror to compensate for that change.
Another possible solution is to change libposix to (tail)call into
libc instead of duplicating the actual syscall code in libposix.
Ideas?
SY, Uwe
No.1 | | 1135 bytes |
| 
Quoting "Valeriy E. Ushakov" <uwe (AT) ptc (DOT) spbu.ru>:
#define _SYSCALL(x,y) \
.text; \
911: mov.l 912f, r3; \
braf r3; \
nop; \
.align 2; \
912: .long cerror-(911b+6); \
^^^^^^^^^^^^^^^^^^^^^^^
_SYSCALL_NERRR(x,y); \
bf 911b; \
nop
A proper PIC call would be to set up r12 and do the call via plt, but
that raises a number of questions.
plt destroys r0, where syscall code passes errno, so that would either
cause a flag day,
What prevents you from just moving errno to a different register before
executing the PLT? Surely you have another callee-saved register you
can destroy. You can probably even put the move instruction in one of
the branch delay slots, so it doesn't cost you anything.
It would cause a flag day only in the sense that libposix and libpthread
would have to be updated in sync with libc, because of the new cerror
calling convention, but I think this is minor -- owing both to a limited
number of users, and the fact that nothing in the build or install
process uses either of those libraries.
No.2 | | 645 bytes |
| 
Sun, Dec 25, 2005 at 13:54:13 -0500, Charles M. Hannum wrote:
What prevents you from just moving errno to a different register before
executing the PLT? Surely you have another callee-saved register you
can destroy. You can probably even put the move instruction in one of
the branch delay slots, so it doesn't cost you anything.
Right, but that kinda reinforces my other point. If the interface
between syscall code and cerror is private, why do we need to bother
with exporting cerror at all? We can just make it .hidden and make
the call to go directly to cerror, instead of going via PLT.
SY, Uwe
No.3 | | 852 bytes |
| 
Valeriy E. Ushakov wrote:
Sun, Dec 25, 2005 at 13:54:13 -0500, Charles M. Hannum wrote:
>>What prevents you from just moving errno to a different register before
>>executing the PLT? Surely you have another callee-saved register you
>>can destroy. You can probably even put the move instruction in one of
>>the branch delay slots, so it doesn't cost you anything.
Right, but that kinda reinforces my other point. If the interface
between syscall code and cerror is private, why do we need to bother
with exporting cerror at all? We can just make it .hidden and make
the call to go directly to cerror, instead of going via PLT.
cerror is also used by libposix. So either posix will need its own or
able to use libc's.
No.4 | | 1474 bytes |
| 
Mon, Dec 26, 2005 at 19:32:26 -0800, Matt Thomas wrote:
Sun, Dec 25, 2005 at 13:54:13 -0500, Charles M. Hannum wrote:
What prevents you from just moving errno to a different register
before executing the PLT? Surely you have another callee-saved
register you can destroy. You can probably even put the move
instruction in one of the branch delay slots, so it doesn't cost
you anything.
Right, but that kinda reinforces my other point. If the interface
between syscall code and cerror is private, why do we need to
bother with exporting cerror at all? We can just make it .hidden
and make the call to go directly to cerror, instead of going via
PLT.
cerror is also used by libposix. So either posix will need its own
or able to use libc's.
I know. As I said in my original mail:
| libposix will need a copy of cerror to compensate for that change.
| Another possible solution is to change libposix to (tail)call into
| libc instead of duplicating the actual syscall code in libposix.
and I think calling libc is a cleaner option, with code like the
following:
#include <sys/cdefs.h>
extern int __posix_rename(const char *, const char *);
#ifdef __weak_alias
#define rename _rename
__weak_alias(rename,_rename)
#endif
int
rename(const char *from, const char *to)
{
return __posix_rename(from, to);
}
SY, Uwe
No.5 | | 562 bytes |
| 
Sunday 25 December 2005 13:02, Valeriy E. Ushakov wrote:
[]
The benefits of calling cerror via plt are not clear, b/c there's
little point in allowing cerror to be overridden, after all it's just
the error path factored out of all the syscalls. I'm really inclined
to think that making cerror .protected or even .hidden is the right
thing to do.
Aren't there *lots* of symbols in libc that don't need to be exposed? Why
special case cerror and the others with text relocations in libc?
Nick
No.6 | | 1187 bytes |
| 
Tue, Dec 27, 2005 at 08:51:33 +0000, Nick Hudson wrote:
Sunday 25 December 2005 13:02, Valeriy E. Ushakov wrote:
[]
The benefits of calling cerror via plt are not clear, b/c there's
little point in allowing cerror to be overridden, after all it's just
the error path factored out of all the syscalls. I'm really inclined
to think that making cerror .protected or even .hidden is the right
thing to do.
Aren't there *lots* of symbols in libc that don't need to be
exposed? Why special case cerror and the others with text
relocations in libc?
Well, ideally we should use version script to only export from libc.so
(and other shared libs) what's meant to be exported, but that's a
topic for another thread.
cerror is "special" in that it does not even have a defined interface,
except a private one between it and SYSCALL macros. It's really just
a common error path factored out of syscall functions. Pretending
that it is really exported and thus forthing all *jumps* (not even
calls) to it from the syscall functions go via PLT seems just
counterproductive.
SY, Uwe
No.7 | | 571 bytes |
| 
Tue, 27 Dec 2005 12:00:39 +0300,
"Valeriy E. Ushakov" <uwe (AT) ptc (DOT) spbu.rusaid:
Well, ideally we should use version script to only export from libc.so
(and other shared libs) what's meant to be exported, but that's a
topic for another thread.
topic note:
Sometimes it's difficult to decide what should be exported.
For example, someone might think we shouldn't export "_open",
but some HPC frameworks (e.g. checkpointing package) need to
override "_open" and other internal entry points of system calls.