📄 gdbtypes.c
字号:
/* Support routines for manipulating internal types for GDB. Copyright (C) 1992 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include <string.h>#include "bfd.h"#include "symtab.h"#include "symfile.h"#include "objfiles.h"#include "gdbtypes.h"#include "expression.h"#include "language.h"#include "target.h"#include "value.h"#include "demangle.h"/* Alloc a new type structure and fill it with some defaults. If OBJFILE is non-NULL, then allocate the space for the type structure in that objfile's type_obstack. */struct type *alloc_type (objfile) struct objfile *objfile;{ register struct type *type; /* Alloc the structure and start off with all fields zeroed. */ if (objfile == NULL) { type = (struct type *) xmalloc (sizeof (struct type)); } else { type = (struct type *) obstack_alloc (&objfile -> type_obstack, sizeof (struct type)); } memset ((char *) type, 0, sizeof (struct type)); /* Initialize the fields that might not be zero. */ TYPE_CODE (type) = TYPE_CODE_UNDEF; TYPE_OBJFILE (type) = objfile; TYPE_VPTR_FIELDNO (type) = -1; return (type);}/* Lookup a pointer to a type TYPE. TYPEPTR, if nonzero, points to a pointer to memory where the pointer type should be stored. If *TYPEPTR is zero, update it to point to the pointer type we return. We allocate new memory if needed. */struct type *make_pointer_type (type, typeptr) struct type *type; struct type **typeptr;{ register struct type *ntype; /* New type */ struct objfile *objfile; ntype = TYPE_POINTER_TYPE (type); if (ntype) if (typeptr == 0) return ntype; /* Don't care about alloc, and have new type. */ else if (*typeptr == 0) { *typeptr = ntype; /* Tracking alloc, and we have new type. */ return ntype; } if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ { ntype = alloc_type (TYPE_OBJFILE (type)); if (typeptr) *typeptr = ntype; } else /* We have storage, but need to reset it. */ { ntype = *typeptr; objfile = TYPE_OBJFILE (ntype); memset ((char *) ntype, 0, sizeof (struct type)); TYPE_OBJFILE (ntype) = objfile; } TYPE_TARGET_TYPE (ntype) = type; TYPE_POINTER_TYPE (type) = ntype; /* FIXME! Assume the machine has only one representation for pointers! */ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT; TYPE_CODE (ntype) = TYPE_CODE_PTR; /* pointers are unsigned */ TYPE_FLAGS (ntype) |= TYPE_FLAG_UNSIGNED; if (!TYPE_POINTER_TYPE (type)) /* Remember it, if don't have one. */ TYPE_POINTER_TYPE (type) = ntype; return ntype;}/* Given a type TYPE, return a type of pointers to that type. May need to construct such a type if this is the first use. */struct type *lookup_pointer_type (type) struct type *type;{ return make_pointer_type (type, (struct type **)0);}/* Lookup a C++ `reference' to a type TYPE. TYPEPTR, if nonzero, points to a pointer to memory where the reference type should be stored. If *TYPEPTR is zero, update it to point to the reference type we return. We allocate new memory if needed. */struct type *make_reference_type (type, typeptr) struct type *type; struct type **typeptr;{ register struct type *ntype; /* New type */ struct objfile *objfile; ntype = TYPE_REFERENCE_TYPE (type); if (ntype) if (typeptr == 0) return ntype; /* Don't care about alloc, and have new type. */ else if (*typeptr == 0) { *typeptr = ntype; /* Tracking alloc, and we have new type. */ return ntype; } if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ { ntype = alloc_type (TYPE_OBJFILE (type)); if (typeptr) *typeptr = ntype; } else /* We have storage, but need to reset it. */ { ntype = *typeptr; objfile = TYPE_OBJFILE (ntype); memset ((char *) ntype, 0, sizeof (struct type)); TYPE_OBJFILE (ntype) = objfile; } TYPE_TARGET_TYPE (ntype) = type; TYPE_REFERENCE_TYPE (type) = ntype; /* FIXME! Assume the machine has only one representation for references, and that it matches the (only) representation for pointers! */ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT; TYPE_CODE (ntype) = TYPE_CODE_REF; if (!TYPE_REFERENCE_TYPE (type)) /* Remember it, if don't have one. */ TYPE_REFERENCE_TYPE (type) = ntype; return ntype;}/* Same as above, but caller doesn't care about memory allocation details. */struct type *lookup_reference_type (type) struct type *type;{ return make_reference_type (type, (struct type **)0);}/* Lookup a function type that returns type TYPE. TYPEPTR, if nonzero, points to a pointer to memory where the function type should be stored. If *TYPEPTR is zero, update it to point to the function type we return. We allocate new memory if needed. */struct type *make_function_type (type, typeptr) struct type *type; struct type **typeptr;{ register struct type *ntype; /* New type */ struct objfile *objfile; ntype = TYPE_FUNCTION_TYPE (type); if (ntype) if (typeptr == 0) return ntype; /* Don't care about alloc, and have new type. */ else if (*typeptr == 0) { *typeptr = ntype; /* Tracking alloc, and we have new type. */ return ntype; } if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ { ntype = alloc_type (TYPE_OBJFILE (type)); if (typeptr) *typeptr = ntype; } else /* We have storage, but need to reset it. */ { ntype = *typeptr; objfile = TYPE_OBJFILE (ntype); memset ((char *) ntype, 0, sizeof (struct type)); TYPE_OBJFILE (ntype) = objfile; } TYPE_TARGET_TYPE (ntype) = type; TYPE_FUNCTION_TYPE (type) = ntype; TYPE_LENGTH (ntype) = 1; TYPE_CODE (ntype) = TYPE_CODE_FUNC; if (!TYPE_FUNCTION_TYPE (type)) /* Remember it, if don't have one. */ TYPE_FUNCTION_TYPE (type) = ntype; return ntype;}/* Given a type TYPE, return a type of functions that return that type. May need to construct such a type if this is the first use. */struct type *lookup_function_type (type) struct type *type;{ return make_function_type (type, (struct type **)0);}/* Implement direct support for MEMBER_TYPE in GNU C++. May need to construct such a type if this is the first use. The TYPE is the type of the member. The DOMAIN is the type of the aggregate that the member belongs to. */struct type *lookup_member_type (type, domain) struct type *type; struct type *domain;{ register struct type *mtype; mtype = alloc_type (TYPE_OBJFILE (type)); smash_to_member_type (mtype, domain, type); return (mtype);}/* Allocate a stub method whose return type is TYPE. This apparently happens for speed of symbol reading, since parsing out the arguments to the method is cpu-intensive, the way we are doing it. So, we will fill in arguments later. This always returns a fresh type. */struct type *allocate_stub_method (type) struct type *type;{ struct type *mtype; mtype = alloc_type (TYPE_OBJFILE (type)); TYPE_TARGET_TYPE (mtype) = type; /* _DOMAIN_TYPE (mtype) = unknown yet */ /* _ARG_TYPES (mtype) = unknown yet */ TYPE_FLAGS (mtype) = TYPE_FLAG_STUB; TYPE_CODE (mtype) = TYPE_CODE_METHOD; TYPE_LENGTH (mtype) = 1; return (mtype);}/* Create an array type. Elements will be of type TYPE, and there will be NUM of them. Eventually this should be extended to take two more arguments which specify the bounds of the array and the type of the index. It should also be changed to be a "lookup" function, with the appropriate data structures added to the type field. Then read array type should call here. */struct type *create_array_type (element_type, number) struct type *element_type; int number;{ struct type *result_type; struct type *range_type; result_type = alloc_type (TYPE_OBJFILE (element_type)); TYPE_CODE (result_type) = TYPE_CODE_ARRAY; TYPE_TARGET_TYPE (result_type) = element_type; TYPE_LENGTH (result_type) = number * TYPE_LENGTH (element_type); TYPE_NFIELDS (result_type) = 1; TYPE_FIELDS (result_type) = (struct field *) TYPE_ALLOC (result_type, sizeof (struct field)); { /* Create range type. */ range_type = alloc_type (TYPE_OBJFILE (result_type)); TYPE_CODE (range_type) = TYPE_CODE_RANGE; TYPE_TARGET_TYPE (range_type) = builtin_type_int; /* FIXME */ /* This should never be needed. */ TYPE_LENGTH (range_type) = sizeof (int); TYPE_NFIELDS (range_type) = 2; TYPE_FIELDS (range_type) = (struct field *) TYPE_ALLOC (range_type, 2 * sizeof (struct field)); TYPE_FIELD_BITPOS (range_type, 0) = 0; /* FIXME */ TYPE_FIELD_BITPOS (range_type, 1) = number-1; /* FIXME */ TYPE_FIELD_TYPE (range_type, 0) = builtin_type_int; /* FIXME */ TYPE_FIELD_TYPE (range_type, 1) = builtin_type_int; /* FIXME */ } TYPE_FIELD_TYPE (result_type, 0) = range_type; TYPE_VPTR_FIELDNO (result_type) = -1; return (result_type);}/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. A MEMBER is a wierd thing -- it amounts to a typed offset into a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't include the offset (that's the value of the MEMBER itself), but does include the structure type into which it points (for some reason). When "smashing" the type, we preserve the objfile that the old type pointed to, since we aren't changing where the type is actually allocated. */voidsmash_to_member_type (type, domain, to_type) struct type *type; struct type *domain; struct type *to_type;{ struct objfile *objfile; objfile = TYPE_OBJFILE (type); memset ((char *) type, 0, sizeof (struct type)); TYPE_OBJFILE (type) = objfile; TYPE_TARGET_TYPE (type) = to_type; TYPE_DOMAIN_TYPE (type) = domain; TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */ TYPE_CODE (type) = TYPE_CODE_MEMBER;}/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE. METHOD just means `function that gets an extra "this" argument'. When "smashing" the type, we preserve the objfile that the old type pointed to, since we aren't changing where the type is actually allocated. */voidsmash_to_method_type (type, domain, to_type, args) struct type *type; struct type *domain; struct type *to_type; struct type **args;{ struct objfile *objfile; objfile = TYPE_OBJFILE (type); memset ((char *) type, 0, sizeof (struct type)); TYPE_OBJFILE (type) = objfile; TYPE_TARGET_TYPE (type) = to_type; TYPE_DOMAIN_TYPE (type) = domain; TYPE_ARG_TYPES (type) = args; TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */ TYPE_CODE (type) = TYPE_CODE_METHOD;}/* Return a typename for a struct/union/enum type without the tag qualifier. If the type has a NULL name, NULL is returned. */char *type_name_no_tag (type) register const struct type *type;{ register char *name; if ((name = TYPE_NAME (type)) != NULL) { switch (TYPE_CODE (type)) { case TYPE_CODE_STRUCT: if(!strncmp (name, "struct ", 7)) { name += 7; } break; case TYPE_CODE_UNION: if(!strncmp (name, "union ", 6)) { name += 6; } break; case TYPE_CODE_ENUM: if(!strncmp (name, "enum ", 5)) { name += 5; } break; default: /* To avoid -Wall warnings */ break; } } return (name);}/* Lookup a primitive type named NAME. Return zero if NAME is not a primitive type.*/struct type *lookup_primitive_typename (name) char *name;{ struct type ** const *p; for (p = current_language -> la_builtin_type_vector; *p != NULL; p++) { if (!strcmp ((**p) -> name, name)) { return (**p); } } return (NULL); }/* Lookup a typedef or primitive type named NAME, visible in lexical block BLOCK. If NOERR is nonzero, return zero if NAME is not suitably defined. */struct type *lookup_typename (name, block, noerr) char *name; struct block *block; int noerr;{ register struct symbol *sym; register struct type *tmp; sym = lookup_symbol (name, block, VAR_NAMESPACE, 0, (struct symtab **) NULL); if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF) { tmp = lookup_primitive_typename (name); if (tmp) { return (tmp); } else if (!tmp && noerr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -