-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unit test to gdbarch methods register_to_value and value_to_register
This patch adds one unit test for gdbarch methods register_to_value and value_to_register. The test pass different combinations of {regnu, type} to gdbarch_register_to_value and gdbarch_value_to_register. In order to do the test, add a new function create_new_frame to create a fake frame. It can be improved after we converted frame_info to class. In order to isolate regcache (from target_ops operations on writing registers, like target_store_registers), the sub-class of regcache in the test override raw_write. Also, in order to get the right regcache from get_thread_arch_aspace_regcache, the sub-class of regcache inserts itself to current_regcache. Suppose I incorrectly modified the size of buffer as below, @@ -1228,7 +1228,7 @@ ia64_register_to_value (struct frame_info *frame, int regnum, int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); - gdb_byte in[MAX_REGISTER_SIZE]; + gdb_byte in[1]; /* Convert to TYPE. */ if (!get_frame_register_bytes (frame, regnum, 0, build GDB with "-fsanitize=address" and run unittest.exp, asan can detect such error ==2302==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff98193870 at pc 0xbd55ea bp 0x7fff981935a0 sp 0x7fff98193598 WRITE of size 16 at 0x7fff98193870 thread T0 #0 0xbd55e9 in frame_register_unwind(frame_info*, int, int*, int*, lval_type*, unsigned long*, int*, unsigned char*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1119 #1 0xbd58c8 in frame_register(frame_info*, int, int*, int*, lval_type*, unsigned long*, int*, unsigned char*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1147 #2 0xbd6e25 in get_frame_register_bytes(frame_info*, int, unsigned long, int, unsigned char*, int*, int*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1427 #3 0x70080a in ia64_register_to_value /home/yao/SourceCode/gnu/gdb/git/gdb/ia64-tdep.c:1236 #4 0xbf570e in gdbarch_register_to_value(gdbarch*, frame_info*, int, type*, unsigned char*, int*, int*) /home/yao/SourceCode/gnu/gdb/git/gdb/gdbarch.c:2619 #5 0xc05975 in register_to_value_test /home/yao/SourceCode/gnu/gdb/git/gdb/gdbarch-selftests.c:131 Or, even if GDB is not built with asan, GDB just crashes. *** stack smashing detected ***: ./gdb terminated Aborted (core dumped) gdb: 2017-05-24 Yao Qi <[email protected]> * Makefile.in (SFILES): Add gdbarch-selftests.c. (COMMON_OBS): Add gdbarch-selftests.o. * frame.c [GDB_SELF_TESTS] (create_new_frame): New function. * frame.h [GDB_SELF_TESTS] (create_new_frame): Declare. * gdbarch-selftests.c: New file. * regcache.h (regcache) <~regcache>: Mark it virtual if GDB_SELF_TEST. <raw_write>: Likewise.
- Loading branch information
Yao Qi
committed
May 24, 2017
1 parent
e521e87
commit b77b02a
Showing
6 changed files
with
205 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
2017-05-24 Yao Qi <[email protected]> | ||
|
||
* Makefile.in (SFILES): Add gdbarch-selftests.c. | ||
(COMMON_OBS): Add gdbarch-selftests.o. | ||
* frame.c [GDB_SELF_TESTS] (create_new_frame): New function. | ||
* frame.h [GDB_SELF_TESTS] (create_new_frame): Declare. | ||
* gdbarch-selftests.c: New file. | ||
* regcache.h (regcache) <~regcache>: Mark it virtual if | ||
GDB_SELF_TEST. | ||
<raw_write>: Likewise. | ||
|
||
2017-05-24 Yao Qi <[email protected]> | ||
|
||
* regcache.c (current_regcache): Change it to | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* Self tests for gdbarch for GDB, the GNU debugger. | ||
Copyright (C) 2017 Free Software Foundation, Inc. | ||
This file is part of GDB. | ||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
|
||
#include "defs.h" | ||
#if GDB_SELF_TEST | ||
#include "selftest.h" | ||
#include "selftest-arch.h" | ||
#include "inferior.h" | ||
|
||
namespace selftests { | ||
|
||
/* A read-write regcache which doesn't write the target. */ | ||
|
||
class regcache_test : public regcache | ||
{ | ||
public: | ||
explicit regcache_test (struct gdbarch *gdbarch) | ||
: regcache (gdbarch, NULL, false) | ||
{ | ||
set_ptid (inferior_ptid); | ||
|
||
current_regcache.push_front (this); | ||
} | ||
|
||
void raw_write (int regnum, const gdb_byte *buf) override | ||
{ | ||
raw_set_cached_value (regnum, buf); | ||
} | ||
}; | ||
|
||
/* Test gdbarch methods register_to_value and value_to_register. */ | ||
|
||
static void | ||
register_to_value_test (struct gdbarch *gdbarch) | ||
{ | ||
const struct builtin_type *builtin = builtin_type (gdbarch); | ||
struct type *types[] = | ||
{ | ||
builtin->builtin_void, | ||
builtin->builtin_char, | ||
builtin->builtin_short, | ||
builtin->builtin_int, | ||
builtin->builtin_long, | ||
builtin->builtin_signed_char, | ||
builtin->builtin_unsigned_short, | ||
builtin->builtin_unsigned_int, | ||
builtin->builtin_unsigned_long, | ||
builtin->builtin_float, | ||
builtin->builtin_double, | ||
builtin->builtin_long_double, | ||
builtin->builtin_complex, | ||
builtin->builtin_double_complex, | ||
builtin->builtin_string, | ||
builtin->builtin_bool, | ||
builtin->builtin_long_long, | ||
builtin->builtin_unsigned_long_long, | ||
builtin->builtin_int8, | ||
builtin->builtin_uint8, | ||
builtin->builtin_int16, | ||
builtin->builtin_uint16, | ||
builtin->builtin_int32, | ||
builtin->builtin_uint32, | ||
builtin->builtin_int64, | ||
builtin->builtin_uint64, | ||
builtin->builtin_int128, | ||
builtin->builtin_uint128, | ||
builtin->builtin_char16, | ||
builtin->builtin_char32, | ||
}; | ||
|
||
current_inferior()->gdbarch = gdbarch; | ||
|
||
struct regcache *regcache = new regcache_test (gdbarch); | ||
struct frame_info *frame = create_test_frame (regcache); | ||
const int num_regs = (gdbarch_num_regs (gdbarch) | ||
+ gdbarch_num_pseudo_regs (gdbarch)); | ||
|
||
SELF_CHECK (regcache == get_current_regcache ()); | ||
|
||
/* Test gdbarch methods register_to_value and value_to_register with | ||
different combinations of register numbers and types. */ | ||
for (const auto &type : types) | ||
{ | ||
for (auto regnum = 0; regnum < num_regs; regnum++) | ||
{ | ||
if (gdbarch_convert_register_p (gdbarch, regnum, type)) | ||
{ | ||
std::vector<gdb_byte> expected (TYPE_LENGTH (type), 0); | ||
|
||
if (TYPE_CODE (type) == TYPE_CODE_FLT) | ||
{ | ||
DOUBLEST d = 1.25; | ||
|
||
/* Generate valid float format. */ | ||
floatformat_from_doublest (floatformat_from_type (type), | ||
&d, expected.data ()); | ||
} | ||
else | ||
{ | ||
for (auto j = 0; j < expected.size (); j++) | ||
expected[j] = (regnum + j) % 16; | ||
} | ||
|
||
gdbarch_value_to_register (gdbarch, frame, regnum, type, | ||
expected.data ()); | ||
|
||
/* Allocate two bytes more for overflow check. */ | ||
std::vector<gdb_byte> buf (TYPE_LENGTH (type) + 2, 0); | ||
int optim, unavail, ok; | ||
|
||
/* Set the fingerprint in the last two bytes. */ | ||
buf [TYPE_LENGTH (type)]= 'w'; | ||
buf [TYPE_LENGTH (type) + 1]= 'l'; | ||
ok = gdbarch_register_to_value (gdbarch, frame, regnum, type, | ||
buf.data (), &optim, &unavail); | ||
|
||
SELF_CHECK (ok); | ||
SELF_CHECK (!optim); | ||
SELF_CHECK (!unavail); | ||
|
||
SELF_CHECK (buf[TYPE_LENGTH (type)] == 'w'); | ||
SELF_CHECK (buf[TYPE_LENGTH (type) + 1] == 'l'); | ||
|
||
for (auto k = 0; k < TYPE_LENGTH(type); k++) | ||
SELF_CHECK (buf[k] == expected[k]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // namespace selftests | ||
#endif /* GDB_SELF_TEST */ | ||
|
||
void | ||
_initialize_gdbarch_selftests (void) | ||
{ | ||
#if GDB_SELF_TEST | ||
register_self_test_foreach_arch (selftests::register_to_value_test); | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters