2018-10-10 12:21:05 +08:00
|
|
|
/* Cache of styled source file text
|
2019-01-01 14:01:51 +08:00
|
|
|
Copyright (C) 2018-2019 Free Software Foundation, Inc.
|
2018-10-10 12:21:05 +08:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
#include "source-cache.h"
|
Rename common to gdbsupport
This is the next patch in the ongoing series to move gdbsever to the
top level.
This patch just renames the "common" directory. The idea is to do
this move in two parts: first rename the directory (this patch), then
move the directory to the top. This approach makes the patches a bit
more tractable.
I chose the name "gdbsupport" for the directory. However, as this
patch was largely written by sed, we could pick a new name without too
much difficulty.
Tested by the buildbot.
gdb/ChangeLog
2019-07-09 Tom Tromey <tom@tromey.com>
* contrib/ari/gdb_ari.sh: Change common to gdbsupport.
* configure: Rebuild.
* configure.ac: Change common to gdbsupport.
* gdbsupport: Rename from common.
* acinclude.m4: Change common to gdbsupport.
* Makefile.in (CONFIG_SRC_SUBDIR, COMMON_SFILES)
(HFILES_NO_SRCDIR, stamp-version, ALLDEPFILES): Change common to
gdbsupport.
* aarch64-tdep.c, ada-lang.c, ada-lang.h, agent.c, alloc.c,
amd64-darwin-tdep.c, amd64-dicos-tdep.c, amd64-fbsd-nat.c,
amd64-fbsd-tdep.c, amd64-linux-nat.c, amd64-linux-tdep.c,
amd64-nbsd-tdep.c, amd64-obsd-tdep.c, amd64-sol2-tdep.c,
amd64-tdep.c, amd64-windows-tdep.c, arch-utils.c,
arch/aarch64-insn.c, arch/aarch64.c, arch/aarch64.h, arch/amd64.c,
arch/amd64.h, arch/arm-get-next-pcs.c, arch/arm-linux.c,
arch/arm.c, arch/i386.c, arch/i386.h, arch/ppc-linux-common.c,
arch/riscv.c, arch/riscv.h, arch/tic6x.c, arm-tdep.c, auto-load.c,
auxv.c, ax-gdb.c, ax-general.c, ax.h, breakpoint.c, breakpoint.h,
btrace.c, btrace.h, build-id.c, build-id.h, c-lang.h, charset.c,
charset.h, cli/cli-cmds.c, cli/cli-cmds.h, cli/cli-decode.c,
cli/cli-dump.c, cli/cli-option.h, cli/cli-script.c,
coff-pe-read.c, command.h, compile/compile-c-support.c,
compile/compile-c.h, compile/compile-cplus-symbols.c,
compile/compile-cplus-types.c, compile/compile-cplus.h,
compile/compile-loc2c.c, compile/compile.c, completer.c,
completer.h, contrib/ari/gdb_ari.sh, corefile.c, corelow.c,
cp-support.c, cp-support.h, cp-valprint.c, csky-tdep.c, ctf.c,
darwin-nat.c, debug.c, defs.h, disasm-selftests.c, disasm.c,
disasm.h, dtrace-probe.c, dwarf-index-cache.c,
dwarf-index-cache.h, dwarf-index-write.c, dwarf2-frame.c,
dwarf2expr.c, dwarf2loc.c, dwarf2read.c, event-loop.c,
event-top.c, exceptions.c, exec.c, extension.h, fbsd-nat.c,
features/aarch64-core.c, features/aarch64-fpu.c,
features/aarch64-pauth.c, features/aarch64-sve.c,
features/i386/32bit-avx.c, features/i386/32bit-avx512.c,
features/i386/32bit-core.c, features/i386/32bit-linux.c,
features/i386/32bit-mpx.c, features/i386/32bit-pkeys.c,
features/i386/32bit-segments.c, features/i386/32bit-sse.c,
features/i386/64bit-avx.c, features/i386/64bit-avx512.c,
features/i386/64bit-core.c, features/i386/64bit-linux.c,
features/i386/64bit-mpx.c, features/i386/64bit-pkeys.c,
features/i386/64bit-segments.c, features/i386/64bit-sse.c,
features/i386/x32-core.c, features/riscv/32bit-cpu.c,
features/riscv/32bit-csr.c, features/riscv/32bit-fpu.c,
features/riscv/64bit-cpu.c, features/riscv/64bit-csr.c,
features/riscv/64bit-fpu.c, features/tic6x-c6xp.c,
features/tic6x-core.c, features/tic6x-gp.c, filename-seen-cache.h,
findcmd.c, findvar.c, fork-child.c, gcore.c, gdb_bfd.c, gdb_bfd.h,
gdb_proc_service.h, gdb_regex.c, gdb_select.h, gdb_usleep.c,
gdbarch-selftests.c, gdbthread.h, gdbtypes.h, gnu-nat.c,
go32-nat.c, guile/guile.c, guile/scm-ports.c,
guile/scm-safe-call.c, guile/scm-type.c, i386-fbsd-nat.c,
i386-fbsd-tdep.c, i386-go32-tdep.c, i386-linux-nat.c,
i386-linux-tdep.c, i386-tdep.c, i387-tdep.c,
ia64-libunwind-tdep.c, ia64-linux-nat.c, inf-child.c,
inf-ptrace.c, infcall.c, infcall.h, infcmd.c, inferior-iter.h,
inferior.c, inferior.h, inflow.c, inflow.h, infrun.c, infrun.h,
inline-frame.c, language.h, linespec.c, linux-fork.c, linux-nat.c,
linux-tdep.c, linux-thread-db.c, location.c, machoread.c,
macrotab.h, main.c, maint.c, maint.h, memattr.c, memrange.h,
mi/mi-cmd-break.h, mi/mi-cmd-env.c, mi/mi-cmd-stack.c,
mi/mi-cmd-var.c, mi/mi-interp.c, mi/mi-main.c, mi/mi-parse.h,
minsyms.c, mips-linux-tdep.c, namespace.h,
nat/aarch64-linux-hw-point.c, nat/aarch64-linux-hw-point.h,
nat/aarch64-linux.c, nat/aarch64-sve-linux-ptrace.c,
nat/amd64-linux-siginfo.c, nat/fork-inferior.c,
nat/linux-btrace.c, nat/linux-btrace.h, nat/linux-namespaces.c,
nat/linux-nat.h, nat/linux-osdata.c, nat/linux-personality.c,
nat/linux-procfs.c, nat/linux-ptrace.c, nat/linux-ptrace.h,
nat/linux-waitpid.c, nat/mips-linux-watch.c,
nat/mips-linux-watch.h, nat/ppc-linux.c, nat/x86-dregs.c,
nat/x86-dregs.h, nat/x86-linux-dregs.c, nat/x86-linux.c,
nto-procfs.c, nto-tdep.c, objfile-flags.h, objfiles.c, objfiles.h,
obsd-nat.c, observable.h, osdata.c, p-valprint.c, parse.c,
parser-defs.h, ppc-linux-nat.c, printcmd.c, probe.c, proc-api.c,
procfs.c, producer.c, progspace.h, psymtab.h,
python/py-framefilter.c, python/py-inferior.c, python/py-ref.h,
python/py-type.c, python/python.c, record-btrace.c, record-full.c,
record.c, record.h, regcache-dump.c, regcache.c, regcache.h,
remote-fileio.c, remote-fileio.h, remote-sim.c, remote.c,
riscv-tdep.c, rs6000-aix-tdep.c, rust-exp.y, s12z-tdep.c,
selftest-arch.c, ser-base.c, ser-event.c, ser-pipe.c, ser-tcp.c,
ser-unix.c, skip.c, solib-aix.c, solib-target.c, solib.c,
source-cache.c, source.c, source.h, sparc-nat.c, spu-linux-nat.c,
stack.c, stap-probe.c, symfile-add-flags.h, symfile.c, symfile.h,
symtab.c, symtab.h, target-descriptions.c, target-descriptions.h,
target-memory.c, target.c, target.h, target/waitstatus.c,
target/waitstatus.h, thread-iter.h, thread.c, tilegx-tdep.c,
top.c, top.h, tracefile-tfile.c, tracefile.c, tracepoint.c,
tracepoint.h, tui/tui-io.c, ui-file.c, ui-out.h,
unittests/array-view-selftests.c,
unittests/child-path-selftests.c, unittests/cli-utils-selftests.c,
unittests/common-utils-selftests.c,
unittests/copy_bitwise-selftests.c, unittests/environ-selftests.c,
unittests/format_pieces-selftests.c,
unittests/function-view-selftests.c,
unittests/lookup_name_info-selftests.c,
unittests/memory-map-selftests.c, unittests/memrange-selftests.c,
unittests/mkdir-recursive-selftests.c,
unittests/observable-selftests.c,
unittests/offset-type-selftests.c, unittests/optional-selftests.c,
unittests/parse-connection-spec-selftests.c,
unittests/ptid-selftests.c, unittests/rsp-low-selftests.c,
unittests/scoped_fd-selftests.c,
unittests/scoped_mmap-selftests.c,
unittests/scoped_restore-selftests.c,
unittests/string_view-selftests.c, unittests/style-selftests.c,
unittests/tracepoint-selftests.c, unittests/unpack-selftests.c,
unittests/utils-selftests.c, unittests/xml-utils-selftests.c,
utils.c, utils.h, valarith.c, valops.c, valprint.c, value.c,
value.h, varobj.c, varobj.h, windows-nat.c, x86-linux-nat.c,
xml-support.c, xml-support.h, xml-tdesc.h, xstormy16-tdep.c,
xtensa-linux-nat.c, dwarf2read.h: Change common to gdbsupport.
gdb/gdbserver/ChangeLog
2019-07-09 Tom Tromey <tom@tromey.com>
* configure: Rebuild.
* configure.ac: Change common to gdbsupport.
* acinclude.m4: Change common to gdbsupport.
* Makefile.in (SFILES, OBS, GDBREPLAY_OBS, IPA_OBJS)
(version-generated.c, gdbsupport/%-ipa.o, gdbsupport/%.o): Change
common to gdbsupport.
* ax.c, event-loop.c, fork-child.c, gdb_proc_service.h,
gdbreplay.c, gdbthread.h, hostio-errno.c, hostio.c, i387-fp.c,
inferiors.c, inferiors.h, linux-aarch64-tdesc-selftest.c,
linux-amd64-ipa.c, linux-i386-ipa.c, linux-low.c,
linux-tic6x-low.c, linux-x86-low.c, linux-x86-tdesc-selftest.c,
linux-x86-tdesc.c, lynx-i386-low.c, lynx-low.c, mem-break.h,
nto-x86-low.c, regcache.c, regcache.h, remote-utils.c, server.c,
server.h, spu-low.c, symbol.c, target.h, tdesc.c, tdesc.h,
thread-db.c, tracepoint.c, win32-i386-low.c, win32-low.c: Change
common to gdbsupport.
2019-05-06 10:29:24 +08:00
|
|
|
#include "gdbsupport/scoped_fd.h"
|
2018-10-10 12:21:05 +08:00
|
|
|
#include "source.h"
|
|
|
|
#include "cli/cli-style.h"
|
Don't include gdbarch.h from defs.h
I touched symtab.h and was surprised to see how many files were
rebuilt. I looked into it a bit, and found that defs.h includes
gdbarch.h, which in turn includes many things.
gdbarch.h is only needed by a minority ofthe files in gdb, so this
patch removes the include from defs.h and updates the fallout.
I did "wc -l" on the files in build/gdb/.deps; this patch reduces the
line count from 139935 to 137030; so there are definitely future
build-time savings here.
Note that while I configured with --enable-targets=all, it's possible
that some *-nat.c file needs an update. I could not test all of
these. The buildbot caught a few problems along these lines.
gdb/ChangeLog
2019-07-10 Tom Tromey <tom@tromey.com>
* defs.h: Don't include gdbarch.h.
* aarch64-ravenscar-thread.c, aarch64-tdep.c, alpha-bsd-tdep.h,
alpha-linux-tdep.c, alpha-mdebug-tdep.c, arch-utils.h, arm-tdep.h,
ax-general.c, btrace.c, buildsym-legacy.c, buildsym.h, c-lang.c,
cli/cli-decode.h, cli/cli-dump.c, cli/cli-script.h,
cli/cli-style.h, coff-pe-read.h, compile/compile-c-support.c,
compile/compile-cplus.h, compile/compile-loc2c.c, corefile.c,
cp-valprint.c, cris-linux-tdep.c, ctf.c, d-lang.c, d-namespace.c,
dcache.c, dicos-tdep.c, dictionary.c, disasm-selftests.c,
dummy-frame.c, dummy-frame.h, dwarf2-frame-tailcall.c,
dwarf2expr.c, expression.h, f-lang.c, frame-base.c,
frame-unwind.c, frv-linux-tdep.c, gdbarch-selftests.c, gdbtypes.h,
go-lang.c, hppa-nbsd-tdep.c, hppa-obsd-tdep.c, i386-dicos-tdep.c,
i386-tdep.h, ia64-vms-tdep.c, interps.h, language.c,
linux-record.c, location.h, m2-lang.c, m32r-linux-tdep.c,
mem-break.c, memattr.c, mn10300-linux-tdep.c, nios2-linux-tdep.c,
objfiles.h, opencl-lang.c, or1k-linux-tdep.c, p-lang.c,
parser-defs.h, ppc-tdep.h, probe.h, python/py-record-btrace.c,
record-btrace.c, record.h, regcache-dump.c, regcache.h,
riscv-fbsd-tdep.c, riscv-linux-tdep.c, rust-exp.y,
sh-linux-tdep.c, sh-nbsd-tdep.c, source-cache.c,
sparc-nbsd-tdep.c, sparc-obsd-tdep.c, sparc-ravenscar-thread.c,
sparc64-fbsd-tdep.c, std-regs.c, target-descriptions.h,
target-float.c, tic6x-linux-tdep.c, tilegx-linux-tdep.c, top.c,
tracefile.c, trad-frame.c, type-stack.h, ui-style.c, utils.c,
utils.h, valarith.c, valprint.c, varobj.c, x86-tdep.c,
xml-support.h, xtensa-linux-tdep.c, cli/cli-cmds.h: Update.
* s390-linux-nat.c, procfs.c, inf-ptrace.c: Likewise.
2019-06-10 05:21:02 +08:00
|
|
|
#include "symtab.h"
|
2019-07-23 22:22:50 +08:00
|
|
|
#include "gdbsupport/selftest.h"
|
2018-10-10 12:21:05 +08:00
|
|
|
|
|
|
|
#ifdef HAVE_SOURCE_HIGHLIGHT
|
2019-03-13 01:47:23 +08:00
|
|
|
/* If Gnulib redirects 'open' and 'close' to its replacements
|
|
|
|
'rpl_open' and 'rpl_close' via cpp macros, including <fstream>
|
|
|
|
below with those macros in effect will cause unresolved externals
|
|
|
|
when GDB is linked. Happens, e.g., in the MinGW build. */
|
|
|
|
#undef open
|
|
|
|
#undef close
|
2018-10-10 12:21:05 +08:00
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <srchilite/sourcehighlight.h>
|
|
|
|
#include <srchilite/langmap.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* The number of source files we'll cache. */
|
|
|
|
|
|
|
|
#define MAX_ENTRIES 5
|
|
|
|
|
|
|
|
/* See source-cache.h. */
|
|
|
|
|
|
|
|
source_cache g_source_cache;
|
|
|
|
|
|
|
|
/* See source-cache.h. */
|
|
|
|
|
|
|
|
bool
|
|
|
|
source_cache::get_plain_source_lines (struct symtab *s, int first_line,
|
|
|
|
int last_line, std::string *lines)
|
|
|
|
{
|
2019-06-15 05:16:52 +08:00
|
|
|
scoped_fd desc (open_source_file_with_line_charpos (s));
|
2018-10-10 12:21:05 +08:00
|
|
|
if (desc.get () < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (first_line < 1 || first_line > s->nlines || last_line < 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (lseek (desc.get (), s->line_charpos[first_line - 1], SEEK_SET) < 0)
|
|
|
|
perror_with_name (symtab_to_filename_for_display (s));
|
|
|
|
|
|
|
|
int last_charpos;
|
|
|
|
if (last_line >= s->nlines)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (fstat (desc.get (), &st) < 0)
|
|
|
|
perror_with_name (symtab_to_filename_for_display (s));
|
|
|
|
/* We could cache this in line_charpos... */
|
|
|
|
last_charpos = st.st_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
last_charpos = s->line_charpos[last_line];
|
|
|
|
|
|
|
|
lines->resize (last_charpos - s->line_charpos[first_line - 1]);
|
|
|
|
if (myread (desc.get (), &(*lines)[0], lines->size ()) < 0)
|
|
|
|
perror_with_name (symtab_to_filename_for_display (s));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-07-23 22:22:50 +08:00
|
|
|
/* A helper function for get_plain_source_lines that extracts the
|
|
|
|
desired source lines from TEXT, putting them into LINES_OUT. The
|
|
|
|
arguments are as for get_source_lines. The return value is the
|
|
|
|
desired lines. */
|
|
|
|
static std::string
|
|
|
|
extract_lines (const std::string &text, int first_line, int last_line)
|
2018-10-10 12:21:05 +08:00
|
|
|
{
|
|
|
|
int lineno = 1;
|
|
|
|
std::string::size_type pos = 0;
|
|
|
|
std::string::size_type first_pos = std::string::npos;
|
|
|
|
|
|
|
|
while (pos != std::string::npos && lineno <= last_line)
|
|
|
|
{
|
2019-07-23 22:22:50 +08:00
|
|
|
std::string::size_type new_pos = text.find ('\n', pos);
|
2018-10-10 12:21:05 +08:00
|
|
|
|
|
|
|
if (lineno == first_line)
|
|
|
|
first_pos = pos;
|
|
|
|
|
|
|
|
pos = new_pos;
|
|
|
|
if (lineno == last_line || pos == std::string::npos)
|
|
|
|
{
|
2019-03-09 04:59:27 +08:00
|
|
|
if (first_pos == std::string::npos)
|
|
|
|
return {};
|
2018-10-10 12:21:05 +08:00
|
|
|
if (pos == std::string::npos)
|
2019-07-23 22:22:50 +08:00
|
|
|
pos = text.size ();
|
|
|
|
else
|
|
|
|
++pos;
|
|
|
|
return text.substr (first_pos, pos - first_pos);
|
2018-10-10 12:21:05 +08:00
|
|
|
}
|
|
|
|
++lineno;
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
|
2019-03-09 04:59:27 +08:00
|
|
|
return {};
|
2018-10-10 12:21:05 +08:00
|
|
|
}
|
|
|
|
|
2018-12-29 12:07:24 +08:00
|
|
|
#ifdef HAVE_SOURCE_HIGHLIGHT
|
|
|
|
|
2018-10-10 12:21:05 +08:00
|
|
|
/* Return the Source Highlight language name, given a gdb language
|
|
|
|
LANG. Returns NULL if the language is not known. */
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
get_language_name (enum language lang)
|
|
|
|
{
|
|
|
|
switch (lang)
|
|
|
|
{
|
|
|
|
case language_c:
|
|
|
|
case language_objc:
|
|
|
|
return "c.lang";
|
|
|
|
|
|
|
|
case language_cplus:
|
|
|
|
return "cpp.lang";
|
|
|
|
|
|
|
|
case language_d:
|
|
|
|
return "d.lang";
|
|
|
|
|
|
|
|
case language_go:
|
|
|
|
return "go.lang";
|
|
|
|
|
|
|
|
case language_fortran:
|
|
|
|
return "fortran.lang";
|
|
|
|
|
|
|
|
case language_m2:
|
|
|
|
/* Not handled by Source Highlight. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case language_asm:
|
|
|
|
return "asm.lang";
|
|
|
|
|
|
|
|
case language_pascal:
|
|
|
|
return "pascal.lang";
|
|
|
|
|
|
|
|
case language_opencl:
|
|
|
|
/* Not handled by Source Highlight. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case language_rust:
|
|
|
|
/* Not handled by Source Highlight. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case language_ada:
|
|
|
|
return "ada.lang";
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-12-29 12:07:24 +08:00
|
|
|
#endif /* HAVE_SOURCE_HIGHLIGHT */
|
|
|
|
|
2018-10-10 12:21:05 +08:00
|
|
|
/* See source-cache.h. */
|
|
|
|
|
|
|
|
bool
|
|
|
|
source_cache::get_source_lines (struct symtab *s, int first_line,
|
|
|
|
int last_line, std::string *lines)
|
|
|
|
{
|
|
|
|
if (first_line < 1 || last_line < 1 || first_line > last_line)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
#ifdef HAVE_SOURCE_HIGHLIGHT
|
2019-03-10 06:55:44 +08:00
|
|
|
if (source_styling && gdb_stdout->can_emit_style_escape ())
|
2018-10-10 12:21:05 +08:00
|
|
|
{
|
|
|
|
const char *fullname = symtab_to_fullname (s);
|
|
|
|
|
|
|
|
for (const auto &item : m_source_map)
|
|
|
|
{
|
|
|
|
if (item.fullname == fullname)
|
2019-03-09 04:59:27 +08:00
|
|
|
{
|
2019-07-23 22:22:50 +08:00
|
|
|
*lines = extract_lines (item.contents, first_line, last_line);
|
2019-03-09 04:59:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
2018-10-10 12:21:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *lang_name = get_language_name (SYMTAB_LANGUAGE (s));
|
|
|
|
if (lang_name != nullptr)
|
|
|
|
{
|
|
|
|
std::ifstream input (fullname);
|
|
|
|
if (input.is_open ())
|
|
|
|
{
|
2019-06-19 02:18:24 +08:00
|
|
|
/* The global source highlight object, or null if one
|
|
|
|
was never constructed. This is stored here rather
|
|
|
|
than in the class so that we don't need to include
|
|
|
|
anything or do conditional compilation in
|
|
|
|
source-cache.h. */
|
|
|
|
static srchilite::SourceHighlight *highlighter;
|
|
|
|
|
2019-03-17 01:53:46 +08:00
|
|
|
if (s->line_charpos == 0)
|
|
|
|
{
|
2019-06-15 05:16:52 +08:00
|
|
|
scoped_fd desc (open_source_file_with_line_charpos (s));
|
2019-03-17 01:53:46 +08:00
|
|
|
if (desc.get () < 0)
|
|
|
|
return false;
|
Fix use-after-free in source_cache::get_source_lines
Commit ab42892fb7d2 ("Fix vertical scrolling of TUI source window")
introduced a use-after-free in source_cache::get_source_lines.
At the beginning of the method, we get the fullname of the symtab:
const char *fullname = symtab_to_fullname (s);
fullname points to the string owned by the symtab (s.fullname). When we
later do
scoped_fd desc = open_source_file (s);
s.fullname gets reallocated (even though the string contents may not
change). The fullname local variable now points to freed memory.
To avoid it, refresh the value of fullname after calling
open_source_file.
Here is the ASan report:
$ ./gdb -nx --data-directory=data-directory ./a.out
(gdb) start
Temporary breakpoint 1 at 0x1130: file test.cpp, line 12.
Starting program: /home/simark/build/binutils-gdb/gdb/a.out
Temporary breakpoint 1, main () at test.cpp:12
=================================================================
==26068==ERROR: AddressSanitizer: heap-use-after-free on address 0x6210003d4100 at pc 0x7fed89a34681 bp 0x7ffd8d185d80 sp 0x7ffd8d185528
READ of size 2 at 0x6210003d4100 thread T0
#0 0x7fed89a34680 in __interceptor_strlen /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:301
#1 0x55b6edf6c2f7 in std::char_traits<char>::length(char const*) /usr/include/c++/8.2.1/bits/char_traits.h:320
#2 0x55b6edf6c9b2 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) /usr/include/c++/8.2.1/bits/basic_string.h:516
#3 0x55b6ef09121b in source_cache::get_source_lines(symtab*, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) /home/simark/src/binutils-gdb/gdb/source-cache.c:214
#4 0x55b6ef0a15cb in print_source_lines_base /home/simark/src/binutils-gdb/gdb/source.c:1340
#5 0x55b6ef0a2045 in print_source_lines(symtab*, int, int, enum_flags<print_source_lines_flag>) /home/simark/src/binutils-gdb/gdb/source.c:1415
#6 0x55b6ef112c87 in print_frame_info(frame_info*, int, print_what, int, int) /home/simark/src/binutils-gdb/gdb/stack.c:914
#7 0x55b6ef10e90d in print_stack_frame(frame_info*, int, print_what, int) /home/simark/src/binutils-gdb/gdb/stack.c:180
#8 0x55b6ee9592f8 in print_stop_location /home/simark/src/binutils-gdb/gdb/infrun.c:7853
#9 0x55b6ee95948f in print_stop_event(ui_out*) /home/simark/src/binutils-gdb/gdb/infrun.c:7870
#10 0x55b6ef34b962 in tui_on_normal_stop /home/simark/src/binutils-gdb/gdb/tui/tui-interp.c:98
#11 0x55b6ee01a14d in std::_Function_handler<void (bpstats*, int), void (*)(bpstats*, int)>::_M_invoke(std::_Any_data const&, bpstats*&&, int&&) /usr/include/c++/8.2.1/bits/std_function.h:297
#12 0x55b6ee965415 in std::function<void (bpstats*, int)>::operator()(bpstats*, int) const /usr/include/c++/8.2.1/bits/std_function.h:687
#13 0x55b6ee962f1b in gdb::observers::observable<bpstats*, int>::notify(bpstats*, int) const /home/simark/src/binutils-gdb/gdb/common/observable.h:106
#14 0x55b6ee95a6e7 in normal_stop() /home/simark/src/binutils-gdb/gdb/infrun.c:8142
#15 0x55b6ee93f236 in fetch_inferior_event(void*) /home/simark/src/binutils-gdb/gdb/infrun.c:3782
#16 0x55b6ee8f2641 in inferior_event_handler(inferior_event_type, void*) /home/simark/src/binutils-gdb/gdb/inf-loop.c:43
#17 0x55b6eea2a1f0 in handle_target_event /home/simark/src/binutils-gdb/gdb/linux-nat.c:4358
#18 0x55b6ee7045f1 in handle_file_event /home/simark/src/binutils-gdb/gdb/event-loop.c:733
#19 0x55b6ee704e89 in gdb_wait_for_event /home/simark/src/binutils-gdb/gdb/event-loop.c:859
#20 0x55b6ee7027b5 in gdb_do_one_event() /home/simark/src/binutils-gdb/gdb/event-loop.c:322
#21 0x55b6ee702907 in start_event_loop() /home/simark/src/binutils-gdb/gdb/event-loop.c:371
#22 0x55b6eeadfc16 in captured_command_loop /home/simark/src/binutils-gdb/gdb/main.c:331
#23 0x55b6eeae2ef9 in captured_main /home/simark/src/binutils-gdb/gdb/main.c:1174
#24 0x55b6eeae30c2 in gdb_main(captured_main_args*) /home/simark/src/binutils-gdb/gdb/main.c:1190
#25 0x55b6edf4fa89 in main /home/simark/src/binutils-gdb/gdb/gdb.c:32
#26 0x7fed88ad8222 in __libc_start_main (/usr/lib/libc.so.6+0x24222)
#27 0x55b6edf4f86d in _start (/home/simark/build/binutils-gdb/gdb/gdb+0x197186d)
0x6210003d4100 is located 0 bytes inside of 4096-byte region [0x6210003d4100,0x6210003d5100)
freed by thread T0 here:
#0 0x7fed89a8ac19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:66
#1 0x55b6edfe12df in xfree<char> /home/simark/src/binutils-gdb/gdb/common/common-utils.h:60
#2 0x55b6edfea675 in gdb::xfree_deleter<char>::operator()(char*) const /home/simark/src/binutils-gdb/gdb/common/gdb_unique_ptr.h:34
#3 0x55b6edfe532c in std::unique_ptr<char, gdb::xfree_deleter<char> >::reset(char*) /usr/include/c++/8.2.1/bits/unique_ptr.h:382
#4 0x55b6edfe7329 in std::unique_ptr<char, gdb::xfree_deleter<char> >::operator=(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /usr/include/c++/8.2.1/bits/unique_ptr.h:289
#5 0x55b6ef09ec2b in find_and_open_source(char const*, char const*, std::unique_ptr<char, gdb::xfree_deleter<char> >*) /home/simark/src/binutils-gdb/gdb/source.c:990
#6 0x55b6ef09f56a in open_source_file(symtab*) /home/simark/src/binutils-gdb/gdb/source.c:1069
#7 0x55b6ef090f78 in source_cache::get_source_lines(symtab*, int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) /home/simark/src/binutils-gdb/gdb/source-cache.c:205
#8 0x55b6ef0a15cb in print_source_lines_base /home/simark/src/binutils-gdb/gdb/source.c:1340
#9 0x55b6ef0a2045 in print_source_lines(symtab*, int, int, enum_flags<print_source_lines_flag>) /home/simark/src/binutils-gdb/gdb/source.c:1415
#10 0x55b6ef112c87 in print_frame_info(frame_info*, int, print_what, int, int) /home/simark/src/binutils-gdb/gdb/stack.c:914
#11 0x55b6ef10e90d in print_stack_frame(frame_info*, int, print_what, int) /home/simark/src/binutils-gdb/gdb/stack.c:180
#12 0x55b6ee9592f8 in print_stop_location /home/simark/src/binutils-gdb/gdb/infrun.c:7853
#13 0x55b6ee95948f in print_stop_event(ui_out*) /home/simark/src/binutils-gdb/gdb/infrun.c:7870
#14 0x55b6ef34b962 in tui_on_normal_stop /home/simark/src/binutils-gdb/gdb/tui/tui-interp.c:98
#15 0x55b6ee01a14d in std::_Function_handler<void (bpstats*, int), void (*)(bpstats*, int)>::_M_invoke(std::_Any_data const&, bpstats*&&, int&&) /usr/include/c++/8.2.1/bits/std_function.h:297
#16 0x55b6ee965415 in std::function<void (bpstats*, int)>::operator()(bpstats*, int) const /usr/include/c++/8.2.1/bits/std_function.h:687
#17 0x55b6ee962f1b in gdb::observers::observable<bpstats*, int>::notify(bpstats*, int) const /home/simark/src/binutils-gdb/gdb/common/observable.h:106
#18 0x55b6ee95a6e7 in normal_stop() /home/simark/src/binutils-gdb/gdb/infrun.c:8142
#19 0x55b6ee93f236 in fetch_inferior_event(void*) /home/simark/src/binutils-gdb/gdb/infrun.c:3782
#20 0x55b6ee8f2641 in inferior_event_handler(inferior_event_type, void*) /home/simark/src/binutils-gdb/gdb/inf-loop.c:43
#21 0x55b6eea2a1f0 in handle_target_event /home/simark/src/binutils-gdb/gdb/linux-nat.c:4358
#22 0x55b6ee7045f1 in handle_file_event /home/simark/src/binutils-gdb/gdb/event-loop.c:733
#23 0x55b6ee704e89 in gdb_wait_for_event /home/simark/src/binutils-gdb/gdb/event-loop.c:859
#24 0x55b6ee7027b5 in gdb_do_one_event() /home/simark/src/binutils-gdb/gdb/event-loop.c:322
#25 0x55b6ee702907 in start_event_loop() /home/simark/src/binutils-gdb/gdb/event-loop.c:371
#26 0x55b6eeadfc16 in captured_command_loop /home/simark/src/binutils-gdb/gdb/main.c:331
#27 0x55b6eeae2ef9 in captured_main /home/simark/src/binutils-gdb/gdb/main.c:1174
#28 0x55b6eeae30c2 in gdb_main(captured_main_args*) /home/simark/src/binutils-gdb/gdb/main.c:1190
#29 0x55b6edf4fa89 in main /home/simark/src/binutils-gdb/gdb/gdb.c:32
previously allocated by thread T0 here:
#0 0x7fed89a8b019 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x7fed88af983f in realpath@@GLIBC_2.3 (/usr/lib/libc.so.6+0x4583f)
#2 0x7fed899dbbbc in __interceptor_canonicalize_file_name /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:3297
#3 0x55b6ee376a03 in gdb_realpath(char const*) /home/simark/src/binutils-gdb/gdb/common/pathstuff.c:72
#4 0x55b6ef09ec12 in find_and_open_source(char const*, char const*, std::unique_ptr<char, gdb::xfree_deleter<char> >*) /home/simark/src/binutils-gdb/gdb/source.c:990
#5 0x55b6ef09f56a in open_source_file(symtab*) /home/simark/src/binutils-gdb/gdb/source.c:1069
#6 0x55b6ef0a0f12 in print_source_lines_base /home/simark/src/binutils-gdb/gdb/source.c:1270
#7 0x55b6ef0a2045 in print_source_lines(symtab*, int, int, enum_flags<print_source_lines_flag>) /home/simark/src/binutils-gdb/gdb/source.c:1415
#8 0x55b6ef112c87 in print_frame_info(frame_info*, int, print_what, int, int) /home/simark/src/binutils-gdb/gdb/stack.c:914
#9 0x55b6ef10e90d in print_stack_frame(frame_info*, int, print_what, int) /home/simark/src/binutils-gdb/gdb/stack.c:180
#10 0x55b6ee9592f8 in print_stop_location /home/simark/src/binutils-gdb/gdb/infrun.c:7853
#11 0x55b6ee95948f in print_stop_event(ui_out*) /home/simark/src/binutils-gdb/gdb/infrun.c:7870
#12 0x55b6ef34b962 in tui_on_normal_stop /home/simark/src/binutils-gdb/gdb/tui/tui-interp.c:98
#13 0x55b6ee01a14d in std::_Function_handler<void (bpstats*, int), void (*)(bpstats*, int)>::_M_invoke(std::_Any_data const&, bpstats*&&, int&&) /usr/include/c++/8.2.1/bits/std_function.h:297
#14 0x55b6ee965415 in std::function<void (bpstats*, int)>::operator()(bpstats*, int) const /usr/include/c++/8.2.1/bits/std_function.h:687
#15 0x55b6ee962f1b in gdb::observers::observable<bpstats*, int>::notify(bpstats*, int) const /home/simark/src/binutils-gdb/gdb/common/observable.h:106
#16 0x55b6ee95a6e7 in normal_stop() /home/simark/src/binutils-gdb/gdb/infrun.c:8142
#17 0x55b6ee93f236 in fetch_inferior_event(void*) /home/simark/src/binutils-gdb/gdb/infrun.c:3782
#18 0x55b6ee8f2641 in inferior_event_handler(inferior_event_type, void*) /home/simark/src/binutils-gdb/gdb/inf-loop.c:43
#19 0x55b6eea2a1f0 in handle_target_event /home/simark/src/binutils-gdb/gdb/linux-nat.c:4358
#20 0x55b6ee7045f1 in handle_file_event /home/simark/src/binutils-gdb/gdb/event-loop.c:733
#21 0x55b6ee704e89 in gdb_wait_for_event /home/simark/src/binutils-gdb/gdb/event-loop.c:859
#22 0x55b6ee7027b5 in gdb_do_one_event() /home/simark/src/binutils-gdb/gdb/event-loop.c:322
#23 0x55b6ee702907 in start_event_loop() /home/simark/src/binutils-gdb/gdb/event-loop.c:371
#24 0x55b6eeadfc16 in captured_command_loop /home/simark/src/binutils-gdb/gdb/main.c:331
#25 0x55b6eeae2ef9 in captured_main /home/simark/src/binutils-gdb/gdb/main.c:1174
#26 0x55b6eeae30c2 in gdb_main(captured_main_args*) /home/simark/src/binutils-gdb/gdb/main.c:1190
#27 0x55b6edf4fa89 in main /home/simark/src/binutils-gdb/gdb/gdb.c:32
#28 0x7fed88ad8222 in __libc_start_main (/usr/lib/libc.so.6+0x24222)
gdb/ChangeLog:
* source-cache.c (source_cache::get_source_lines): Re-read
fullname after calling open_source_file.
2019-03-26 08:29:18 +08:00
|
|
|
|
|
|
|
/* FULLNAME points to a value owned by the symtab
|
|
|
|
(symtab::fullname). Calling open_source_file reallocates
|
|
|
|
that value, so we must refresh FULLNAME to avoid a
|
|
|
|
use-after-free. */
|
|
|
|
fullname = symtab_to_fullname (s);
|
2019-03-17 01:53:46 +08:00
|
|
|
}
|
2019-06-19 02:18:24 +08:00
|
|
|
|
|
|
|
if (highlighter == nullptr)
|
|
|
|
{
|
|
|
|
highlighter = new srchilite::SourceHighlight ("esc.outlang");
|
|
|
|
highlighter->setStyleFile ("esc.style");
|
|
|
|
}
|
2018-10-10 12:21:05 +08:00
|
|
|
|
|
|
|
std::ostringstream output;
|
2019-06-19 02:18:24 +08:00
|
|
|
highlighter->highlight (input, output, lang_name, fullname);
|
2018-10-10 12:21:05 +08:00
|
|
|
|
|
|
|
source_text result = { fullname, output.str () };
|
|
|
|
m_source_map.push_back (std::move (result));
|
|
|
|
|
|
|
|
if (m_source_map.size () > MAX_ENTRIES)
|
|
|
|
m_source_map.erase (m_source_map.begin ());
|
|
|
|
|
2019-07-23 22:22:50 +08:00
|
|
|
*lines = extract_lines (m_source_map.back ().contents,
|
|
|
|
first_line, last_line);
|
2019-03-09 04:59:27 +08:00
|
|
|
return true;
|
2018-10-10 12:21:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_SOURCE_HIGHLIGHT */
|
|
|
|
|
|
|
|
return get_plain_source_lines (s, first_line, last_line, lines);
|
|
|
|
}
|
2019-07-23 22:22:50 +08:00
|
|
|
|
|
|
|
#if GDB_SELF_TEST
|
|
|
|
namespace selftests
|
|
|
|
{
|
|
|
|
static void extract_lines_test ()
|
|
|
|
{
|
|
|
|
std::string input_text = "abc\ndef\nghi\njkl\n";
|
|
|
|
|
|
|
|
SELF_CHECK (extract_lines (input_text, 1, 1) == "abc\n");
|
|
|
|
SELF_CHECK (extract_lines (input_text, 2, 1) == "");
|
|
|
|
SELF_CHECK (extract_lines (input_text, 1, 2) == "abc\ndef\n");
|
|
|
|
SELF_CHECK (extract_lines ("abc", 1, 1) == "abc");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
_initialize_source_cache ()
|
|
|
|
{
|
|
|
|
#if GDB_SELF_TEST
|
|
|
|
selftests::register_test ("source-cache", selftests::extract_lines_test);
|
|
|
|
#endif
|
|
|
|
}
|