diff mbox

Add support for embedding scripts in .debug_gdb_scripts.

Message ID CAP9bCMSC0TgsuZ+K0qb6Fkdafh_vbbCL+gBZ3V1h6aM6kUqW+A@mail.gmail.com
State New
Headers show

Commit Message

Doug Evans Jan. 16, 2015, 5:15 p.m. UTC
On Thu, Jan 15, 2015 at 10:11 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> From: Doug Evans <xdje42@gmail.com>
>> Date: Thu, 15 Jan 2015 09:31:48 -0800
>>
>> +* Python/Guile scripting
>> +
>> +** GDB now supports auto-loading of Python/Guile scripts contained in the
>> +   special section named `.debug_gdb_scripts'.
>
> I think we should tell here on what systems/targets this is supported.
> Otherwise, the NEWS entry is OK.

The previous news entry didn't, and I'm following that.

>>  For systems using file formats like ELF and COFF,
>>  when @value{GDBN} loads a new object file
>>  it will look for a special section named @code{.debug_gdb_scripts}.
>
> Is this really supported with non-ELF targets?  E.g., does pe-coff
> (Windows) support such sections?

My mingw32 toolchain generates DWARF
(i.e., has .debug_* sections).

>> +If this section exists, its contents is a list of NUL-terminated entries
>> +specifying scripts to load.  Each entry begins with a non-NULL prefix byte that
>
> Let's be consistent here" "null", lower-case and with 2 'l'.  This is
> just a plain English word, not an acronym or a C symbol.

NULL is a typo, thanks for catching that.
I'm just following usage elsewhere in gdb.texinfo,
and I like this choice.

>
>> +Supported values for the prefix byte are define in the
>                                             ^^^^^^
> "defined"

Done.

>
>> +@file{include/gdb/section-scripts.h} file in the @value{GDBN} source tree.
>
> Is this really helpful?  If that file is installed, let's mention
> where to find it in the installed tree; if it is not installed, we
> ought to list the values here, since the reader might not have access
> to the source tree, let alone the one from which the binary was
> produced.
>
>> +The following entries are supported:
>> +
>> +@table @code
>> +@item SECTION_SCRIPT_ID_PYTHON_FILE = 1
>> +@item SECTION_SCRIPT_ID_SCHEME_FILE = 3
>> +@item SECTION_SCRIPT_ID_PYTHON_TEXT = 4
>> +@item SECTION_SCRIPT_ID_SCHEME_TEXT = 6
>> +@end table
>
> Are these the values of the prefix byte?  If so, we should simply skip
> the pointer to the source tree.

Done.

>
>> +@subsubsection Script Text Entries
>> +
>> +In script text entries the script to execute is contained in the entry
>> +instead of being loaded from a file.
>
> Suggest to reword this sentence:
>
>   Script text entries allow to put the executable script in the entry
>   itself instead of loading it from a file.

Done.

>
>> +The rest of the entry, up to the trailing NUL byte,
>                                              ^^^
> "null"

Copied from gdb.texinfo.
Plus we've had this conversation before. :-)

https://sourceware.org/ml/gdb-patches/2013-12/msg00892.html
https://sourceware.org/ml/gdb-patches/2013-12/msg00894.html

>
>>                                                      is the script to
>> +execute in the specified language.
>
> Specified how and by what means?
>
>> +Loading of inlined scripts require a properly configured
>                               ^^^^^^^
> "requires"

Done.
2015-01-16  Doug Evans  <xdje42@gmail.com>

	Add support for inlining scripts into .debug_gdb_scripts.

	include/
	* gdb/section-scripts.h: Remove "future extension" comment.
	(SECTION_SCRIPT_ID_PYTHON_TEXT): New macro.
	(SECTION_SCRIPT_ID_SCHEME_TEXT): New macro.

	gdb/
	* NEWS: Mention inlined scripts in .debug_gdb_scripts section.
	* auto-load.c: #include ctype.h.
	(struct auto_load_pspace_info): Replace member loaded_scripts with
	new members loaded_script_files, loaded_script_texts.
	(auto_load_pspace_data_cleanup): Update.
	(init_loaded_scripts_info): Update.
	(get_auto_load_pspace_data_for_loading): Update.
	(maybe_add_script_file): Renamed from maybe_add_script.  All callers
	updated.
	(maybe_add_script_text): New function.
	(clear_section_scripts): Update.
	(source_script_file, execute_script_contents): New functions.
	(source_section_scripts): Add support for
	SECTION_SCRIPT_ID_PYTHON_TEXT, SECTION_SCRIPT_ID_GUILE_TEXT.
	(print_scripts): New function.
	(auto_load_info_scripts): Also print inlined scripts.
	(maybe_print_unsupported_script_warning): Renamed from
	unsupported_script_warning_print.  All callers updated.
	(maybe_print_script_not_found_warning): Renamed from
	script_not_found_warning_print.  All callers updated.
	* extension-priv.h (struct extension_language_script_ops): New member
	objfile_script_executor.
	* extension.c (ext_lang_objfile_script_executor): New function.
	* extension.h (objfile_script_executor_func): New typedef.
	(ext_lang_objfile_script_executor): Declare.
	* guile/guile-internal.h (gdbscm_execute_objfile_script): Declare.
	* guile/guile.c (guile_extension_script_ops): Update.
	* guile/scm-objfile.c (gdbscm_execute_objfile_script): New function.
	* python/python.c (python_extension_script_ops): Update.
	(gdbpy_execute_objfile_script): New function.

	doc/
	* gdb.texinfo (dotdebug_gdb_scripts section): Update docs to
	distinguish script files vs inlined scripts.
	* python.texi (Python Auto-loading): Ditto.

	testsuite/
	* gdb.guile/scm-section-script.c: Add duplicate inlined section script
	entries.  Duplicate file section script entries.
	* gdb.guile/scm-section-script.exp: Add tests for duplicate entries,
	inlined entries.  Add test for safe-path rejection.
	* gdb.python/py-section-script.c: Add duplicate inlined section script
	entries.  Duplicate file section script entries.
	* gdb.python/py-section-script.exp: Add tests for duplicate entries,
	inlined entries.  Add test for safe-path rejection.

Comments

Eli Zaretskii Jan. 16, 2015, 6:01 p.m. UTC | #1
> Date: Fri, 16 Jan 2015 09:15:35 -0800
> From: Doug Evans <xdje42@gmail.com>
> Cc: binutils@sourceware.org, 	"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> 
> >> +* Python/Guile scripting
> >> +
> >> +** GDB now supports auto-loading of Python/Guile scripts contained in the
> >> +   special section named `.debug_gdb_scripts'.
> >
> > I think we should tell here on what systems/targets this is supported.
> > Otherwise, the NEWS entry is OK.
> 
> The previous news entry didn't, and I'm following that.

So we have no hope for ever fixing past mistakes?

> > Let's be consistent here" "null", lower-case and with 2 'l'.  This is
> > just a plain English word, not an acronym or a C symbol.
> 
> NULL is a typo, thanks for catching that.
> I'm just following usage elsewhere in gdb.texinfo,
> and I like this choice.

So we have no hope for ever fixing past mistakes?

> >> +The rest of the entry, up to the trailing NUL byte,
> >                                              ^^^
> > "null"
> 
> Copied from gdb.texinfo.
> Plus we've had this conversation before. :-)
> 
> https://sourceware.org/ml/gdb-patches/2013-12/msg00892.html
> https://sourceware.org/ml/gdb-patches/2013-12/msg00894.html

So we have no hope for ever fixing past mistakes?
Doug Evans Jan. 17, 2015, 1:15 a.m. UTC | #2
[- binutils]

On Fri, Jan 16, 2015 at 10:01 AM, Eli Zaretskii <eliz@gnu.org> wrote:
> So we have no hope for ever fixing past mistakes?

Past mistakes?
.debug_gdb_scripts isn't that old of a feature.

Maybe we need more formal community-agreed-on
conventions and rules for NEWS and docs.
These things seem to be of a "shall be this way" flavor,
and I wasn't expecting that.
When I cut-n-paste from code I can usually
tell what's expected, but I can't do that for NEWS/doc,
and we should fix that.  [Imagine if coding conventions
changed like this.]
Eli Zaretskii Jan. 17, 2015, 8:17 a.m. UTC | #3
> Date: Fri, 16 Jan 2015 17:15:49 -0800
> From: Doug Evans <xdje42@gmail.com>
> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> 
> On Fri, Jan 16, 2015 at 10:01 AM, Eli Zaretskii <eliz@gnu.org> wrote:
> > So we have no hope for ever fixing past mistakes?
> 
> Past mistakes?
> .debug_gdb_scripts isn't that old of a feature.

I wasn't talking only about that.  I was talking in general about the
argument "we do this elsewhere 'like this', so let's continue doing
that 'like this'".  For example, the "NUL" thingie.

> Maybe we need more formal community-agreed-on
> conventions and rules for NEWS and docs.

Maybe we should, but I'd like first to agree that an argument of this
kind doesn't have too much weight.  It's okay to look at past
practices when the choice is purely stylistic.  But when there are
clear advantages to deviating from past practices, those past
practices shouldn't hold us back, otherwise we will stagnate.  Agreed?

In this case, "NUL" is simply incorrect English: there's no such word
or acronym.  The only legitimate use of "NUL" I know of is in
reference to the DOS/Windows null device.

As for showing the systems where .debug_gdb_scripts feature is
supported, there are clear advantages to providing that information in
NEWS, and the price is quite low, I hope you will agree.

I can also live with you asking me in response to please change all
the other instances to use the same style.  But what I would prefer
not to live with is flat refusal to make a requested change in your
patch because "we do that elsewhere".

> These things seem to be of a "shall be this way" flavor,
> and I wasn't expecting that.

Isn't that normal during patch review process?

> When I cut-n-paste from code I can usually
> tell what's expected, but I can't do that for NEWS/doc,

From experience, my requests are remarkably consistent, even if the
same issues pop up with quite some time in-between.  You've just cited
a similar discussion about NUL from more than a year ago, which I
didn't event remember.

> [Imagine if coding conventions changed like this.]

They do, because standards.texi is actively maintained.  Things I've
read and memorized years ago have changed, sometimes radically so, and
I keep bumping into them when people say my code isn't according to
GCS and cite from there.  That's life, and I accept it.
Doug Evans Jan. 18, 2015, 4:15 a.m. UTC | #4
On Sat, Jan 17, 2015 at 12:17 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> Date: Fri, 16 Jan 2015 17:15:49 -0800
>> From: Doug Evans <xdje42@gmail.com>
>> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
>>
>> On Fri, Jan 16, 2015 at 10:01 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> > So we have no hope for ever fixing past mistakes?
>>
>> Past mistakes?
>> .debug_gdb_scripts isn't that old of a feature.
>
> I wasn't talking only about that.  I was talking in general about the
> argument "we do this elsewhere 'like this', so let's continue doing
> that 'like this'".  For example, the "NUL" thingie.

NUL has been the name of the zero byte in ASCII since the early 60s.
It's hardly a "thingie".

http://en.wikipedia.org/wiki/ASCII

