📄 prdbg.c
字号:
/* prdbg.c -- Print out generic debugging information.
Copyright 1995, 1996 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GNU Binutils.
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 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 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* This file prints out the generic debugging information, by
supplying a set of routines to debug_write. */
#include <stdio.h>
#include <assert.h>
#include <bfd.h>
#include "bucomm.h"
#include <libiberty.h>
#include "debug.h"
#include "budbg.h"
/* This is the structure we use as a handle for these routines. */
struct pr_handle
{
/* File to print information to. */
FILE *f;
/* Current indentation level. */
unsigned int indent;
/* Type stack. */
struct pr_stack *stack;
/* Parameter number we are about to output. */
int parameter;
};
/* The type stack. */
struct pr_stack
{
/* Next element on the stack. */
struct pr_stack *next;
/* This element. */
char *type;
/* Current visibility of fields if this is a class. */
enum debug_visibility visibility;
/* Name of the current method we are handling. */
const char *method;
};
static void indent PARAMS ((struct pr_handle *));
static bfd_boolean push_type PARAMS ((struct pr_handle *, const char *));
static bfd_boolean prepend_type PARAMS ((struct pr_handle *, const char *));
static bfd_boolean append_type PARAMS ((struct pr_handle *, const char *));
static bfd_boolean substitute_type PARAMS ((struct pr_handle *, const char *));
static bfd_boolean indent_type PARAMS ((struct pr_handle *));
static char *pop_type PARAMS ((struct pr_handle *));
static void print_vma PARAMS ((bfd_vma, char *, bfd_boolean, bfd_boolean));
static bfd_boolean pr_fix_visibility
PARAMS ((struct pr_handle *, enum debug_visibility));
static bfd_boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
static bfd_boolean pr_start_source PARAMS ((PTR, const char *));
static bfd_boolean pr_empty_type PARAMS ((PTR));
static bfd_boolean pr_void_type PARAMS ((PTR));
static bfd_boolean pr_int_type PARAMS ((PTR, unsigned int, bfd_boolean));
static bfd_boolean pr_float_type PARAMS ((PTR, unsigned int));
static bfd_boolean pr_complex_type PARAMS ((PTR, unsigned int));
static bfd_boolean pr_bool_type PARAMS ((PTR, unsigned int));
static bfd_boolean pr_enum_type
PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
static bfd_boolean pr_pointer_type PARAMS ((PTR));
static bfd_boolean pr_function_type PARAMS ((PTR, int, bfd_boolean));
static bfd_boolean pr_reference_type PARAMS ((PTR));
static bfd_boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
static bfd_boolean pr_array_type
PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, bfd_boolean));
static bfd_boolean pr_set_type PARAMS ((PTR, bfd_boolean));
static bfd_boolean pr_offset_type PARAMS ((PTR));
static bfd_boolean pr_method_type PARAMS ((PTR, bfd_boolean, int, bfd_boolean));
static bfd_boolean pr_const_type PARAMS ((PTR));
static bfd_boolean pr_volatile_type PARAMS ((PTR));
static bfd_boolean pr_start_struct_type
PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int));
static bfd_boolean pr_struct_field
PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
static bfd_boolean pr_end_struct_type PARAMS ((PTR));
static bfd_boolean pr_start_class_type
PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
bfd_boolean));
static bfd_boolean pr_class_static_member
PARAMS ((PTR, const char *, const char *, enum debug_visibility));
static bfd_boolean pr_class_baseclass
PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility));
static bfd_boolean pr_class_start_method PARAMS ((PTR, const char *));
static bfd_boolean pr_class_method_variant
PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
bfd_vma, bfd_boolean));
static bfd_boolean pr_class_static_method_variant
PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean));
static bfd_boolean pr_class_end_method PARAMS ((PTR));
static bfd_boolean pr_end_class_type PARAMS ((PTR));
static bfd_boolean pr_typedef_type PARAMS ((PTR, const char *));
static bfd_boolean pr_tag_type
PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
static bfd_boolean pr_typdef PARAMS ((PTR, const char *));
static bfd_boolean pr_tag PARAMS ((PTR, const char *));
static bfd_boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
static bfd_boolean pr_float_constant PARAMS ((PTR, const char *, double));
static bfd_boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma));
static bfd_boolean pr_variable
PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
static bfd_boolean pr_start_function PARAMS ((PTR, const char *, bfd_boolean));
static bfd_boolean pr_function_parameter
PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
static bfd_boolean pr_start_block PARAMS ((PTR, bfd_vma));
static bfd_boolean pr_end_block PARAMS ((PTR, bfd_vma));
static bfd_boolean pr_end_function PARAMS ((PTR));
static bfd_boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
static const struct debug_write_fns pr_fns =
{
pr_start_compilation_unit,
pr_start_source,
pr_empty_type,
pr_void_type,
pr_int_type,
pr_float_type,
pr_complex_type,
pr_bool_type,
pr_enum_type,
pr_pointer_type,
pr_function_type,
pr_reference_type,
pr_range_type,
pr_array_type,
pr_set_type,
pr_offset_type,
pr_method_type,
pr_const_type,
pr_volatile_type,
pr_start_struct_type,
pr_struct_field,
pr_end_struct_type,
pr_start_class_type,
pr_class_static_member,
pr_class_baseclass,
pr_class_start_method,
pr_class_method_variant,
pr_class_static_method_variant,
pr_class_end_method,
pr_end_class_type,
pr_typedef_type,
pr_tag_type,
pr_typdef,
pr_tag,
pr_int_constant,
pr_float_constant,
pr_typed_constant,
pr_variable,
pr_start_function,
pr_function_parameter,
pr_start_block,
pr_end_block,
pr_end_function,
pr_lineno
};
/* Print out the generic debugging information recorded in dhandle. */
bfd_boolean
print_debugging_info (f, dhandle)
FILE *f;
PTR dhandle;
{
struct pr_handle info;
info.f = f;
info.indent = 0;
info.stack = NULL;
info.parameter = 0;
return debug_write (dhandle, &pr_fns, (PTR) &info);
}
/* Indent to the current indentation level. */
static void
indent (info)
struct pr_handle *info;
{
unsigned int i;
for (i = 0; i < info->indent; i++)
putc (' ', info->f);
}
/* Push a type on the type stack. */
static bfd_boolean
push_type (info, type)
struct pr_handle *info;
const char *type;
{
struct pr_stack *n;
if (type == NULL)
return false;
n = (struct pr_stack *) xmalloc (sizeof *n);
memset (n, 0, sizeof *n);
n->type = xstrdup (type);
n->visibility = DEBUG_VISIBILITY_IGNORE;
n->method = NULL;
n->next = info->stack;
info->stack = n;
return true;
}
/* Prepend a string onto the type on the top of the type stack. */
static bfd_boolean
prepend_type (info, s)
struct pr_handle *info;
const char *s;
{
char *n;
assert (info->stack != NULL);
n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
sprintf (n, "%s%s", s, info->stack->type);
free (info->stack->type);
info->stack->type = n;
return true;
}
/* Append a string to the type on the top of the type stack. */
static bfd_boolean
append_type (info, s)
struct pr_handle *info;
const char *s;
{
unsigned int len;
if (s == NULL)
return false;
assert (info->stack != NULL);
len = strlen (info->stack->type);
info->stack->type = (char *) xrealloc (info->stack->type,
len + strlen (s) + 1);
strcpy (info->stack->type + len, s);
return true;
}
/* We use an underscore to indicate where the name should go in a type
string. This function substitutes a string for the underscore. If
there is no underscore, the name follows the type. */
static bfd_boolean
substitute_type (info, s)
struct pr_handle *info;
const char *s;
{
char *u;
assert (info->stack != NULL);
u = strchr (info->stack->type, '|');
if (u != NULL)
{
char *n;
n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
memcpy (n, info->stack->type, u - info->stack->type);
strcpy (n + (u - info->stack->type), s);
strcat (n, u + 1);
free (info->stack->type);
info->stack->type = n;
return true;
}
if (strchr (s, '|') != NULL
&& (strchr (info->stack->type, '{') != NULL
|| strchr (info->stack->type, '(') != NULL))
{
if (! prepend_type (info, "(")
|| ! append_type (info, ")"))
return false;
}
if (*s == '\0')
return true;
return (append_type (info, " ")
&& append_type (info, s));
}
/* Indent the type at the top of the stack by appending spaces. */
static bfd_boolean
indent_type (info)
struct pr_handle *info;
{
unsigned int i;
for (i = 0; i < info->indent; i++)
{
if (! append_type (info, " "))
return false;
}
return true;
}
/* Pop a type from the type stack. */
static char *
pop_type (info)
struct pr_handle *info;
{
struct pr_stack *o;
char *ret;
assert (info->stack != NULL);
o = info->stack;
info->stack = o->next;
ret = o->type;
free (o);
return ret;
}
/* Print a VMA value into a string. */
static void
print_vma (vma, buf, unsignedp, hexp)
bfd_vma vma;
char *buf;
bfd_boolean unsignedp;
bfd_boolean hexp;
{
if (sizeof (vma) <= sizeof (unsigned long))
{
if (hexp)
sprintf (buf, "0x%lx", (unsigned long) vma);
else if (unsignedp)
sprintf (buf, "%lu", (unsigned long) vma);
else
sprintf (buf, "%ld", (long) vma);
}
else
{
buf[0] = '0';
buf[1] = 'x';
sprintf_vma (buf + 2, vma);
}
}
/* Start a new compilation unit. */
static bfd_boolean
pr_start_compilation_unit (p, filename)
PTR p;
const char *filename;
{
struct pr_handle *info = (struct pr_handle *) p;
assert (info->indent == 0);
fprintf (info->f, "%s:\n", filename);
return true;
}
/* Start a source file within a compilation unit. */
static bfd_boolean
pr_start_source (p, filename)
PTR p;
const char *filename;
{
struct pr_handle *info = (struct pr_handle *) p;
assert (info->indent == 0);
fprintf (info->f, " %s:\n", filename);
return true;
}
/* Push an empty type onto the type stack. */
static bfd_boolean
pr_empty_type (p)
PTR p;
{
struct pr_handle *info = (struct pr_handle *) p;
return push_type (info, "<undefined>");
}
/* Push a void type onto the type stack. */
static bfd_boolean
pr_void_type (p)
PTR p;
{
struct pr_handle *info = (struct pr_handle *) p;
return push_type (info, "void");
}
/* Push an integer type onto the type stack. */
static bfd_boolean
pr_int_type (p, size, unsignedp)
PTR p;
unsigned int size;
bfd_boolean unsignedp;
{
struct pr_handle *info = (struct pr_handle *) p;
char ab[10];
sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
return push_type (info, ab);
}
/* Push a floating type onto the type stack. */
static bfd_boolean
pr_float_type (p, size)
PTR p;
unsigned int size;
{
struct pr_handle *info = (struct pr_handle *) p;
char ab[10];
if (size == 4)
return push_type (info, "float");
else if (size == 8)
return push_type (info, "double");
sprintf (ab, "float%d", size * 8);
return push_type (info, ab);
}
/* Push a complex type onto the type stack. */
static bfd_boolean
pr_complex_type (p, size)
PTR p;
unsigned int size;
{
struct pr_handle *info = (struct pr_handle *) p;
if (! pr_float_type (p, size))
return false;
return prepend_type (info, "complex ");
}
/* Push a bfd_boolean type onto the type stack. */
static bfd_boolean
pr_bool_type (p, size)
PTR p;
unsigned int size;
{
struct pr_handle *info = (struct pr_handle *) p;
char ab[10];
sprintf (ab, "bool%d", size * 8);
return push_type (info, ab);
}
/* Push an enum type onto the type stack. */
static bfd_boolean
pr_enum_type (p, tag, names, values)
PTR p;
const char *tag;
const char **names;
bfd_signed_vma *values;
{
struct pr_handle *info = (struct pr_handle *) p;
unsigned int i;
bfd_signed_vma val;
if (! push_type (info, "enum "))
return false;
if (tag != NULL)
{
if (! append_type (info, tag)
|| ! append_type (info, " "))
return false;
}
if (! append_type (info, "{ "))
return false;
if (names == NULL)
{
if (! append_type (info, "/* undefined */"))
return false;
}
else
{
val = 0;
for (i = 0; names[i] != NULL; i++)
{
if (i > 0)
{
if (! append_type (info, ", "))
return false;
}
if (! append_type (info, names[i]))
return false;
if (values[i] != val)
{
char ab[20];
print_vma (values[i], ab, false, false);
if (! append_type (info, " = ")
|| ! append_type (info, ab))
return false;
val = values[i];
}
++val;
}
}
return append_type (info, " }");
}
/* Turn the top type on the stack into a pointer. */
static bfd_boolean
pr_pointer_type (p)
PTR p;
{
struct pr_handle *info = (struct pr_handle *) p;
char *s;
assert (info->stack != NULL);
s = strchr (info->stack->type, '|');
if (s != NULL && s[1] == '[')
return substitute_type (info, "(*|)");
return substitute_type (info, "*|");
}
/* Turn the top type on the stack into a function returning that type. */
static bfd_boolean
pr_function_type (p, argcount, varargs)
PTR p;
int argcount;
bfd_boolean varargs;
{
struct pr_handle *info = (struct pr_handle *) p;
char **arg_types;
unsigned int len;
char *s;
assert (info->stack != NULL);
len = 10;
if (argcount <= 0)
{
arg_types = NULL;
len += 15;
}
else
{
int i;
arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
for (i = argcount - 1; i >= 0; i--)
{
if (! substitute_type (info, ""))
return false;
arg_types[i] = pop_type (info);
if (arg_types[i] == NULL)
return false;
len += strlen (arg_types[i]) + 2;
}
if (varargs)
len += 5;
}
/* Now the return type is on the top of the stack. */
s = (char *) xmalloc (len);
strcpy (s, "(|) (");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -