Next Previous Contents

1. The GNU C Library

The latest version of GLIBC is based on the official GNU 2.1 release. The changes made by Rebel.com and Phil Blundell are fully integrated into the main source tree. It is possible to get the source from the GLIBC CVS archive and build it for the NetWinder without patches. The next disk image release (build 15) uses this latest version of GLIBC.

Note that the GLIBC used on the NetWinder has versioning disabled. When we first started shipping the NetWinder, versioning was broken in GLIBC on the ARM. This causes problems for us as GLIBC is backwards compatible with LIBC 2.0, but not backwards compatible with a non-versioned build of 2.1. As a consequence, the upgrading to a versioned libc is a big job. All the executables have to be upgraded as well.

The Titan, Debian and Redhat distributions currently being worked upon are all using versioned GLIBC libraries. Eventually Rebel.com will as well.

1.1 Fixed bugs

The tftphdr structure in /usr/include/arpa/tftp.h had problems due to the alignment on the ARM. The structure as it comes across the network is 5 bytes of packed data, while the struct on the arm has padding after the initial short, the union, and is padded to an even number of words in length. Adding __attribute__ ((packed)) to the struct as shown below fixes the problem.

         struct { 
           short th_opcode; 
           union { 
             unsigned short tu_block; 
             short tu_code; 
             char tu_stuff[1]; 
           } __attribute__ ((packed)) th_u 
           char th_data[1] __attribute__ ((packed)); 
         } __attribute__ ((packed)) tftphdr; 

This bug is known to break the tftp client, tftpd daemon, and the NetWinder firmware. It is fixed in the current GLIBC.

The ether_header and ether_addr structures in /usr/include/net/ethernet.h had problems due to the alignment on the ARM. Both structures have padding problems at the end of the structure making them a different length than the data that is received across the wire. Adding __attribute__ ((packed)) to the structures as shown below fixes the problem.

         struct ether_addr { 
           u_int8_t ether_addr_octet[ETH_ALEN];
         } __attribute__ ((packed)); 

         struct ether_header { 
           u_int8_t ether_dhost[ETH_ALEN];
           u_int8_t ether_shost[ETH_ALEN];
           u_int16_t ether_type;
         } __attribute__ ((packed));

This bug is known to break tcpdump. Actually tcpdump defines it's own version of these structures, but the principle is the same. I have sent a bug report to the tcpdump maintainers. This bug is fixed in the current GLIBC sources.

I found a nasty bug in the ARM socket call code. We had a bug with ping. It was always printing the error `Socket operation on non-socket.`. At least on my machine. On others a different error would occur.

strace showed the recvfrom call in ping was failing on restart after the SIGALRM signal was handled. Its parameters on restart were garbage. This is because the socket call never modified sp; it moved sp into ip and used ip to push the args, so it never had to clean up the stack.

This is nice as it saves one instruction, however the syscall is not an atomic operation. It can be interrupted if a signal occurs. If the signal handler used any stack it trashed the socket call args, because according to it the next available stack slot is pointed at by sp.

Now for the really bad news. mmap() suffers from the same bug. All of these bugs have been fixed and integrated into the CVS source tree. The current GLIBC RPM on netwinder.org also contains these fixes.


Next Previous Contents