>
>> Maybe we need more formal community-agreed-on
>> conventions and rules for NEWS and docs.
>
> Maybe we should, but I'd like first to agree that an argument of this
> kind doesn't have too much weight.  It's okay to look at past
> practices when the choice is purely stylistic.  But when there are
> clear advantages to deviating from past practices, those past
> practices shouldn't hold us back, otherwise we will stagnate.  Agreed?

Only to the extent that such reasoning must be re-evaluated
every time it is applied.

Plus, I don't understand the point about more formal conventions
not having too much weight.  People should be able to write code
with some expectation that what they've written is correct.
The same should be true with NEWS/doc.
And one way we do that is with documented rules and conventions.

If we're going to have such stringent rules in gdb for NEWS/docs,
then I think at least things that have been non-obvious in the past
should be written down.

> In this case, "NUL" is simply incorrect English: there's no such word
> or acronym.  The only legitimate use of "NUL" I know of is in
> reference to the DOS/Windows null device.

Au contraire.
NUL has been the common name of the zero byte since long before
gdb was born.
Ref: above link on ASCII, for example

> As for showing the systems where .debug_gdb_scripts feature is
> supported, there are clear advantages to providing that information in
> NEWS, and the price is quite low, I hope you will agree.

It is documented in gdb.texinfo.
I don't see the point of repeating it in NEWS,
especially for a case such as this.
[I just don't see its presence in this particular
case making a material difference in anyone's life.]

https://sourceware.org/gdb/current/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html#dotdebug_005fgdb_005fscripts-section

Tell ya what though.
Let's add a new section to the conventions wiki for NEWS/docs.
One of those entries will be:

All NEWS entries for new features shall specify the platform(s) on which
the feature is available, if it is not a generally available feature.
[or words to that effect]
And let's enforce all these rules the way we do
coding conventions (which I don't have a problem with).

Ok?

That way everyone can be on the same page,
and there is a document one can refer people to.

> I can also live with you asking me in response to please change all
> the other instances to use the same style.  But what I would prefer
> not to live with is flat refusal to make a requested change in your
> patch because "we do that elsewhere".

If I believe the request is invalid (e.g., NUL), then
I've got to push back.  In the NUL case,
this term is so common that to outlaw it in
gdb docs would be a real shame.
I wasn't aware, until now, that you weren't aware of
how common NUL is.  Otherwise I would have
pointed it out sooner. Sorry!

Also, until the patch is checked in, it's premature
to assess whether anything was flatly refused.

I proposed writing down rules NEWS/doc entries are expected to follow.
Ideally there won't be many, but certainly non-obvious ones
should be, and as for who decides what's non-obvious:
anytime discussions like these comes up works for me.

If the community agrees to requiring new non-general features
in NEWS to always specify the platform they're for, then I'm happy
to go with the flow.

>> These things seem to be of a "shall be this way" flavor,
>> and I wasn't expecting that.
>
> Isn't that normal during patch review process?

Not when one of the choices is perfectly valid (e.g., NUL).

>> When I cut-n-paste from code I can usually
>> tell what's expected, but I can't do that for NEWS/doc,
>
> From experience, my requests are remarkably consistent, even if the
> same issues pop up with quite some time in-between.  You've just cited
> a similar discussion about NUL from more than a year ago, which I
> didn't event remember.
>
>> [Imagine if coding conventions changed like this.]
>
> They do, because standards.texi is actively maintained.  Things I've
> read and memorized years ago have changed, sometimes radically so, and
> I keep bumping into them when people say my code isn't according to
> GCS and cite from there.  That's life, and I accept it.

They don't change the way I was thinking of when I wrote that.
a) gdb's coding standards don't change that frequently.
b) they're documented.
Eli Zaretskii Jan. 18, 2015, 4:22 p.m. UTC | #5
> Date: Sat, 17 Jan 2015 20:15:46 -0800
> From: Doug Evans <xdje42@gmail.com>
> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> 
> > I wasn't talking only about that.  I was talking in general about the
> > argument "we do this elsewhere 'like this', so let's continue doing
> > that 'like this'".  For example, the "NUL" thingie.
> 
> NUL has been the name of the zero byte in ASCII since the early 60s.

Not any longer: its Unicode name is "NULL" (upper-case, because
Unicode uses upper-case for all character names).  And even back then,
this was an abbreviation, not the full name.

> > Maybe we should, but I'd like first to agree that an argument of this
> > kind doesn't have too much weight.  It's okay to look at past
> > practices when the choice is purely stylistic.  But when there are
> > clear advantages to deviating from past practices, those past
> > practices shouldn't hold us back, otherwise we will stagnate.  Agreed?
> 
> Only to the extent that such reasoning must be re-evaluated
> every time it is applied.

I agree with "re-evaluated".  I don't agree with "rejected" as the
default modus operandi.

> Plus, I don't understand the point about more formal conventions
> not having too much weight.  People should be able to write code
> with some expectation that what they've written is correct.
> The same should be true with NEWS/doc.
> And one way we do that is with documented rules and conventions.

I don't think it's reasonable, or even practical, to codify each and
every case like that.  Did you really mean that we write down
something like "use 'null byte' for the byte whose value is zero,
including, but not limited to, when talking about C-style string
terminator"?  There would be any number of such "rules"; following
them will probably be a much higher PITA than occasionally having to
replace words after a review.

I normally don't argue about style, except when I think there's more
than just style at stake.  Eventually, people should trust the
validity of my views on these matters, or ask me to step down.

> > In this case, "NUL" is simply incorrect English: there's no such word
> > or acronym.  The only legitimate use of "NUL" I know of is in
> > reference to the DOS/Windows null device.
> 
> Au contraire.
> NUL has been the common name of the zero byte since long before
> gdb was born.
> Ref: above link on ASCII, for example

See above.

In any case, you weren't talking about "NUL" the name, you said things
like "NUL-terminated names" and "non-NUL prefix byte".  This isn't
about "NUL" the character's archaic name, this is about a byte whose
value is zero, a.k.a. "null".  And our audience is 21st century
readers, not vintage 1960s flock of assembly-language programmers, for
whom NUL and STX were acronyms they saw all day every day.  Nowadays,
this is simply an obstacle to reading and understanding the text.  The
purpose of my comments was to make the text more readable.

> Let's add a new section to the conventions wiki for NEWS/docs.
> One of those entries will be:
> 
> All NEWS entries for new features shall specify the platform(s) on which
> the feature is available, if it is not a generally available feature.
> [or words to that effect]
> And let's enforce all these rules the way we do
> coding conventions (which I don't have a problem with).
> 
> Ok?

I'm fine with that, if no one objects.  But you cannot possibly codify
all such minor issues, they are too many.  And it isn't needed, from
my POV.

> > I can also live with you asking me in response to please change all
> > the other instances to use the same style.  But what I would prefer
> > not to live with is flat refusal to make a requested change in your
> > patch because "we do that elsewhere".
> 
> If I believe the request is invalid (e.g., NUL), then
> I've got to push back.

You did, and I called you.  If it weren't important, I would've
accepted.  I didn't.  Where do we go from here?

> Also, until the patch is checked in, it's premature
> to assess whether anything was flatly refused.

You didn't agree and didn't propose any compromise, so how else to
understand your reaction?

> If the community agrees to requiring new non-general features
> in NEWS to always specify the platform they're for, then I'm happy
> to go with the flow.

IMO, which changes need to mention the platforms is a judgment call.
So no such generally enforced rule is necessary.  But if we want to
state that always, I don't object, although in many cases it will be
redundant, and will probably say something like "supported on all
platforms".  I suspect we won't like the result.

> >> These things seem to be of a "shall be this way" flavor,
> >> and I wasn't expecting that.
> >
> > Isn't that normal during patch review process?
> 
> Not when one of the choices is perfectly valid (e.g., NUL).

So is the text I proposed instead.  This isn't about validity, this is
about making the text more easily read and understood.

Judging human-readable text includes suggesting better wording, even
if the original one is valid.  When I suggest a different wording or
spelling, I don't necessarily mean to say the original was incorrect
or invalid, just that there's a better one.  Don't we want our manual
to be as best as possible?
Doug Evans Jan. 18, 2015, 8:47 p.m. UTC | #6
On Sun, Jan 18, 2015 at 8:22 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>> Date: Sat, 17 Jan 2015 20:15:46 -0800
>> From: Doug Evans <xdje42@gmail.com>
>> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
>>
>> > I wasn't talking only about that.  I was talking in general about the
>> > argument "we do this elsewhere 'like this', so let's continue doing
>> > that 'like this'".  For example, the "NUL" thingie.
>>
>> NUL has been the name of the zero byte in ASCII since the early 60s.
>
> Not any longer: its Unicode name is "NULL" (upper-case, because
> Unicode uses upper-case for all character names).

I guess what we need is an agreed upon reference saying NUL
is gone.  I *like* NUL. It's explicitly different than null or NULL.
Last time you said you wouldn't argue,
but now it's become an absolute requirement.
The rules for how to write NUL/null/NULL have changed,
and that's unfortunate.  And there was no discussion
going into this decision (I guess we're having it now, but still ...).

> And even back then,
> this was an abbreviation, not the full name.

It's a name, abbreviated or otherwise.
And a nice one to because it's clear and unambiguous.

>> > Maybe we should, but I'd like first to agree that an argument of this
>> > kind doesn't have too much weight.  It's okay to look at past
>> > practices when the choice is purely stylistic.  But when there are
>> > clear advantages to deviating from past practices, those past
>> > practices shouldn't hold us back, otherwise we will stagnate.  Agreed?
>>
>> Only to the extent that such reasoning must be re-evaluated
>> every time it is applied.
>
> I agree with "re-evaluated".  I don't agree with "rejected" as the
> default modus operandi.
>
>> Plus, I don't understand the point about more formal conventions
>> not having too much weight.  People should be able to write code
>> with some expectation that what they've written is correct.
>> The same should be true with NEWS/doc.
>> And one way we do that is with documented rules and conventions.
>
> I don't think it's reasonable, or even practical, to codify each and
> every case like that.  Did you really mean that we write down
> something like "use 'null byte' for the byte whose value is zero,
> including, but not limited to, when talking about C-style string
> terminator"?

I'm not sure I'd use formal phrasings such as "but not limited to",
but I would want to say that one must write, e.g., null-terminated
instead of NUL-terminated.
We have a bazillion coding convention rules,
for good reasons.
I think we can manage a few more for docs.

There are doc writing conventions already, btw,

http://www.gnu.org/prep/standards/standards.html#Documentation

and, heh, I'd forgotten that I'd already started a wiki
page for local rules/conventions.

https://sourceware.org/gdb/wiki/Internals%20GDB-Doc-Standards

So at least that part is done. :-)

> There would be any number of such "rules"; following
> them will probably be a much higher PITA than occasionally having to
> replace words after a review.

Depends, I think.
If in the future one doesn't understand or even disagrees with the
replacement (how many disagree with our coding
convention of half-indented braces! 1/2 :-)) then having
such things written down will help advance the discussion,
in part because the discussion has already been had
and decided!

> I normally don't argue about style, except when I think there's more
> than just style at stake.  Eventually, people should trust the
> validity of my views on these matters, or ask me to step down.

This isn't about asking anyone to step down.
This should also not be about trust.
If you can present a convincing argument
that draws on external references to support
your claim that NUL is "archaic" and shall not be used
in new documentation, I'll certainly re-evaluate
my opinion.
[I'll also hold an Irish-style wake for NUL.
Guinness for everyone! 1/2 :-)]

>> > In this case, "NUL" is simply incorrect English: there's no such word
>> > or acronym.  The only legitimate use of "NUL" I know of is in
>> > reference to the DOS/Windows null device.
>>
>> Au contraire.
>> NUL has been the common name of the zero byte since long before
>> gdb was born.
>> Ref: above link on ASCII, for example
>
> See above.

I still see NUL being referred to in the various places I look
as a valid name (abbreviation or otherwise).

> In any case, you weren't talking about "NUL" the name, you said things
> like "NUL-terminated names" and "non-NUL prefix byte".  This isn't
> about "NUL" the character's archaic name, this is about a byte whose
> value is zero, a.k.a. "null".

The distinction is lost on me.
E.g., NUL-terminated names are strings of characters,
the last one of which has the valid name of NUL.

> And our audience is 21st century
> readers, not vintage 1960s flock of assembly-language programmers, for
> whom NUL and STX were acronyms they saw all day every day.

for reference sake,
This characterization bothers me.

> Nowadays,
> this is simply an obstacle to reading and understanding the text.  The
> purpose of my comments was to make the text more readable.

Alas the loss in readability is lost on me.
Is it really an obstacle to reading and understanding the text?
I'm not convinced.

>> Let's add a new section to the conventions wiki for NEWS/docs.
>> One of those entries will be:
>>
>> All NEWS entries for new features shall specify the platform(s) on which
>> the feature is available, if it is not a generally available feature.
>> [or words to that effect]
>> And let's enforce all these rules the way we do
>> coding conventions (which I don't have a problem with).
>>
>> Ok?
>
> I'm fine with that, if no one objects.  But you cannot possibly codify
> all such minor issues, they are too many.  And it isn't needed, from
> my POV.

If it serves to put in writing absolute rules that someone is likely
to get tripped up by or not understand then it will have served its purpose.

>> > I can also live with you asking me in response to please change all
>> > the other instances to use the same style.  But what I would prefer
>> > not to live with is flat refusal to make a requested change in your
>> > patch because "we do that elsewhere".
>>
>> If I believe the request is invalid (e.g., NUL), then
>> I've got to push back.
>
> You did, and I called you.  If it weren't important, I would've
> accepted.  I didn't.  Where do we go from here?

Called me?  I'm not sure how to interpret that.

I'm guessing no one else is interested in the discussion,
which is not unreasonable :-), so where we go is
I write "null-terminated" and get it written down so
that I can remember it.

>> Also, until the patch is checked in, it's premature
>> to assess whether anything was flatly refused.
>
> You didn't agree and didn't propose any compromise, so how else to
> understand your reaction?

Not rush to judgment would be a start.
"flatly refused" is pretty out there.
If our roles were reversed (the topic would have be different of course)
I would have said something like "I really think [...] is the
way to go because [...]. Please reconsider."
And even then I may not impose any kind of veto.

[E.g., in a different thread the pascal folks want to add
a patch that I think is unnecessary (though there's still
an outstanding question, and there may be a use-case
where the patch adds value) but I can live with it,
with perhaps a few mods and comments to the effect
that it's a pascal-specific choice. Depending on the
answer to the outstanding question, I'd be uncomfortable
with that choice becoming more general though.]

>> If the community agrees to requiring new non-general features
>> in NEWS to always specify the platform they're for, then I'm happy
>> to go with the flow.
>
> IMO, which changes need to mention the platforms is a judgment call.
> So no such generally enforced rule is necessary.  But if we want to
> state that always, I don't object, although in many cases it will be
> redundant, and will probably say something like "supported on all
> platforms".  I suspect we won't like the result.

I don't understand.
I explicitly wrote that I was only talking about the cases other than
"supported on all platforms."  Of course we wouldn't like THAT result.

>> >> These things seem to be of a "shall be this way" flavor,
>> >> and I wasn't expecting that.
>> >
>> > Isn't that normal during patch review process?
>>
>> Not when one of the choices is perfectly valid (e.g., NUL).
>
> So is the text I proposed instead.  This isn't about validity, this is
> about making the text more easily read and understood.

IMO it's not an improvement.

> Judging human-readable text includes suggesting better wording, even
> if the original one is valid.  When I suggest a different wording or
> spelling, I don't necessarily mean to say the original was incorrect
> or invalid, just that there's a better one.  Don't we want our manual
> to be as best as possible?

"Suggest"?
Are you sure you meant to write that?
[I do try to review what I say before I hit Send,
but I don't always succeed and catch everything,
and I certainly allow anyone else to hit Send to soon as well.]

If I've made a suggestion to someone, and they
don't take it, then if it really was just a suggestion
I'd accept that.  If, OTOH, they still preferred their solution,
and while I may have used the word suggestion
the first time when in reality it was intended as a command,
then I would then say so.  The person I'm talking
to might take my future "suggestions" a little more
tepidly though, so clarity is important here.
Joel Brobecker Jan. 19, 2015, 2:49 p.m. UTC | #7
> >> All NEWS entries for new features shall specify the platform(s) on which
> >> the feature is available, if it is not a generally available feature.
> >> [or words to that effect]
> >> And let's enforce all these rules the way we do
> >> coding conventions (which I don't have a problem with).
> >>
> >> Ok?
> >
> > I'm fine with that, if no one objects.  But you cannot possibly codify
> > all such minor issues, they are too many.  And it isn't needed, from
> > my POV.
> 
> If it serves to put in writing absolute rules that someone is likely
> to get tripped up by or not understand then it will have served its
> purpose.

I just personally think this is too extreme a measure.  There are times
when absolute rules may be useful, but I don't think this is the case
here.

Eli is our documentation maintainer,so let's continue trusting
his judgement. This discussion is not about black and white, and
as such, it's easy to disagree. But I don't think it's important
enough to spend more time on this. I know it can be fustrating
to make a change one does not believe in, but after a reasonable
attempt at discussing it, I'd go with his call.
Eli Zaretskii Jan. 19, 2015, 4:05 p.m. UTC | #8
> Date: Sun, 18 Jan 2015 12:47:55 -0800
> From: Doug Evans <xdje42@gmail.com>
> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> 
> I'm guessing no one else is interested in the discussion,
> which is not unreasonable :-), so where we go is
> I write "null-terminated" and get it written down so
> that I can remember it.

Yes, let's do that, please.  TIA.

(I don't see a good reason to continue arguing about the rest of the
points, as doing that evidently doesn't bring us closer to a
resolution.)
Doug Evans Jan. 20, 2015, 4:35 p.m. UTC | #9
On Mon, Jan 19, 2015 at 6:49 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>> >> All NEWS entries for new features shall specify the platform(s) on which
>> >> the feature is available, if it is not a generally available feature.
>> >> [or words to that effect]
>> >> And let's enforce all these rules the way we do
>> >> coding conventions (which I don't have a problem with).
>> >>
>> >> Ok?
>> >
>> > I'm fine with that, if no one objects.  But you cannot possibly codify
>> > all such minor issues, they are too many.  And it isn't needed, from
>> > my POV.
>>
>> If it serves to put in writing absolute rules that someone is likely
>> to get tripped up by or not understand then it will have served its
>> purpose.
>
> I just personally think this is too extreme a measure.  There are times
> when absolute rules may be useful, but I don't think this is the case
> here.

Eh? What we have here *is* an absolute rule:
We used to be allowed to use phrases like NUL-terminated
in documentation, now we are not.

> Eli is our documentation maintainer,so let's continue trusting
> his judgement. This discussion is not about black and white, and
> as such, it's easy to disagree. But I don't think it's important
> enough to spend more time on this. I know it can be fustrating
> to make a change one does not believe in, but after a reasonable
> attempt at discussing it, I'd go with his call.

I for one would liked to have seen the data to back up
the claim that NUL-terminated is archaic.
It's not that I don't trust someone's judgement, rather it's that that's
the wrong way to impose the change.
Joel Brobecker Jan. 21, 2015, 9:57 a.m. UTC | #10
> > I just personally think this is too extreme a measure.  There are times
> > when absolute rules may be useful, but I don't think this is the case
> > here.
> 
> Eh? What we have here *is* an absolute rule:
> We used to be allowed to use phrases like NUL-terminated
> in documentation, now we are not.

True, but I just think it's not worth starting to write _rules_
down. If we start writing such rules down, then that means that
we must write down all other rules. Which seems OK in principle,
but when you get to that level of details, the list can become
so long as to be really hard to keep in mind. What I'm getting
at is that this is really a detail, and if we want to make
a rule of it, I'd create one more general that says "no outdated
expression" may be used.

> > Eli is our documentation maintainer,so let's continue trusting
> > his judgement. This discussion is not about black and white, and
> > as such, it's easy to disagree. But I don't think it's important
> > enough to spend more time on this. I know it can be fustrating
> > to make a change one does not believe in, but after a reasonable
> > attempt at discussing it, I'd go with his call.
> 
> I for one would liked to have seen the data to back up
> the claim that NUL-terminated is archaic.
> It's not that I don't trust someone's judgement, rather it's that that's
> the wrong way to impose the change.

FWIW, and this is only my personal opinion of course, since you are
in fact entitled to getting an explanation: Eli telling me, as our
Documentation Maintainer, "it reads better if you use [blah]", is
usually enough for me to follow his lead and make the change. I'd have
to disagree fairly strongly to argue further. Since (I think) Eli tried
to explain, is that the case, here? That you disagree fairly strongly
with Eli's assessment?
Stan Shebs Feb. 13, 2015, 4:15 p.m. UTC | #11
On 1/20/15 8:35 AM, Doug Evans wrote:
> [...]
> 
> I for one would liked to have seen the data to back up
> the claim that NUL-terminated is archaic.
> It's not that I don't trust someone's judgement, rather it's that that's
> the wrong way to impose the change.

Reminiscent of my Wikipedia editing days!  It's pretty difficult to
prove obsolescence of a particular usage; Wikipedia editors trying to
decide the "most common" form of a term would resort to elaborate
combinations of Google searches, and then get mired down in meta-debate
about whether the searches were returning valid numbers - or whether 55%
for A and 45% for B was a meaningful difference.

My instant reaction is that "NUL-terminated" is an old-fashioned usage,
but I can't say exactly when it declined.  To some extent all the
control codes became more obscure due to the shift from terminals to
window systems, and I imagine the increasing use of char encodings
beyond original ASCII has had an effect as well.

In general, I would like to have the documentation maintainer be more of
an editor, to have more of a free hand in deciding style rules, and to
not insist that everything has to be written down beforehand.  The flip
side of the expectation is that we do need patches that make the
documents follow the rules reliably, so future contributors are not misled.

Stan
Eli Zaretskii Feb. 13, 2015, 4:45 p.m. UTC | #12
> Date: Fri, 13 Feb 2015 08:15:32 -0800
> From: Stan Shebs <stanshebs@earthlink.net>
> 
> In general, I would like to have the documentation maintainer be more of
> an editor, to have more of a free hand in deciding style rules, and to
> not insist that everything has to be written down beforehand.

I'm okay with that, but I'm also trying not to prevent contributors
from saying things their way.  Some people quite understandably feel
attached to what they wrote, so unnecessary changes risk causing
aggravation.
Andreas Schwab Feb. 13, 2015, 4:46 p.m. UTC | #13
How about using "zero-terminated"?

Andreas.
Pedro Alves Feb. 13, 2015, 6:05 p.m. UTC | #14
On 01/20/2015 04:35 PM, Doug Evans wrote:

> I for one would liked to have seen the data to back up
> the claim that NUL-terminated is archaic.
> It's not that I don't trust someone's judgement, rather it's that that's
> the wrong way to impose the change.

I think saying NUL instead of "null" is as archaic as saying CR instead of
"carriage return", LF instead of "line feed", NL instead of "new line",
etc.  I mean, maybe archaicness is not really the issue.

IMO, it's just a matter of whether we think using the character's
control code symbol is OK instead of the full name.  I think the
decision should be based on that alone.

E.g., would we write:

 "If this section exists, its contents is a list of entries separated
  by CR NL, specifying scripts to load.  The list is terminated with
  a NUL character."

?

Thanks,
Pedro Alves
Corinna Vinschen Feb. 15, 2015, 11:53 a.m. UTC | #15
On Feb 13 18:05, Pedro Alves wrote:
> On 01/20/2015 04:35 PM, Doug Evans wrote:
> 
> > I for one would liked to have seen the data to back up
> > the claim that NUL-terminated is archaic.
> > It's not that I don't trust someone's judgement, rather it's that that's
> > the wrong way to impose the change.
> 
> I think saying NUL instead of "null" is as archaic as saying CR instead of
> "carriage return", LF instead of "line feed", NL instead of "new line",
> etc.  I mean, maybe archaicness is not really the issue.
> 
> IMO, it's just a matter of whether we think using the character's
> control code symbol is OK instead of the full name.  I think the
> decision should be based on that alone.
> 
> E.g., would we write:
> 
>  "If this section exists, its contents is a list of entries separated
>   by CR NL, specifying scripts to load.  The list is terminated with
>   a NUL character."

Sure, except for s/NL/LF/g.

What I don't grok here either is the usage of the word "archaic" in
terms of a well-known, well-established, documented, and, above all,
*standardised*(*) set of abreviations of characters with a certain
meaning.

NUL is the character with the value \0.  Why is that suddenly a problem?
Aren't developers the target group of the GDB documentation?  Isn't ASCII
developer 101?


Corinna

(*) https://tools.ietf.org/html/rfc20
    https://mailarchive.ietf.org/arch/msg/ietf-announce/KIbuNLhChScLC2JBTmFOjj8fT78
    http://www.rfc-editor.org/std/std-index.txt
diff mbox

Patch

diff --git a/include/gdb/section-scripts.h b/include/gdb/section-scripts.h
index c4b7a1c..effce62 100644
--- a/include/gdb/section-scripts.h
+++ b/include/gdb/section-scripts.h
@@ -28,8 +28,6 @@ 
    Other unused values needn't specify different scripting languages,
    but we have no need for anything else at the moment.
 
-   Future extension: Include the contents of the script in the section.
-
    These values are defined as macros so that they can be used in embedded
    asms and assembler source files.  */
 
@@ -47,4 +45,18 @@ 
    file.  */
 #define SECTION_SCRIPT_ID_SCHEME_FILE 3
 
+/* The record is a nul-terminated string.
+   The first line is the name of the script.
+   Subsequent lines are interpreted as a python script.  */
+#define SECTION_SCRIPT_ID_PYTHON_TEXT 4
+
+/* Native GDB scripts are not currently supported in .debug_gdb_scripts,
+   but we reserve a value for it.  */
+/*#define SECTION_SCRIPT_ID_GDB_TEXT 5*/
+
+/* The record is a nul-terminated string.
+   The first line is the name of the script.
+   Subsequent lines are interpreted as a guile(scheme) script.  */
+#define SECTION_SCRIPT_ID_SCHEME_TEXT 6
+
 #endif /* GDB_SECTION_SCRIPTS_H */
diff --git a/gdb/NEWS b/gdb/NEWS
index 2d2c941..baf1868 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,11 @@ 
 
 *** Changes since GDB 7.9
 
+* Python/Guile scripting
+
+** GDB now supports auto-loading of Python/Guile scripts contained in the
+   special section named `.debug_gdb_scripts'.
+
 *** Changes in GDB 7.9
 
 * GDB now supports hardware watchpoints on x86 GNU Hurd.
diff --git a/gdb/auto-load.c b/gdb/auto-load.c
index c152778..778eeb6 100644
--- a/gdb/auto-load.c
+++ b/gdb/auto-load.c
@@ -18,6 +18,7 @@ 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include <ctype.h>
 #include "auto-load.h"
 #include "progspace.h"
 #include "gdb_regex.h"
@@ -48,14 +49,15 @@ 
    followed by the path of a python script to load.  */
 #define AUTO_SECTION_NAME ".debug_gdb_scripts"
 
-static int maybe_add_script (struct auto_load_pspace_info *pspace_info,
-			     int loaded, const char *name,
-			     const char *full_path,
-			     const struct extension_language_defn *language);
+static void maybe_print_unsupported_script_warning
+  (struct auto_load_pspace_info *, struct objfile *objfile,
+   const struct extension_language_defn *language,
+   const char *section_name, unsigned offset);
 
-static int unsupported_script_warning_print (struct auto_load_pspace_info *);
-
-static int script_not_found_warning_print (struct auto_load_pspace_info *);
+static void maybe_print_script_not_found_warning
+  (struct auto_load_pspace_info *, struct objfile *objfile,
+   const struct extension_language_defn *language,
+   const char *section_name, unsigned offset);
 
 /* Value of the 'set debug auto-load' configuration variable.  */
 static int debug_auto_load = 0;
@@ -541,8 +543,10 @@  For more information about this security protection see the\n\
 
 struct auto_load_pspace_info
 {
-  /* For each program space we keep track of loaded scripts.  */
-  struct htab *loaded_scripts;
+  /* For each program space we keep track of loaded scripts, both when
+     specified as file names and as scripts to be executed directly.  */
+  struct htab *loaded_script_files;
+  struct htab *loaded_script_texts;
 
   /* Non-zero if we've issued the warning about an auto-load script not being
      supported.  We only want to issue this warning once.  */
@@ -553,7 +557,7 @@  struct auto_load_pspace_info
   int script_not_found_warning_printed;
 };
 
-/* Objects of this type are stored in the loaded script hash table.  */
+/* Objects of this type are stored in the loaded_script hash table.  */
 
 struct loaded_script
 {
@@ -561,7 +565,7 @@  struct loaded_script
   const char *name;
 
   /* Full path name or NULL if script wasn't found (or was otherwise
-     inaccessible).  */
+     inaccessible), or NULL for loaded_script_texts.  */
   const char *full_path;
 
   /* Non-zero if this script has been loaded.  */
@@ -578,8 +582,10 @@  auto_load_pspace_data_cleanup (struct program_space *pspace, void *arg)
 {
   struct auto_load_pspace_info *info = arg;
 
-  if (info->loaded_scripts)
-    htab_delete (info->loaded_scripts);
+  if (info->loaded_script_files)
+    htab_delete (info->loaded_script_files);
+  if (info->loaded_script_texts)
+    htab_delete (info->loaded_script_texts);
   xfree (info);
 }
 
@@ -632,10 +638,14 @@  init_loaded_scripts_info (struct auto_load_pspace_info *pspace_info)
      Space for each entry is obtained with one malloc so we can free them
      easily.  */
 
-  pspace_info->loaded_scripts = htab_create (31,
-					     hash_loaded_script_entry,
-					     eq_loaded_script_entry,
-					     xfree);
+  pspace_info->loaded_script_files = htab_create (31,
+						  hash_loaded_script_entry,
+						  eq_loaded_script_entry,
+						  xfree);
+  pspace_info->loaded_script_texts = htab_create (31,
+						  hash_loaded_script_entry,
+						  eq_loaded_script_entry,
+						  xfree);
 
   pspace_info->unsupported_script_warning_printed = FALSE;
   pspace_info->script_not_found_warning_printed = FALSE;
@@ -650,23 +660,24 @@  get_auto_load_pspace_data_for_loading (struct program_space *pspace)
   struct auto_load_pspace_info *info;
 
   info = get_auto_load_pspace_data (pspace);
-  if (info->loaded_scripts == NULL)
+  if (info->loaded_script_files == NULL)
     init_loaded_scripts_info (info);
 
   return info;
 }
 
-/* Add script NAME in LANGUAGE to hash table of PSPACE_INFO.  LOADED 1 if the
-   script has been (is going to) be loaded, 0 otherwise (such as if it has not
-   been found).  FULL_PATH is NULL if the script wasn't found.  The result is
-   true if the script was already in the hash table.  */
+/* Add script file NAME in LANGUAGE to hash table of PSPACE_INFO.
+   LOADED 1 if the script has been (is going to) be loaded, 0 otherwise
+   (such as if it has not been found).
+   FULL_PATH is NULL if the script wasn't found.
+   The result is true if the script was already in the hash table.  */
 
 static int
-maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded,
-		  const char *name, const char *full_path,
-		  const struct extension_language_defn *language)
+maybe_add_script_file (struct auto_load_pspace_info *pspace_info, int loaded,
+		       const char *name, const char *full_path,
+		       const struct extension_language_defn *language)
 {
-  struct htab *htab = pspace_info->loaded_scripts;
+  struct htab *htab = pspace_info->loaded_script_files;
   struct loaded_script **slot, entry;
   int in_hash_table;
 
@@ -677,7 +688,7 @@  maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded,
 
   /* If this script is not in the hash table, add it.  */
 
-  if (! in_hash_table)
+  if (!in_hash_table)
     {
       char *p;
 
@@ -703,6 +714,44 @@  maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded,
   return in_hash_table;
 }
 
+/* Add script contents NAME in LANGUAGE to hash table of PSPACE_INFO.
+   LOADED 1 if the script has been (is going to) be loaded, 0 otherwise
+   (such as if it has not been found).
+   The result is true if the script was already in the hash table.  */
+
+static int
+maybe_add_script_text (struct auto_load_pspace_info *pspace_info,
+		       int loaded, const char *name,
+		       const struct extension_language_defn *language)
+{
+  struct htab *htab = pspace_info->loaded_script_texts;
+  struct loaded_script **slot, entry;
+  int in_hash_table;
+
+  entry.name = name;
+  entry.language = language;
+  slot = (struct loaded_script **) htab_find_slot (htab, &entry, INSERT);
+  in_hash_table = *slot != NULL;
+
+  /* If this script is not in the hash table, add it.  */
+
+  if (!in_hash_table)
+    {
+      char *p;
+
+      /* Allocate all space in one chunk so it's easier to free.  */
+      *slot = xmalloc (sizeof (**slot) + strlen (name) + 1);
+      p = ((char*) *slot) + sizeof (**slot);
+      strcpy (p, name);
+      (*slot)->name = p;
+      (*slot)->full_path = NULL;
+      (*slot)->loaded = loaded;
+      (*slot)->language = language;
+    }
+
+  return in_hash_table;
+}
+
 /* Clear the table of loaded section scripts.  */
 
 static void
@@ -712,10 +761,12 @@  clear_section_scripts (void)
   struct auto_load_pspace_info *info;
 
   info = program_space_data (pspace, auto_load_pspace_data);
-  if (info != NULL && info->loaded_scripts != NULL)
+  if (info != NULL && info->loaded_script_files != NULL)
     {
-      htab_delete (info->loaded_scripts);
-      info->loaded_scripts = NULL;
+      htab_delete (info->loaded_script_files);
+      htab_delete (info->loaded_script_texts);
+      info->loaded_script_files = NULL;
+      info->loaded_script_texts = NULL;
       info->unsupported_script_warning_printed = FALSE;
       info->script_not_found_warning_printed = FALSE;
     }
@@ -803,7 +854,8 @@  auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
 	 "info auto-load ${lang}-scripts" can print it.  */
       pspace_info
 	= get_auto_load_pspace_data_for_loading (current_program_space);
-      maybe_add_script (pspace_info, is_safe, debugfile, debugfile, language);
+      maybe_add_script_file (pspace_info, is_safe, debugfile, debugfile,
+			     language);
 
       /* To preserve existing behaviour we don't check for whether the
 	 script was already in the table, and always load it.
@@ -864,17 +916,183 @@  auto_load_objfile_script (struct objfile *objfile,
   do_cleanups (cleanups);
 }
 
+/* Subroutine of source_section_scripts to simplify it.
+   Load FILE as a script in extension language LANGUAGE.
+   The script is from section SECTION_NAME in OBJFILE at offset OFFSET.  */
+
+static void
+source_script_file (struct auto_load_pspace_info *pspace_info,
+		    struct objfile *objfile,
+		    const struct extension_language_defn *language,
+		    const char *section_name, unsigned int offset,
+		    const char *file)
+{
+  FILE *stream;
+  char *full_path;
+  int opened, in_hash_table;
+  struct cleanup *cleanups;
+  objfile_script_sourcer_func *sourcer;
+
+  /* Skip this script if support is not compiled in.  */
+  sourcer = ext_lang_objfile_script_sourcer (language);
+  if (sourcer == NULL)
+    {
+      /* We don't throw an error, the program is still debuggable.  */
+      maybe_print_unsupported_script_warning (pspace_info, objfile, language,
+					      section_name, offset);
+      /* We *could* still try to open it, but there's no point.  */
+      maybe_add_script_file (pspace_info, 0, file, NULL, language);
+      return;
+    }
+
+  /* Skip this script if auto-loading it has been disabled.  */
+  if (!ext_lang_auto_load_enabled (language))
+    {
+      /* No message is printed, just skip it.  */
+      return;
+    }
+
+  opened = find_and_open_script (file, 1 /*search_path*/,
+				 &stream, &full_path);
+
+  cleanups = make_cleanup (null_cleanup, NULL);
+  if (opened)
+    {
+      make_cleanup_fclose (stream);
+      make_cleanup (xfree, full_path);
+
+      if (!file_is_auto_load_safe (full_path,
+				   _("auto-load: Loading %s script "
+				     "\"%s\" from section \"%s\" of "
+				     "objfile \"%s\".\n"),
+				   ext_lang_name (language), full_path,
+				   section_name, objfile_name (objfile)))
+	opened = 0;
+    }
+  else
+    {
+      full_path = NULL;
+
+      /* If one script isn't found it's not uncommon for more to not be
+	 found either.  We don't want to print a message for each script,
+	 too much noise.  Instead, we print the warning once and tell the
+	 user how to find the list of scripts that weren't loaded.
+	 We don't throw an error, the program is still debuggable.
+
+	 IWBN if complaints.c were more general-purpose.  */
+
+      maybe_print_script_not_found_warning (pspace_info, objfile, language,
+					    section_name, offset);
+    }
+
+  in_hash_table = maybe_add_script_file (pspace_info, opened, file, full_path,
+					 language);
+
+  /* If this file is not currently loaded, load it.  */
+  if (opened && !in_hash_table)
+    sourcer (language, objfile, stream, full_path);
+
+  do_cleanups (cleanups);
+}
+
+/* Subroutine of source_section_scripts to simplify it.
+   Execute SCRIPT as a script in extension language LANG.
+   The script is from section SECTION_NAME in OBJFILE at offset OFFSET.  */
+
+static void
+execute_script_contents (struct auto_load_pspace_info *pspace_info,
+			 struct objfile *objfile,
+			 const struct extension_language_defn *language,
+			 const char *section_name, unsigned int offset,
+			 const char *script)
+{
+  objfile_script_executor_func *executor;
+  const char *newline, *script_text;
+  char *name, *end;
+  int is_safe, in_hash_table;
+  struct cleanup *cleanups;
+
+  cleanups = make_cleanup (null_cleanup, NULL);
+
+  /* The first line of the script is the name of the script.
+     It must not contain any kind of space character.  */
+  name = NULL;
+  newline = strchr (script, '\n');
+  if (newline != NULL)
+    {
+      char *buf, *p;
+
+      /* Put the name in a buffer and validate it.  */
+      buf = xstrndup (script, newline - script);
+      make_cleanup (xfree, buf);
+      for (p = buf; *p != '\0'; ++p)
+	{
+	  if (isspace (*p))
+	    break;
+	}
+      /* We don't allow nameless scripts, they're not helpful to the user.  */
+      if (p != buf && *p == '\0')
+	name = buf;
+    }
+  if (name == NULL)
+    {
+      /* We don't throw an error, the program is still debuggable.  */
+      warning (_("\
+Missing/bad script name in entry at offset %u in section %s\n\
+of file %s."),
+	       offset, section_name, objfile_name (objfile));
+      do_cleanups (cleanups);
+      return;
+    }
+  script_text = newline + 1;
+
+  /* Skip this script if support is not compiled in.  */
+  executor = ext_lang_objfile_script_executor (language);
+  if (executor == NULL)
+    {
+      /* We don't throw an error, the program is still debuggable.  */
+      maybe_print_unsupported_script_warning (pspace_info, objfile, language,
+					      section_name, offset);
+      maybe_add_script_text (pspace_info, 0, name, language);
+      do_cleanups (cleanups);
+      return;
+    }
+
+  /* Skip this script if auto-loading it has been disabled.  */
+  if (!ext_lang_auto_load_enabled (language))
+    {
+      /* No message is printed, just skip it.  */
+      do_cleanups (cleanups);
+      return;
+    }
+
+  is_safe = file_is_auto_load_safe (objfile_name (objfile),
+				    _("auto-load: Loading %s script "
+				      "\"%s\" from section \"%s\" of "
+				      "objfile \"%s\".\n"),
+				    ext_lang_name (language), name,
+				    section_name, objfile_name (objfile));
+
+  in_hash_table = maybe_add_script_text (pspace_info, is_safe, name, language);
+
+  /* If this file is not currently loaded, load it.  */
+  if (is_safe && !in_hash_table)
+    executor (language, objfile, name, script_text);
+
+  do_cleanups (cleanups);
+}
+
 /* Load scripts specified in OBJFILE.
    START,END delimit a buffer containing a list of nul-terminated
    file names.
    SECTION_NAME is used in error messages.
 
-   Scripts are found per normal "source -s" command processing.
-   First the script is looked for in $cwd.  If not found there the
-   source search path is used.
+   Scripts specified as file names are found per normal "source -s" command
+   processing.  First the script is looked for in $cwd.  If not found there
+   the source search path is used.
 
-   The section contains a list of path names of script files to load.
-   Each path is null-terminated.  */
+   The section contains a list of path names of script files to load or
+   actual script contents.  Each entry is nul-terminated.  */
 
 static void
 source_section_scripts (struct objfile *objfile, const char *section_name,
@@ -887,20 +1105,19 @@  source_section_scripts (struct objfile *objfile, const char *section_name,
 
   for (p = start; p < end; ++p)
     {
-      const char *file;
-      FILE *stream;
-      char *full_path;
-      int opened, in_hash_table;
-      struct cleanup *back_to;
+      const char *entry;
       const struct extension_language_defn *language;
-      objfile_script_sourcer_func *sourcer;
+      unsigned int offset = p - start;
+      int code = *p;
 
-      switch (*p)
+      switch (code)
 	{
 	case SECTION_SCRIPT_ID_PYTHON_FILE:
+	case SECTION_SCRIPT_ID_PYTHON_TEXT:
 	  language = get_ext_lang_defn (EXT_LANG_PYTHON);
 	  break;
 	case SECTION_SCRIPT_ID_SCHEME_FILE:
+	case SECTION_SCRIPT_ID_SCHEME_TEXT:
 	  language = get_ext_lang_defn (EXT_LANG_GUILE);
 	  break;
 	default:
@@ -909,105 +1126,37 @@  source_section_scripts (struct objfile *objfile, const char *section_name,
 	     but it's safer to just punt.  */
 	  return;
 	}
-      file = ++p;
+      entry = ++p;
 
       while (p < end && *p != '\0')
 	++p;
       if (p == end)
 	{
-	  char *buf = alloca (p - file + 1);
-
-	  memcpy (buf, file, p - file);
-	  buf[p - file] = '\0';
-	  warning (_("Non-null-terminated path in %s: %s"),
-		   section_name, buf);
-	  /* Don't load it.  */
+	  warning (_("Non-nul-terminated entry in %s at offset %u"),
+		   section_name, offset);
+	  /* Don't load/execute it.  */
 	  break;
 	}
-      if (p == file)
-	{
-	  warning (_("Empty path in %s"), section_name);
-	  continue;
-	}
-
-      /* Until we support more types of records in .debug_gdb_scripts we do
-	 all the processing here.  The expectation is to add a new
-	 extension_language_script_ops "method" that handles all the records
-	 for the language.  For now we can just use
-	 extension_language_script_ops.objfile_script_sourcer.  */
 
-      /* Skip this script if support is not compiled in.  */
-      sourcer = ext_lang_objfile_script_sourcer (language);
-      if (sourcer == NULL)
+      switch (code)
 	{
-	  /* We don't throw an error, the program is still debuggable.  */
-	  if (!unsupported_script_warning_print (pspace_info))
+	case SECTION_SCRIPT_ID_PYTHON_FILE:
+	case SECTION_SCRIPT_ID_SCHEME_FILE:
+	  if (p == entry)
 	    {
-	      warning (_("Unsupported auto-load scripts referenced in"
-			 " %s section\n"
-			 "of file %s.\n"
-			 "Use `info auto-load %s-scripts [REGEXP]'"
-			 " to list them."),
-		       section_name, objfile_name (objfile),
-		       ext_lang_name (language));
+	      warning (_("Empty entry in %s at offset %u"),
+		       section_name, offset);
+	      continue;
 	    }
