From: Sergio Durigan Junior <sergiodj@redhat.com>
To: Simon Marchi <simon.marchi@polymtl.ca>
Cc: GDB Patches <gdb-patches@sourceware.org>,
Pedro Alves <palves@redhat.com>, Eli Zaretskii <eliz@gnu.org>
Subject: Re: [PATCH v3] Implement the ability to set/unset environment variables to GDBserver when starting the inferior
Date: Mon, 28 Aug 2017 21:25:00 -0000 [thread overview]
Message-ID: <87a82j9yi8.fsf@redhat.com> (raw)
In-Reply-To: <73bf6c70a8a12b4291385374867db9ba@polymtl.ca> (Simon Marchi's message of "Thu, 24 Aug 2017 21:25:07 +0200")
On Thursday, August 24 2017, Simon Marchi wrote:
> Hi Sergio,
>
> Just some nits about the code, and I also looked at the tests, which I
> hadn't looked at before.
Thanks for the review, Simon!
> On 2017-08-13 08:19, Sergio Durigan Junior wrote:
>> @@ -73,9 +78,26 @@ public:
>> /* Return the environment vector represented as a 'char **'. */
>> char **envp () const;
>>
>> + /* Return the user-set environment vector. */
>> + const std::set<std::string> &user_set_env () const;
>> +
>> + /* Return the user-set environment vector. */
>
> user-set -> user-unset ?
Fixed.
>> + const std::set<std::string> &user_unset_env () const;
>> +
>> private:
>> + /* Unset VAR in environment. If UPDATE_UNSET_LIST is true, then
>> + also update M_USER_UNSET_ENV to reflect the unsetting of the
>> + environment variable. */
>> + void unset (const char *var, bool update_unset_list);
>> +
>> /* A vector containing the environment variables. */
>> std::vector<char *> m_environ_vector;
>> +
>> + /* The environment variables explicitly set by the user. */
>> + std::set<std::string> m_user_set_env;
>> +
>> + /* The environment variables explicitly unset by the user. */
>> + std::set<std::string> m_user_unset_env;
>> };
>>
>> #endif /* defined (ENVIRON_H) */
>> diff --git a/gdb/common/rsp-low.c b/gdb/common/rsp-low.c
>> index eb85ab5701..9f71699144 100644
>> --- a/gdb/common/rsp-low.c
>> +++ b/gdb/common/rsp-low.c
>> @@ -132,6 +132,29 @@ hex2bin (const char *hex, gdb_byte *bin, int
>> count)
>>
>> /* See rsp-low.h. */
>>
>> +std::string
>> +hex2str (const char *hex)
>> +{
>> + std::string ret;
>> + size_t len = strlen (hex);
>
> We could call ret.reserve (len / 2) to avoid reallocations when
> appending to the string.
Done.
>> +
>> + for (size_t i = 0; i < len; ++i)
>> + {
>> + if (hex[0] == '\0' || hex[1] == '\0')
>> + {
>> + /* Hex string is short, or of uneven length. Return what we
>> + have so far. */
>> + return ret;
>> + }
>> + ret += fromhex (hex[0]) * 16 + fromhex (hex[1]);
>> + hex += 2;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +/* See rsp-low.h. */
>> +
>> int
>> bin2hex (const gdb_byte *bin, char *hex, int count)
>> {
>> @@ -146,6 +169,22 @@ bin2hex (const gdb_byte *bin, char *hex, int
>> count)
>> return i;
>> }
>>
>> +/* See rsp-low.h. */
>> +
>> +std::string
>> +bin2hex (const gdb_byte *bin, int count)
>> +{
>> + std::string ret;
>
> Here too (but with count * 2).
Done.
>> +
>> + for (int i = 0; i < count; ++i)
>> + {
>> + ret += tohex ((*bin >> 4) & 0xf);
>> + ret += tohex (*bin++ & 0xf);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> /* Return whether byte B needs escaping when sent as part of binary
>> data. */
>>
>> static int
>> diff --git a/gdb/common/rsp-low.h b/gdb/common/rsp-low.h
>> index b57f58bc75..91cff4dac5 100644
>> --- a/gdb/common/rsp-low.h
>> +++ b/gdb/common/rsp-low.h
>> @@ -52,6 +52,10 @@ extern char *unpack_varlen_hex (char *buff,
>> ULONGEST *result);
>>
>> extern int hex2bin (const char *hex, gdb_byte *bin, int count);
>>
>> +/* Like hex2bin, but return a std::string. */
>> +
>> +extern std::string hex2str (const char *hex);
>> +
>> /* Convert some bytes to a hexadecimal representation. BIN holds the
>> bytes to convert. COUNT says how many bytes to convert. The
>> resulting characters are stored in HEX, followed by a NUL
>> @@ -59,6 +63,10 @@ extern int hex2bin (const char *hex, gdb_byte *bin,
>> int count);
>>
>> extern int bin2hex (const gdb_byte *bin, char *hex, int count);
>>
>> +/* Overloaded version of bin2hex that return a std::string. */
>
> "returns"
Fixed.
>> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
>> index 38383510e8..fa1116a5ee 100644
>> --- a/gdb/gdbserver/server.c
>> +++ b/gdb/gdbserver/server.c
>> @@ -631,6 +631,67 @@ handle_general_set (char *own_buf)
>> return;
>> }
>>
>> + if (startswith (own_buf, "QEnvironmentReset"))
>
> I would use strcmp here. Otherwise, it would also match if we sent a
> packet "QEnvironmentResetFoo" (that could conflict with some packet we
> add in the future).
Hm, good point. Fixed.
>> diff --git a/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
>> b/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
>> new file mode 100644
>> index 0000000000..0aca8f6b5e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/share-env-with-gdbserver.exp
>> @@ -0,0 +1,254 @@
>> +# This testcase is part of GDB, the GNU debugger.
>> +
>> +# Copyright 2017 Free Software Foundation, Inc.
>> +
>> +# 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/>.
>> +
>> +# This test doesn't make sense on native-gdbserver.
>> +if { [use_gdb_stub] } {
>> + untested "not supported"
>> + return
>> +}
>> +
>> +standard_testfile
>> +
>> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile
>> debug] } {
>> + return -1
>> +}
>> +
>> +set test_var_name "GDB_TEST_VAR"
>> +
>> +# Helper function that performs a check on the output of "getenv".
>> +#
>> +# - VAR_NAME is the name of the variable to be checked.
>> +#
>> +# - VAR_VALUE is the value expected.
>> +#
>> +# - TEST_MSG, if not empty, is the test message to be used by the
>> +# "gdb_test".
>> +#
>> +# - EMPTY_VAR_P, if non-zero, means that the variable is not expected
>> +# to exist. In this case, VAR_VALUE is not considered.
>> +
>> +proc check_getenv { var_name var_value { test_msg "" } {
>> empty_var_p 0 } } {
>> + global hex decimal
>> +
>> + if { $test_msg == "" } {
>> + set test_msg "print result of getenv for $var_name"
>> + }
>> +
>> + if { $empty_var_p } {
>> + set var_value_match "0x0"
>> + } else {
>> + set var_value_match "$hex \"$var_value\""
>> + }
>> +
>> + gdb_test "print my_getenv (\"$var_name\")" "\\\$$decimal =
>> $var_value_match" \
>> + $test_msg
>> +}
>> +
>> +# Helper function to re-run to main and breaking at the "break-here"
>> +# label.
>> +
>> +proc do_prepare_inferior { } {
>> + global decimal hex
>> +
>> + if { ![runto_main] } {
>> + return -1
>> + }
>> +
>> + gdb_breakpoint [gdb_get_line_number "break-here"]
>> +
>> + gdb_test "continue" "Breakpoint $decimal, main \\\(argc=1,
>> argv=$hex\\\) at.*" \
>> + "continue until breakpoint"
>> +}
>> +
>> +# Helper function that does the actual testing.
>> +#
>> +# - VAR_VALUE is the value of the environment variable.
>> +#
>> +# - VAR_NAME is the name of the environment variable. If empty,
>> +# defaults to $test_var_name.
>> +#
>> +# - VAR_NAME_MATCH is the name (regex) that will be used to query the
>> +# environment about the variable (via getenv). This is useful when
>> +# we're testing variables with strange names (e.g., with an equal
>> +# sign in the name) and we know that the variable will actually be
>> +# set using another name. If empty, defatults, to $var_name.
>> +#
>> +# - VAR_VALUE_MATCH is the value (regex) that will be used to match
>> +# the result of getenv. The rationale is the same as explained for
>> +# VAR_NAME_MATCH. If empty, defaults, to $var_value.
>> +
>> +proc do_test { var_value { var_name "" } { var_name_match "" } {
>> var_value_match "" } } {
>> + global hex decimal binfile test_var_name
>
> hex and decimal are unused
Removed.
>> +
>> + clean_restart $binfile
>> +
>> + if { $var_name == "" } {
>> + set var_name $test_var_name
>> + }
>> +
>> + if { $var_name_match == "" } {
>> + set var_name_match $var_name
>> + }
>> +
>> + if { $var_value_match == "" } {
>> + set var_value_match $var_value
>> + }
>> +
>> + if { $var_value != "" } {
>> + gdb_test_no_output "set environment $var_name = $var_value" \
>> + "set $var_name = $var_value"
>> + } else {
>> + gdb_test "set environment $var_name =" \
>> + "Setting environment variable \"$var_name\" to null value." \
>> + "set $var_name to null value"
>> + }
>> +
>> + do_prepare_inferior
>> +
>> + check_getenv "$var_name_match" "$var_value_match" \
>> + "print result of getenv for $var_name"
>> +}
>> +
>> +with_test_prefix "long var value" {
>> + do_test "this is my test variable; testing long vars; {}"
>> +}
>> +
>> +with_test_prefix "empty var" {
>> + do_test ""
>> +}
>> +
>> +with_test_prefix "strange named var" {
>> + # In this test we're doing the following:
>> + #
>
> git am complains about a trailing whitespace here.
Removed.
>> + # (gdb) set environment 'asd =' = 123 43; asd b ### [];;;
>> + #
>> + # However, due to how GDB parses this line, the environment
>> + # variable will end up named <'asd> (without the <>), and its
>> + # value will be <' = 123 43; asd b ### [];;;> (without the <>).
>> + do_test "123 43; asd b ### [];;;" "'asd ='" "'asd" "' = 123 43;
>> asd b ### [];;;"
>
> Watch out, these square brackets are evaluated by tcl and replaced
> with an empty string.
Hm, OK. I'll make sure to properly quote them.
>> +}
>> +
>> +# Test setting and unsetting environment variables in various
>> +# fashions.
>> +
>> +proc test_set_unset_vars { } {
>> + global hex decimal binfile
>
> hex and decimal are unused.
Removed.
>> @@ -89,6 +112,23 @@ run_tests ()
>> ++num_found;
>> SELF_CHECK (num_found == 1);
>>
>> + /* Before unsetting our test variable, test that user-unset works
>> + fine. */
>> + env.unset ("GDB_SELFTEST_ENVIRON");
>> + SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON") == NULL);
>> + SELF_CHECK (env.user_set_env ().size () == 0);
>> + SELF_CHECK (env.user_unset_env ().size () == 1);
>> + SELF_CHECK (set_contains (env.user_unset_env (),
>> + std::string ("GDB_SELFTEST_ENVIRON")));
>
> It seems to me that the same thing has been tested a few lines higher.
> Can we keep just one? But in general, I find it quite confusing to
> find out what is tested and see if anything it missing. I think it
> would be better to have several functions (run_tests can call
> sub-functions), where each function tests one particular behavior.
> Not only would it help readability, but it would also make it easier
> to add tests without fear of breaking the existing tests.
Good point. I'll make some adjustments to the way things are tested
here.
I'll submit v4 soon.
Thanks,
--
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF 31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
next prev parent reply other threads:[~2017-08-28 21:25 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-29 19:41 [PATCH] Implement the ability to transmit " Sergio Durigan Junior
2017-07-10 21:32 ` Sergio Durigan Junior
2017-07-13 21:47 ` Simon Marchi
2017-07-14 17:34 ` Sergio Durigan Junior
2017-07-27 3:36 ` [PATCH v2] Implement the ability to set/unset " Sergio Durigan Junior
2017-07-27 17:10 ` Eli Zaretskii
2017-07-27 22:05 ` Simon Marchi
2017-08-01 2:33 ` Sergio Durigan Junior
2017-08-01 9:35 ` Simon Marchi
2017-08-04 22:56 ` Sergio Durigan Junior
2017-07-29 22:36 ` Simon Marchi
2017-08-01 2:43 ` Sergio Durigan Junior
2017-08-01 9:54 ` Simon Marchi
2017-08-04 23:03 ` Sergio Durigan Junior
2017-08-05 18:14 ` Simon Marchi
2017-08-12 4:34 ` Sergio Durigan Junior
2017-08-12 8:11 ` Simon Marchi
[not found] ` <256083325d9f9c4cc4f5518fe6e5292d@polymtl.ca>
2017-08-12 4:19 ` Sergio Durigan Junior
2017-08-13 6:19 ` [PATCH v3] " Sergio Durigan Junior
2017-08-21 19:11 ` Sergio Durigan Junior
2017-08-24 19:25 ` Simon Marchi
2017-08-28 21:25 ` Sergio Durigan Junior [this message]
2017-08-28 23:13 ` [PATCH v4] " Sergio Durigan Junior
2017-08-31 19:37 ` Simon Marchi
2017-08-31 20:34 ` Sergio Durigan Junior
2017-08-31 20:39 ` Simon Marchi
2017-08-31 20:49 ` [PATCH v5] " Sergio Durigan Junior
2017-08-31 21:03 ` Simon Marchi
2017-08-31 21:26 ` Sergio Durigan Junior
2017-09-05 15:33 ` Thomas Preudhomme
2017-09-05 16:26 ` Simon Marchi
2017-09-05 17:09 ` Thomas Preudhomme
2017-09-05 18:41 ` Simon Marchi
2017-09-06 8:36 ` Thomas Preudhomme
2017-09-01 6:19 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87a82j9yi8.fsf@redhat.com \
--to=sergiodj@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
--cc=simon.marchi@polymtl.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox