Date: Wed, 13 Jan 2016 22:58:35 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Konstantin Belousov <kostikbel@gmail.com> Cc: Bruce Evans <brde@optusnet.com.au>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r293792 - head/sys/boot/uboot/lib Message-ID: <20160113215530.Y2397@besplex.bde.org> In-Reply-To: <20160113091418.GD72455@kib.kiev.ua> References: <201601130022.u0D0MCWu029299@repo.freebsd.org> <20160113142527.U1277@besplex.bde.org> <20160113091418.GD72455@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 13 Jan 2016, Konstantin Belousov wrote: > On Wed, Jan 13, 2016 at 03:03:07PM +1100, Bruce Evans wrote: >> Oops. It is only declared in <machine/profile.h> outside of the kernel. >> Only __uintfptr_t is always declared by sys/types.h. > > So what is the intended use of the uintfptr_t type ? Looking at the > implementation only, I am unable to find a difference with uintptr_t. uintfptr_t is inded for functions. uintptr_t is an optional type that is only required to work for object pointers (only if it is a supported option of course). A similar type is needed for functions. I added uintfptr_t at much the same time that I added uintptr_t in 1998. Actually I added uintptr_t a little earlier under a different name, then changed it to be more like the draft C9x name uintptr_t. Unfortunately, standards haven't caught up with that yet. POSIX now uses various hacks near dlsym(). In the 2001 version it specifies impossible things if the arch is not a vax so that function pointers are too different from data pointers. It gives the bad example of casting dlsym() to a function pointer. dlsym() returns void *. dlopen() doesn't have this design error. It returns a handle. > Even on ia64 it is 64bit, which breaks my hypothesis about f standing > for 'function'. This might be a bug in ia64, but uintfptr_t works on it AFAIK. It is used for profiling. This is hard to test since profiling support is broken (profiling libraries not installed) on pluto. Function pointers have size 64 bits on ia64, so they can be represented in uint64_t's by memcpy()ing them. Casting them might give a different representation. I think ia64 really has fat function pointers but they are represented specially in 64-bit objects. E.g., in a small program, nm says that putchar is at 0x100000640, but when (putchar) is cast to int (*f)(int), the bits in f are 0x1000acbb0 and casting f to uint64_t doesn't change these bits. f is just a pointer to data containing the actual function address and possibly other data. (It points to .opd+16 which contains the same address that nm prints. There seem to be only 64 bits of address and no extra data there too.) binutils has to understand this of course. Profiling too. I think gprof doesn't understand this. It needs raw addresses represented in uintfptr_t with the same encoding that ELF uses. So uintfptr_t is not suitable for representing function pointers after all. It is for raw addresses or a simple encoding of them. Profiling hits record the "program counter". It is not obvious what this is when it might be represented indirectly. I think its raw register value is recorded, and this can only work if its value is a raw virtual address (if not, a table must be looked up to convert to something that gprof understand). Other data must use the same representation or convert to it. Data with C function pointers in it would need conversion. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160113215530.Y2397>