-	  /* We *could* still try to open it, but there's no point.  */
-	  maybe_add_script (pspace_info, 0, file, NULL, language);
-	  continue;
-	}
-
-      /* Skip this script if auto-loading it has been disabled.  */
-      if (!ext_lang_auto_load_enabled (language))
-	{
-	  /* No message is printed, just skip it.  */
-	  continue;
-	}
-
-      opened = find_and_open_script (file, 1 /*search_path*/,
-				     &stream, &full_path);
-
-      back_to = make_cleanup (null_cleanup, NULL);
-      if (opened)
-	{
-	  make_cleanup_fclose (stream);
-	  make_cleanup (xfree, full_path);
-
-	  if (!file_is_auto_load_safe (full_path,
-				       _("auto-load: Loading %s script "
-					 "\"%s\" from section \"%s\" of "
-					 "objfile \"%s\".\n"),
-				       ext_lang_name (language), full_path,
-				       section_name, objfile_name (objfile)))
-	    opened = 0;
-	}
-      else
-	{
-	  full_path = NULL;
-
-	  /* If one script isn't found it's not uncommon for more to not be
-	     found either.  We don't want to print a message for each script,
-	     too much noise.  Instead, we print the warning once and tell the
-	     user how to find the list of scripts that weren't loaded.
-	     We don't throw an error, the program is still debuggable.
-
-	     IWBN if complaints.c were more general-purpose.  */
-
-	  if (script_not_found_warning_print (pspace_info))
-	    warning (_("Missing auto-load scripts referenced in section %s\n\
-of file %s\n\
-Use `info auto-load %s-scripts [REGEXP]' to list them."),
-		     section_name, objfile_name (objfile),
-		     ext_lang_name (language));
+	  source_script_file (pspace_info, objfile, language,
+			      section_name, offset, entry);
+	  break;
+	case SECTION_SCRIPT_ID_PYTHON_TEXT:
+	case SECTION_SCRIPT_ID_SCHEME_TEXT:
+	  execute_script_contents (pspace_info, objfile, language,
+				   section_name, offset, entry);
+	  break;
 	}
