Gnulib generates a warning if the system version of certain functions
are used (to redirect the developer to use Gnulib version). It caused a
compiler error when...
- Compiled with Clang
- -Werror is specified (by default)
- C++ standard used by Clang is before C++17 (by default as of 15.0.0)
when this unit test is activated.
This issue is raised as PR28413.
However, previous proposal to fix this issue (a "fix" to Gnulib):
<https://lists.gnu.org/archive/html/bug-gnulib/2021-10/msg00003.html>
was rejected because it ruins the intent of Gnulib warnings.
So, we need a Binutils/GDB-side solution.
This commit tries to address this issue on the GDB side. We have
"include/diagnostics.h" to disable certain warnings only when necessary.
This commit suppresses the Gnulib warnings by surrounding entire #include
block with DIAGNOSTIC_IGNORE_USER_DEFINED_WARNINGS to disable Gnulib-
generated warnings on all standard C++ header files.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28413
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Change-Id: Ieeb5a31a6902808d4c7263a2868ae19a35e0ccaa
When running selftest run_on_main_thread and pressing ^C, we can run into:
...
Running selftest run_on_main_thread.
terminate called without an active exception
Fatal signal: Aborted
...
The selftest function looks like this:
...
static void
run_tests ()
{
std::thread thread;
done = false;
{
gdb::block_signals blocker;
thread = std::thread (set_done);
}
while (!done && gdb_do_one_event () >= 0)
;
/* Actually the test will just hang, but we want to test
something. */
SELF_CHECK (done);
thread.join ();
}
...
The error message we see is due to the destructor of thread being called while
thread is joinable.
This is supposed to be taken care of by thread.join (), but the ^C prevents
that one from being called, while the destructor is still called.
Fix this by ensuring thread.join () is called (if indeed required) before the
destructor using SCOPE_EXIT.
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29549
With commit 18a5766d09 ("[gdbsupport] Add sequential_for_each") I added a
drop-in replacement for gdb::parallel_for_each, but there's nothing making
sure that the two remain in sync.
Extend the unit test for gdb::parallel_for_each to test both.
Do this using a slightly unusual file-self-inclusion. Doing so keep things
readable and maintainable, and avoids macrofying functions.
Tested on x86_64-linux.
Add a task_size parameter to parallel_for_each, defaulting to nullptr, and use
the task size to distribute similarly-sized chunks to the threads.
Tested on x86_64-linux.
This adds gdb::make_function_view, which lets you create a function
view from a callable without specifying the function_view's template
parameter. For example, this:
auto lambda = [&] (int) { ... };
auto fv = gdb::make_function_view (lambda);
instead of:
auto lambda = [&] (int) { ... };
gdb::function_view<void (int)> fv = lambda;
It is particularly useful if you have a template function with an
optional function_view parameter, whose type depends on the function's
template parameters. Like:
template<typename T>
void my_function (T v, gdb::function_view<void(T)> callback = nullptr);
For such a function, the type of the callback argument you pass must
already be a function_view. I.e., this wouldn't compile:
auto lambda = [&] (int) { ... };
my_function (1, lambda);
With gdb::make_function_view, you can write the call like so:
auto lambda = [&] (int) { ... };
my_function (1, gdb::make_function_view (lambda));
Unit tests included.
Tested by building with GCC 9.4, Clang 10, and GCC 4.8.5, on x86_64
GNU/Linux, and running the unit tests.
Change-Id: I5c4b3b4455ed6f0d8878cf1be189bea3ee63f626
For PR gdb/29373, I wrote an alternative implementation of struct
packed that uses a gdb_byte array for internal representation, needed
for mingw+clang. While adding that, I wrote some unit tests to make
sure both implementations behave the same. While at it, I implemented
all relational operators. This commit adds said unit tests and
relational operators. The alternative gdb_byte array implementation
will come next.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29373
Change-Id: I023315ee03622c59c397bf4affc0b68179c32374
In this review [1], Eli pointed out that we should be careful when
concatenating file names to avoid duplicated slashes. On Windows, a
double slash at the beginning of a file path has a special meaning. So
naively concatenating "/" and "foo/bar" would give "//foo/bar", which
would not give the desired results. We already have a few spots doing:
if (first_path ends with a slash)
path = first_path + second_path
else
path = first_path + slash + second_path
In general, I think it's nice to avoid superfluous slashes in file
paths, since they might end up visible to the user and look a bit
unprofessional.
Introduce the path_join function that can be used to join multiple path
components together (along with unit tests).
I initially wanted to make it possible to join two absolute paths, to
support the use case of prepending a sysroot path to a target file path,
or the prepending the debug-file-directory to a target file path. But
the code in solib_find_1 shows that it is more complex than this anyway
(for example, when the right hand side is a Windows path with a drive
letter). So I don't think we need to support that case in path_join.
That also keeps the implementation simpler.
Change a few spots to use path_join to show how it can be used. I
believe that all the spots I changed are guarded by some checks that
ensure the right hand side operand is not an absolute path.
Regression-tested on Ubuntu 18.04. Built-tested on Windows, and I also
ran the new unit-test there.
[1] https://sourceware.org/pipermail/gdb-patches/2022-April/187559.html
Change-Id: I0df889f7e3f644e045f42ff429277b732eb6c752
parallel_for_each currently requires each thread to process at least
10 elements. However, when indexing, it's fine for a thread to handle
just a single CU. This patch parameterizes this, and updates the one
user.
Now that filtered and unfiltered output can be treated identically, we
can unify the printf family of functions. This is done under the name
"gdb_printf". Most of this patch was written by script.
This commit adds operator+= and operator+ overloads for adding
gdb::unique_xmalloc_ptr<char> to a std::string. I could only find 3
places in GDB where this was useful right now, and these all make use
of operator+=.
I've also added a self test for gdb::unique_xmalloc_ptr<char>, which
makes use of both operator+= and operator+, so they are both getting
used/tested.
There should be no user visible changes after this commit, except when
running 'maint selftest', where the new self test is visible.
In an earlier version of the pager rewrite series, it was important to
audit unfiltered output calls to see which were truly necessary.
This is no longer necessary, but it still seems like a decent cleanup
to change calls to avoid explicitly passing gdb_stdout. That is,
rather than using something like fprintf_unfiltered with gdb_stdout,
the code ought to use plain printf_unfiltered instead.
This patch makes this change. I went ahead and converted all the
_filtered calls I could find, as well, for the same clarity.
In my tour of the ui_file subsystem, I found that fputstr and fputstrn
can be simplified. The _filtered forms are never used (and IMO
unlikely to ever be used) and so can be removed. And, the interface
can be simplified by removing a callback function and moving the
implementation directly to ui_file.
A new self-test is included. Previously, I think nothing was testing
this code.
Regression tested on x86-64 Fedora 34.
This commit brings all the changes made by running gdb/copyright.py
as per GDB's Start of New Year Procedure.
For the avoidance of doubt, all changes in this commits were
performed by the script.
I think it would make sense for extract_integer, extract_signed_integer
and extract_unsigned_integer to take an array_view. This way, when we
extract an integer, we can validate that we don't overflow the buffer
passed by the caller (e.g. ask to extract a 4-byte integer but pass a
2-byte buffer).
- Change extract_integer to take an array_view
- Add overloads of extract_signed_integer and extract_unsigned_integer
that take array_views. Keep the existing versions so we don't
need to change all callers, but make them call the array_view
versions.
This shortens some places like:
result = extract_unsigned_integer (value_contents (result_val).data (),
TYPE_LENGTH (value_type (result_val)),
byte_order);
into
result = extract_unsigned_integer (value_contents (result_val), byte_order);
value_contents returns an array view that is of length
`TYPE_LENGTH (value_type (result_val))` already, so the length is
implicitly communicated through the array view.
Change-Id: Ic1c1f98c88d5c17a8486393af316f982604d6c95
An assertion was recently added to array_view::operator[] to ensure we
don't do out of bounds accesses. However, when the array_view is copied
to or from using memcpy, it bypasses that safety.
To address this, add a `copy` free function that copies data from an
array view to another, ensuring that the destination and source array
views have the same size. When copying to or from parts of an
array_view, we are expected to use gdb::array_view::slice, which does
its own bounds check. With all that, any copy operation that goes out
of bounds should be caught by an assertion at runtime.
copy is implemented using std::copy and std::copy_backward, which, at
least on libstdc++, appears to pick memmove when copying trivial data.
So in the end there shouldn't be much difference vs using a bare memcpy,
as we do right now. When copying non-trivial data, std::copy and
std::copy_backward assigns each element in a loop.
To properly support overlapping ranges, we must use std::copy or
std::copy_backward, depending on whether the destination is before the
source or vice-versa. std::copy and std::copy_backward don't support
copying exactly overlapping ranges (where the source range is equal to
the destination range). But in this case, no copy is needed anyway, so
we do nothing.
The order of parameters of the new copy function is based on std::copy
and std::copy_backward, where the source comes before the destination.
Change a few randomly selected spots to use the new function, to show
how it can be used.
Add a test for the new function, testing both with arrays of a trivial
type (int) and of a non-trivial type (foo). Test non-overlapping
ranges as well as three kinds of overlapping ranges: source before dest,
dest before source, and dest == source.
Change-Id: Ibeaca04e0028410fd44ce82f72e60058d6230a03
I would like to print target_waitkind values in debug messages, so I
think that a target_waitkind-to-string function would be useful. While
at it, use it in target_waitstatus::to_string. This changes the output
of target_waitstatus::to_string a bit, but I think it is for the better.
The debug messages will show a string matching exactly the
target_waitkind enumerator (minus the TARGET_WAITKIND prefix).
As a convenience, make string_appendf return the same reference to
string it got as a parameter. This allows doing this:
return string_appendf (str, "foo");
... keeping the code concise.
Change-Id: I383dffc9c78614e7d0668b1516073905e798eef7
When building with g++ 4.8, I get:
CXX unittests/array-view-selftests.o
/home/smarchi/src/binutils-gdb/gdb/unittests/array-view-selftests.c:123:42: error: expected 'class' before 'Container'
template<template<typename ...> typename Container>
^
I am no C++ template expert, but it looks like if I change "typename" for
"class", as the compiler kind of suggests, the code compiles.
Change-Id: I9c3edd29fb2b190069f0ce0dbf3bc3604d175f48
While reading the interface of gdb::array_view, I realized that the
constructor that builds an array_view on top of a contiguous container
(such as std::vector, std::array or even gdb::array_view) can be
missused.
Lets consider the following code sample:
struct Parent
{
Parent (int a): a { a } {}
int a;
};
std::ostream &operator<< (std::ostream& os, const Parent & p)
{ os << "Parent {a=" << p.a << "}"; return os; }
struct Child : public Parent
{
Child (int a, int b): Parent { a }, b { b } {}
int b;
};
std::ostream &operator<< (std::ostream& os, const Child & p)
{ os << "Child {a=" << p.a << ", b=" << p.b << "}"; return os; }
template <typename T>
void print (const gdb::array_view<const T> &p)
{
std::for_each (p.begin (), p.end (), [](const T &p) { std::cout << p << '\n'; });
}
Then with the current interface nothinng prevents this usage of
array_view to be done:
const std::array<Child, 3> elts = {
Child {1, 2},
Child {3, 4},
Child {5, 6}
};
print_all<Parent> (elts);
This compiles fine and produces the following output:
Parent {a=1}
Parent {a=2}
Parent {a=3}
which is obviously wrong. There is nowhere in memory a Parent-like
object for which the A member is 2 and this call to print_all<Parent>
shold not compile at all (calling print_all<Child> is however fine).
This comes down to the fact that a Child* is convertible into a Parent*,
and that an array view is constructed to a pointer to the first element
and a size. The valid type pointed to that can be used with this
constructor are restricted using SFINAE, which requires that a
pointer to a member into the underlying container can be converted into a
pointer the array_view's data type.
This patch proposes to change the constraints on the gdb::array_view
ctor which accepts a container now requires that the (decayed) type of
the elements in the container match the (decayed) type of the array_view
being constructed.
Applying this change required minimum adjustment in GDB codebase, which
are also included in this patch.
Tested by rebuilding.
The format_pieces selftest currently fails on Windows hosts.
The selftest doesn't handle the "%ll" -> "%I64" rewrite that the
formatter may perform, but also gdbsupport was missing a configure
check for PRINTF_HAS_LONG_LONG. This patch fixes both issues.
Change register_test to use std::function arg, such that we can do:
...
register_test (test_name, [=] () { SELF_CHECK (...); });
...
Tested on x86_64-linux.
Like Tom de Vries' earlier patch to fix the no-CXX_STD_THREAD case in
maint.c, this patch fixes a similar problem in
parallel-for-selftests.c. This fixes a build failure on Windows.
We get this error when building GDB on some platforms. I get it using
g++-10 on Ubuntu 20.04 (installed using the distro package). It was
also reported by John Baldwin, using a clang that uses libc++.
CXX unittests/parallel-for-selftests.o
cc1plus: warning: command line option '-Wmissing-prototypes' is valid for C/ObjC but not for C++
/home/smarchi/src/binutils-gdb/gdb/unittests/parallel-for-selftests.c: In function 'void selftests::parallel_for::test(int)':
/home/smarchi/src/binutils-gdb/gdb/unittests/parallel-for-selftests.c:53:30: error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
53 | std::atomic<int> counter = 0;
| ^
In file included from /usr/include/c++/9/future:42,
from /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/thread-pool.h:29,
from /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/parallel-for.h:26,
from /home/smarchi/src/binutils-gdb/gdb/unittests/parallel-for-selftests.c:22:
/usr/include/c++/9/atomic:755:7: note: declared here
755 | atomic(const atomic&) = delete;
| ^~~~~~
/usr/include/c++/9/atomic:759:17: note: after user-defined conversion: 'constexpr std::atomic<int>::atomic(std::atomic<int>::__integral_type)'
759 | constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
| ^~~~~~
I haven't dug to know why it does not happen everywhere, but this patch
fixes it by using the constructor to initialize the variable, rather
than the assignment operator.
Change-Id: I6b27958171bf6187f6a875657395fd10441db7e6
Tom de Vries noticed that a patch in the DWARF scanner rewrite series
caused a regression in parallel_for_each -- it started crashing in the
case where the number of threads is 0 (there was an unchecked use of
"n-1" that was used to size an array).
He also pointed out that there were no tests of parallel_for_each.
This adds a few tests of parallel_for_each, primarily testing that
different settings for the number of threads will work. This test
catches the bug that he found in that series.
The threads that need a step-over are currently linked using an
hand-written intrusive doubly-linked list, so that seems a very good
candidate for intrusive_list, convert it.
For this, we have a use case of appending a list to another one (in
start_step_over). Based on the std::list and Boost APIs, add a splice
method. However, only support splicing the other list at the end of the
`this` list, since that's all we need.
Add explicit default assignment operators to
reference_to_pointer_iterator, which are otherwise implicitly deleted.
This is needed because to define thread_step_over_list_safe_iterator, we
wrap reference_to_pointer_iterator inside a basic_safe_iterator, and
basic_safe_iterator needs to be able to copy-assign the wrapped
iterator. The move-assignment operator is therefore not needed, only
the copy-assignment operator is. But for completeness, add both.
Change-Id: I31b2ff67c7b78251314646b31887ef1dfebe510c
GDB currently has several objects that are put in a singly linked list,
by having the object's type have a "next" pointer directly. For
example, struct thread_info and struct inferior. Because these are
simply-linked lists, and we don't keep track of a "tail" pointer, when
we want to append a new element on the list, we need to walk the whole
list to find the current tail. It would be nice to get rid of that
walk. Removing elements from such lists also requires a walk, to find
the "previous" position relative to the element being removed. To
eliminate the need for that walk, we could make those lists
doubly-linked, by adding a "prev" pointer alongside "next". It would be
nice to avoid the boilerplate associated with maintaining such a list
manually, though. That is what the new intrusive_list type addresses.
With an intrusive list, it's also possible to move items out of the
list without destroying them, which is interesting in our case for
example for threads, when we exit them, but can't destroy them
immediately. We currently keep exited threads on the thread list, but
we could change that which would simplify some things.
Note that with std::list, element removal is O(N). I.e., with
std::list, we need to walk the list to find the iterator pointing to
the position to remove. However, we could store a list iterator
inside the object as soon as we put the object in the list, to address
it, because std::list iterators are not invalidated when other
elements are added/removed. However, if you need to put the same
object in more than one list, then std::list<object> doesn't work.
You need to instead use std::list<object *>, which is less efficient
for requiring extra memory allocations. For an example of an object
in multiple lists, see the step_over_next/step_over_prev fields in
thread_info:
/* Step-over chain. A thread is in the step-over queue if these are
non-NULL. If only a single thread is in the chain, then these
fields point to self. */
struct thread_info *step_over_prev = NULL;
struct thread_info *step_over_next = NULL;
The new intrusive_list type gives us the advantages of an intrusive
linked list, while avoiding the boilerplate associated with manually
maintaining it.
intrusive_list's API follows the standard container interface, and thus
std::list's interface. It is based the API of Boost's intrusive list,
here:
https://www.boost.org/doc/libs/1_73_0/doc/html/boost/intrusive/list.html
Our implementation is relatively simple, while Boost's is complicated
and intertwined due to a lot of customization options, which our version
doesn't have.
The easiest way to use an intrusive_list is to make the list's element
type inherit from intrusive_node. This adds a prev/next pointers to
the element type. However, to support putting the same object in more
than one list, intrusive_list supports putting the "node" info as a
field member, so you can have more than one such nodes, one per list.
As a first guinea pig, this patch makes the per-inferior thread list use
intrusive_list using the base class method.
Unlike Boost's implementation, ours is not a circular list. An earlier
version of the patch was circular: the intrusive_list type included an
intrusive_list_node "head". In this design, a node contained pointers
to the previous and next nodes, not the previous and next elements.
This wasn't great for when debugging GDB with GDB, as it was difficult
to get from a pointer to the node to a pointer to the element. With the
design proposed in this patch, nodes contain pointers to the previous
and next elements, making it easy to traverse the list by hand and
inspect each element.
The intrusive_list object contains pointers to the first and last
elements of the list. They are nullptr if the list is empty.
Each element's node contains a pointer to the previous and next
elements. The first element's previous pointer is nullptr and the last
element's next pointer is nullptr. Therefore, if there's a single
element in the list, both its previous and next pointers are nullptr.
To differentiate such an element from an element that is not linked into
a list, the previous and next pointers contain a special value (-1) when
the node is not linked. This is necessary to be able to reliably tell
if a given node is currently linked or not.
A begin() iterator points to the first item in the list. An end()
iterator contains nullptr. This makes iteration until end naturally
work, as advancing past the last element will make the iterator contain
nullptr, making it equal to the end iterator. If the list is empty,
a begin() iterator will contain nullptr from the start, and therefore be
immediately equal to the end.
Iterating on an intrusive_list yields references to objects (e.g.
`thread_info&`). The rest of GDB currently expects iterators and ranges
to yield pointers (e.g. `thread_info*`). To bridge the gap, add the
reference_to_pointer_iterator type. It is used to define
inf_threads_iterator.
Add a Python pretty-printer, to help inspecting intrusive lists when
debugging GDB with GDB. Here's an example of the output:
(top-gdb) p current_inferior_.m_obj.thread_list
$1 = intrusive list of thread_info = {0x61700002c000, 0x617000069080, 0x617000069400, 0x61700006d680, 0x61700006eb80}
It's not possible with current master, but with this patch [1] that I
hope will be merged eventually, it's possible to index the list and
access the pretty-printed value's children:
(top-gdb) p current_inferior_.m_obj.thread_list[1]
$2 = (thread_info *) 0x617000069080
(top-gdb) p current_inferior_.m_obj.thread_list[1].ptid
$3 = {
m_pid = 406499,
m_lwp = 406503,
m_tid = 0
}
Even though iterating the list in C++ yields references, the Python
pretty-printer yields pointers. The reason for this is that the output
of printing the thread list above would be unreadable, IMO, if each
thread_info object was printed in-line, since they contain so much
information. I think it's more useful to print pointers, and let the
user drill down as needed.
[1] https://sourceware.org/pipermail/gdb-patches/2021-April/178050.html
Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
Change-Id: I3412a14dc77f25876d742dab8f44e0ba7c7586c0
Same idea as the previous patch, but for prefix instead of alias.
gdb/ChangeLog:
* cli/cli-decode.h (cmd_list_element) <is_prefix>: New, use it.
Change-Id: I76a9d2e82fc8d7429904424674d99ce6f9880e2b
Add the cmd_list_element::is_alias helper to check whether a command is
an alias. I find it easier to understand the intention in:
if (c->is_alias ())
than
if (c->alias_target != nullptr)
Change all the spots that are reading alias_target just to compare it to
NULL/nullptr to use is_alias instead.
gdb/ChangeLog:
* cli/cli-decode.h (cmd_list_element) <is_alias>: New, use it.
Change-Id: I26ed56f99ee47fe884fdfedf87016501631693ce
cmd_pointer is another field whose name I found really not clear. Yes,
it's a pointer to a command, the type tells me that. But what's the
relationship of that command to the current command? This field
contains, for an alias, the command that it aliases. So I think that
the name "alias_target" would be more appropriate.
Also, rename "old" parameters to "target" in the functions that add
aliases.
gdb/ChangeLog:
* cli/cli-decode.h (cmd_list_element) <cmd_pointer>: Rename
to...
<alias_target>: ... this.
(add_alias_cmd): Rename old to target.
(add_info_alias): Rename old_name to target_name.
(add_com_alias): Likewise.
Change-Id: I8db36c6dd799fae155f7acd3805f6d62d98befa9
While browsing this code, I found the name "prefixlist" really
confusing. I kept reading it as "list of prefixes". Which it isn't:
it's a list of sub-commands, for a prefix command. I think that
renaming it to "subcommands" would make things clearer.
gdb/ChangeLog:
* Rename "prefixlist" parameters to "subcommands" throughout.
* cli/cli-decode.h (cmd_list_element) <prefixlist>: Rename to...
<subcommands>: ... this.
* cli/cli-decode.c (lookup_cmd_for_prefixlist): Rename to...
(lookup_cmd_with_subcommands): ... this.
Change-Id: I150da10d03052c2420aa5b0dee41f422e2a97928
Previously, the prefixname field of struct cmd_list_element was manually
set for prefix commands. This seems verbose and error prone as it
required every single call to functions adding prefix commands to
specify the prefix name while the same information can be easily
generated.
Historically, this was not possible as the prefix field was null for
many commands, but this was fixed in commit
3f4d92ebdf by Philippe Waroquiers, so
we can rely on the prefix field being set when generating the prefix
name.
This commit also fixes a use after free in this scenario:
* A command gets created via Python (using the gdb.Command class).
The prefix name member is dynamically allocated.
* An alias to the new command is created. The alias's prefixname is set
to point to the prefixname for the original command with a direct
assignment.
* A new command with the same name as the Python command is created.
* The object for the original Python command gets freed and its
prefixname gets freed as well.
* The alias is updated to point to the new command, but its prefixname
is not updated so it keeps pointing to the freed one.
gdb/ChangeLog:
* command.h (add_prefix_cmd): Remove the prefixname argument as
it can now be generated automatically. Update all callers.
(add_basic_prefix_cmd): Ditto.
(add_show_prefix_cmd): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_abbrev_prefix_cmd): Ditto.
* cli/cli-decode.c (add_prefix_cmd): Ditto.
(add_basic_prefix_cmd): Ditto.
(add_show_prefix_cmd): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_abbrev_prefix_cmd): Ditto.
* cli/cli-decode.h (struct cmd_list_element): Replace the
prefixname member variable with a method which generates the
prefix name at runtime. Update all code reading the prefix
name to use the method, and remove all code setting it.
* python/py-cmd.c (cmdpy_destroyer): Remove code to free the
prefixname member as it's now a method.
(cmdpy_function): Determine if the command is a prefix by
looking at prefixlist, not prefixname.
Previously, the observers attached to an observable were always notified
in the order in which they had been attached. That order is not easily
controlled, because observers are typically attached in _initialize_*
functions, which are called in an undefined order.
However, an observer may require that another observer attached only
later is called before itself is.
Therefore, extend the 'observable' class to allow explicitly specifying
dependencies when attaching observers, by adding the possibility to
specify tokens for observers that it depends on.
To make sure dependencies are notified before observers depending on
them, the vector holding the observers is sorted in a way that
dependencies come before observers depending on them. The current
implementation for sorting uses the depth-first search algorithm for
topological sorting as described at [1].
Extend the observable unit tests to cover this case as well. Check that
this works for a few different orders in which the observers are
attached.
This newly introduced mechanism to explicitly specify dependencies will
be used in a follow-up commit.
[1] https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
Tested on x86_64-linux (Debian testing).
gdb/ChangeLog:
* unittests/observable-selftests.c (dependency_test_counters):
New.
(observer_token0, observer_token1, observer_token2,
observer_token3, observer_token4, observer_token5): New.
(struct dependency_observer_data): New struct.
(observer_dependency_test_callback): New function.
(test_observers): New.
(run_dependency_test): New function.
(test_dependency): New.
(_initialize_observer_selftest): Register dependency test.
gdbsupport/ChangeLog:
* observable.h (class observable): Extend to allow specifying
dependencies between observers, keep vector holding observers
sorted so that dependencies are notified before observers
depending on them.
Change-Id: I5399def1eeb69ca99e28c9f1fdf321d78b530bdb
Give a name to each observer, this will help produce more meaningful
debug message.
gdbsupport/ChangeLog:
* observable.h (class observable) <struct observer> <observer>:
Add name parameter.
<name>: New field.
<attach>: Add name parameter, update all callers.
Change-Id: Ie0cc4664925215b8d2b09e026011b7803549fba0
Before this patch, gdb_tilde_expand would use glob(3) in order to expand
tilde at the begining of a path. This implementation has limitation when
expanding a tilde leading path to a non existing file since glob fails to
expand.
This patch proposes to use glob only to expand the tilde component of the
path and leaves the rest of the path unchanged.
This patch is a followup to the following discution:
https://sourceware.org/pipermail/gdb-patches/2021-January/174776.html
Before the patch:
gdb_tilde_expand("~") -> "/home/lsix"
gdb_tilde_expand("~/a/c/b") -> error() is called
After the patch:
gdb_tilde_expand("~") -> "/home/lsix"
gdb_tilde_expand("~/a/c/b") -> "/home/lsix/a/c/b"
Tested on x84_64 linux.
gdb/ChangeLog:
* Makefile.in (SELFTESTS_SRCS): Add
unittests/gdb_tilde_expand-selftests.c.
* unittests/gdb_tilde_expand-selftests.c: New file.
gdbsupport/ChangeLog:
* gdb_tilde_expand.cc (gdb_tilde_expand): Improve
implementation.
(gdb_tilde_expand_up): Delegate logic to gdb_tilde_expand.
* gdb_tilde_expand.h (gdb_tilde_expand): Update description.
This commits the result of running gdb/copyright.py as per our Start
of New Year procedure...
gdb/ChangeLog
Update copyright year range in copyright header of all GDB files.
The gdb_mpz class currently provides a couple of methods which
essentially export an mpz_t value into either a buffer, or an integral
type. The export is based on using the mpz_export function which
we discovered can be a bit treacherous if used without caution.
In particular, the initial motivation for this patch was to catch
situations where the mpz_t value was so large that it would not fit
in the destination area. mpz_export does not know the size of
the buffer, and therefore can happily write past the end of our buffer.
While designing a solution to the above problem, I also discovered
that we also needed to be careful when exporting signed numbers.
In particular, numbers which are larger than the maximum value
for a given signed type size, but no so large as to fit in the
*unsigned* version with the same size, would end up being exported
incorrectly. This is related to the fact that mpz_export ignores
the sign of the value being exportd, and assumes an unsigned export.
Thus, for such large values, the appears as if mpz_export is able
to fit our value into our buffer, but in fact, it does not.
Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
parameter, which was a hole.
For all these reasons, a new low-level private method called
"safe_export" has been added to class gdb_mpz, whose goal is
to perform all necessary checks and manipulations for a safe
and correct export. As a bonus, this method allows us to factorize
the handling of negative value exports.
The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
to take advantage of this new safe_export method.
gdb/ChangeLog:
* gmp-utils.h (gdb_mpz::safe_export): New private method.
(gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
* gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
(gdb_mpz::safe_export): New method.
* unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
Update function description.
(check_as_integer_raises_out_of_range_error): New function.
(gdb_mpz_as_integer_out_of_range): New function.
(_initialize_gmp_utils_selftests): Register
gdb_mpz_as_integer_out_of_range as a selftest.
This commit changes the interfaces of some of the methods declared
in gmp-utils to take a gdb::array_view of gdb_byte instead of a
(gdb_byte *, size) couple.
This makes these methods' API probably more C++-idiomatic.
* gmp-utils.h (gdb_mpz::read): Change buf and len parameters
into one single gdb::array_view parameter.
(gdb_mpz::write): Likewise.
(gdb_mpq::read_fixed_point, gdb_mpq::write_fixed_point): Likewise.
* gmp-utils.c (gdb_mpz::read): Change buf and len parameters
into one single gdb::array_view parameter.
Adjust implementation accordingly.
(gdb_mpz::write): Likewise.
(gdb_mpq::read_fixed_point, gdb_mpq::write_fixed_point): Likewise.
* unittests/gmp-utils-selftests.c: Adapt following changes above.
* valarith.c, valops.c, valprint.c, value.c: Likewise.
When building GDB using Ubuntu 20.04's system libgmp and compiler,
running the "maintenance selftest" command triggers the following error:
| Running selftest gdb_mpq_write_fixed_point.
| *** stack smashing detected ***: terminated
| [1] 1092790 abort (core dumped) ./gdb gdb
This happens while trying to construct an mpq_t object (a rational)
from two integers representing the numerator and denominator.
In our test, the numerator is -8, and the denominator is 1.
The problem was that the rational was constructed using the wrong
function. This is what we were doing prior to this patch:
mpq_set_ui (v.val, numerator, denominator);
The 'u' in "ui" stands for *unsigned*, which is wrong because
numerator and denominator's type is "int".
As a result of the above, instead of getting a rational value of -8,
we get a rational with a very large positive value (gmp_printf
says "18446744073709551608").
From there, the test performs an operation which is expected to
write this value into a buffer which was not dimensioned to fit
such a number, thus leading GMP into a buffer overflow.
This was verified by applying the formula that GMP's documentation
gives for the required memory buffer size needed during export:
| When an application is allocating space itself the required size can
| be determined with a calculation like the following. Since
| mpz_sizeinbase always returns at least 1, count here will be at
| least one, which avoids any portability problems with malloc(0),
| though if z is zero no space at all is actually needed (or written).
|
| numb = 8*size - nail;
| count = (mpz_sizeinbase (z, 2) + numb-1) / numb;
| p = malloc (count * size);
With the very large number, mpz_sizeinbase returns 66 and thus
the malloc size becomes 16 bytes instead of the 8 we allocated.
This patch fixes the issue by using the correct "set" function.
gdb/ChangeLog:
* unittests/gmp-utils-selftests.c (write_fp_test): Use mpq_set_si
instead of mpq_set_ui to initialize our GMP rational.
When building on solaris (gcc farm machine gcc211), I get:
CXX unittests/gmp-utils-selftests.o
/export/home/simark/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c: In function 'void selftests::gdb_mpz_read_all_from_small()' :
/export/home/simark/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c:128:43: error: call of overloaded 'pow(int, int)' is ambiguous
LONGEST l_min = -pow (2, buf_len * 8 - 1);
^
In file included from /opt/csw/lib/gcc/sparc-sun-solaris2.10/5.5.0/include-fixed/math.h:22:0,
from ../gnulib/import/math.h:27,
from /export/home/simark/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c:23:
/opt/csw/lib/gcc/sparc-sun-solaris2.10/5.5.0/include-fixed/iso/math_iso.h:210:21: note: candidate: long double std::pow(long double, long double)
inline long double pow(long double __X, long double __Y) { return
^
/opt/csw/lib/gcc/sparc-sun-solaris2.10/5.5.0/include-fixed/iso/math_iso.h:170:15: note: candidate: float std::pow(float, float)
inline float pow(float __X, float __Y) { return __powf(__X, __Y); }
^
/opt/csw/lib/gcc/sparc-sun-solaris2.10/5.5.0/include-fixed/iso/math_iso.h:71:15: note: candidate: double std::pow(double, double)
extern double pow __P((double, double));
^
The "pow" function overloads only exist for float-like types, and the
compiler doesn't know which one we want. Change "2" for "2.0", which
makes the compiler choose one alternative (the double one, I believe).
gdb/ChangeLog:
* unittests/gmp-utils-selftests.c (gdb_mpz_read_all_from_small):
Pass 2.0 to pow.
(gdb_mpz_write_all_from_small): Likewise.
Change-Id: Ied2ae0f01494430244a7c94f8a38b07d819f4213
This API was motivated by a number of reasons:
- GMP's API does not handle "long long" and "unsigned long long",
so using LONGEST and ULONGEST is not straightforward;
- Automate the need to initialize GMP objects before use, and
clear them when no longer used.
However, this API grew also to help with similar matter such
as formatting to a string, and also reading/writing fixed-point
values from byte buffers.
Dedicated unit testing is also added.
gdb/ChangeLog:
* gmp-utils.h, gmp-utils.h: New file.
* unittests/gmp-utils-selftests.c: New file.
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
unittests/gmp-utils-selftests.c.
(COMMON_SFILES) Add gmp-utils.c.
(HFILES_NO_SRCDIR): Add gmp-utils.h.
This adds some unit tests for simple_search_memory. I tried here to
reproduce some bugs (PR gdb/11158 and PR gdb/17756), but was unable
to.
gdb/ChangeLog
2020-10-07 Tom Tromey <tromey@adacore.com>
* unittests/search-memory-selftests.c: New file.
* Makefile.in (SELFTESTS_SRCS): Add
unittests/search-memory-selftests.c.
With GCC 6.4 and 6.5 (at least), unit tests that use
gdbsupport/valid-expr.h's CHECK_VALID fail to compile, with:
In file included from src/gdb/unittests/offset-type-selftests.c:24:0:
src/gdb/unittests/offset-type-selftests.c: In substitution of 'template<class Expected, template<class ...> class Op, class ... Args> using is_detected_exact = std::is_same<Expected, typename gdb::detection_detail::detector<gdb::nonesuch, void, Op, Args ...>::type> [with Expected = selftests::offset_type::off_A&; Op = selftests::offset_type::check_valid_expr75::archetype; Args = {selftests::offset_type::off_A, selftests::offset_type::off_B}]':
src/gdb/unittests/offset-type-selftests.c:75:1: required from here
src/gdb/../gdbsupport/valid-expr.h:65:20: error: type/value mismatch at argument 2 in template parameter list for 'template<class Expected, template<class ...> class Op, class ... Args> using is_detected_exact = std::is_same<Expected, typename gdb::detection_detail::detector<gdb::nonesuch, void, Op, Args ...>::type>'
archetype, TYPES>::value == VALID, \
^
The important part is the "error: type/value mismatch" error. Seems
like that GCC doesn't understand that archetype is an alias template,
and is being strict in requiring a template class.
The fix here is then to make archetype a template class, to pacify
GCC. The resulting code looks like this:
template <TYPENAMES, typename = decltype (EXPR)>
struct archetype
{
};
static_assert (gdb::is_detected_exact<archetype<TYPES, EXPR_TYPE>,
archetype, TYPES>::value == VALID, "");
is_detected_exact<Expected, Op, Args> checks whether Op<Args> is type
Expected:
- For Expected, we pass the explicit EXPR_TYPE, overriding the
default parameter type of archetype.
- For Args we don't pass the last template parameter, so archtype
defaults to the EXPR's decltype.
So in essence, we're really checking whether EXPR_TYPE is the same as
decltype(EXPR).
We need to do the decltype in a template context in order to trigger
SFINAE instead of failing to compile.
The hunk in unittests/enum-flags-selftests.c becomes necessary,
because unlike with the current alias template version, this new
version makes GCC trigger -Wenum-compare warnings as well:
src/gdb/unittests/enum-flags-selftests.c:328:33: error: comparison between 'enum selftests::enum_flags_tests::RE' and 'enum selftests::enum_flags_tests::RE2' [-Werror=enum-compare]
CHECK_VALID (true, bool, RE () != RE2 ())
^
src/gdb/../gdbsupport/valid-expr.h:61:45: note: in definition of macro 'CHECK_VALID_EXPR_INT'
template <TYPENAMES, typename = decltype (EXPR)> \
^
Build-tested with:
- GCC {4.8.5, 6.4, 6.5, 7.3.1, 9.3.0, 11.0.0-20200910}
- Clang 10.0.0
gdbsupport/ChangeLog:
* valid-expr.h (CHECK_VALID_EXPR_INT): Make archetype a template
class instead of an alias template and adjust static_assert.
gdb/ChangeLog:
* unittests/enum-flags-selftests.c: Check whether __GNUC__ is
defined before using '#pragma GCC diagnostic' instead of checking
__clang__.
This changes the TUI source and disassembly windows to use a curses
pad for their text. This is an important step toward properly
handling non-ASCII characters, because it makes it easy to scroll
horizontally without needing gdb to also understand multi-byte
character boundaries -- this can be wholly delegated to curses.
Horizontal scrolling is probably also faster now, because no
re-rendering is required.
gdb/ChangeLog
2020-09-27 Tom Tromey <tom@tromey.com>
* unittests/tui-selftests.c: Update.
* tui/tui-winsource.h (struct tui_source_window_base)
<extra_margin, show_line_number, refresh_pad>: New methods.
<m_max_length, m_pad>: New members.
(tui_copy_source_line): Update.
* tui/tui-winsource.c (tui_copy_source_line): Remove line_no,
first_col, line_width, ndigits parameters. Add length.
(tui_source_window_base::show_source_line): Write to pad. Line
number now 0-based.
(tui_source_window_base::refresh_pad): New method.
(tui_source_window_base::show_source_content): Write to pad. Call
refresh_pad.
(tui_source_window_base::do_scroll_horizontal): Call refresh_pad,
not refill.
(tui_source_window_base::update_exec_info): Call
show_line_number.
* tui/tui-source.h (struct tui_source_window) <extra_margin>: New
method.
<m_digits>: New member.
* tui/tui-source.c (tui_source_window::set_contents): Set m_digits
and m_max_length.
(tui_source_window::show_line_number): New method.
* tui/tui-io.h (tui_puts): Fix comment.
* tui/tui-disasm.c (tui_disasm_window::set_contents): Set
m_max_length.
My understanding is that it's mildly better to use a static const
array, as opposed to a "const char *", for a global string constant,
when possible. This makes sense to me because the pointer requires a
load from an address, whereas the array is just the address.
So, I searched for these in gdb and gdbserver. This patch fixes the
ones I found.
gdb/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* unittests/memory-map-selftests.c (valid_mem_map): Now array.
* ui-style.c (ansi_regex_text): Now array.
* rust-exp.y (number_regex_text): Now array.
* linespec.c (linespec_quote_characters): Now array.
* jit.c (jit_break_name, jit_descriptor_name, reader_init_fn_sym):
Now arrays.
gdbserver/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* linux-x86-low.cc (xmltarget_i386_linux_no_xml)
(xmltarget_amd64_linux_no_xml): Now arrays.