|  | glibc.txt: | 
|  | Barret Rhoden | 
|  | Last updated: 2010-08-22 | 
|  | ---------------------------------------------- | 
|  | This document is an attempt to gather knowledge about how to work with the | 
|  | glibc port.  This is based on my half-assed struggling with the port done by | 
|  | kevin and andrew. | 
|  |  | 
|  | When to recompile (other than when changing libc) | 
|  | -------------------------- | 
|  | Whenever you change a kernel header (something in kern/include/ros), | 
|  | technically you should rebuild.  It isn't critical in all places, such as for | 
|  | files that aren't included by glibc, or for files that haven't changed | 
|  | something that glibc relies on. | 
|  |  | 
|  | After any recompile, don't forget to rebuild userspace apps (make userclean, | 
|  | make install-libs) and to refresh your FS. | 
|  |  | 
|  | How to recompile glibc | 
|  | -------------------------- | 
|  | Normally, make x86 (or whatever) works fairly well.  However, sometimes you | 
|  | need to rebuild all of glibc.  This might be on a hunch, or to get rid of | 
|  | things that might have compiled, but are failing to link and don't seem to | 
|  | rebuild.  This happens when you change parts of glibc. | 
|  |  | 
|  | If you know what file(s) you changed and it doesn't seem like the changes are | 
|  | being applied, you can copy the file from the -ros directory to the glibc-XXX | 
|  | directory.  The glibc make process doesn't apply diffs or track the changes | 
|  | from -ros to the glibc directory, so your recompile won't notice the changes. | 
|  |  | 
|  | If things are stil messed up, the next step is to remove the build directories | 
|  | (i686-ros-glibc-*) and also the hidden files (.i686-ros-glibc*).  If you get | 
|  | errors from make very early on about not finding some targets (such as | 
|  | install-headers), you forgot to delete the hidden files. | 
|  |  | 
|  | Then next step up would be to remove the glibc-XXX folder (whatever the | 
|  | version is).  Sometimes you aren't sure if old changes are sitting around in | 
|  | this folder that aren't getting overwritten by the real source of our changes, | 
|  | the -ros folder.  A lovely example of this is an old Makefile for the nss | 
|  | subdir.  It was altered to remove some things, notably the files service, | 
|  | which translates into libnss_files - which is needed by other things (nis, | 
|  | etc).  To fix this, I had to notice an -ros version of the Makefile (after I | 
|  | realized it was the problem), and that the Makefile was being included - it | 
|  | was just faulty. | 
|  |  | 
|  | Finally, you can always make clean, but the overall XCC Makefile will clean | 
|  | everything - including gcc and binutils. | 
|  |  | 
|  | Note that if you are making a trivial addition to a kernel header, you can get | 
|  | away with just copying it to its location in the XCC install directory | 
|  | (sys-include). | 
|  |  | 
|  | The -ros folder | 
|  | -------------------------- | 
|  | All changes to glibc must be made in the glibc-XXX-ros folder.  Any changes | 
|  | here will be copied over to the real glibc folder when it is made.  If you | 
|  | want to remove a file that was originally in the -ros folder, you need to | 
|  | manually remove it from the glibc-XXX folder as well.  The updating scripts | 
|  | will not remove a file. | 
|  |  | 
|  | The sysdeps folder | 
|  | -------------------------- | 
|  | Most of your changes will go here.  Every system that has a glibc port should | 
|  | have one of these folders, with its system-specific ports.  The files here are | 
|  | normally files expected elsewhere in libc, and the glibc build system knows to | 
|  | look in these places. | 
|  |  | 
|  | Simply dropping a file in here will not get it built.  It will for many files, | 
|  | but some others that weren't expected will need to be manually added to a | 
|  | Makefile.  If you notice some files not getting compiled, (drop a #error in | 
|  | there), you'll need to add it to a Makefile.  In the main sysdeps/Makefile, | 
|  | add the filename (minus .c) to the sysdeps var.  Look at sa_len for an | 
|  | example.  Sometimes you'll need to be careful about adding it for some | 
|  | subdirectories and not others (you probably only want to add a C file for one | 
|  | subdir).  Check out Linux's port for help. | 
|  |  | 
|  | Sometimes you have files that you want to change outside of the sysdeps | 
|  | folder.  These still go in the glibc-XXX-ros folder, but not in sysdeps.  The | 
|  | main example we have right now is features.h.  At one point, I wanted to | 
|  | change sys/socket.h.  Simply adding it to sysdeps/ros/sys/socket.h would not | 
|  | change the main sys/socket.h, nor would the sysdep version get included first. | 
|  | Putting it in the -ros/sys/ folder did it (though ultimately I didn't want the | 
|  | change).  The point is, sysdeps doesn't mirror and override the main tree for | 
|  | all files - it is behind some others in the search/include path. | 
|  |  | 
|  | Another situation requiring a change outside of the sysdeps directory was | 
|  | sunrpc/netname.c.  I wanted to change the functions (stub out the ones that | 
|  | used NSS).  Adding the sysdep worked, but it turns out that *both* the sysdep | 
|  | netname.c and the original sunrpc/netname.c were being compiled.  The root | 
|  | cause seems to be compat-netname.os.  There are make rules in sunrpc to | 
|  | generate some compatibility routines.  Grep for rpc-compat-routines.os.  The | 
|  | rule seems to ignore sysdeps and just use the normal C file - in this case | 
|  | netname.c. | 
|  |  | 
|  | Subdirs | 
|  | -------------------------- | 
|  | As a note, these 'subdirectories' are the "primary folders" (i.e. addons), | 
|  | such as inet, ncsd, libio, whatever.  These are the root folders in glibc, | 
|  | representing some major functionality.  They can be built with the | 
|  | --enable-addons switch, which by default builds all of them.  Sort of! | 
|  |  | 
|  | To really get them to even be available for a port, you need to "include" them | 
|  | in a certain manner.  There are two ways.  One is the Subdirs file in the | 
|  | sysdeps/ros/ directory.  Putting a subdir name in here means glibc will try to | 
|  | build it; it is available to be an addon.  Careful with these, since a lot of | 
|  | the folders tend to need each other (like most all of the ones in unix/inet). | 
|  |  | 
|  | If you want a massive subsystem, such as "unix/inet" or "posix", you can add | 
|  | it to the sysdeps/ros/Implies file.  You will get a bunch of these folders at | 
|  | once, plus some other unspecified stuff (necessary for the overall system, | 
|  | perhaps?).  If you add "unix/inet", you get more than just its Subdirs. | 
|  |  | 
|  | Also note that these subdirs can depend on each other, noted in the "Depends" | 
|  | file.  Presumably this will cause them to get made... | 
|  |  | 
|  | Errno & TLS | 
|  | -------------------------- | 
|  | errno is a macro that may point to different locations depending on where you | 
|  | are in Glibc. errno_location is simply one of the options. | 
|  | During dynamic linking, the linker points errno to a different location, so it | 
|  | is usable and can be referenced before TLS is fully set up in TLS_INIT_TP. | 
|  | Because errno is valid when the linker runs, regular syscalls can be made. | 
|  |  | 
|  | However for statically linked apps, several syscalls cannot use the ros_syscall | 
|  | macro, because there is no valid errno set up. | 
|  |  | 
|  | Unimplemented Stubs | 
|  | -------------------------- | 
|  | There are a lot of things we haven't ported, but we have the stub functions so | 
|  | that we can at least compile things against it.  When you compile (including | 
|  | regular programs), you'll get warnings about this. | 
|  |  | 
|  | Linux ASM bits | 
|  | -------------------------- | 
|  | We've included some header files from Linux's kernel.  For now, we just need | 
|  | something to keep glibc happy, even though ROS doesn't have any networking | 
|  | syscalls.  Don't rely on this stuff too much.  These files, and other future | 
|  | glibc compatibility kernel headers, are in kern/include/ros/glibc-asm. | 
|  |  | 
|  | Weak Symbols, start.c, and ros_syscall_blockon | 
|  | -------------------------- | 
|  | For a long time, __ros_syscall_blockon was not getting overridden by the | 
|  | strong symbol in parlib.  This means that glibc's syscalls were not blocking | 
|  | uthreads properly.  Why did the weak symbols work for vcore_entry() and | 
|  | vcore_event_init(), but not blockon? | 
|  |  | 
|  | Side note: we needed to force the linker to find out about vcore_entry and | 
|  | vcore_event_init, via the -u tricks of commit f188983.  The linker is not | 
|  | obligated to look in libraries to override a weak symbol. | 
|  |  | 
|  | The crux of the matter is that start.c is not linked with applications in the | 
|  | same manner as the rest of glibc (notably all the I/O syscalls).  start.c will | 
|  | get linked with the program at compile time, while libc can be linked | 
|  | dynamically.  Because of this, start.c's weak symbols would get (correctly) | 
|  | overridden by the strong symbols of libparlib.a.  But glibc would build | 
|  | libc.so, and that would not get a chance to link against the binary (and | 
|  | libparlib.a) until load time.  The weak symbols in libc get promoted to strong | 
|  | symbols when it is done linking libc.so, and when it later is linked against | 
|  | the program, there is no longer an opportunity to override the weak symbol. | 
|  |  | 
|  | Also note that rtld will never link with parlib, so any weak symbol in there | 
|  | will never get overriden.  I briefly considered linking rtld with -lparlib, | 
|  | but it blows up in a nasty way: parlib needs lots of libc, which rtld is not | 
|  | built with (memset for example). | 
|  |  | 
|  | Anyway, the moral of the story is to be careful with your weak | 
|  | symbols/aliases.  Only put them in start.c, or similar files. | 
|  |  | 
|  | Adding a Global Variable to the ABI | 
|  | -------------------------- | 
|  | It's not enough to simply 'extern' a variable (or declare a function, which is | 
|  | extern by default).  At some point, glibc will change those symbols from | 
|  | GLOBAL to LOCAL. | 
|  |  | 
|  | You need to add an entry to the Versions file (sysdeps/ros/Versions).  Be sure | 
|  | to indent with spaces, not tabs, or else glibc's scripts will not handle your | 
|  | symbol. | 
|  |  | 
|  | Putting them in the libc, glibc 2.0 section seems to work fine. | 
|  |  | 
|  | Tips, Questions, and Misc Notes | 
|  | -------------------------- | 
|  | - Grep and find are your friend. | 
|  | - Watch what Linux does. | 
|  | - The kernel headers end up getting installed to the sys-include/ directory, | 
|  | while the regular glib headers go to the include directory. | 
|  | - atomic_swap might have issues (warnings about signedness differences) | 
|  | - It's not always clear which files in the -ros folder actually need to be | 
|  | there (presumably they all do), and in what manner they were modified and | 
|  | from which original copy.  Ideally, the ROS-specific changes to large files | 
|  | will be commented. | 
|  | - the SHARED flag is a bit of a mess - things get compiled differently for | 
|  | shared vs static, and it can get complicated with start.c, tls.c, etc. | 
|  | - What things in one file rely heavily on another file?  Are there non-obvious | 
|  | gotchas?  (yes, and no one documented them). | 
|  | - Is the build failing without any clear error messages?  Scroll up a lot, and | 
|  | there may be messages farther up (like a hundred+ lines up).  I've had some | 
|  | gcc stage2 builds that fail with no obvious issue in the short term console | 
|  | output, but the real error is much higher.  Some aspect of the build system | 
|  | will continue on failures and only fail much later, after building other | 
|  | packages. | 
|  | - Note that libstdc++ is a subpart of gcc, built during stage2, and has its | 
|  | own configure script and settings. | 
|  |  | 
|  | Ghetto Things (Feel free to fix them): | 
|  | -------------------------- | 
|  | - ptsname: we needed to have the sysdep (was being looked for by the login | 
|  | subdir make process), but having the actual functions in it caused a link | 
|  | error (multiple declarations).  So we have an empty file... |