New /s modifier for the disassemble command.

The "source centric" /m option to the disassemble command is often
unhelpful, e.g., in the presence of optimized code.
This patch adds a /s modifier that is better.
For one, /m only prints instructions from the originating source file,
leaving out instructions from e.g., inlined functions from other files.

gdb/ChangeLog:

	PR gdb/11833
	* NEWS: Document new /s modifier for the disassemble command.
	* cli/cli-cmds.c (disassemble_command): Add support for /s.
	(_initialize_cli_cmds): Update online docs of disassemble command.
	* disasm.c: #include "source.h".
	(struct deprecated_dis_line_entry): Renamed from dis_line_entry.
	All uses updated.
	(dis_line_entry): New struct.
	(hash_dis_line_entry, eq_dis_line_entry): New functions.
	(allocate_dis_line_table): New functions.
	(maybe_add_dis_line_entry, line_has_code_p): New functions.
	(dump_insns): New arg end_pc.  All callers updated.
	(do_mixed_source_and_assembly_deprecated): Renamed from
	do_mixed_source_and_assembly.  All callers updated.
	(do_mixed_source_and_assembly): New function.
	(gdb_disassembly): Handle /s (DISASSEMBLY_SOURCE).
	* disasm.h (DISASSEMBLY_SOURCE_DEPRECATED): Renamed from
	DISASSEMBLY_SOURCE.  All uses updated.
	(DISASSEMBLY_SOURCE): New macro.
	* mi/mi-cmd-disas.c (mi_cmd_disassemble): New modes 4,5.

gdb/doc/ChangeLog:

	* gdb.texinfo (Machine Code): Update docs for mixed source/assembly
	disassembly.
	(GDB/MI Data Manipulation): Update docs for new disassembly modes.

gdb/testsuite/ChangeLog:

	* gdb.mi/mi-disassemble.exp: Update.
	* gdb.base/disasm-optim.S: New file.
	* gdb.base/disasm-optim.c: New file.
	* gdb.base/disasm-optim.h: New file.
	* gdb.base/disasm-optim.exp: New file.
This commit is contained in:
Doug Evans 2015-08-14 21:45:54 -07:00
parent b56ccc202a
commit 6ff0ba5f7b
15 changed files with 1045 additions and 59 deletions

View File

@ -1,3 +1,26 @@
2015-08-14 Doug Evans <xdje42@gmail.com>
PR gdb/11833
* NEWS: Document new /s modifier for the disassemble command.
* cli/cli-cmds.c (disassemble_command): Add support for /s.
(_initialize_cli_cmds): Update online docs of disassemble command.
* disasm.c: #include "source.h".
(struct deprecated_dis_line_entry): Renamed from dis_line_entry.
All uses updated.
(dis_line_entry): New struct.
(hash_dis_line_entry, eq_dis_line_entry): New functions.
(allocate_dis_line_table): New functions.
(maybe_add_dis_line_entry, line_has_code_p): New functions.
(dump_insns): New arg end_pc. All callers updated.
(do_mixed_source_and_assembly_deprecated): Renamed from
do_mixed_source_and_assembly. All callers updated.
(do_mixed_source_and_assembly): New function.
(gdb_disassembly): Handle /s (DISASSEMBLY_SOURCE).
* disasm.h (DISASSEMBLY_SOURCE_DEPRECATED): Renamed from
DISASSEMBLY_SOURCE. All uses updated.
(DISASSEMBLY_SOURCE): New macro.
* mi/mi-cmd-disas.c (mi_cmd_disassemble): New modes 4,5.
2015-08-14 Keith Seitz <keiths@redhat.com>
* d-exp.y (PrimaryExpression : TypeExp '.' IdentifierExp): Rename

View File

@ -20,6 +20,13 @@ maint show target-non-stop
"set non-stop" is "off". The default is "auto", meaning non-stop
mode is enabled if supported by the target.
* The "disassemble" command accepts a new modifier: /s.
It prints mixed source+disassembly like /m with two differences:
- disassembled instructions are now printed in program order, and
- and source for all relevant files is now printed.
The "/m" option is now considered deprecated: its "source-centric"
output hasn't proved useful in practice.
*** Changes in GDB 7.10
* Support for process record-replay and reverse debugging on aarch64*-linux*

View File

