diff --git a/gdb/utils.c b/gdb/utils.c index 9e2dfd7..dd606a2 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -3071,10 +3071,44 @@ 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" + is large enough to contain 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". */ + +#ifdef PRINTF_HAS_LONG_LONG + sprintf (str, "0x%llx", (unsigned long long) (uintptr_t) addr); +#else + sprintf (str, "0x%lx", (unsigned long) (uintptr_t) addr); +#endif return str; }