diff options
author | Tom Tromey <tromey@adacore.com> | 2019-11-14 15:00:19 -0700 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2019-11-21 14:39:40 -0700 |
commit | 6ba185213659517b4299a3e4c92813839f19f045 (patch) | |
tree | 78644366f6071accd40a41a98eaea41d1d0e0615 /gdb/gdbsupport/format.c | |
parent | 34877895ca38f74ae31bd65a6916560020d9d62b (diff) | |
download | gdb-6ba185213659517b4299a3e4c92813839f19f045.zip gdb-6ba185213659517b4299a3e4c92813839f19f045.tar.gz gdb-6ba185213659517b4299a3e4c92813839f19f045.tar.bz2 |
Handle %I64d in format_pieces
We found a bug internally where gdb would crash while disassembling a
certain instruction. This was tracked down to the handling of %I64d
in format_pieces.
format_pieces will convert %ll to %I64d on mingw -- so format_pieces
should also handle parsing this format. In this patch, I've made the
parsing unconditional, since I think it is harmless to accept extra
formats. I've also taken the opportunity to convert the length
modifier test to a "switch".
Tested internally using our failing test case.
gdb/ChangeLog
2019-11-21 Tom Tromey <tromey@adacore.com>
* gdbsupport/format.c (format_pieces): Parse %I64d.
* unittests/format_pieces-selftests.c (test_windows_formats): New
function.
(run_tests): Call it.
Change-Id: If335c7c2fc8d01e629cd55182394a483334d79c7
Diffstat (limited to 'gdb/gdbsupport/format.c')
-rw-r--r-- | gdb/gdbsupport/format.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/gdb/gdbsupport/format.c b/gdb/gdbsupport/format.c index 2e2d90a..67daa6d 100644 --- a/gdb/gdbsupport/format.c +++ b/gdb/gdbsupport/format.c @@ -126,6 +126,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions) int seen_size_t = 0; int bad = 0; int n_int_args = 0; + bool seen_i64 = false; /* Skip over "%%", it will become part of a literal piece. */ if (*f == '%') @@ -195,13 +196,13 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions) } /* The next part of a format specifier is a length modifier. */ - if (*f == 'h') + switch (*f) { + case 'h': seen_h = 1; f++; - } - else if (*f == 'l') - { + break; + case 'l': f++; lcount++; if (*f == 'l') @@ -209,21 +210,18 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions) f++; lcount++; } - } - else if (*f == 'L') - { + break; + case 'L': seen_big_l = 1; f++; - } - /* Decimal32 modifier. */ - else if (*f == 'H') - { + break; + case 'H': + /* Decimal32 modifier. */ seen_big_h = 1; f++; - } - /* Decimal64 and Decimal128 modifiers. */ - else if (*f == 'D') - { + break; + case 'D': + /* Decimal64 and Decimal128 modifiers. */ f++; /* Check for a Decimal128. */ @@ -234,13 +232,24 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions) } else seen_big_d = 1; - } - /* For size_t or ssize_t. */ - else if (*f == 'z') - { + break; + case 'z': + /* For size_t or ssize_t. */ seen_size_t = 1; f++; - } + break; + case 'I': + /* Support the Windows '%I64' extension, because an + earlier call to format_pieces might have converted %lld + to %I64d. */ + if (f[1] == '6' && f[2] == '4') + { + f += 3; + lcount = 2; + seen_i64 = true; + } + break; + } switch (*f) { @@ -353,7 +362,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions) sub_start = current_substring; - if (lcount > 1 && USE_PRINTF_I64) + if (lcount > 1 && !seen_i64 && USE_PRINTF_I64) { /* Windows' printf does support long long, but not the usual way. Convert %lld to %I64d. */ |