@ -1175,16 +1175,26 @@ disassemble_current_function (int flags)
/* Dump a specified section of assembly code.
Usage:
disassemble [/mr]
disassemble [/mrs]
- dump the assembly code for the function of the current pc
disassemble [/mr] addr
disassemble [/mrs] addr
- dump the assembly code for the function at ADDR
disassemble [/mr] low,high
disassemble [/mr] low,+length
disassemble [/mrs] low,high
disassemble [/mrs] low,+length
- dump the assembly code in the range [LOW,HIGH), or [LOW,LOW+length)
A /m modifier will include source code with the assembly.
A /r modifier will include raw instructions in hex with the assembly. */
A /m modifier will include source code with the assembly in a
"source centric" view. This view lists only the file of the first insn,
even if other source files are involved (e.g., inlined functions), and
the output is in source order, even with optimized code. This view is
considered deprecated as it hasn't been useful in practice.
A /r modifier will include raw instructions in hex with the assembly.
A /s modifier will include source code with the assembly, like /m, with
two important differences:
1) The output is still in pc address order.
2) File names and contents for all relevant source files are displayed. */
static void
disassemble_command (char *arg, int from_tty)
@ -1212,11 +1222,14 @@ disassemble_command (char *arg, int from_tty)
switch (*p++)
{
case 'm':
flags |= DISASSEMBLY_SOURCE;
flags |= DISASSEMBLY_SOURCE_DEPRECATED;
break;
case 'r':
flags |= DISASSEMBLY_RAW_INSN;
break;
case 's':
flags |= DISASSEMBLY_SOURCE;
break;
default:
error (_("Invalid disassembly modifier."));
}
@ -1225,6 +1238,10 @@ disassemble_command (char *arg, int from_tty)
p = skip_spaces_const (p);
}
if ((flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
== (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
error (_("Cannot specify both /m and /s."));
if (! p || ! *p)
{
flags |= DISASSEMBLY_OMIT_FNAME;
@ -1885,8 +1902,21 @@ the other arg."));
c = add_com ("disassemble", class_vars, disassemble_command, _("\
Disassemble a specified section of memory.\n\
Default is the function surrounding the pc of the selected frame.\n\
\n\
With a /m modifier, source lines are included (if available).\n\
This view is \"source centric\": the output is in source line order,\n\
regardless of any optimization that is present. Only the main source file\n\
is displayed, not those of, e.g., any inlined functions.\n\
This modifier hasn't proved useful in practice and is deprecated\n\
in favor of /s.\n\
\n\
With a /s modifier, source lines are included (if available).\n\
This differs from /m in two important respects:\n\
- the output is still in pc address order, and\n\
- file names and contents for all relevant source files are displayed.\n\
\n\
With a /r modifier, raw instructions in hex are included.\n\
\n\
With a single argument, the function surrounding that address is dumped.\n\
Two arguments (separated by a comma) are taken as a range of memory to dump,\n\
in the form of \"start,end\", or \"start,+length\".\n\

View File

@ -24,11 +24,25 @@
#include "disasm.h"
#include "gdbcore.h"
#include "dis-asm.h"
#include "source.h"
/* Disassemble functions.
FIXME: We should get rid of all the duplicate code in gdb that does
the same thing: disassemble_command() and the gdbtk variation. */
/* This structure is used to store line number information for the
deprecated /m option.
We need a different sort of line table from the normal one cuz we can't
depend upon implicit line-end pc's for lines to do the
reordering in this function. */
struct deprecated_dis_line_entry
{
int line;
CORE_ADDR start_pc;
CORE_ADDR end_pc;
};
/* This Structure is used to store line number information.
We need a different sort of line table from the normal one cuz we can't
depend upon implicit line-end pc's for lines to do the
@ -36,11 +50,75 @@
struct dis_line_entry
{
struct symtab *symtab;
int line;
CORE_ADDR start_pc;
CORE_ADDR end_pc;
};
/* Hash function for dis_line_entry. */
static hashval_t
hash_dis_line_entry (const void *item)
{
const struct dis_line_entry *dle = item;
return htab_hash_pointer (dle->symtab) + dle->line;
}
/* Equal function for dis_line_entry. */
static int
eq_dis_line_entry (const void *item_lhs, const void *item_rhs)
{
const struct dis_line_entry *lhs = item_lhs;
const struct dis_line_entry *rhs = item_rhs;
return (lhs->symtab == rhs->symtab
&& lhs->line == rhs->line);
}
/* Create the table to manage lines for mixed source/disassembly. */
static htab_t
allocate_dis_line_table (void)
{
return htab_create_alloc (41,
hash_dis_line_entry, eq_dis_line_entry,
xfree, xcalloc, xfree);
}
/* Add DLE to TABLE.
Returns 1 if added, 0 if already present. */
static void
maybe_add_dis_line_entry (htab_t table, struct symtab *symtab, int line)
{
void **slot;
struct dis_line_entry dle, *dlep;
dle.symtab = symtab;
dle.line = line;
slot = htab_find_slot (table, &dle, INSERT);
if (*slot == NULL)
{
dlep = XNEW (struct dis_line_entry);
dlep->symtab = symtab;
dlep->line = line;
*slot = dlep;
}
}
/* Return non-zero if SYMTAB, LINE are in TABLE. */
static int
line_has_code_p (htab_t table, struct symtab *symtab, int line)
{
struct dis_line_entry dle;
dle.symtab = symtab;
dle.line = line;
return htab_find (table, &dle) != NULL;
}
/* Like target_read_memory, but slightly different parameters. */
static int
dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
@ -69,11 +147,11 @@ dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
static int
compare_lines (const void *mle1p, const void *mle2p)
{
struct dis_line_entry *mle1, *mle2;
struct deprecated_dis_line_entry *mle1, *mle2;
int val;
mle1 = (struct dis_line_entry *) mle1p;
mle2 = (struct dis_line_entry *) mle2p;
mle1 = (struct deprecated_dis_line_entry *) mle1p;
mle2 = (struct deprecated_dis_line_entry *) mle2p;
/* End of sequence markers have a line number of 0 but don't want to
be sorted to the head of the list, instead sort by PC. */
@ -96,7 +174,8 @@ static int
dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
struct disassemble_info * di,
CORE_ADDR low, CORE_ADDR high,
int how_many, int flags, struct ui_file *stb)
int how_many, int flags, struct ui_file *stb,
CORE_ADDR *end_pc)
{
int num_displayed = 0;
CORE_ADDR pc;
@ -182,24 +261,30 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
}
if (end_pc != NULL)
*end_pc = pc;
return num_displayed;
}
/* The idea here is to present a source-O-centric view of a
function to the user. This means that things are presented
in source order, with (possibly) out of order assembly
immediately following. */
immediately following.
N.B. This view is deprecated. */
static void
do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
struct disassemble_info *di, int nlines,
struct linetable_entry *le,
CORE_ADDR low, CORE_ADDR high,
struct symtab *symtab,
int how_many, int flags, struct ui_file *stb)
do_mixed_source_and_assembly_deprecated
(struct gdbarch *gdbarch, struct ui_out *uiout,
struct disassemble_info *di, struct symtab *symtab,
CORE_ADDR low, CORE_ADDR high,
int how_many, int flags, struct ui_file *stb)
{
int newlines = 0;
struct dis_line_entry *mle;
int nlines;
struct linetable_entry *le;
struct deprecated_dis_line_entry *mle;
struct symtab_and_line sal;
int i;
int out_of_order = 0;
@ -210,11 +295,16 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
gdb_assert (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL);
nlines = SYMTAB_LINETABLE (symtab)->nitems;
le = SYMTAB_LINETABLE (symtab)->item;
if (flags & DISASSEMBLY_FILENAME)
psl_flags |= PRINT_SOURCE_LINES_FILENAME;
mle = (struct dis_line_entry *) alloca (nlines
* sizeof (struct dis_line_entry));
mle = (struct deprecated_dis_line_entry *)
alloca (nlines * sizeof (struct deprecated_dis_line_entry));
/* Copy linetable entries for this function into our data
structure, creating end_pc's and setting out_of_order as
@ -255,11 +345,11 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
newlines++;
}
/* Now, sort mle by line #s (and, then by addresses within
lines). */
/* Now, sort mle by line #s (and, then by addresses within lines). */
if (out_of_order)
qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
qsort (mle, newlines, sizeof (struct deprecated_dis_line_entry),
compare_lines);
/* Now, for each line entry, emit the specified lines (unless
they have been emitted before), followed by the assembly code
@ -324,7 +414,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
num_displayed += dump_insns (gdbarch, uiout, di,
mle[i].start_pc, mle[i].end_pc,
how_many, flags, stb);
how_many, flags, stb, NULL);
/* When we've reached the end of the mle array, or we've seen the last
assembly range for this source line, close out the list/tuple. */
@ -342,6 +432,260 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
do_cleanups (ui_out_chain);
}
/* The idea here is to present a source-O-centric view of a
function to the user. This means that things are presented
in source order, with (possibly) out of order assembly
immediately following. */
static void
do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
struct disassemble_info *di,
struct symtab *main_symtab,
CORE_ADDR low, CORE_ADDR high,
int how_many, int flags, struct ui_file *stb)
{
int newlines = 0;
const struct linetable_entry *le, *first_le;
struct symtab_and_line sal;
int i, nlines;
int out_of_order = 0;
int next_line = 0;
int num_displayed = 0;
enum print_source_lines_flags psl_flags = 0;
struct cleanup *cleanups;
struct cleanup *ui_out_chain;
struct cleanup *ui_out_tuple_chain;
struct cleanup *ui_out_list_chain;
CORE_ADDR pc;
struct symtab *last_symtab;
int last_line;
htab_t dis_line_table;
gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL);
/* First pass: collect the list of all source files and lines.
We do this so that we can only print lines containing code once.
We try to print the source text leading up to the next instruction,
but if that text is for code that will be disassembled later, then
we'll want to defer printing it until later with its associated code. */
dis_line_table = allocate_dis_line_table ();
cleanups = make_cleanup_htab_delete (dis_line_table);
pc = low;
/* The prologue may be empty, but there may still be a line number entry
for the opening brace which is distinct from the first line of code.
If the prologue has been eliminated find_pc_line may return the source
line after the opening brace. We still want to print this opening brace.
first_le is used to implement this. */
nlines = SYMTAB_LINETABLE (main_symtab)->nitems;
le = SYMTAB_LINETABLE (main_symtab)->item;
first_le = NULL;
/* Skip all the preceding functions. */
for (i = 0; i < nlines && le[i].pc < low; i++)
continue;
if (i < nlines && le[i].pc < high)
first_le = &le[i];
/* Add lines for every pc value. */
while (pc < high)
{
struct symtab_and_line sal;
int length;
sal = find_pc_line (pc, 0);
length = gdb_insn_length (gdbarch, pc);
pc += length;
if (sal.symtab != NULL)
maybe_add_dis_line_entry (dis_line_table, sal.symtab, sal.line);
}
/* Second pass: print the disassembly.
Output format, from an MI perspective:
The result is a ui_out list, field name "asm_insns", where elements have
name "src_and_asm_line".
Each element is a tuple of source line specs (field names line, file,
fullname), and field "line_asm_insn" which contains the disassembly.
Field "line_asm_insn" is a list of tuples: address, func-name, offset,
opcodes, inst.
CLI output works on top of this because MI ignores ui_out_text output,
which is where we put file name and source line contents output.
Cleanup usage:
cleanups:
For things created at the beginning of this function and need to be
kept until the end of this function.
ui_out_chain
Handles the outer "asm_insns" list.
ui_out_tuple_chain
The tuples for each group of consecutive disassemblies.
ui_out_list_chain
List of consecutive source lines or disassembled insns. */
if (flags & DISASSEMBLY_FILENAME)
psl_flags |= PRINT_SOURCE_LINES_FILENAME;
ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
ui_out_tuple_chain = NULL;
ui_out_list_chain = NULL;
last_symtab = NULL;
last_line = 0;
pc = low;
while (pc < high)
{
struct linetable_entry *le = NULL;
struct symtab_and_line sal;
CORE_ADDR end_pc;
int start_preceding_line_to_display = 0;
int end_preceding_line_to_display = 0;
int new_source_line = 0;
sal = find_pc_line (pc, 0);
if (sal.symtab != last_symtab)
{
/* New source file. */
new_source_line = 1;
/* If this is the first line of output, check for any preceding
lines. */
if (last_line == 0
&& first_le != NULL
&& first_le->line < sal.line)
{
start_preceding_line_to_display = first_le->line;
end_preceding_line_to_display = sal.line;
}
}
else
{
/* Same source file as last time. */
if (sal.symtab != NULL)
{
if (sal.line > last_line + 1 && last_line != 0)
{
int l;
/* Several preceding source lines. Print the trailing ones
not associated with code that we'll print later. */
for (l = sal.line - 1; l > last_line; --l)
{
if (line_has_code_p (dis_line_table, sal.symtab, l))
break;
}
if (l < sal.line - 1)
{
start_preceding_line_to_display = l + 1;
end_preceding_line_to_display = sal.line;
}
}
if (sal.line != last_line)
new_source_line = 1;
else
{
/* Same source line as last time. This can happen, depending
on the debug info. */
}
}
}
if (new_source_line)
{
/* Skip the newline if this is the first instruction. */
if (pc > low)
ui_out_text (uiout, "\n");
if (ui_out_tuple_chain != NULL)
{
gdb_assert (ui_out_list_chain != NULL);
do_cleanups (ui_out_list_chain);
do_cleanups (ui_out_tuple_chain);
}
if (sal.symtab != last_symtab
&& !(flags & DISASSEMBLY_FILENAME))
{
/* Remember MI ignores ui_out_text.
We don't have to do anything here for MI because MI
output includes the source specs for each line. */
if (sal.symtab != NULL)
{
ui_out_text (uiout,
symtab_to_filename_for_display (sal.symtab));
}
else
ui_out_text (uiout, "unknown");
ui_out_text (uiout, ":\n");
}
if (start_preceding_line_to_display > 0)
{
/* Several source lines w/o asm instructions associated.
We need to preserve the structure of the output, so output
a bunch of line tuples with no asm entries. */
int l;
struct cleanup *ui_out_list_chain_line;
struct cleanup *ui_out_tuple_chain_line;
gdb_assert (sal.symtab != NULL);
for (l = start_preceding_line_to_display;
l < end_preceding_line_to_display;
++l)
{
ui_out_tuple_chain_line
= make_cleanup_ui_out_tuple_begin_end (uiout,
"src_and_asm_line");
print_source_lines (sal.symtab, l, l + 1, psl_flags);
ui_out_list_chain_line
= make_cleanup_ui_out_list_begin_end (uiout,
"line_asm_insn");
do_cleanups (ui_out_list_chain_line);
do_cleanups (ui_out_tuple_chain_line);
}
}
ui_out_tuple_chain
= make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
if (sal.symtab != NULL)
print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags);
else
ui_out_text (uiout, _("--- no source info for this pc ---\n"));
ui_out_list_chain
= make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
}
else
{
/* Here we're appending instructions to an existing line.
By construction the very first insn will have a symtab
and follow the new_source_line path above. */
gdb_assert (ui_out_tuple_chain != NULL);
gdb_assert (ui_out_list_chain != NULL);
}
if (sal.end != 0)
end_pc = min (sal.end, high);
else
end_pc = pc + 1;
num_displayed += dump_insns (gdbarch, uiout, di, pc, end_pc,
how_many, flags, stb, &end_pc);
pc = end_pc;
if (how_many >= 0 && num_displayed >= how_many)
break;
last_symtab = sal.symtab;
last_line = sal.line;
}
do_cleanups (ui_out_chain);
do_cleanups (cleanups);
}
static void
do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
@ -355,7 +699,7 @@ do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
flags, stb);
flags, stb, NULL);
do_cleanups (ui_out_chain);
}
@ -418,19 +762,19 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
symtab = find_pc_line_symtab (low);
if (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL)
{
/* Convert the linetable to a bunch of my_line_entry's. */
le = SYMTAB_LINETABLE (symtab)->item;
nlines = SYMTAB_LINETABLE (symtab)->nitems;
}
nlines = SYMTAB_LINETABLE (symtab)->nitems;
if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
|| symtab == NULL || SYMTAB_LINETABLE (symtab) == NULL)
if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
|| nlines <= 0)
do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
else if (flags & DISASSEMBLY_SOURCE)
do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
high, symtab, how_many, flags, stb);
do_mixed_source_and_assembly (gdbarch, uiout, &di, symtab, low, high,
how_many, flags, stb);
else if (flags & DISASSEMBLY_SOURCE_DEPRECATED)
do_mixed_source_and_assembly_deprecated (gdbarch, uiout, &di, symtab,
low, high, how_many, flags, stb);
do_cleanups (cleanups);
gdb_flush (gdb_stdout);

