Index: src/gdb/utils.c =================================================================== --- src.orig/gdb/utils.c +++ src/gdb/utils.c @@ -3071,11 +3071,54 @@ host_address_to_string (const void *addr { char *str = get_cell (); - /* We could use the %p conversion specifier to sprintf if we had any - way of knowing whether this host supports it. But the following - should work on the Alpha and on 32 bit machines. */ - sprintf (str, "0x%lx", (unsigned long) addr); + /* We do not use the %p conversion specifier, because the resulting + image can vary from implementation to implementation. For instance, + some implementations format the pointer value with a leading "0x" + whereas others don't (Solaris, for instance). Also, it is unspecified + whether the alphabetical digits are printed using uppercase letters + or not (in GDB, we want lowercase). + + So we use the %x type instead. This, however, introduces + a couple of issues: + + 1. The %x type expects an integer value, not a pointer. + So we first need to cast our pointer to an integer type + whose size is identical to the size of our pointer. + We use uintptr_t for that. + + 2. The %x type alone expects and int, which is not always + large enough to hold an address. Usually, type "long" + has the same size as pointers, but certain ABIs define + the size of pointers to be larger than the size of long + (64bit Windows is one such example). + + So, to be certain to have a type that's large enough + to hold an address, we need to use "long long". But + the trick is that not all printf implementations support + the "ll" modifier. On those platforms where the "ll" + modifier is not available, we'll assume that type "long" + can be used to print an address. + + To make sure that the type we pass to sprintf matches + the type we specified in our expression, we perform + a second cast to "unsigned long long" if we used "%llx", + or "unsigned long" if we used "%lx". */ + +#if defined(PRINTF_HAS_LONG_LONG) && BITSIZEOF_SIZE_T == 64 && \ + SIZEOF_LONG == 4 + sprintf (str, "0x%llx", (unsigned long long) (uintptr_t) addr); +#elif BITSIZEOF_SIZE_T == 64 && SIZEOF_LONG == 4 + unsigned long long val = (unsigned long) (uintptr_t) addr; + if ((val & ~0xffffffffull) != 0) + sprintf (str, "0x%lx%08lx", + (unsigned long) (val >> 32), (unsigned long) val); + else + sprintf (str, "0x%lx", (unsigned long) (uintptr_t) val); +#else + sprintf (str, "0x%lx", (unsigned long) (uintptr_t) addr); +#endif return str; + BITSIZEOF_SIZE_T SIZEOF_LONG } char *