-
-      in_hash_table = maybe_add_script (pspace_info, opened, file, full_path,
-					language);
-
-      /* If this file is not currently loaded, load it.  */
-      if (opened && !in_hash_table)
-	sourcer (language, objfile, stream, full_path);
-
-      do_cleanups (back_to);
     }
 }
 
@@ -1146,6 +1295,23 @@  sort_scripts_by_name (const void *ap, const void *bp)
    "info auto-load" invocation.  Extra newline will be printed if needed.  */
 char auto_load_info_scripts_pattern_nl[] = "";
 
+/* Subroutine of auto_load_info_scripts to simplify it.
+   Print SCRIPTS.  */
+
+static void
+print_scripts (VEC (loaded_script_ptr) *scripts)
+{
+  struct ui_out *uiout = current_uiout;
+  int i;
+  loaded_script_ptr script;
+
+  qsort (VEC_address (loaded_script_ptr, scripts),
+	 VEC_length (loaded_script_ptr, scripts),
+	 sizeof (loaded_script_ptr), sort_scripts_by_name);
+  for (i = 0; VEC_iterate (loaded_script_ptr, scripts, i, script); ++i)
+    print_script (script);
+}
+
 /* Implementation for "info auto-load gdb-scripts"
    (and "info auto-load python-scripts").  List scripts in LANGUAGE matching
    PATTERN.  FROM_TTY is the usual GDB boolean for user interactivity.  */