View File

@ -21,11 +21,12 @@
#include "dis-asm.h"
#define DISASSEMBLY_SOURCE (0x1 << 0)
#define DISASSEMBLY_SOURCE_DEPRECATED (0x1 << 0)
#define DISASSEMBLY_RAW_INSN (0x1 << 1)
#define DISASSEMBLY_OMIT_FNAME (0x1 << 2)
#define DISASSEMBLY_FILENAME (0x1 << 3)
#define DISASSEMBLY_OMIT_PC (0x1 << 4)
#define DISASSEMBLY_SOURCE (0x1 << 5)
struct gdbarch;
struct ui_out;

View File

@ -1,3 +1,9 @@
2015-08-14 Doug Evans <xdje42@gmail.com>
* gdb.texinfo (Machine Code): Update docs for mixed source/assembly
disassembly.
(GDB/MI Data Manipulation): Update docs for new disassembly modes.
2015-08-11 Keith Seitz <keiths@redhat.com>
* gdb.texinfo (Thread-Specific Breakpoints, Printing Source Lines):

View File

@ -8098,11 +8098,12 @@ Variables}).
@cindex listing machine instructions
@item disassemble
@itemx disassemble /m
@itemx disassemble /s
@itemx disassemble /r
This specialized command dumps a range of memory as machine
instructions. It can also print mixed source+disassembly by specifying
the @code{/m} modifier and print the raw instructions in hex as well as
in symbolic form by specifying the @code{/r}.
the @code{/m} or @code{/s} modifier and print the raw instructions in hex
as well as in symbolic form by specifying the @code{/r} modifier.
The default memory range is the function surrounding the
program counter of the selected frame. A single argument to this
command is a program counter value; @value{GDBN} dumps the function
@ -8146,8 +8147,9 @@ Dump of assembler code from 0x32c4 to 0x32e4:
End of assembler dump.
@end smallexample
Here is an example showing mixed source+assembly for Intel x86, when the
program is stopped just after function prologue:
Here is an example showing mixed source+assembly for Intel x86
with @code{/m} or @code{/s}, when the program is stopped just after
function prologue in a non-optimized function with no inline code.
@smallexample
(@value{GDBP}) disas /m main
@ -8172,6 +8174,96 @@ Dump of assembler code for function main:
End of assembler dump.
@end smallexample
The @code{/m} option is deprecated as its output is not useful when
there is either inlined code or re-ordered code.
The @code{/s} option is the preferred choice.
Here is an example for AMD x86-64 showing the difference between
@code{/m} output and @code{/s} output.
This example has one inline function defined in a header file,
and the code is compiled with @samp{-O2} optimization.
Note how the @code{/m} output is missing the disassembly of
several instructions that are present in the @code{/s} output.
@file{foo.h}:
@smallexample
int
foo (int a)
@{
if (a < 0)
return a * 2;
if (a == 0)
return 1;
return a + 10;
@}
@end smallexample
@file{foo.c}:
@smallexample
#include "foo.h"
volatile int x, y;
int
main ()
@{
x = foo (y);
return 0;
@}
@end smallexample
@smallexample
(@value{GDBP}) disas /m main
Dump of assembler code for function main:
5 @{
6 x = foo (y);
0x0000000000400400 <+0>: mov 0x200c2e(%rip),%eax # 0x601034 <y>
0x0000000000400417 <+23>: mov %eax,0x200c13(%rip) # 0x601030 <x>
7 return 0;
8 @}
0x000000000040041d <+29>: xor %eax,%eax
0x000000000040041f <+31>: retq
0x0000000000400420 <+32>: add %eax,%eax
0x0000000000400422 <+34>: jmp 0x400417 <main+23>
End of assembler dump.
(@value{GDBP}) disas /s main
Dump of assembler code for function main:
foo.c:
5 @{
6 x = foo (y);
0x0000000000400400 <+0>: mov 0x200c2e(%rip),%eax # 0x601034 <y>
foo.h:
4 if (a < 0)
0x0000000000400406 <+6>: test %eax,%eax
0x0000000000400408 <+8>: js 0x400420 <main+32>
6 if (a == 0)
7 return 1;
8 return a + 10;
0x000000000040040a <+10>: lea 0xa(%rax),%edx
0x000000000040040d <+13>: test %eax,%eax
0x000000000040040f <+15>: mov $0x1,%eax
0x0000000000400414 <+20>: cmovne %edx,%eax
foo.c:
6 x = foo (y);
0x0000000000400417 <+23>: mov %eax,0x200c13(%rip) # 0x601030 <x>
7 return 0;
8 @}
0x000000000040041d <+29>: xor %eax,%eax
0x000000000040041f <+31>: retq
foo.h:
5 return a * 2;
0x0000000000400420 <+32>: add %eax,%eax
0x0000000000400422 <+34>: jmp 0x400417 <main+23>
End of assembler dump.
@end smallexample
Here is another example showing raw instructions in hex for AMD x86-64,
@smallexample
@ -29782,9 +29874,20 @@ displayed; if @var{lines} is higher than the number of lines between
@var{start-addr} and @var{end-addr}, only the lines up to @var{end-addr}
are displayed.
@item @var{mode}
is either 0 (meaning only disassembly), 1 (meaning mixed source and
disassembly), 2 (meaning disassembly with raw opcodes), or 3 (meaning
mixed source and disassembly with raw opcodes).
is one of:
@itemize @bullet
@item 0 disassembly only
@item 1 mixed source and disassembly (deprecated)
@item 2 disassembly with raw opcodes
@item 3 mixed source and disassembly with raw opcodes (deprecated)
@item 4 mixed source and disassembly
@item 5 mixed source and disassembly with raw opcodes
@end itemize
Modes 1 and 3 are deprecated. The output is ``source centric''
which hasn't proved useful in practice.
@xref{Machine Code}, for a discussion of the difference between
@code{/m} and @code{/s} output of the @code{disassemble} command.
@end table
@subsubheading Result
@ -29810,12 +29913,12 @@ The decimal offset in bytes from the start of @samp{func-name}.
The text disassembly for this @samp{address}.
@item opcodes
This field is only present for mode 2. This contains the raw opcode
This field is only present for modes 2, 3 and 5. This contains the raw opcode
bytes for the @samp{inst} field.
@end table
For modes 1 and 3 the @samp{asm_insns} list contains tuples named
For modes 1, 3, 4 and 5 the @samp{asm_insns} list contains tuples named
@samp{src_and_asm_line}, each of which has the following fields:
@table @code

