Mar 5, 2010

GCC Macro Questions

http://lists.uclibc.org/pipermail/uclibc/2007-September/039311.html

On Saturday 15 September 2007, Denys Vlasenko wrote:
> On Saturday 15 September 2007 09:19, Mike Frysinger wrote:
> > On Monday 30 July 2007, Denis Vlasenko wrote:
> >/* The following macros are used for PLT bypassing within libc.so
> >   (and if needed other libraries similarly).
> >   First of all, you need to have the function prototyped somewhere,
> >   say in foo/foo.h:
> >
> >   int foo (int __bar);
> >
> >   If calls to foo within libc.so should always go to foo defined in
> > libc.so, then in include/foo.h you add:
> >
> >   libc_hidden_proto (foo)
> >
> >   line and after the foo function definition:
> >
> >   int foo (int __bar)
> >   {
> >     return __bar;
> >   }
> >   libc_hidden_def (foo)
> >
> >   or
> >
> >   int foo (int __bar)
> >   {
> >     return __bar;
> >   }
> >   libc_hidden_weak (foo)
>
> I have several questions. first one:
>
> libc_hidden_def (foo) /* whan to use this?... */
> libc_hidden_weak (foo) /* ...and when this? */

it depends on how you want the global symbol defined ... historically, glibc 
has had some exported symbols defined as weak (like the string symbols or the 
malloc api) so that users can override those symbols.  unless you know for 
sure you want the exported symbol a weak one, use libc_hidden_def()

> Next. In actual uclibc code, usage is different. For example,
> libc_hidden_proto(mmap) and libc_hidden_def(mmap) are scattered in 16
> files. 15 of them .c files and remaining one is malloc.h. Why?

there should only be one libc_hidden_def(mmap) per build ... grepping ... yep, 
that's the case

the abundance of libc_hidden_proto() in files is because we havent done what 
glibc has (and we really should transition to) by creating local copies of 
headers which simply contain libc_hidden_proto() decls so that individual 
files dont need them.

think of libc_hidden_proto() as a function prototype and libc_hidden_def() as 
the function definition ... the proto makes sure everyone who calls said 
function uses the internal hidden version while the def creates that internal 
hidden version.  thus you should see libc_hidden_proto(mmap) in every file 
that calls mmap() while you should see libc_hidden_proto(mmap) in every file 
that defines mmap().

> Next. The names of thse macros are not decriptive. "libc_hidden_def(foo)".
> Hmmm. It must be a "hidden definition of foo"?

all the indirection is so that certain features can control minute behaviors 
in visibility and across libraries (doing symbol hidding in libm or libc or 
librt or ...).  yes it can get pretty crazy, but it's to prevent duplication.

> What is __USER_LABEL_PREFIX__? It is never defined.

gcc defines it for some ports to the ABI prefix (most likely an underscore).  
on pretty much every Linux arch out there, it'll be:
#define __USER_LABEL_PREFIX__
but on say Blackfin, it'll be:
#define __USER_LABEL_PREFIX__ _
since all C symbols in Blackfin have an underscore prefix

> So it is converted into
>
> extern __typeof (foo) __EI_foo __asm__(__USER_LABEL_PREFIX__"foo");
> extern __typeof (foo) __EI_foo __attribute__((alias ("__GI_foo")));
>
> Hrm, so __USER_LABEL_PREFIX__ will vanish? Why? Oh well...
>
> Ok, googling...
> So "__EI_foo" in C will be equivalent to "foo" in asm. Why is this needed?

this is the hidden direction alluded to at the begginning of the file to avoid 
going through the PLT.  libc_hidden_proto(mmap) pretty much expands into:
extern __typeof(mmap) mmap asm("__GI_mmap") 
__attribute__((visibility("hidden")));
this tells anyone who wishes to call mmap() to use the hidden ELF symbol 
__GI_mmap instead of the global ELF symbol mmap.  at link time, all hidden 
ELF relocs get processed and dropped while at run time, all global ELF relocs 
get processed.  we put a lot more overhead into the source code so that at 
runtime, the overhead (speed/size) is significantly decreased.

now consider libc_hidden_proto(mmap) which expands to:
extern __typeof(mmap) __EI_mmap asm("mmap");
extern __typeof(mmap) __EI_mmap __attribute__((alias("__GI_mmap")));
this goes in the file where the mmap symbol is defined and creates the actual 
binding between the global mmap ELF symbol and the hidden __GI_mmap ELF 
symbol.

pretty simple eh ? :)

> Anyway I have a feeling that I am lost in the #define maze
> and the only thing which I understand is that
>
> libc_hidden_def(foo)
>
> is not a "hidden definition of foo", it's a "definition of hidden symbol
> _MAGIC_JUNK_foo which is aliased to foo", and

correct

> libc_hidden_proto(foo)
>
> is not a "hidden prototype of foo" but rather "please make all references
> to foo in this .c file refer to _MAGIC_JUNK_foo".

correct

> Which is utterly confusing.

not really ... you cant combine the symbols since they have conflicting 
visibility, so you need to create a little bit of indirection

> Can I have macro names which do not lie to me?
>
> libc_define_internal_alias(foo)
>   [or libc_define_internal_name(foo) or libc_define_internal(foo) or...]
> and
> libc_use_internal_alias(foo)

*shrug* we took it from glibc so changing the names would just put an annoying 
support burden on us

> > more to the point ... how exactly would __uc_malloc be useful ?  i dont
> > think ive ever seen malloc() return NULL as the kernel is the first to
> > find out about the OOM situation and properly nukes any userspace app
> > before it ever sees the relevant NULL ...
>
> malloc may fail because this particular process has memory limits set:
>
> softlimit -m 300000 passwd
>
> (softlimit is a busybox applet)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.