@@ -1157,7 +1323,7 @@  auto_load_info_scripts (char *pattern, int from_tty,
   struct ui_out *uiout = current_uiout;
   struct auto_load_pspace_info *pspace_info;
   struct cleanup *script_chain;
-  VEC (loaded_script_ptr) *scripts;
+  VEC (loaded_script_ptr) *script_files, *script_texts;
   int nr_scripts;
 
   dont_repeat ();
@@ -1180,25 +1346,38 @@  auto_load_info_scripts (char *pattern, int from_tty,
      Plus we want to sort the scripts by name.
      So first traverse the hash table collecting the matching scripts.  */
 
-  scripts = VEC_alloc (loaded_script_ptr, 10);
-  script_chain = make_cleanup (VEC_cleanup (loaded_script_ptr), &scripts);
+  script_files = VEC_alloc (loaded_script_ptr, 10);
+  script_texts = VEC_alloc (loaded_script_ptr, 10);
+  script_chain = make_cleanup (VEC_cleanup (loaded_script_ptr), &script_files);
+  make_cleanup (VEC_cleanup (loaded_script_ptr), &script_texts);
+
+  if (pspace_info != NULL && pspace_info->loaded_script_files != NULL)
+    {
+      struct collect_matching_scripts_data data = { &script_files, language };
+
+      /* Pass a pointer to scripts as VEC_safe_push can realloc space.  */
+      htab_traverse_noresize (pspace_info->loaded_script_files,
+			      collect_matching_scripts, &data);
+    }
 
-  if (pspace_info != NULL && pspace_info->loaded_scripts != NULL)
+  if (pspace_info != NULL && pspace_info->loaded_script_texts != NULL)
     {
-      struct collect_matching_scripts_data data = { &scripts, language };
+      struct collect_matching_scripts_data data = { &script_texts, language };
 
       /* Pass a pointer to scripts as VEC_safe_push can realloc space.  */
-      htab_traverse_noresize (pspace_info->loaded_scripts,
+      htab_traverse_noresize (pspace_info->loaded_script_texts,
 			      collect_matching_scripts, &data);
     }
 
-  nr_scripts = VEC_length (loaded_script_ptr, scripts);
+  nr_scripts = (VEC_length (loaded_script_ptr, script_files)
+		+ VEC_length (loaded_script_ptr, script_texts));
 
   /* Table header shifted right by preceding "gdb-scripts:  " would not match
      its columns.  */
   if (nr_scripts > 0 && pattern == auto_load_info_scripts_pattern_nl)
     ui_out_text (uiout, "\n");
 
+  /* Note: This creates a cleanup to output the table end marker.  */
   make_cleanup_ui_out_table_begin_end (uiout, 2, nr_scripts,
 				       "AutoLoadedScriptsTable");
 
@@ -1206,18 +1385,10 @@  auto_load_info_scripts (char *pattern, int from_tty,
   ui_out_table_header (uiout, 70, ui_left, "script", "Script");
   ui_out_table_body (uiout);
 
-  if (nr_scripts > 0)
-    {
-      int i;
-      loaded_script_ptr script;
-
-      qsort (VEC_address (loaded_script_ptr, scripts),
-	     VEC_length (loaded_script_ptr, scripts),
-	     sizeof (loaded_script_ptr), sort_scripts_by_name);
-      for (i = 0; VEC_iterate (loaded_script_ptr, scripts, i, script); ++i)
-	print_script (script);
-    }
+  print_scripts (script_files);
+  print_scripts (script_texts);
 
+  /* Finish up the table before checking for no matching scripts.  */
   do_cleanups (script_chain);
 
   if (nr_scripts == 0)
@@ -1253,32 +1424,48 @@  info_auto_load_local_gdbinit (char *args, int from_tty)
 		     auto_load_local_gdbinit_pathname);
 }
 
-/* Return non-zero if UNSUPPORTED_SCRIPT_WARNING_PRINTED of PSPACE_INFO was
-   unset before calling this function.  Always set
-   UNSUPPORTED_SCRIPT_WARNING_PRINTED of PSPACE_INFO.  */
+/* Print an "unsupported script" warning if it has not already been printed.
+   The script is in language LANGUAGE at offset OFFSET in section SECTION_NAME
+   of OBJFILE.  */
 
-static int
-unsupported_script_warning_print (struct auto_load_pspace_info *pspace_info)
+static void
+maybe_print_unsupported_script_warning
+  (struct auto_load_pspace_info *pspace_info,
+   struct objfile *objfile, const struct extension_language_defn *language,
+   const char *section_name, unsigned offset)
 {
-  int retval = !pspace_info->unsupported_script_warning_printed;
-
-  pspace_info->unsupported_script_warning_printed = 1;
-
-  return retval;
+  if (!pspace_info->unsupported_script_warning_printed)
+    {
+      warning (_("\
+Unsupported auto-load script at offset %u in section %s\n\
+of file %s.\n\
+Use `info auto-load %s-scripts [REGEXP]' to list them."),
+	       offset, section_name, objfile_name (objfile),
+	       ext_lang_name (language));
+      pspace_info->unsupported_script_warning_printed = 1;
+    }
 }
 
 /* Return non-zero if SCRIPT_NOT_FOUND_WARNING_PRINTED of PSPACE_INFO was unset
    before calling this function.  Always set SCRIPT_NOT_FOUND_WARNING_PRINTED
    of PSPACE_INFO.  */
 
-static int
-script_not_found_warning_print (struct auto_load_pspace_info *pspace_info)
+static void
+maybe_print_script_not_found_warning
+  (struct auto_load_pspace_info *pspace_info,
+   struct objfile *objfile, const struct extension_language_defn *language,
+   const char *section_name, unsigned offset)
 {
-  int retval = !pspace_info->script_not_found_warning_printed;
-
-  pspace_info->script_not_found_warning_printed = 1;
-
-  return retval;
+  if (!pspace_info->script_not_found_warning_printed)
+    {
+      warning (_("\
+Missing auto-load script at offset %u in section %s\n\
+of file %s.\n\
+Use `info auto-load %s-scripts [REGEXP]' to list them."),
+	       offset, section_name, objfile_name (objfile),
+	       ext_lang_name (language));
+      pspace_info->script_not_found_warning_printed = 1;
+    }
 }
 
 /* The only valid "set auto-load" argument is off|0|no|disable.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b059ac2..31f3138 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23971,17 +23971,29 @@  is evaluated more than once.
 For systems using file formats like ELF and COFF,
 when @value{GDBN} loads a new object file
 it will look for a special section named @code{.debug_gdb_scripts}.
-If this section exists, its contents is a list of NUL-terminated names
-of scripts to load.  Each entry begins with a non-NULL prefix byte that
-specifies the kind of entry, typically the extension language.
+If this section exists, its contents is a list of NUL-terminated entries
+specifying scripts to load.  Each entry begins with a non-NUL prefix byte that
+specifies the kind of entry, typically the extension language and whether the
+script is in a file or inlined in @code{.debug_gdb_scripts}.
 
-@value{GDBN} will look for each specified script file first in the
-current directory and then along the source search path
+The following entries are supported:
+
+@table @code
+@item SECTION_SCRIPT_ID_PYTHON_FILE = 1
+@item SECTION_SCRIPT_ID_SCHEME_FILE = 3
+@item SECTION_SCRIPT_ID_PYTHON_TEXT = 4
+@item SECTION_SCRIPT_ID_SCHEME_TEXT = 6
+@end table
+
+@subsubsection Script File Entries
+
+If the entry specifies a file, @value{GDBN} will look for the file first
+in the current directory and then along the source search path
 (@pxref{Source Path, ,Specifying Source Directories}),
 except that @file{$cdir} is not searched, since the compilation
 directory is not relevant to scripts.
 
-Entries can be placed in section @code{.debug_gdb_scripts} with,
+File entries can be placed in section @code{.debug_gdb_scripts} with,
 for example, this GCC macro for Python scripts.
 
 @example
@@ -24013,6 +24025,45 @@  using this header will get a reference to the specified script,
 and with the use of @code{"MS"} attributes on the section, the linker
 will remove duplicates.
 
+@subsubsection Script Text Entries
+
+Script text entries allow to put the executable script in the entry
+itself instead of loading it from a file.
+The first line of the entry, everything up to the first newline (@code{0xa})
+character, is the script name, and must not contain any kind of space
+character, e.g., spaces or tabs.
+The rest of the entry, up to the trailing NUL byte, is the script to
+execute in the specified language.  The name needs to be unique among
+all script names, as @value{GDBN} executes each script only once based
+on its name.
+
+Here is an example from file @file{py-section-script.c} in the @value{GDBN}
+testsuite.
+
+@example
+#include "symcat.h"
+#include "gdb/section-scripts.h"
+asm(
+".pushsection \".debug_gdb_scripts\", \"MS\",@@progbits,1\n"
+".byte " XSTRING (SECTION_SCRIPT_ID_PYTHON_TEXT) "\n"
+".ascii \"gdb.inlined-script\\n\"\n"
+".ascii \"class test_cmd (gdb.Command):\\n\"\n"
+".ascii \"  def __init__ (self):\\n\"\n"
+".ascii \"    super (test_cmd, self).__init__ ("
+    "\\\"test-cmd\\\", gdb.COMMAND_OBSCURE)\\n\"\n"
+".ascii \"  def invoke (self, arg, from_tty):\\n\"\n"
+".ascii \"    print (\\\"test-cmd output, arg = %s\\\" % arg)\\n\"\n"
+".ascii \"test_cmd ()\\n\"\n"
+".byte 0\n"
+".popsection\n"
+);
+@end example
+
+Loading of inlined scripts requires a properly configured
+@code{auto-load safe-path} (@pxref{Auto-loading safe path}).
+The path to specify in @code{auto-load safe-path} is the path of the file
+containing the @code{.debug_gdb_scripts} section.
+
 @node Which flavor to choose?
 @subsection Which flavor to choose?
 
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index b9a50d0..e8548e1 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -4744,8 +4744,9 @@  Show whether auto-loading of Python scripts is enabled or disabled.
 Print the list of all Python scripts that @value{GDBN} auto-loaded.
 
 Also printed is the list of Python scripts that were mentioned in
-the @code{.debug_gdb_scripts} section and were not found
-(@pxref{dotdebug_gdb_scripts section}).
+the @code{.debug_gdb_scripts} section and were either not found
+(@pxref{dotdebug_gdb_scripts section}) or were not auto-loaded due to
+@code{auto-load safe-path} rejection (@pxref{Auto-loading}).
 This is useful because their names are not printed when @value{GDBN}
 tries to load them and fails.  There may be many of them, and printing
 an error message for each one is problematic.
@@ -4763,7 +4764,7 @@  No     my-foo-pretty-printers.py
 @end smallexample
 @end table
 
-When reading an auto-loaded file, @value{GDBN} sets the
+When reading an auto-loaded file or script, @value{GDBN} sets the
 @dfn{current objfile}.  This is available via the @code{gdb.current_objfile}
 function (@pxref{Objfiles In Python}).  This can be useful for
 registering objfile-specific pretty-printers and frame-filters.
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
index fc05137..dd2600e 100644
--- a/gdb/extension-priv.h
+++ b/gdb/extension-priv.h
@@ -103,6 +103,11 @@  struct extension_language_script_ops
      but is not required to, throw an error.  */
   objfile_script_sourcer_func *objfile_script_sourcer;
 
+  /* Execute a script attached to an objfile.
+     If there's an error while processing the script this function may,
+     but is not required to, throw an error.  */
+  objfile_script_executor_func *objfile_script_executor;
+
   /* Return non-zero if auto-loading scripts in this extension language
      is enabled.  */
   int (*auto_load_enabled) (const struct extension_language_defn *);
diff --git a/gdb/extension.c b/gdb/extension.c
index 853ef67..77b62e0 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -61,6 +61,7 @@  static const struct extension_language_script_ops
 {
   source_gdb_script,
   source_gdb_objfile_script,
+  NULL, /* objfile_script_executor */
   auto_load_gdb_scripts_enabled
 };
 
@@ -286,6 +287,21 @@  ext_lang_objfile_script_sourcer (const struct extension_language_defn *extlang)
   return extlang->script_ops->objfile_script_sourcer;
 }
 
+/* Return the objfile script "executor" function for EXTLANG.
+   This is the function that executes a script for a particular objfile.
+   If support for this language isn't compiled in, NULL is returned.
+   The extension language is not required to implement this function.  */
+
+objfile_script_executor_func *
+ext_lang_objfile_script_executor
+  (const struct extension_language_defn *extlang)
+{
+  if (extlang->script_ops == NULL)
+    return NULL;
+
+  return extlang->script_ops->objfile_script_executor;
+}
+
 /* Return non-zero if auto-loading of EXTLANG scripts is enabled.
    Zero is returned if support for this language isn't compiled in.  */
 
diff --git a/gdb/extension.h b/gdb/extension.h
index a53f0a7..e8d7478 100644
--- a/gdb/extension.h
+++ b/gdb/extension.h
@@ -48,6 +48,12 @@  typedef void objfile_script_sourcer_func
   (const struct extension_language_defn *,
    struct objfile *, FILE *stream, const char *filename);
 
+/* A function to execute a script for an objfile.
+   Any exceptions are not caught, and are passed to the caller.  */
+typedef void objfile_script_executor_func
+  (const struct extension_language_defn *,
+   struct objfile *, const char *name, const char *script);
+
 /* Enum of each extension(/scripting) language.  */
 
 enum extension_language
@@ -197,6 +203,9 @@  extern script_sourcer_func *ext_lang_script_sourcer
 extern objfile_script_sourcer_func *ext_lang_objfile_script_sourcer
   (const struct extension_language_defn *);
 
+extern objfile_script_executor_func *ext_lang_objfile_script_executor
+  (const struct extension_language_defn *);
+
 extern int ext_lang_auto_load_enabled (const struct extension_language_defn *);
 
 /* Wrappers for each extension language API function that iterate over all
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
index 968b4d3..9a8ef68 100644
--- a/gdb/guile/guile-internal.h
+++ b/gdb/guile/guile-internal.h
@@ -549,6 +549,7 @@  extern struct value *vlscm_convert_value_from_scheme
 /* stript_lang methods */
 
 extern objfile_script_sourcer_func gdbscm_source_objfile_script;
+extern objfile_script_executor_func gdbscm_execute_objfile_script;
 
 extern int gdbscm_auto_load_enabled (const struct extension_language_defn *);
 
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index c434ec0..319b583 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -128,6 +128,7 @@  static const struct extension_language_script_ops guile_extension_script_ops =
 {
   gdbscm_source_script,
   gdbscm_source_objfile_script,
+  gdbscm_execute_objfile_script,
   gdbscm_auto_load_enabled
 };
 
diff --git a/gdb/guile/scm-objfile.c b/gdb/guile/scm-objfile.c
index 8162d01..8e94b96 100644
--- a/gdb/guile/scm-objfile.c
+++ b/gdb/guile/scm-objfile.c
@@ -283,7 +283,8 @@  gdbscm_set_objfile_pretty_printers_x (SCM self, SCM printers)
 
 /* The "current" objfile.  This is set when gdb detects that a new
    objfile has been loaded.  It is only set for the duration of a call to
-   gdbscm_source_objfile_script; it is NULL at other times.  */
+   gdbscm_source_objfile_script and gdbscm_execute_objfile_script; it is NULL
+   at other times.  */
 static struct objfile *ofscm_current_objfile;
 
 /* Set the current objfile to OBJFILE and then read FILE named FILENAME
@@ -311,6 +312,31 @@  gdbscm_source_objfile_script (const struct extension_language_defn *extlang,
   ofscm_current_objfile = NULL;
 }
 
+/* Set the current objfile to OBJFILE and then read FILE named FILENAME
+   as Guile code.  This does not throw any errors.  If an exception
+   occurs Guile will print the backtrace.
+   This is the extension_language_script_ops.objfile_script_sourcer
+   "method".  */
+
+void
+gdbscm_execute_objfile_script (const struct extension_language_defn *extlang,
+			       struct objfile *objfile, const char *name,
+			       const char *script)
+{
+  char *msg;
+
+  ofscm_current_objfile = objfile;
+
+  msg = gdbscm_safe_eval_string (script, 0 /* display_result */);
+  if (msg != NULL)
+    {
+      fprintf_filtered (gdb_stderr, "%s", msg);
+      xfree (msg);
+    }
+
+  ofscm_current_objfile = NULL;
+}
+
 /* (current-objfile) -> <gdb:obfjile>
    Return the current objfile, or #f if there isn't one.
    Ideally this would be named ofscm_current_objfile, but that name is
diff --git a/gdb/python/python.c b/gdb/python/python.c
index f4b8fcf..344d8d2 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -131,6 +131,7 @@  PyObject *gdbpy_gdb_memory_error;
 
 static script_sourcer_func gdbpy_source_script;
 static objfile_script_sourcer_func gdbpy_source_objfile_script;
+static objfile_script_executor_func gdbpy_execute_objfile_script;
 static void gdbpy_finish_initialization
   (const struct extension_language_defn *);
 static int gdbpy_initialized (const struct extension_language_defn *);
@@ -155,6 +156,7 @@  static const struct extension_language_script_ops python_extension_script_ops =
 {
   gdbpy_source_script,
   gdbpy_source_objfile_script,
+  gdbpy_execute_objfile_script,
   gdbpy_auto_load_enabled
 };
 
@@ -1262,7 +1264,8 @@  gdbpy_progspaces (PyObject *unused1, PyObject *unused2)
 
 /* The "current" objfile.  This is set when gdb detects that a new
    objfile has been loaded.  It is only set for the duration of a call to
-   gdbpy_source_objfile_script; it is NULL at other times.  */
+   gdbpy_source_objfile_script and gdbpy_execute_objfile_script; it is NULL
+   at other times.  */
 static struct objfile *gdbpy_current_objfile;
 
 /* Set the current objfile to OBJFILE and then read FILE named FILENAME
@@ -1290,6 +1293,31 @@  gdbpy_source_objfile_script (const struct extension_language_defn *extlang,
   gdbpy_current_objfile = NULL;
 }
 
+/* Set the current objfile to OBJFILE and then execute SCRIPT
+   as Python code.  This does not throw any errors.  If an exception
+   occurs python will print the traceback and clear the error indicator.
+   This is the extension_language_script_ops.objfile_script_executor
+   "method".  */
+
+static void
+gdbpy_execute_objfile_script (const struct extension_language_defn *extlang,
+			      struct objfile *objfile, const char *name,
+			      const char *script)
+{
+  struct cleanup *cleanups;
+
+  if (!gdb_python_initialized)
+    return;
+
+  cleanups = ensure_python_env (get_objfile_arch (objfile), current_language);
+  gdbpy_current_objfile = objfile;
+
+  PyRun_SimpleString (script);
+
+  do_cleanups (cleanups);
+  gdbpy_current_objfile = NULL;
+}
+
 /* Return the current Objfile, or None if there isn't one.  */
 
 static PyObject *
diff --git a/gdb/testsuite/gdb.guile/scm-section-script.c b/gdb/testsuite/gdb.guile/scm-section-script.c
index e668a49..cbff698 100644
--- a/gdb/testsuite/gdb.guile/scm-section-script.c
+++ b/gdb/testsuite/gdb.guile/scm-section-script.c
@@ -19,18 +19,52 @@ 
 #include "gdb/section-scripts.h"
 
 /* Put the path to the pretty-printer script in .debug_gdb_scripts so
-   gdb will automagically loaded it.  */
+   gdb will automagically loaded it.
+   Normally "MS" would appear here, as in
+   .pushsection ".debug_gdb_scripts", "MS",@progbits,1
+   but we remove it to test files appearing twice in the section.  */
 
 #define DEFINE_GDB_SCRIPT(script_name) \
   asm("\
-.pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n\
+.pushsection \".debug_gdb_scripts\", \"S\",@progbits\n\
 .byte " XSTRING (SECTION_SCRIPT_ID_SCHEME_FILE) "\n\
 .asciz \"" script_name "\"\n\
 .popsection \n\
 ");
 
+#ifndef SCRIPT_FILE
+#error "SCRIPT_FILE not defined"
+#endif
+
+/* Specify it twice to verify the file is only loaded once.  */
+DEFINE_GDB_SCRIPT (SCRIPT_FILE)
 DEFINE_GDB_SCRIPT (SCRIPT_FILE)
 
+/* Inlined scripts are harder to create in the same way as
+   DEFINE_GDB_SCRIPT_FILE.  Keep things simple and just define it here.
+   Normally "MS" would appear here, as in
+   .pushsection ".debug_gdb_scripts", "MS",@progbits,1
+   but we remove it to test scripts appearing twice in the section.  */
+
+#define DEFINE_GDB_SCRIPT_TEXT \
+asm( \
+".pushsection \".debug_gdb_scripts\", \"S\",@progbits\n" \
+".byte " XSTRING (SECTION_SCRIPT_ID_SCHEME_TEXT) "\n" \
+".ascii \"gdb.inlined-script\\n\"\n" \
+".ascii \"(define test-cmd\\n\"\n" \
+".ascii \" (make-command \\\"test-cmd\\\"\\n\"\n" \
+".ascii \"  #:command-class COMMAND_OBSCURE\\n\"\n" \
+".ascii \"  #:invoke (lambda (self arg from-tty)\\n\"\n" \
+".ascii \"    (display (format #f \\\"test-cmd output, arg = ~a\\n\\\" arg)))))\\n\"\n" \
+".ascii \"(register-command! test-cmd)\\n\"\n" \
+".byte 0\n" \
+".popsection\n" \
+);
+
+/* Specify it twice to verify the script is only executed once.  */
+DEFINE_GDB_SCRIPT_TEXT
+DEFINE_GDB_SCRIPT_TEXT
+
 struct ss
 {
   int a;
diff --git a/gdb/testsuite/gdb.guile/scm-section-script.exp b/gdb/testsuite/gdb.guile/scm-section-script.exp
index 93a10a0..8c04ac8 100644
--- a/gdb/testsuite/gdb.guile/scm-section-script.exp
+++ b/gdb/testsuite/gdb.guile/scm-section-script.exp
@@ -53,14 +53,51 @@  gdb_start
 if { [skip_guile_tests] } { continue }
 
 gdb_reinitialize_dir $srcdir/$subdir
-gdb_test_no_output "set auto-load safe-path ${remote_guile_file}" \
+
+# Try first with a restrictive safe-path.
+
+gdb_test_no_output "set auto-load safe-path /restricted" \
+    "set restricted auto-load safe-path"
+gdb_load ${binfile}
+
+# Verify gdb did not load the scripts.
+set test_name "verify scripts not loaded"
+gdb_test_multiple "info auto-load guile-scripts" "$test_name" {
+    -re "Yes.*${testfile}.scm.*Yes.*inlined-script.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "No.*${testfile}.scm.*No.*inlined-script.*$gdb_prompt $" {
+	pass "$test_name"
+    }
+}
+
+# Try again with a working safe-path.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_no_output "set auto-load safe-path ${remote_guile_file}:${binfile}" \
     "set auto-load safe-path"
 gdb_load ${binfile}
 
-# Verify gdb loaded the script.
-gdb_test "info auto-load guile-scripts" "Yes.*${testfile}.scm.*"
+# Verify gdb loaded each script and they appear once in the list.
+set test_name "verify scripts loaded"
+gdb_test_multiple "info auto-load guile-scripts" "$test_name" {
+    -re "${testfile}.scm.*${testfile}.scm.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "inlined-script.*inlined-script.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "Yes.*${testfile}.scm.*Yes.*inlined-script.*$gdb_prompt $" {
+	pass "$test_name"
+    }
+}
+
 # Again, with a regexp this time.
 gdb_test "info auto-load guile-scripts ${testfile}" "Yes.*${testfile}.scm.*"
+
 # Again, with a regexp that matches no scripts.
 gdb_test "info auto-load guile-scripts no-script-matches-this" \
   "No auto-load scripts matching no-script-matches-this."
@@ -74,3 +111,5 @@  gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
 gdb_test "continue" ".*Breakpoint.*"
 
 gdb_test "print ss" " = a=<1> b=<2>"
+
+gdb_test "test-cmd 1 2 3" "test-cmd output, arg = 1 2 3"
diff --git a/gdb/testsuite/gdb.python/py-section-script.c b/gdb/testsuite/gdb.python/py-section-script.c
index 2cb606b..53af8cb 100644
--- a/gdb/testsuite/gdb.python/py-section-script.c
+++ b/gdb/testsuite/gdb.python/py-section-script.c
@@ -15,18 +15,55 @@ 
    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 "symcat.h"
+#include "gdb/section-scripts.h"
+
 /* Put the path to the pretty-printer script in .debug_gdb_scripts so
-   gdb will automagically loaded it.  */
+   gdb will automagically loaded it.
+   Normally "MS" would appear here, as in
+   .pushsection ".debug_gdb_scripts", "MS",@progbits,1
+   but we remove it to test files appearing twice in the section.  */
 
-#define DEFINE_GDB_SCRIPT(script_name) \
+#define DEFINE_GDB_SCRIPT_FILE(script_name) \
   asm("\
-.pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n\
-.byte 1\n\
+.pushsection \".debug_gdb_scripts\", \"S\",@progbits\n\
+.byte " XSTRING (SECTION_SCRIPT_ID_PYTHON_FILE) "\n\
 .asciz \"" script_name "\"\n\
-.popsection \n\
+.popsection\n\
 ");
 
-DEFINE_GDB_SCRIPT (SCRIPT_FILE)
+#ifndef SCRIPT_FILE
+#error "SCRIPT_FILE not defined"
+#endif
+
+/* Specify it twice to verify the file is only loaded once.  */
+DEFINE_GDB_SCRIPT_FILE (SCRIPT_FILE)
+DEFINE_GDB_SCRIPT_FILE (SCRIPT_FILE)
+
+/* Inlined scripts are harder to create in the same way as
+   DEFINE_GDB_SCRIPT_FILE.  Keep things simple and just define it here.
+   Normally "MS" would appear here, as in
+   .pushsection ".debug_gdb_scripts", "MS",@progbits,1
+   but we remove it to test scripts appearing twice in the section.  */
+
+#define DEFINE_GDB_SCRIPT_TEXT \
+asm( \
+".pushsection \".debug_gdb_scripts\", \"S\",@progbits\n" \
+".byte " XSTRING (SECTION_SCRIPT_ID_PYTHON_TEXT) "\n" \
+".ascii \"gdb.inlined-script\\n\"\n" \
+".ascii \"class test_cmd (gdb.Command):\\n\"\n" \
+".ascii \"  def __init__ (self):\\n\"\n" \
+".ascii \"    super (test_cmd, self).__init__ (\\\"test-cmd\\\", gdb.COMMAND_OBSCURE)\\n\"\n" \
+".ascii \"  def invoke (self, arg, from_tty):\\n\"\n" \
+".ascii \"    print (\\\"test-cmd output, arg = %s\\\" % arg)\\n\"\n" \
+".ascii \"test_cmd ()\\n\"\n" \
+".byte 0\n" \
+".popsection\n" \
+);
+
+/* Specify it twice to verify the script is only executed once.  */
+DEFINE_GDB_SCRIPT_TEXT
+DEFINE_GDB_SCRIPT_TEXT
 
 struct ss
 {
diff --git a/gdb/testsuite/gdb.python/py-section-script.exp b/gdb/testsuite/gdb.python/py-section-script.exp
index 11c0453..840430d 100644
--- a/gdb/testsuite/gdb.python/py-section-script.exp
+++ b/gdb/testsuite/gdb.python/py-section-script.exp
@@ -39,7 +39,9 @@  set remote_python_file [gdb_remote_download host \
 set quoted_name "\"$remote_python_file\""
 
 if {[build_executable $testfile.exp $testfile $srcfile \
-	 [list debug additional_flags=-DSCRIPT_FILE=$quoted_name]] == -1} {
+	 [list debug \
+	      additional_flags=-I${srcdir}/../../include \
+	      additional_flags=-DSCRIPT_FILE=$quoted_name]] == -1} {
     return -1
 }
 
@@ -51,13 +53,51 @@  gdb_start
 if { [skip_python_tests] } { continue }
 
 gdb_reinitialize_dir $srcdir/$subdir
-gdb_test_no_output "set auto-load safe-path ${remote_python_file}" "set auto-load safe-path"
+
+# Try first with a restrictive safe-path.
+
+gdb_test_no_output "set auto-load safe-path /restricted" \
+    "set restricted auto-load safe-path"
 gdb_load ${binfile}
 
-# Verify gdb loaded the script.
-gdb_test "info auto-load python-scripts" "Yes.*${testfile}.py.*"
+# Verify gdb did not load the scripts.
+set test_name "verify scripts not loaded"
+gdb_test_multiple "info auto-load python-scripts" "$test_name" {
+    -re "Yes.*${testfile}.py.*Yes.*inlined-script.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "No.*${testfile}.py.*No.*inlined-script.*$gdb_prompt $" {
+	pass "$test_name"
+    }
+}
+
+# Try again with a working safe-path.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_no_output "set auto-load safe-path ${remote_python_file}:${binfile}" \
+    "set auto-load safe-path"
+gdb_load ${binfile}
+
+# Verify gdb loaded each script and they appear once in the list.
+set test_name "verify scripts loaded"
+gdb_test_multiple "info auto-load python-scripts" "$test_name" {
+    -re "${testfile}.py.*${testfile}.py.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "inlined-script.*inlined-script.*$gdb_prompt $" {
+	fail "$test_name"
+    }
+    -re "Yes.*${testfile}.py.*Yes.*inlined-script.*$gdb_prompt $" {
+	pass "$test_name"
+    }
+}
+
 # Again, with a regexp this time.
 gdb_test "info auto-load python-scripts ${testfile}" "Yes.*${testfile}.py.*"
+
 # Again, with a regexp that matches no scripts.
 gdb_test "info auto-load python-scripts no-script-matches-this" \
   "No auto-load scripts matching no-script-matches-this."
@@ -72,3 +112,5 @@  gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
 gdb_test "continue" ".*Breakpoint.*"
 
 gdb_test "print ss" " = a=<1> b=<2>"
+
+gdb_test "test-cmd 1 2 3" "test-cmd output, arg = 1 2 3"