binutils-gdb/gdbsupport/def-vector.h

37 lines
1.3 KiB
C
Raw Normal View History

/* Copyright (C) 2017-2022 Free Software Foundation, Inc.
Introduce gdb::byte_vector, add allocator that default-initializes In some cases we've been replacing heap-allocated gdb_byte buffers managed with xmalloc/make_cleanup(xfree) with gdb::vector<gdb_byte>. That usually pessimizes the code a little bit because std::vector value-initializes elements (which for gdb_byte means zero-initialization), while if you're creating a temporary buffer, you're most certaintly going to fill it in with some data. An alternative is to use unique_ptr<gdb_byte[]> buf (new gdb_byte[size]); but it looks like that's not very popular. Recently, a use of obstacks in dwarf2read.c was replaced with std::vector<gdb_byte> and that as well introduced a pessimization for always memsetting the buffer when it's garanteed that the zeros will be overwritten immediately. (see dwarf2read.c change in this patch to find it.) So here's a different take at addressing this issue "by design": #1 - Introduce default_init_allocator<T> I.e., a custom allocator that does default construction using default initialization, meaning, no more zero initialization. That's the default_init_allocation<T> class added in this patch. See "Notes" at <http://en.cppreference.com/w/cpp/container/vector/resize>. #2 - Introduce def_vector<T> I.e., a convenience typedef, because typing the allocator is annoying: using def_vector<T> = std::vector<T, gdb::default_init_allocator<T>>; #3 - Introduce byte_vector Because gdb_byte vectors will be the common thing, add a convenience "byte_vector" typedef: using byte_vector = def_vector<gdb_byte>; which is really the same as: std::vector<gdb_byte, gdb::default_init_allocator<gdb_byte>>; The intent then is to make "gdb::byte_vector" be the go-to for dynamic byte buffers. So the less friction, the better. #4 - Adjust current code to use it. To set the example going forward. Replace std::vector uses and also unique_ptr<byte[]> uses. One nice thing is that with this allocator, for changes like these: -std::unique_ptr<byte[]> buf (new gdb_byte[some_size]); +gdb::byte_vector buf (some_size); fill_with_data (buf.data (), buf.size ()); the generated code is the same as before. I.e., the compiler de-structures the vector and gets rid of the unused "reserved vs size" related fields. The other nice thing is that it's easier to write gdb::byte_vector buf (size); than std::unique_ptr<gdb_byte[]> buf (new gdb_byte[size]); or even (C++14): auto buf = std::make_unique<gdb_byte[]> (size); // zero-initializes... #5 - Suggest s/std::vector<gdb_byte>/gdb::byte_vector/ going forward. Note that this commit actually fixes a couple of bugs where the current code is incorrectly using "std::vector::reserve(new_size)" and then accessing the vector's internal buffer beyond the vector's size: see dwarf2loc.c and charset.c. That's undefined behavior and may trigger debug mode assertion failures. With default_init_allocator, "resize()" behaves like "reserve()" performance wise, in that it leaves new elements with unspecified values, but, it does that safely without triggering undefined behavior when you access those values. gdb/ChangeLog: 2017-06-14 Pedro Alves <palves@redhat.com> * ada-lang.c: Include "common/byte-vector.h". (ada_value_primitive_packed_val): Use gdb::byte_vector. * charset.c (wchar_iterator::iterate): Resize the vector instead of reserving it. * common/byte-vector.h: Include "common/def-vector.h". (wchar_iterator::m_out): Now a gdb::def_vector<gdb_wchar_t>. * cli/cli-dump.c: Include "common/byte-vector.h". (dump_memory_to_file, restore_binary_file): Use gdb::byte_vector. * common/byte-vector.h: New file. * common/def-vector.h: New file. * common/default-init-alloc.h: New file. * dwarf2loc.c: Include "common/byte-vector.h". (rw_pieced_value): Use gdb::byte_vector, and resize the vector instead of reserving it. * dwarf2read.c: Include "common/byte-vector.h". (data_buf::m_vec): Now a gdb::byte_vector. * gdb_regex.c: Include "common/def-vector.h". (compiled_regex::compiled_regex): Use gdb::def_vector<char>. * mi/mi-main.c: Include "common/byte-vector.h". (mi_cmd_data_read_memory): Use gdb::byte_vector. * printcmd.c: Include "common/byte-vector.h". (print_scalar_formatted): Use gdb::byte_vector. * valprint.c: Include "common/byte-vector.h". (maybe_negate_by_bytes, print_decimal_chars): Use gdb::byte_vector.
2017-06-14 18:08:52 +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/>. */
#ifndef COMMON_DEF_VECTOR_H
#define COMMON_DEF_VECTOR_H
#include <vector>
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/default-init-alloc.h"
Introduce gdb::byte_vector, add allocator that default-initializes In some cases we've been replacing heap-allocated gdb_byte buffers managed with xmalloc/make_cleanup(xfree) with gdb::vector<gdb_byte>. That usually pessimizes the code a little bit because std::vector value-initializes elements (which for gdb_byte means zero-initialization), while if you're creating a temporary buffer, you're most certaintly going to fill it in with some data. An alternative is to use unique_ptr<gdb_byte[]> buf (new gdb_byte[size]); but it looks like that's not very popular. Recently, a use of obstacks in dwarf2read.c was replaced with std::vector<gdb_byte> and that as well introduced a pessimization for always memsetting the buffer when it's garanteed that the zeros will be overwritten immediately. (see dwarf2read.c change in this patch to find it.) So here's a different take at addressing this issue "by design": #1 - Introduce default_init_allocator<T> I.e., a custom allocator that does default construction using default initialization, meaning, no more zero initialization. That's the default_init_allocation<T> class added in this patch. See "Notes" at <http://en.cppreference.com/w/cpp/container/vector/resize>. #2 - Introduce def_vector<T> I.e., a convenience typedef, because typing the allocator is annoying: using def_vector<T> = std::vector<T, gdb::default_init_allocator<T>>; #3 - Introduce byte_vector Because gdb_byte vectors will be the common thing, add a convenience "byte_vector" typedef: using byte_vector = def_vector<gdb_byte>; which is really the same as: std::vector<gdb_byte, gdb::default_init_allocator<gdb_byte>>; The intent then is to make "gdb::byte_vector" be the go-to for dynamic byte buffers. So the less friction, the better. #4 - Adjust current code to use it. To set the example going forward. Replace std::vector uses and also unique_ptr<byte[]> uses. One nice thing is that with this allocator, for changes like these: -std::unique_ptr<byte[]> buf (new gdb_byte[some_size]); +gdb::byte_vector buf (some_size); fill_with_data (buf.data (), buf.size ()); the generated code is the same as before. I.e., the compiler de-structures the vector and gets rid of the unused "reserved vs size" related fields. The other nice thing is that it's easier to write gdb::byte_vector buf (size); than std::unique_ptr<gdb_byte[]> buf (new gdb_byte[size]); or even (C++14): auto buf = std::make_unique<gdb_byte[]> (size); // zero-initializes... #5 - Suggest s/std::vector<gdb_byte>/gdb::byte_vector/ going forward. Note that this commit actually fixes a couple of bugs where the current code is incorrectly using "std::vector::reserve(new_size)" and then accessing the vector's internal buffer beyond the vector's size: see dwarf2loc.c and charset.c. That's undefined behavior and may trigger debug mode assertion failures. With default_init_allocator, "resize()" behaves like "reserve()" performance wise, in that it leaves new elements with unspecified values, but, it does that safely without triggering undefined behavior when you access those values. gdb/ChangeLog: 2017-06-14 Pedro Alves <palves@redhat.com> * ada-lang.c: Include "common/byte-vector.h". (ada_value_primitive_packed_val): Use gdb::byte_vector. * charset.c (wchar_iterator::iterate): Resize the vector instead of reserving it. * common/byte-vector.h: Include "common/def-vector.h". (wchar_iterator::m_out): Now a gdb::def_vector<gdb_wchar_t>. * cli/cli-dump.c: Include "common/byte-vector.h". (dump_memory_to_file, restore_binary_file): Use gdb::byte_vector. * common/byte-vector.h: New file. * common/def-vector.h: New file. * common/default-init-alloc.h: New file. * dwarf2loc.c: Include "common/byte-vector.h". (rw_pieced_value): Use gdb::byte_vector, and resize the vector instead of reserving it. * dwarf2read.c: Include "common/byte-vector.h". (data_buf::m_vec): Now a gdb::byte_vector. * gdb_regex.c: Include "common/def-vector.h". (compiled_regex::compiled_regex): Use gdb::def_vector<char>. * mi/mi-main.c: Include "common/byte-vector.h". (mi_cmd_data_read_memory): Use gdb::byte_vector. * printcmd.c: Include "common/byte-vector.h". (print_scalar_formatted): Use gdb::byte_vector. * valprint.c: Include "common/byte-vector.h". (maybe_negate_by_bytes, print_decimal_chars): Use gdb::byte_vector.
2017-06-14 18:08:52 +08:00
namespace gdb {
/* A vector that uses an allocator that default constructs using
default-initialization rather than value-initialization. The idea
is to use this when you don't want zero-initialization of elements
of vectors of trivial types. E.g., byte buffers. */
template<typename T> using def_vector
= std::vector<T, gdb::default_init_allocator<T>>;
} /* namespace gdb */
#endif /* COMMON_DEF_VECTOR_H */