View File

@ -44,10 +44,11 @@
always required:
MODE: 0 -- disassembly.
1 -- disassembly and source.
1 -- disassembly and source (with deprecated source-centric view).
2 -- disassembly and opcodes.
3 -- disassembly, source and opcodes.
*/
3 -- disassembly, source-centric and opcodes.
4 -- disassembly, and source (with pc-centric view).
5 -- disassembly, source (pc-centric) and opcodes. */
void
mi_cmd_disassemble (char *command, char **argv, int argc)
@ -141,16 +142,34 @@ mi_cmd_disassemble (char *command, char **argv, int argc)
"[-n howmany]] [-s startaddr -e endaddr] [--] mode."));
mode = atoi (argv[0]);
if (mode < 0 || mode > 3)
error (_("-data-disassemble: Mode argument must be 0, 1, 2, or 3."));
if (mode < 0 || mode > 5)
error (_("-data-disassemble: Mode argument must be in the range 0-5."));
/* Convert the mode into a set of disassembly flags. */
disasm_flags = 0;
if (mode & 0x1)
disasm_flags |= DISASSEMBLY_SOURCE;
if (mode & 0x2)
disasm_flags |= DISASSEMBLY_RAW_INSN;
disasm_flags = 0; /* Initialize here for -Wall. */
switch (mode)
{
case 0:
break;
case 1:
disasm_flags |= DISASSEMBLY_SOURCE_DEPRECATED;
break;
case 2:
disasm_flags |= DISASSEMBLY_RAW_INSN;
break;
case 3:
disasm_flags |= DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_RAW_INSN;
break;
case 4:
disasm_flags |= DISASSEMBLY_SOURCE;
break;
case 5:
disasm_flags |= DISASSEMBLY_SOURCE | DISASSEMBLY_RAW_INSN;
break;
default:
gdb_assert_not_reached ("bad disassembly mode");
}
/* We must get the function beginning and end where line_num is
contained. */

