From: Mark Harmstone <mark@harmstone.com>
To: binutils@sourceware.org
Cc: Mark Harmstone <mark@harmstone.com>
Subject: [PATCH 2/2] gdb: Allow reading of enum definitions in PDB files
Date: Tue, 9 May 2023 01:32:47 +0100 [thread overview]
Message-ID: <20230509003247.24156-2-mark@harmstone.com> (raw)
In-Reply-To: <20230509003247.24156-1-mark@harmstone.com>
Adds a new file pdbread.c, which parses LF_ENUM records in PDB files.
---
gdb/Makefile.in | 2 +
gdb/configure.tgt | 4 +-
gdb/pdbread.c | 573 +++++++++++++++++++++++++++++++++
gdb/pdbread.h | 105 ++++++
gdb/testsuite/gdb.pdb/enum.exp | 39 +++
gdb/testsuite/gdb.pdb/enum1.s | 116 +++++++
6 files changed, 837 insertions(+), 2 deletions(-)
create mode 100644 gdb/pdbread.c
create mode 100644 gdb/pdbread.h
create mode 100644 gdb/testsuite/gdb.pdb/enum.exp
create mode 100644 gdb/testsuite/gdb.pdb/enum1.s
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 93f506ee391..ac0d7e35a02 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -838,6 +838,7 @@ ALL_TARGET_OBS = \
obsd-tdep.o \
or1k-linux-tdep.o \
or1k-tdep.o \
+ pdbread.o \
ppc-fbsd-tdep.o \
ppc-linux-tdep.o \
ppc-netbsd-tdep.o \
@@ -1770,6 +1771,7 @@ ALLDEPFILES = \
obsd-nat.c \
obsd-tdep.c \
or1k-linux-nat.c \
+ pdbread.c \
posix-hdep.c \
ppc-fbsd-nat.c \
ppc-fbsd-tdep.c \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index d5b7dd1e7d7..899acd67ae6 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -335,7 +335,7 @@ i[34567]86-*-cygwin*)
;;
i[34567]86-*-mingw32*)
# Target: Intel 386 running win32
- gdb_target_obs="i386-windows-tdep.o windows-tdep.o"
+ gdb_target_obs="i386-windows-tdep.o windows-tdep.o pdbread.o"
;;
i[34567]86-*-go32* | i[34567]86-*-msdosdjgpp*)
# Target: i386 running DJGPP/go32.
@@ -728,7 +728,7 @@ x86_64-*-mingw* | x86_64-*-cygwin*)
# Target: MingW/amd64
gdb_target_obs="amd64-windows-tdep.o \
${i386_tobjs} i386-windows-tdep.o \
- windows-tdep.o"
+ windows-tdep.o pdbread.o"
;;
x86_64-*-netbsd* | x86_64-*-knetbsd*-gnu)
# Target: NetBSD/amd64
diff --git a/gdb/pdbread.c b/gdb/pdbread.c
new file mode 100644
index 00000000000..faabbcf2240
--- /dev/null
+++ b/gdb/pdbread.c
@@ -0,0 +1,573 @@
+/* GDB code to parse PDB debug files.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ 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 "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "coff/i386.h"
+#include "coff/external.h"
+#include "pdbread.h"
+
+struct pdb_type
+{
+ file_ptr offset;
+ uint16_t kind;
+};
+
+static void
+pdb_new_init (struct objfile *ignore)
+{
+}
+
+static void
+pdb_symfile_init (struct objfile *objfile)
+{
+}
+
+/* Map the PDB builtin types to GDB's. */
+static struct type *
+pdb_builtin_type (const struct builtin_type *builtin, uint32_t t)
+{
+ switch (t)
+ {
+ case T_CHAR:
+ case T_INT1:
+ return builtin->builtin_char;
+
+ case T_UCHAR:
+ case T_UINT1:
+ return builtin->builtin_unsigned_char;
+
+ case T_SHORT:
+ case T_INT2:
+ return builtin->builtin_short;
+
+ case T_USHORT:
+ case T_UINT2:
+ return builtin->builtin_unsigned_short;
+
+ case T_LONG:
+ return builtin->builtin_long;
+
+ case T_ULONG:
+ return builtin->builtin_unsigned_long;
+
+ case T_INT4:
+ return builtin->builtin_int;
+
+ case T_UINT4:
+ return builtin->builtin_unsigned_int;
+
+ case T_QUAD:
+ case T_INT8:
+ return builtin->builtin_long_long;
+
+ case T_UQUAD:
+ case T_UINT8:
+ return builtin->builtin_unsigned_long_long;
+ }
+
+ return NULL;
+}
+
+/* Return the size in bytes of a PDB builtin type. */
+static ULONGEST
+pdb_builtin_type_length (uint32_t t)
+{
+ switch (t)
+ {
+ case T_CHAR:
+ case T_INT1:
+ case T_UCHAR:
+ case T_UINT1:
+ return 1;
+
+ case T_SHORT:
+ case T_INT2:
+ case T_USHORT:
+ case T_UINT2:
+ return 2;
+
+ case T_LONG:
+ case T_ULONG:
+ case T_INT4:
+ case T_UINT4:
+ return 4;
+
+ case T_QUAD:
+ case T_INT8:
+ case T_UQUAD:
+ case T_UINT8:
+ return 8;
+ }
+
+ return 0;
+}
+
+/* Some integers, such as enum values, get stored as an extended value if
+ they're too large to fit into two bytes. The two bytes that would normally
+ be the value are instead a type indicator, and the actual value follows. */
+static bool
+pdb_read_extended_value (uint16_t kind, char **ptr, uint16_t *length,
+ LONGEST *ret)
+{
+ switch (kind)
+ {
+ case LF_CHAR:
+ if (*length < 1)
+ return false;
+
+ *ret = *(signed char*) *ptr;
+ (*ptr)++;
+ (*length)--;
+
+ break;
+
+ case LF_SHORT:
+ if (*length < sizeof (int16_t))
+ return false;
+
+ *ret = (int16_t) bfd_getl16 (*ptr);
+ *ptr += sizeof (int16_t);
+ *length -= sizeof (int16_t);
+
+ break;
+
+ case LF_USHORT:
+ if (*length < sizeof (uint16_t))
+ return false;
+
+ *ret = bfd_getl16 (*ptr);
+ *ptr += sizeof (uint16_t);
+ *length -= sizeof (uint16_t);
+
+ break;
+
+ case LF_LONG:
+ if (*length < sizeof (int32_t))
+ return false;
+
+ *ret = (int32_t) bfd_getl32 (*ptr);
+ *ptr += sizeof (int32_t);
+ *length -= sizeof (int32_t);
+
+ break;
+
+ case LF_ULONG:
+ if (*length < sizeof (uint32_t))
+ return false;
+
+ *ret = bfd_getl32 (*ptr);
+ *ptr += sizeof (uint32_t);
+ *length -= sizeof (uint32_t);
+
+ break;
+
+ case LF_QUADWORD:
+ if (*length < sizeof (int64_t))
+ return false;
+
+ *ret = (int64_t) bfd_getl64 (*ptr);
+ *ptr += sizeof (int64_t);
+ *length -= sizeof (int64_t);
+
+ break;
+
+ case LF_UQUADWORD:
+ if (*length < sizeof (uint64_t))
+ return false;
+
+ *ret = bfd_getl64 (*ptr);
+ *ptr += sizeof (uint64_t);
+ *length -= sizeof (uint64_t);
+
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/* Read an LF_FIELDLIST entry for an enum. This can have two possible subtypes:
+ LF_ENUMERATE, for a value, and LF_INDEX, which points to an overflow
+ fieldlist if this one gets too large. */
+static void
+pdb_read_enum_fieldlist (std::vector<struct field> &fields, bfd *tpi,
+ struct pdb_type *types, uint32_t fieldlist_type,
+ uint32_t first_type, uint32_t last_type)
+{
+ struct pdb_type *type;
+ char int_buf [sizeof (uint16_t)];
+ uint16_t length;
+ char *buf, *ptr;
+
+ if (fieldlist_type < first_type || fieldlist_type > last_type)
+ return;
+
+ type = &types [fieldlist_type - first_type];
+
+ if (type->kind != LF_FIELDLIST)
+ return;
+
+ if (bfd_seek (tpi, type->offset, SEEK_SET) != 0)
+ return;
+
+ if (bfd_bread (int_buf, sizeof (int_buf), tpi) != sizeof (int_buf))
+ return;
+
+ length = bfd_getl16 (int_buf);
+
+ if (length <= sizeof (uint16_t))
+ return;
+
+ buf = (char *) xmalloc (length);
+
+ if (bfd_bread (buf, length, tpi) != length)
+ goto end;
+
+ /* Skip LF_FIELDLIST value. */
+ ptr = buf + sizeof (uint16_t);
+ length -= sizeof (uint16_t);
+
+ while (length >= sizeof (uint16_t))
+ {
+ uint16_t sub_type;
+
+ sub_type = bfd_getl16 (ptr);
+ ptr += sizeof (uint16_t);
+ length -= sizeof (uint16_t);
+
+ switch (sub_type)
+ {
+ case LF_ENUMERATE: {
+ struct lf_enumerate *en;
+ LONGEST val;
+ size_t name_len;
+ char *name;
+
+ if (length < sizeof (*en))
+ goto end;
+
+ en = (struct lf_enumerate *) ptr;
+
+ ptr += sizeof (*en);
+ length -= sizeof (*en);
+
+ val = bfd_getl16 (&en->value);
+
+ /* Extended value - actual value follows. */
+ if (val >= 0x8000)
+ {
+ if (!pdb_read_extended_value (val, &ptr, &length, &val))
+ goto end;
+ }
+
+ name_len = strnlen (ptr, length);
+
+ /* Should be zero-terminated. */
+ if (name_len == length)
+ goto end;
+
+ name = ptr;
+ ptr += name_len + 1;
+ length -= name_len + 1;
+
+ if (name_len != 0)
+ {
+ fields.emplace_back ();
+ struct field &field = fields.back ();
+ field.set_name (xstrdup (name));
+ field.set_loc_enumval (val);
+ }
+
+ /* Round to 4-byte boundary. */
+ if ((ptr - buf + 2) % 4)
+ {
+ if (length < 4)
+ goto end;
+
+ length -= 4 - ((ptr - buf + 2) % 4);
+ ptr += 4 - ((ptr - buf + 2) % 4);
+ }
+
+ break;
+ }
+
+ case LF_INDEX: {
+ struct lf_index *ind;
+ uint32_t fl_type;
+
+ if (length < sizeof (*ind))
+ goto end;
+
+ ind = (struct lf_index *) ptr;
+
+ ptr += sizeof (*ind);
+ length -= sizeof (*ind);
+
+ fl_type = bfd_getl32 (&ind->index);
+
+ pdb_read_enum_fieldlist (fields, tpi, types, fl_type, first_type,
+ last_type);
+
+ break;
+ }
+
+ default:
+ goto end;
+ }
+ }
+
+end:
+ free (buf);
+}
+
+/* Parse an LF_ENUM record, and add it as an enum symbol. */
+static void
+pdb_add_enum (struct objfile *objfile, buildsym_compunit &builder,
+ bfd *tpi, struct pdb_type *types, uint32_t type_off,
+ uint32_t first_type, uint32_t last_type)
+{
+ char int_buf [sizeof (uint16_t)];
+ uint16_t length;
+ struct lf_enum en;
+ struct type *t;
+ struct symbol *sym;
+ size_t name_len;
+ char *name;
+ std::vector<struct field> fields;
+ struct pdb_type *type = &types [type_off];
+
+ if (bfd_seek (tpi, type->offset, SEEK_SET) != 0)
+ return;
+
+ if (bfd_bread (int_buf, sizeof (int_buf), tpi) != sizeof (int_buf))
+ return;
+
+ length = bfd_getl16 (int_buf);
+
+ if (length <= sizeof (en))
+ return;
+
+ if (bfd_bread (&en, sizeof (en), tpi) != sizeof (en))
+ return;
+
+ if (bfd_getl16 (&en.properties) & CV_PROP_FORWARD_REF)
+ return;
+
+ name_len = length - sizeof (en);
+ name = (char * ) xmalloc (name_len + 1);
+
+ if (bfd_bread (name, name_len, tpi) != name_len)
+ {
+ free (name);
+ return;
+ }
+
+ /* Should be zero-terminated, but just in case. */
+ name[name_len] = 0;
+
+ t = type_allocator (objfile).new_type ();
+ t->set_code (TYPE_CODE_ENUM);
+ t->set_name (name);
+
+ t->set_target_type (pdb_builtin_type (builtin_type (objfile),
+ bfd_getl32 (&en.underlying_type)));
+ t->set_length (pdb_builtin_type_length (bfd_getl32 (&en.underlying_type)));
+
+ pdb_read_enum_fieldlist (fields, tpi, types, bfd_getl32 (&en.field_list),
+ first_type, last_type);
+
+ if (!fields.empty ())
+ {
+ t->set_num_fields (fields.size ());
+ t->set_fields
+ ((struct field *)
+ TYPE_ALLOC (t, sizeof (struct field) * fields.size ()));
+ memcpy (t->fields (), fields.data (),
+ sizeof (struct field) * fields.size ());
+ }
+
+ sym = new (&objfile->objfile_obstack) symbol;
+ sym->set_language (language_c, &objfile->objfile_obstack);
+ sym->set_domain (STRUCT_DOMAIN);
+ sym->set_aclass_index (LOC_TYPEDEF);
+ sym->set_linkage_name (name);
+ sym->set_type (t);
+
+ add_symbol_to_list (sym, builder.get_global_symbols ());
+}
+
+/* Read and parse the TPI stream, which contains the type definitions. */
+static bool
+pdb_read_tpi_stream (struct objfile *objfile, buildsym_compunit &builder)
+{
+ bfd *tpi;
+ struct pdb_tpi_stream_header h;
+ uint32_t first_type, last_type, num_types;
+ struct pdb_type *types;
+
+ tpi = bfd_get_elt_at_index (objfile->obfd.get (), PDB_TPI_STREAM_NUM);
+
+ if (!tpi)
+ return false;
+
+ if (bfd_seek (tpi, 0, SEEK_SET) != 0)
+ {
+ bfd_close (tpi);
+ return false;
+ }
+
+ if (bfd_bread (&h, sizeof (h), tpi) != sizeof (h))
+ {
+ bfd_close (tpi);
+ return false;
+ }
+
+ if (bfd_getl32 (&h.version) != TPI_STREAM_VERSION_80)
+ {
+ bfd_close (tpi);
+ return false;
+ }
+
+ if (bfd_seek (tpi, bfd_getl32 (&h.header_size), SEEK_SET) != 0)
+ {
+ bfd_close (tpi);
+ return false;
+ }
+
+ first_type = bfd_getl32 (&h.type_index_begin);
+ last_type = bfd_getl32 (&h.type_index_end) - 1;
+
+ if (last_type <= first_type)
+ {
+ bfd_close (tpi);
+ return true;
+ }
+
+ num_types = last_type - first_type + 1;
+ types = (struct pdb_type *) xmalloc (sizeof (*types) * num_types);
+
+ for (unsigned int i = 0; i < num_types; i++)
+ {
+ char int_buf[sizeof (uint16_t)];
+ uint16_t length;
+
+ types[i].offset = bfd_tell(tpi);
+
+ if (bfd_bread (int_buf, sizeof (int_buf), tpi) != sizeof (int_buf))
+ {
+ free (types);
+ bfd_close (tpi);
+ return false;
+ }
+
+ length = bfd_getl16 (int_buf);
+
+ if (length < sizeof (uint16_t))
+ {
+ free (types);
+ bfd_close (tpi);
+ return false;
+ }
+
+ if (bfd_bread (int_buf, sizeof (int_buf), tpi) != sizeof (int_buf))
+ {
+ free (types);
+ bfd_close (tpi);
+ return false;
+ }
+
+ types[i].kind = bfd_getl16 (int_buf);
+
+ if (bfd_seek (tpi, length - sizeof (uint16_t), SEEK_CUR) != 0)
+ {
+ free (types);
+ bfd_close (tpi);
+ return false;
+ }
+ }
+
+ for (unsigned int i = 0; i < num_types; i++)
+ {
+ switch (types[i].kind)
+ {
+ case LF_ENUM:
+ pdb_add_enum (objfile, builder, tpi, types, i, first_type, last_type);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ free (types);
+
+ bfd_close (tpi);
+
+ return true;
+}
+
+static void
+pdb_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
+{
+ buildsym_compunit builder(objfile, "", nullptr, language_c, 0);
+
+ if (!pdb_read_tpi_stream (objfile, builder))
+ complaint (_("Failed to read types stream"));
+
+ builder.end_compunit_symtab (0);
+}
+
+static void
+pdb_symfile_finish (struct objfile *objfile)
+{
+}
+
+static const struct sym_fns pdb_sym_fns =
+{
+ pdb_new_init, /* sym_new_init: init anything gbl to
+ entire symtab */
+ pdb_symfile_init, /* sym_init: read initial info, setup
+ for sym_read() */
+ pdb_symfile_read, /* sym_read: read a symbol file into
+ symtab */
+ pdb_symfile_finish, /* sym_finish: finished with file,
+ cleanup */
+ default_symfile_offsets, /* sym_offsets: xlate external to
+ internal form */
+ default_symfile_segments, /* sym_segments: Get segment
+ information from a file */
+ NULL, /* sym_read_linetable */
+
+ default_symfile_relocate, /* sym_relocate: Relocate a debug
+ section. */
+ NULL, /* sym_probe_fns */
+};
+
+void _initialize_pdbread ();
+void
+_initialize_pdbread ()
+{
+ add_symtab_fns (bfd_target_pdb_flavour, &pdb_sym_fns);
+}
diff --git a/gdb/pdbread.h b/gdb/pdbread.h
new file mode 100644
index 00000000000..dd5982ed9d8
--- /dev/null
+++ b/gdb/pdbread.h
@@ -0,0 +1,105 @@
+/* Include file for PDB debugging format support.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Header files referred to below can be found in Microsoft's PDB
+ repository: https://github.com/microsoft/microsoft-pdb. */
+
+#ifndef PDBREAD_H
+#define PDBREAD_H
+
+#define PDB_TPI_STREAM_NUM 2
+
+#define LF_FIELDLIST 0x1203
+#define LF_INDEX 0x1404
+#define LF_ENUMERATE 0x1502
+#define LF_ENUM 0x1507
+#define LF_CHAR 0x8000
+#define LF_SHORT 0x8001
+#define LF_USHORT 0x8002
+#define LF_LONG 0x8003
+#define LF_ULONG 0x8004
+#define LF_QUADWORD 0x8009
+#define LF_UQUADWORD 0x800a
+
+#define T_CHAR 0x0010
+#define T_UCHAR 0x0020
+#define T_INT1 0x0068
+#define T_UINT1 0x0069
+#define T_SHORT 0x0011
+#define T_USHORT 0x0021
+#define T_INT2 0x0072
+#define T_UINT2 0x0073
+#define T_LONG 0x0012
+#define T_ULONG 0x0022
+#define T_INT4 0x0074
+#define T_UINT4 0x0075
+#define T_QUAD 0x0013
+#define T_UQUAD 0x0023
+#define T_INT8 0x0076
+#define T_UINT8 0x0077
+
+/* from bitfield structure CV_prop_t in cvinfo.h */
+#define CV_PROP_FORWARD_REF 0x80
+
+/* HDR in tpi.h */
+struct pdb_tpi_stream_header
+{
+ uint32_t version;
+ uint32_t header_size;
+ uint32_t type_index_begin;
+ uint32_t type_index_end;
+ uint32_t type_record_bytes;
+ uint16_t hash_stream_index;
+ uint16_t hash_aux_stream_index;
+ uint32_t hash_key_size;
+ uint32_t num_hash_buckets;
+ uint32_t hash_value_buffer_offset;
+ uint32_t hash_value_buffer_length;
+ uint32_t index_offset_buffer_offset;
+ uint32_t index_offset_buffer_length;
+ uint32_t hash_adj_buffer_offset;
+ uint32_t hash_adj_buffer_length;
+};
+
+#define TPI_STREAM_VERSION_80 20040203
+
+/* lfEnum in cvinfo.h */
+struct lf_enum
+{
+ uint16_t kind;
+ uint16_t num_elements;
+ uint16_t properties;
+ uint32_t underlying_type;
+ uint32_t field_list;
+} ATTRIBUTE_PACKED;
+
+/* lfEnumerate in cvinfo.h */
+struct lf_enumerate
+{
+ uint16_t attributes;
+ uint16_t value;
+} ATTRIBUTE_PACKED;
+
+/* lfIndex in cvinfo.h */
+struct lf_index
+{
+ uint16_t padding;
+ uint32_t index;
+} ATTRIBUTE_PACKED;
+
+#endif /* PDBREAD_H */
diff --git a/gdb/testsuite/gdb.pdb/enum.exp b/gdb/testsuite/gdb.pdb/enum.exp
new file mode 100644
index 00000000000..ab2e2cff3b8
--- /dev/null
+++ b/gdb/testsuite/gdb.pdb/enum.exp
@@ -0,0 +1,39 @@
+# Copyright 2023 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/>.
+
+if {![istarget i*86-*-mingw*]
+ && ![istarget x86_64-*-mingw*]} {
+ return 0
+}
+
+set obj [standard_output_file enum1.o]
+
+if {[target_assemble ${srcdir}/${subdir}/enum1.s ${obj} ""] != ""} then {
+ untested "failed to assemble"
+ return -1
+}
+
+set exe [standard_output_file enum1.exe]
+set pdb [standard_output_file enum1.pdb]
+
+if {[target_link ${obj} ${exe} "--pdb=${pdb}"] != "" } then {
+ untested "failed to link"
+ return -1
+}
+
+clean_restart ${pdb}
+
+gdb_test "ptype enum enum1" "type = enum enum1 \{red, green, blue = -1, yellow = 32768, purple = 4294967296\}.*" "ptype enum enum1"
+gdb_test "ptype enum enum2" "type = enum enum2 \{foo = 1, bar = 1, baz, xyzzy, plugh = 5\}.*" "ptype enum enum2"
diff --git a/gdb/testsuite/gdb.pdb/enum1.s b/gdb/testsuite/gdb.pdb/enum1.s
new file mode 100644
index 00000000000..4d4b2ed4f6a
--- /dev/null
+++ b/gdb/testsuite/gdb.pdb/enum1.s
@@ -0,0 +1,116 @@
+.equ CV_SIGNATURE_C13, 4
+
+.equ T_UQUAD, 0x0023
+
+.equ LF_FIELDLIST, 0x1203
+.equ LF_INDEX, 0x1404
+.equ LF_ENUMERATE, 0x1502
+.equ LF_ENUM, 0x1507
+
+.equ LF_USHORT, 0x8002
+.equ LF_LONG, 0x8003
+.equ LF_UQUADWORD, 0x800a
+
+.section ".debug$T", "rn"
+
+.long CV_SIGNATURE_C13
+
+# Type 1000, field list for enum enum1 (red = 0, green = 1, blue = -1, yellow = 0x8000, purple = 0x100000000)
+.fieldlist1:
+.short .enum1 - .fieldlist1 - 2
+.short LF_FIELDLIST
+.short LF_ENUMERATE
+.short 3 # public
+.short 0 # value
+.asciz "red"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+.short LF_ENUMERATE
+.short 3 # public
+.short 1 # value
+.asciz "green"
+.short LF_ENUMERATE
+.short 3 # public
+.short LF_LONG
+.long 0xffffffff # value
+.asciz "blue"
+.byte 0xf1 # padding
+.short LF_ENUMERATE
+.short 3 # public
+.short LF_USHORT
+.short 0x8000 # value
+.asciz "yellow"
+.byte 0xf1 # padding
+.short LF_ENUMERATE
+.short 3 # public
+.short LF_UQUADWORD
+.quad 0x100000000 # value
+.asciz "purple"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+# Type 1001, enum enum1
+.enum1:
+.short .fieldlist2 - .enum1 - 2
+.short LF_ENUM
+.short 3 # no. elements
+.short 0 # property
+.long T_UQUAD # underlying type
+.long 0x1000 # field list
+.asciz "enum1"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+# Type 1002, continuation field list for enum enum2 (xyzzy = 3, plugh = 5)
+.fieldlist2:
+.short .fieldlist3 - .fieldlist2 - 2
+.short LF_FIELDLIST
+.short LF_ENUMERATE
+.short 3 # public
+.short 3 # value
+.asciz "xyzzy"
+.short LF_ENUMERATE
+.short 3 # public
+.short 5 # value
+.asciz "plugh"
+
+# Type 1003, field list for enum enum2 (foo = 1, bar = 1, baz = 2, ...)
+.fieldlist3:
+.short .enum2 - .fieldlist3 - 2
+.short LF_FIELDLIST
+.short LF_ENUMERATE
+.short 3 # public
+.short 1 # value
+.asciz "foo"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+.short LF_ENUMERATE
+.short 3 # public
+.short 1 # value
+.asciz "bar"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+.short LF_ENUMERATE
+.short 3 # public
+.short 2 # value
+.asciz "baz"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+.short LF_INDEX
+.short 0 # padding
+.long 0x1002
+
+# Type 1004, enum enum2
+.enum2:
+.short .types_end - .enum2 - 2
+.short LF_ENUM
+.short 5 # no. elements
+.short 0 # property
+.long T_UINT4 # underlying type
+.long 0x1003 # field list
+.asciz "enum2"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.types_end:
--
2.39.2
next prev parent reply other threads:[~2023-05-09 0:32 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-09 0:32 [PATCH 1/2] pdb: Allow loading by gdb Mark Harmstone
2023-05-09 0:32 ` Mark Harmstone [this message]
2023-05-11 13:41 ` [PATCH 2/2] gdb: Allow reading of enum definitions in PDB files Tom Tromey
2023-05-10 0:56 ` [PATCH 1/2] pdb: Allow loading by gdb Alan Modra
2023-05-15 1:04 ` Mark Harmstone
2023-05-15 1:26 ` Alan Modra
2023-05-16 15:03 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230509003247.24156-2-mark@harmstone.com \
--to=mark@harmstone.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).