mailing list of musl libc
 help / color / mirror / code / Atom feed
* C++ ABI TODO list
@ 2013-07-20  5:26 Rich Felker
  2013-07-22 15:45 ` Rich Felker
  0 siblings, 1 reply; 3+ messages in thread
From: Rich Felker @ 2013-07-20  5:26 UTC (permalink / raw)
  To: musl

Here are the changes I'm aware of that would be needed to bring musl's
C++ ABI in line with glibc/LSB, enabling C++ library reuse with musl:

Making FILE match is easy: __FILE_s -> _IO_FILE

glibc defines mbstate_t as a structure with no tag. As far as I can
tell (simple C++ test program), the name mangling then comes fully
from the typedef name, so I think we might be okay on mbstate_t
already.

glibc's fpos_t is defined as _G_fpos_t or _G_fpos64_t depending on
_FILE_OFFSET_BITS, so the type name for C++ name mangling should be
_G_fpos64_t on 32-bit machines, but I'm uncertain which it should be
on 64-bit ones. Does anybody use these horrible fpos functions anyway?

Fixing jmp_buf and sigjmp_buf requires making them both the same type,
struct __jmp_buf_tag. Instead of storing a whole HURD sigset, the
unified jmp_buf should only store _NSIG. The full type with the extra
slots for sigsets (not just space for machine regs) should be defined
in alltypes.h (since it needs to be aware of the number of signals the
arch has, and _NSIG is not visible in setjmp.h).

In order to keep the error detection properties of musl's pthread_t,
it should be redefined as:

#ifdef __cplusplus
TYPEDEF unsigned long pthread_t;
#else
TYPEDEF struct __pthread pthread_t;
#endif

(We could further add similar conditional definition for timer_t.)

Most of the above were taken from the old "Remaining ABI issues"
thread (January 2013) and some quick experimentation with glibc. Note
that the old issues (in that thread) about timer_t having pointer type
are gone; POSIX-2008-TC1 adopted my requested change to remove the
requirement that timer_t have arithmetic type.

I'm hoping the above list is all...

Rich


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++ ABI TODO list
  2013-07-20  5:26 C++ ABI TODO list Rich Felker
@ 2013-07-22 15:45 ` Rich Felker
  2013-07-22 18:20   ` Rich Felker
  0 siblings, 1 reply; 3+ messages in thread
From: Rich Felker @ 2013-07-22 15:45 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 2898 bytes --]

On Sat, Jul 20, 2013 at 01:26:14AM -0400, Rich Felker wrote:
> Here are the changes I'm aware of that would be needed to bring musl's
> C++ ABI in line with glibc/LSB, enabling C++ library reuse with musl:
> [...]
> 
> I'm hoping the above list is all...

It wasn't. I've just committed the first patch for this agenda item,
massively refactoring the headers, reducing the dependency on the
alltypes system where it's not really needed, moving most of the
arch-generic types to a shared alltypes file, and fixing the
low-hanging fruit for ABI compatibility. The reason these changes were
committed together rather than either without the other is:

- Fixing ABI compatibility first would have been ugly when the same
  type was scattered across multiple archs' alltypes files.

- Refactoring without fixing at least some of the low-hanging ABI
  issues would have meant gratuitously writing new alltypes.h.in files
  with the wrong types, only to rewrite them immediately in the next
  commit.

The remaining differences from glibc:

- fd_mask signedness - glibc is wrong; their definition invokes UB
  when used in the headers. I believe they're actually fixing the type
  on their end anyway)

- jmp_buf and sigjmp_buf - fixing this requires changing the
  underlying types to be the same, as discussed before, and is a much
  more functional change than I wanted in this patch.

- pthread_*attr_t - despite just being single integers, glibc has
  these wrapped in structures; changing musl to match will require
  some minor code changes.

- regex_t - glibc's struct tag violates the namespace. we could change
  it just in C++ mode, though...

- regoff_t - glibc's definition is wrong; it's too short on 64-bit
  archs. but we could fix it on 32-bit archs.

- wint_t - glibc has wint_t defined as unsigned int on all archs
  (actually it defers to gcc if gcc defines it, but gcc also defines
  it as unsigned int on at least all current archs). since this is an
  actual arithmetic type, not an opaque type like dev_t, I felt that
  changing it as part of this commit would be too much of a functional
  change. also I need to review whether any code in musl assumes it's
  signed.

So this comes down to only 3-4 changes left to make, each of which
have some impact on the code (either change or just review for
correctness). In other words, the C++ ABI compatibility goal is almost
done.

For those interested, I'm attaching the C++ ABI check tool I've been
using. It's based on the type sizes check code from nsz's musl tools
repo, but with the macros changed (and hacked up a bit to remove
irrelevant types) to output C++ code that gets the compiler to do the
desired name mangling. The intended usage is:

g++ abi.cxx
nm abi.o | sed s/^.*check_// | sort

Then you can diff the outputs from different libcs/compilers to check
for compatibility and get a report of which types differ.

Rich

[-- Attachment #2: abi.cxx --]
[-- Type: text/plain, Size: 7309 bytes --]

#define _GNU_SOURCE 1
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#define SYSLOG_NAMES 1
#include <stddef.h>
#include <sys/types.h>

#include <aio.h>
#include <alloca.h>
#include <ar.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <arpa/telnet.h>
#include <assert.h>
#include <byteswap.h>
#include <complex.h>
#include <cpio.h>
#include <crypt.h>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
#include <elf.h>
#include <endian.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <features.h>
#include <fenv.h>
#include <float.h>
#include <fnmatch.h>
#include <ftw.h>
#include <getopt.h>
#include <glob.h>
#include <grp.h>
#include <iconv.h>
#include <inttypes.h>
#include <iso646.h>
#include <langinfo.h>
#include <lastlog.h>
#include <libgen.h>
#include <libintl.h>
#include <limits.h>
#include <link.h>
#include <locale.h>
#include <malloc.h>
#include <math.h>
#include <memory.h>
#include <mntent.h>
#include <monetary.h>
#include <mqueue.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>
#include <netdb.h>
#include <netinet/icmp6.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netpacket/packet.h>
#include <nl_types.h>
#include <paths.h>
#include <poll.h>
#include <pthread.h>
#include <pty.h>
#include <pwd.h>
#include <regex.h>
#include <resolv.h>
#include <sched.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <search.h>
#include <semaphore.h>
#include <setjmp.h>
#include <shadow.h>
#include <signal.h>
#include <spawn.h>
//#include <stdalign.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
//#include <stdnoreturn.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <sys/acct.h>
//#include <sys/cachectl.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/file.h>
#include <sys/fsuid.h>
#include <sys/inotify.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/kd.h>
#include <sys/klog.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/msg.h>
#include <sys/mtio.h>
#include <sys/param.h>
#include <sys/personality.h>
#include <sys/poll.h>
#include <sys/prctl.h>
#include <sys/procfs.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/reg.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/sem.h>
#include <sys/sendfile.h>
#include <sys/shm.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/soundcard.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
#include <sys/stropts.h>
#include <sys/swap.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/sysinfo.h>
#include <sys/syslog.h>
#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/timerfd.h>
#include <sys/times.h>
#include <sys/timex.h>
#include <sys/types.h>
#include <sys/ucontext.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <sys/vt.h>
#include <sys/wait.h>
#include <sys/xattr.h>
#include <syscall.h>
#include <sysexits.h>
#include <syslog.h>
#include <tar.h>
#include <termios.h>
#include <tgmath.h>
#include <time.h>
#include <ucontext.h>
#include <ulimit.h>
#include <unistd.h>
#include <utime.h>
#include <utmp.h>
#include <utmpx.h>
#include <values.h>
#include <wchar.h>
#include <wctype.h>
#include <wordexp.h>

#define p(x) void check_##x##____ (x dummy) { }
#define q(x) void check_ptr_##x##____ (x * dummy) { }
#define s(x) void check_struct_##x##____ (struct x dummy) { }
q(DIR)
p(Dl_info)
q(FILE)
p(blkcnt_t)
p(blksize_t)
p(caddr_t)
p(cc_t)
p(clock_t)
p(clockid_t)
p(comp_t)
p(dev_t)
p(div_t)
p(double)
p(double_t)
p(fd_mask)
p(fd_set)
p(fenv_t)
p(fexcept_t)
p(float)
p(float_t)
p(fpos_t)
p(fsblkcnt_t)
p(fsfilcnt_t)
p(fsid_t)
p(gid_t)
p(glob_t)
p(iconv_t)
p(id_t)
p(idtype_t)
p(imaxdiv_t)
p(in_addr_t)
p(in_port_t)
p(ino_t)
p(int)
p(int16_t)
p(int32_t)
p(int64_t)
p(int8_t)
p(int_fast16_t)
p(int_fast32_t)
p(int_fast64_t)
p(int_fast8_t)
p(int_least16_t)
p(int_least32_t)
p(int_least64_t)
p(int_least8_t)
p(intmax_t)
p(intptr_t)
p(jmp_buf)
p(key_t)
p(ldiv_t)
p(lldiv_t)
p(locale_t)
p(lwpid_t)
p(mbstate_t)
p(mcontext_t)
p(mode_t)
p(mqd_t)
p(msglen_t)
p(msgqnum_t)
p(n_long)
p(n_short)
p(n_time)
p(nfds_t)
p(nl_catd)
p(nl_item)
p(nlink_t)
p(off_t)
p(pid_t)
p(posix_spawn_file_actions_t)
p(posix_spawnattr_t)
p(prfpregset_t)
p(prgregset_t)
p(prpsinfo_t)
p(prstatus_t)
p(psaddr_t)
p(pthread_attr_t)
p(pthread_barrier_t)
p(pthread_barrierattr_t)
p(pthread_cond_t)
p(pthread_condattr_t)
p(pthread_key_t)
p(pthread_mutex_t)
p(pthread_mutexattr_t)
p(pthread_once_t)
p(pthread_rwlock_t)
p(pthread_rwlockattr_t)
p(pthread_spinlock_t)
p(pthread_t)
p(ptrdiff_t)
p(quad_t)
p(regex_t)
p(register_t)
p(regmatch_t)
p(regoff_t)
p(rlim_t)
p(sa_family_t)
p(sem_t)
p(sig_atomic_t)
p(sig_t)
p(sighandler_t)
p(siginfo_t)
p(sigjmp_buf)
p(sigset_t)
p(size_t)
p(socklen_t)
p(speed_t)
p(ssize_t)
p(stack_t)
s(FTW)

s(acct)
s(acct_v3)
s(addrinfo)
s(aiocb)
s(ar_hdr)
s(arpd_request)
s(arphdr)
s(arpreq)
s(arpreq_old)
s(bandinfo)
s(ccs_modesel_head)
s(cmsghdr)
s(crypt_data)
s(dirent)
s(dl_phdr_info)
s(elf_prpsinfo)
s(elf_prstatus)
s(elf_siginfo)
s(epoll_event)
s(ether_addr)
s(ether_arp)
s(ether_header)
s(ethhdr)
s(f_owner_ex)
s(flock)
s(group)
s(hostent)
s(icmp)
s(icmp6_filter)
s(icmp6_hdr)
s(icmp6_router_renum)
s(icmp_ra_addr)
s(icmphdr)
s(if_nameindex)
s(ifaddr)
s(ifconf)
s(ifmap)
s(ifreq)
s(in_addr)
s(in_pktinfo)
s(inotify_event)
s(iovec)
s(ip)
s(ip_mreq)
s(ip_mreqn)
s(ip_opts)
s(ip_timestamp)
s(ipc_perm)
s(iphdr)
s(ipv6_mreq)
s(itimerspec)
s(itimerval)
s(lastlog)
s(lconv)
s(linger)
s(link_map)
s(mld_hdr)
s(mntent)
s(mq_attr)
s(msgbuf)
s(msghdr)
s(msginfo)
s(msqid_ds)
s(mt_tape_info)
s(mtconfiginfo)
s(mtget)
s(mtop)
s(mtpos)
s(netent)
s(ntptimeval)
s(option)
s(packet_mreq)
s(passwd)
s(pollfd)
s(protoent)
s(qelem)
s(r_debug)
s(res_sym)
s(rlimit)
s(rr_pco_match)
s(rr_pco_use)
s(rr_result)
s(rtentry)
s(rusage)
s(sched_param)
s(sembuf)
s(semid_ds)
s(seminfo)
s(servent)
s(sg_header)
s(sg_io_hdr)
s(sg_iovec)
s(sg_req_info)
s(sg_scsi_id)
s(shm_info)
s(shmid_ds)
s(shminfo)
s(sigaction)
s(sigcontext)
s(sigevent)
s(signalfd_siginfo)
s(sockaddr)
s(sockaddr_in)
s(sockaddr_in6)
s(sockaddr_ll)
s(sockaddr_storage)
s(sockaddr_un)
s(spwd)
s(stat)
s(statfs)
s(statvfs)
s(str_list)
s(str_mlist)
s(strbuf)
s(strfdinsert)
s(strioctl)
s(strpeek)
s(strrecvfd)
s(termios)
s(timespec)
s(timestamp)
s(timeval)
s(timex)
s(tm)
s(tms)
s(ucred)
s(udphdr)
s(user)
s(utimbuf)
s(utmpx)
s(utsname)
s(winsize)

p(suseconds_t)
p(tcflag_t)
p(time_t)
p(timer_t)
p(u_char)
p(u_int)
p(u_int16_t)
p(u_int32_t)
p(u_int64_t)
p(u_int8_t)
p(u_long)
p(u_quad_t)
p(u_short)
p(ucontext_t)
p(uid_t)
p(uint)
p(uint16_t)
p(uint32_t)
p(uint64_t)
p(uint8_t)
p(uint_fast16_t)
p(uint_fast32_t)
p(uint_fast64_t)
p(uint_fast8_t)
p(uint_least16_t)
p(uint_least32_t)
p(uint_least64_t)
p(uint_least8_t)
p(uintmax_t)
p(uintptr_t)
p(ulong)
//p(union sigval)
p(ushort)
p(va_list)
p(wchar_t)
p(wctrans_t)
p(wctype_t)
p(wint_t)
p(wordexp_t)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++ ABI TODO list
  2013-07-22 15:45 ` Rich Felker
@ 2013-07-22 18:20   ` Rich Felker
  0 siblings, 0 replies; 3+ messages in thread
From: Rich Felker @ 2013-07-22 18:20 UTC (permalink / raw)
  To: musl

On Mon, Jul 22, 2013 at 11:45:51AM -0400, Rich Felker wrote:
> - regex_t - glibc's struct tag violates the namespace. we could change
>   it just in C++ mode, though...

I was mistaken about this. re_* is in the reserved namespace, so we
can simply use re_pattern_buffer unconditionally. I'll change it.

> - regoff_t - glibc's definition is wrong; it's too short on 64-bit
>   archs. but we could fix it on 32-bit archs.

I'm going to try to fix this too. regoff_t can just be defined with
the _Addr macro from alltypes.h, but I'd rather avoid spreading use of
that macro, which is intended to be alltypes-internal, so I'll
probably just move regoff_t itself into alltypes.

Rich


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-07-22 18:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-20  5:26 C++ ABI TODO list Rich Felker
2013-07-22 15:45 ` Rich Felker
2013-07-22 18:20   ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).