View File

@ -458,7 +458,7 @@ get_insn_history_modifiers (char **arg)
switch (*args)
{
case 'm':
modifiers |= DISASSEMBLY_SOURCE;
modifiers |= DISASSEMBLY_SOURCE_DEPRECATED;
modifiers |= DISASSEMBLY_FILENAME;
break;
case 'r':

View File

@ -1,3 +1,11 @@
2015-08-14 Doug Evans <xdje42@gmail.com>
* gdb.mi/mi-disassemble.exp: Update.
* gdb.base/disasm-optim.S: New file.
* gdb.base/disasm-optim.c: New file.
* gdb.base/disasm-optim.h: New file.
* gdb.base/disasm-optim.exp: New file.
2015-08-14 Keith Seitz <keiths@redhat.com>
* lib/mi-support.exp (mi_make_breakpoint): Add option/handling for

View File

@ -0,0 +1,352 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright (C) 2015 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 file was created with gcc -O2 -g -S -fverbose-asm -dA disasm-optim.c
and then cleaning up the output. */
.file "disasm-optim.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB1:
.file 1 "disasm-optim.c"
# disasm-optim.c:24
.loc 1 24 0
.cfi_startproc
# disasm-optim.c:25
.loc 1 25 0
movl y(%rip), %eax
.LVL0:
.LBB4:
.LBB5:
.file 2 "disasm-optim.h"
# disasm-optim.h:21
.loc 2 21 0
testl %eax, %eax
js .L6
# disasm-optim.h:25
.loc 2 25 0
leal 10(%rax), %edx
testl %eax, %eax
movl $1, %eax
.LVL1:
cmovne %edx, %eax
.LVL2:
.L3:
.LBE5:
.LBE4:
# disasm-optim.c:25
.loc 1 25 0
movl %eax, x(%rip)
# disasm-optim.c:27
.loc 1 27 0
xorl %eax, %eax
ret
.LVL3:
.L6:
.LBB7:
.LBB6:
# disasm-optim.h:22
.loc 2 22 0
addl %eax, %eax
.LVL4:
jmp .L3
.LBE6:
.LBE7:
.cfi_endproc
.LFE1:
.size main, .-main
.comm y,4,4
.comm x,4,4
.text
.Letext0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.long 0xb1 # Length of Compilation Unit Info
.value 0x4 # DWARF version number
.long .Ldebug_abbrev0 # Offset Into Abbrev. Section
.byte 0x8 # Pointer Size (in bytes)
.uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
.long .LASF0 # DW_AT_producer: "GNU C 4.9.2 20150212 (Red Hat 4.9.2-6) -mtune=generic -march=x86-64 -g -O2"
.byte 0x1 # DW_AT_language
.long .LASF1 # DW_AT_name: "disasm-optim.c"
.long .LASF2 # DW_AT_comp_dir: "/main/disassemble3/gdb/testsuite/gdb.base"
.long .Ldebug_ranges0+0x30 # DW_AT_ranges
.quad 0 # DW_AT_low_pc
.long .Ldebug_line0 # DW_AT_stmt_list
.uleb128 0x2 # (DIE (0x29) DW_TAG_subprogram)
# DW_AT_external
.ascii "foo\0" # DW_AT_name
.byte 0x2 # DW_AT_decl_file (disasm-optim.h)
.byte 0x13 # DW_AT_decl_line
# DW_AT_prototyped
.long 0x43 # DW_AT_type
.byte 0x3 # DW_AT_inline
.long 0x43 # DW_AT_sibling
.uleb128 0x3 # (DIE (0x39) DW_TAG_formal_parameter)
.ascii "a\0" # DW_AT_name
.byte 0x2 # DW_AT_decl_file (disasm-optim.h)
.byte 0x13 # DW_AT_decl_line
.long 0x43 # DW_AT_type
.byte 0 # end of children of DIE 0x29
.uleb128 0x4 # (DIE (0x43) DW_TAG_base_type)
.byte 0x4 # DW_AT_byte_size
.byte 0x5 # DW_AT_encoding
.ascii "int\0" # DW_AT_name
.uleb128 0x5 # (DIE (0x4a) DW_TAG_subprogram)
# DW_AT_external
.long .LASF3 # DW_AT_name: "main"
.byte 0x1 # DW_AT_decl_file (disasm-optim.c)
.byte 0x17 # DW_AT_decl_line
.long 0x43 # DW_AT_type
.quad .LFB1 # DW_AT_low_pc
.quad .LFE1-.LFB1 # DW_AT_high_pc
.uleb128 0x1 # DW_AT_frame_base
.byte 0x9c # DW_OP_call_frame_cfa
# DW_AT_GNU_all_call_sites
.long 0x89 # DW_AT_sibling
.uleb128 0x6 # (DIE (0x6b) DW_TAG_inlined_subroutine)
.long 0x29 # DW_AT_abstract_origin
.quad .LBB4 # DW_AT_entry_pc
.long .Ldebug_ranges0+0 # DW_AT_ranges
.byte 0x1 # DW_AT_call_file (disasm-optim.c)
.byte 0x19 # DW_AT_call_line
.uleb128 0x7 # (DIE (0x7e) DW_TAG_formal_parameter)
.long 0x39 # DW_AT_abstract_origin
.long .LLST0 # DW_AT_location
.byte 0 # end of children of DIE 0x6b
.byte 0 # end of children of DIE 0x4a
.uleb128 0x8 # (DIE (0x89) DW_TAG_variable)
.ascii "x\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (disasm-optim.c)
.byte 0x14 # DW_AT_decl_line
.long 0x9c # DW_AT_type
# DW_AT_external
.uleb128 0x9 # DW_AT_location
.byte 0x3 # DW_OP_addr
.quad x
.uleb128 0x9 # (DIE (0x9c) DW_TAG_volatile_type)
.long 0x43 # DW_AT_type
.uleb128 0x8 # (DIE (0xa1) DW_TAG_variable)
.ascii "y\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file (disasm-optim.c)
.byte 0x14 # DW_AT_decl_line
.long 0x9c # DW_AT_type
# DW_AT_external
.uleb128 0x9 # DW_AT_location
.byte 0x3 # DW_OP_addr
.quad y
.byte 0 # end of children of DIE 0xb
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.uleb128 0x1 # (abbrev code)
.uleb128 0x11 # (TAG: DW_TAG_compile_unit)
.byte 0x1 # DW_children_yes
.uleb128 0x25 # (DW_AT_producer)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x13 # (DW_AT_language)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x1b # (DW_AT_comp_dir)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x55 # (DW_AT_ranges)
.uleb128 0x17 # (DW_FORM_sec_offset)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x10 # (DW_AT_stmt_list)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x2 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3f # (DW_AT_external)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x27 # (DW_AT_prototyped)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x20 # (DW_AT_inline)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x3 # (abbrev code)
.uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x4 # (abbrev code)
.uleb128 0x24 # (TAG: DW_TAG_base_type)
.byte 0 # DW_children_no
.uleb128 0xb # (DW_AT_byte_size)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3e # (DW_AT_encoding)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.byte 0
.byte 0
.uleb128 0x5 # (abbrev code)
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
.byte 0x1 # DW_children_yes
.uleb128 0x3f # (DW_AT_external)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x3 # (DW_AT_name)
.uleb128 0xe # (DW_FORM_strp)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x11 # (DW_AT_low_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x12 # (DW_AT_high_pc)
.uleb128 0x7 # (DW_FORM_data8)
.uleb128 0x40 # (DW_AT_frame_base)
.uleb128 0x18 # (DW_FORM_exprloc)
.uleb128 0x2117 # (DW_AT_GNU_all_call_sites)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x1 # (DW_AT_sibling)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.uleb128 0x6 # (abbrev code)
.uleb128 0x1d # (TAG: DW_TAG_inlined_subroutine)
.byte 0x1 # DW_children_yes
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x52 # (DW_AT_entry_pc)
.uleb128 0x1 # (DW_FORM_addr)
.uleb128 0x55 # (DW_AT_ranges)
.uleb128 0x17 # (DW_FORM_sec_offset)
.uleb128 0x58 # (DW_AT_call_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x59 # (DW_AT_call_line)
.uleb128 0xb # (DW_FORM_data1)
.byte 0
.byte 0
.uleb128 0x7 # (abbrev code)
.uleb128 0x5 # (TAG: DW_TAG_formal_parameter)
.byte 0 # DW_children_no
.uleb128 0x31 # (DW_AT_abstract_origin)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x2 # (DW_AT_location)
.uleb128 0x17 # (DW_FORM_sec_offset)
.byte 0
.byte 0
.uleb128 0x8 # (abbrev code)
.uleb128 0x34 # (TAG: DW_TAG_variable)
.byte 0 # DW_children_no
.uleb128 0x3 # (DW_AT_name)
.uleb128 0x8 # (DW_FORM_string)
.uleb128 0x3a # (DW_AT_decl_file)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x3b # (DW_AT_decl_line)
.uleb128 0xb # (DW_FORM_data1)
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.uleb128 0x3f # (DW_AT_external)
.uleb128 0x19 # (DW_FORM_flag_present)
.uleb128 0x2 # (DW_AT_location)
.uleb128 0x18 # (DW_FORM_exprloc)
.byte 0
.byte 0
.uleb128 0x9 # (abbrev code)
.uleb128 0x35 # (TAG: DW_TAG_volatile_type)
.byte 0 # DW_children_no
.uleb128 0x49 # (DW_AT_type)
.uleb128 0x13 # (DW_FORM_ref4)
.byte 0
.byte 0
.byte 0
.section .debug_loc,"",@progbits
.Ldebug_loc0:
.LLST0:
.quad .LVL0 # Location list begin address (*.LLST0)
.quad .LVL1 # Location list end address (*.LLST0)
.value 0x1 # Location expression size
.byte 0x50 # DW_OP_reg0
.quad .LVL1 # Location list begin address (*.LLST0)
.quad .LVL2 # Location list end address (*.LLST0)
.value 0x3 # Location expression size
.byte 0x71 # DW_OP_breg1
.sleb128 -10
.byte 0x9f # DW_OP_stack_value
.quad .LVL3 # Location list begin address (*.LLST0)
.quad .LVL4 # Location list end address (*.LLST0)
.value 0x1 # Location expression size
.byte 0x50 # DW_OP_reg0
.quad 0 # Location list terminator begin (*.LLST0)
.quad 0 # Location list terminator end (*.LLST0)
.section .debug_aranges,"",@progbits
.long 0x2c # Length of Address Ranges Info
.value 0x2 # DWARF Version
.long .Ldebug_info0 # Offset of Compilation Unit Info
.byte 0x8 # Size of Address
.byte 0 # Size of Segment Descriptor
.value 0 # Pad to 16 byte boundary
.value 0
.quad .LFB1 # Address
.quad .LFE1-.LFB1 # Length
.quad 0
.quad 0
.section .debug_ranges,"",@progbits
.Ldebug_ranges0:
.quad .LBB4 # Offset 0
.quad .LBE4
.quad .LBB7
.quad .LBE7
.quad 0
.quad 0
.quad .LFB1 # Offset 0x30
.quad .LFE1
.quad 0
.quad 0
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.LASF2:
.string "/main/disassemble3/gdb/testsuite/gdb.base"
.LASF1:
.string "disasm-optim.c"
.LASF3:
.string "main"
.LASF0:
.string "GNU C 4.9.2 20150212 (Red Hat 4.9.2-6) -mtune=generic -march=x86-64 -g -O2"
.ident "GCC: (GNU) 4.9.2 20150212 (Red Hat 4.9.2-6)"
.section .note.GNU-stack,"",@progbits

View File

@ -0,0 +1,27 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright (C) 2015 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/>. */
#include "disasm-optim.h"
volatile int x, y;
int
main ()
{
x = foo (y);
return 0;
}

View File

@ -0,0 +1,40 @@
# Copyright (C) 2015 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 exercises disassemble /s with optimized and inlined code.
if { ![istarget "x86_64-*-linux*"] } {
continue
}
standard_testfile .S
if { [prepare_for_testing ${testfile}.exp $testfile ${testfile}.S {nodebug}] } {
return -1
}
if ![runto_main] {
return -1
}
gdb_test_sequence "disassemble /s main" \
"Disassemble main with source" {
"Dump of assembler code for function main:"
"disasm-optim\\.c:\r\n24"
"disasm-optim\\.h:\r\n21"
"disasm-optim\\.c:\r\n25"
"disasm-optim\\.h:\r\n22"
"End of assembler dump\\."
}

View File

@ -0,0 +1,26 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright (C) 2015 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/>. */
extern inline int
foo (int a)
{
if (a < 0)
return a * 2;
if (a == 0)
return 1;
return a + 10;
}

View File

@ -223,7 +223,7 @@ proc test_disassembly_bogus_args {} {
"data-disassemble mix different args"
mi_gdb_test "789-data-disassemble -f basics.c -l $line_main_body -- 9" \
"789\\^error,msg=\"-data-disassemble: Mode argument must be 0, 1, 2, or 3.\"" \
"789\\^error,msg=\"-data-disassemble: Mode argument must be in the range 0-5.\"" \
"data-disassemble wrong mode arg"
}