Implement generic debugging support. Implement a stabs reader and
a generic printer. * budbg.h, debug.c, debug.h, prdbg.c, rddbg.c, stabs.c: New files. * objdump.c: Include "debug.h" and "budbg.h". (dump_debugging): New global variable. (usage): Mention --debugging. (long_options): Add "debugging". (display_bfd): Handle --debugging. * Makefile.in (OBJDUMP_OBJS): New variable. ($(OBJDUMP_PROG)): Use $(OBJDUMP_OBJS). * binutils.texi, objdump.1: Document --debugging.
This commit is contained in:
parent
cd46af111e
commit
e1c145993e
|
@ -40,6 +40,7 @@ arsup.h
|
|||
binutils.texi
|
||||
bucomm.c
|
||||
bucomm.h
|
||||
budbg.h
|
||||
coffdump.c
|
||||
coffgrok.c
|
||||
coffgrok.h
|
||||
|
@ -49,6 +50,9 @@ configure.bat
|
|||
configure.in
|
||||
cxxfilt.man
|
||||
dlltool.c
|
||||
debug.c
|
||||
debug.h
|
||||
dep-in.sed
|
||||
defparse.y
|
||||
deflex.l
|
||||
filemode.c
|
||||
|
@ -72,12 +76,15 @@ objcopy.1
|
|||
objcopy.c
|
||||
objdump.1
|
||||
objdump.c
|
||||
prdbg.c
|
||||
ranlib.1
|
||||
ranlib.sh
|
||||
rddbg.c
|
||||
sanity.sh
|
||||
size.1
|
||||
size.c
|
||||
srconv.c
|
||||
stabs.c
|
||||
strings.1
|
||||
strings.c
|
||||
strip.1
|
||||
|
|
|
@ -955,7 +955,7 @@ Show a summary of the options to @code{objcopy}.
|
|||
|
||||
@smallexample
|
||||
objdump [ -a | --archive-headers ]
|
||||
[ -b @var{bfdname} | --target=@var{bfdname} ]
|
||||
[ -b @var{bfdname} | --target=@var{bfdname} ] [ --debugging ]
|
||||
[ -d | --disassemble ] [ -D | --disassemble-all ]
|
||||
[ -f | --file-headers ]
|
||||
[ -h | --section-headers | --headers ] [ -i | --info ]
|
||||
|
@ -1010,6 +1010,11 @@ file in the format produced by Oasys compilers. You can list the
|
|||
formats available with the @samp{-i} option.
|
||||
@xref{Target Selection}, for more information.
|
||||
|
||||
@item --debugging
|
||||
Display debugging information. This attempts to parse debugging
|
||||
information stored in the file and print it out using a C like syntax.
|
||||
Only certain types of debugging information have been implemented.
|
||||
|
||||
@item -d
|
||||
@itemx --disassemble
|
||||
@cindex disassembling object code
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* budbg.c -- Interfaces to the generic debugging information routines.
|
||||
Copyright (C) 1995 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. */
|
||||
|
||||
#ifndef BUDBG_H
|
||||
#define BUDBG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Routine used to read generic debugging information. */
|
||||
|
||||
extern PTR read_debugging_info PARAMS ((bfd *));
|
||||
|
||||
/* Routine used to print generic debugging information. */
|
||||
|
||||
extern boolean print_debugging_info PARAMS ((FILE *, PTR));
|
||||
|
||||
/* Routines used to read stabs information. */
|
||||
|
||||
extern PTR start_stab PARAMS ((PTR));
|
||||
|
||||
extern boolean finish_stab PARAMS ((PTR, PTR));
|
||||
|
||||
extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *));
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,701 @@
|
|||
/* debug.h -- Describe generic debugging information.
|
||||
Copyright (C) 1995 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. */
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
/* This header file describes a generic debugging information format.
|
||||
We may eventually have readers which convert different formats into
|
||||
this generic format, and writers which write it out. The initial
|
||||
impetus for this was writing a convertor from stabs to HP IEEE-695
|
||||
debugging format. */
|
||||
|
||||
/* Different kinds of types. */
|
||||
|
||||
enum debug_type_kind
|
||||
{
|
||||
/* Indirect via a pointer. */
|
||||
DEBUG_KIND_INDIRECT,
|
||||
/* Void. */
|
||||
DEBUG_KIND_VOID,
|
||||
/* Integer. */
|
||||
DEBUG_KIND_INT,
|
||||
/* Floating point. */
|
||||
DEBUG_KIND_FLOAT,
|
||||
/* Complex. */
|
||||
DEBUG_KIND_COMPLEX,
|
||||
/* Boolean. */
|
||||
DEBUG_KIND_BOOL,
|
||||
/* Struct. */
|
||||
DEBUG_KIND_STRUCT,
|
||||
/* Union. */
|
||||
DEBUG_KIND_UNION,
|
||||
/* Class. */
|
||||
DEBUG_KIND_CLASS,
|
||||
/* Union class (can this really happen?). */
|
||||
DEBUG_KIND_UNION_CLASS,
|
||||
/* Enumeration type. */
|
||||
DEBUG_KIND_ENUM,
|
||||
/* Pointer. */
|
||||
DEBUG_KIND_POINTER,
|
||||
/* Function. */
|
||||
DEBUG_KIND_FUNCTION,
|
||||
/* Reference. */
|
||||
DEBUG_KIND_REFERENCE,
|
||||
/* Range. */
|
||||
DEBUG_KIND_RANGE,
|
||||
/* Array. */
|
||||
DEBUG_KIND_ARRAY,
|
||||
/* Set. */
|
||||
DEBUG_KIND_SET,
|
||||
/* Based pointer. */
|
||||
DEBUG_KIND_OFFSET,
|
||||
/* Method. */
|
||||
DEBUG_KIND_METHOD,
|
||||
/* Const qualified type. */
|
||||
DEBUG_KIND_CONST,
|
||||
/* Volatile qualified type. */
|
||||
DEBUG_KIND_VOLATILE,
|
||||
/* Named type. */
|
||||
DEBUG_KIND_NAMED,
|
||||
/* Tagged type. */
|
||||
DEBUG_KIND_TAGGED
|
||||
};
|
||||
|
||||
/* Different kinds of variables. */
|
||||
|
||||
enum debug_var_kind
|
||||
{
|
||||
/* A global variable. */
|
||||
DEBUG_GLOBAL,
|
||||
/* A static variable. */
|
||||
DEBUG_STATIC,
|
||||
/* A local static variable. */
|
||||
DEBUG_LOCAL_STATIC,
|
||||
/* A local variable. */
|
||||
DEBUG_LOCAL,
|
||||
/* A register variable. */
|
||||
DEBUG_REGISTER
|
||||
};
|
||||
|
||||
/* Different kinds of function parameters. */
|
||||
|
||||
enum debug_parm_kind
|
||||
{
|
||||
/* A stack based parameter. */
|
||||
DEBUG_PARM_STACK,
|
||||
/* A register parameter. */
|
||||
DEBUG_PARM_REG,
|
||||
/* A stack based reference parameter. */
|
||||
DEBUG_PARM_REFERENCE,
|
||||
/* A register reference parameter. */
|
||||
DEBUG_PARM_REF_REG
|
||||
};
|
||||
|
||||
/* Different kinds of visibility. */
|
||||
|
||||
enum debug_visibility
|
||||
{
|
||||
/* A public field (e.g., a field in a C struct). */
|
||||
DEBUG_VISIBILITY_PUBLIC,
|
||||
/* A protected field. */
|
||||
DEBUG_VISIBILITY_PROTECTED,
|
||||
/* A private field. */
|
||||
DEBUG_VISIBILITY_PRIVATE,
|
||||
/* A field which should be ignored. */
|
||||
DEBUG_VISIBILITY_IGNORE
|
||||
};
|
||||
|
||||
/* A type. */
|
||||
|
||||
typedef struct debug_type *debug_type;
|
||||
|
||||
#define DEBUG_TYPE_NULL ((debug_type) NULL)
|
||||
|
||||
/* A field in a struct or union. */
|
||||
|
||||
typedef struct debug_field *debug_field;
|
||||
|
||||
#define DEBUG_FIELD_NULL ((debug_field) NULL)
|
||||
|
||||
/* A base class for an object. */
|
||||
|
||||
typedef struct debug_baseclass *debug_baseclass;
|
||||
|
||||
#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL)
|
||||
|
||||
/* A method of an object. */
|
||||
|
||||
typedef struct debug_method *debug_method;
|
||||
|
||||
#define DEBUG_METHOD_NULL ((debug_method) NULL)
|
||||
|
||||
/* The arguments to a method function of an object. These indicate
|
||||
which method to run. */
|
||||
|
||||
typedef struct debug_method_variant *debug_method_variant;
|
||||
|
||||
#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL)
|
||||
|
||||
/* This structure is passed to debug_write. It holds function
|
||||
pointers that debug_write will call based on the accumulated
|
||||
debugging information. */
|
||||
|
||||
struct debug_write_fns
|
||||
{
|
||||
/* This is called at the start of each new compilation unit with the
|
||||
name of the main file in the new unit. */
|
||||
boolean (*start_compilation_unit) PARAMS ((PTR, const char *));
|
||||
|
||||
/* This is called at the start of each source file within a
|
||||
compilation unit, before outputting any global information for
|
||||
that file. The argument is the name of the file. */
|
||||
boolean (*start_source) PARAMS ((PTR, const char *));
|
||||
|
||||
/* Each writer must keep a stack of types. */
|
||||
|
||||
/* Push an empty type onto the type stack. This type can appear if
|
||||
there is a reference to a type which is never defined. */
|
||||
boolean (*empty_type) PARAMS ((PTR));
|
||||
|
||||
/* Push a void type onto the type stack. */
|
||||
boolean (*void_type) PARAMS ((PTR));
|
||||
|
||||
/* Push an integer type onto the type stack, given the size and
|
||||
whether it is unsigned. */
|
||||
boolean (*int_type) PARAMS ((PTR, unsigned int, boolean));
|
||||
|
||||
/* Push a floating type onto the type stack, given the size. */
|
||||
boolean (*float_type) PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Push a complex type onto the type stack, given the size. */
|
||||
boolean (*complex_type) PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Push a boolean type onto the type stack, given the size. */
|
||||
boolean (*bool_type) PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Push an enum type onto the type stack, given a NULL terminated
|
||||
array of names and the associated values. */
|
||||
boolean (*enum_type) PARAMS ((PTR, const char **, bfd_signed_vma *));
|
||||
|
||||
/* Pop the top type on the type stack, and push a pointer to that
|
||||
type onto the type stack. */
|
||||
boolean (*pointer_type) PARAMS ((PTR));
|
||||
|
||||
/* Pop the top type on the type stack, and push a function returning
|
||||
that type onto the type stack. */
|
||||
boolean (*function_type) PARAMS ((PTR));
|
||||
|
||||
/* Pop the top type on the type stack, and push a reference to that
|
||||
type onto the type stack. */
|
||||
boolean (*reference_type) PARAMS ((PTR));
|
||||
|
||||
/* Pop the top type on the type stack, and push a range of that type
|
||||
with the given lower and upper bounds onto the type stack. */
|
||||
boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
|
||||
|
||||
/* Push an array type onto the type stack. The top type on the type
|
||||
stack is the range, and the next type on the type stack is the
|
||||
element type. These should be popped before the array type is
|
||||
pushed. The arguments are the lower bound, the upper bound, and
|
||||
whether the array is a string. */
|
||||
boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma,
|
||||
boolean));
|
||||
|
||||
/* Pop the top type on the type stack, and push a set of that type
|
||||
onto the type stack. The argument indicates whether this set is
|
||||
a bitstring. */
|
||||
boolean (*set_type) PARAMS ((PTR, boolean));
|
||||
|
||||
/* Push an offset type onto the type stack. The top type on the
|
||||
type stack is the target type, and the next type on the type
|
||||
stack is the base type. These should be popped before the offset
|
||||
type is pushed. */
|
||||
boolean (*offset_type) PARAMS ((PTR));
|
||||
|
||||
/* Push a method type onto the type stack. If the second argument
|
||||
is true, the top type on the stack is the class to which the
|
||||
method belongs; otherwise, the class must be determined by the
|
||||
class to which the method is attached. The third argument is the
|
||||
number of argument types; these are pushed onto the type stack in
|
||||
reverse order (the first type popped is the last argument to the
|
||||
method). An argument type of -1 means that no argument in
|
||||
formation is available. The next type on the type stack below
|
||||
the domain and the argument types is the return type of the
|
||||
method. All these types must be poppsed, and then the method
|
||||
type must be pushed. */
|
||||
boolean (*method_type) PARAMS ((PTR, boolean, int));
|
||||
|
||||
/* Pop the top type off the type stack, and push a const qualified
|
||||
version of that type onto the type stack. */
|
||||
boolean (*const_type) PARAMS ((PTR));
|
||||
|
||||
/* Pop the top type off the type stack, and push a volatile
|
||||
qualified version of that type onto the type stack. */
|
||||
boolean (*volatile_type) PARAMS ((PTR));
|
||||
|
||||
/* Start building a struct. This is followed by calls to the
|
||||
struct_field function, and finished by a call to the
|
||||
end_struct_type function. The boolean argument is true for a
|
||||
struct, false for a union. The unsigned int argument is the
|
||||
size. */
|
||||
boolean (*start_struct_type) PARAMS ((PTR, boolean, unsigned int));
|
||||
|
||||
/* Add a field to the struct type currently being built. The type
|
||||
of the field should be popped off the type stack. The arguments
|
||||
are the name, the bit position, the bit size (may be zero if the
|
||||
field is not packed), and the visibility. */
|
||||
boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma,
|
||||
enum debug_visibility));
|
||||
|
||||
/* Finish building a struct, and push it onto the type stack. */
|
||||
boolean (*end_struct_type) PARAMS ((PTR));
|
||||
|
||||
/* Start building a class. This is followed by calls to several
|
||||
functions: struct_field, class_static_member, class_baseclass,
|
||||
class_start_method, class_method_variant,
|
||||
class_static_method_variant, and class_end_method. The class is
|
||||
finished by a call to end_class_type. The boolean argument is
|
||||
true for a struct, false for a union. The next argument is the
|
||||
size. The next argument is true if there is a virtual function
|
||||
table; if there is, the next argument is true if the virtual
|
||||
function table can be found in the type itself, and is false if
|
||||
the type of the object holding the virtual function table should
|
||||
be popped from the type stack. */
|
||||
boolean (*start_class_type) PARAMS ((PTR, boolean, unsigned int,
|
||||
boolean, boolean));
|
||||
|
||||
/* Add a static member to the class currently being built. The
|
||||
arguments are the field name, the physical name, and the
|
||||
visibility. */
|
||||
boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
|
||||
enum debug_visibility));
|
||||
|
||||
/* Add a baseclass to the class currently being built. The type of
|
||||
the baseclass must be popped off the type stack. The arguments
|
||||
are the bit position, whether the class is virtual, and the
|
||||
visibility. */
|
||||
boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean,
|
||||
enum debug_visibility));
|
||||
|
||||
/* Start adding a method to the class currently being built. This
|
||||
is followed by calls to class_method_variant and
|
||||
class_static_method_variant to describe different variants of the
|
||||
method which take different arguments. The method is finished
|
||||
with a call to class_end_method. The argument is the method
|
||||
name. */
|
||||
boolean (*class_start_method) PARAMS ((PTR, const char *));
|
||||
|
||||
/* Describe a variant to the class method currently being built.
|
||||
The type of the variant must be popped off the type stack. The
|
||||
second argument is a string which is either the physical name of
|
||||
the function or describes the argument types; see the comment for
|
||||
debug_make_method variant. The following arguments are the
|
||||
visibility, whether the variant is const, whether the variant is
|
||||
volatile, the offset in the virtual function table, and whether
|
||||
the context is on the type stack (below the variant type). */
|
||||
boolean (*class_method_variant) PARAMS ((PTR, const char *,
|
||||
enum debug_visibility,
|
||||
boolean, boolean,
|
||||
bfd_vma, boolean));
|
||||
|
||||
/* Describe a static variant to the class method currently being
|
||||
built. The arguments are the same as for class_method_variant,
|
||||
except that the last two arguments are omitted. */
|
||||
boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
|
||||
enum debug_visibility,
|
||||
boolean, boolean));
|
||||
|
||||
/* Finish describing a class method. */
|
||||
boolean (*class_end_method) PARAMS ((PTR));
|
||||
|
||||
/* Finish describing a class, and push it onto the type stack. */
|
||||
boolean (*end_class_type) PARAMS ((PTR));
|
||||
|
||||
/* Push a type on the stack which was given a name by an earlier
|
||||
call to typdef. */
|
||||
boolean (*typedef_type) PARAMS ((PTR, const char *));
|
||||
|
||||
/* Push a type on the stack which was given a name by an earlier
|
||||
call to tag. */
|
||||
boolean (*tag_type) PARAMS ((PTR, const char *, enum debug_type_kind));
|
||||
|
||||
/* Pop the type stack, and typedef it to the given name. */
|
||||
boolean (*typdef) PARAMS ((PTR, const char *));
|
||||
|
||||
/* Pop the type stack, and declare it as a tagged struct or union or
|
||||
enum or whatever. */
|
||||
boolean (*tag) PARAMS ((PTR, const char *));
|
||||
|
||||
/* This is called to record a named integer constant. */
|
||||
boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma));
|
||||
|
||||
/* This is called to record a named floating point constant. */
|
||||
boolean (*float_constant) PARAMS ((PTR, const char *, double));
|
||||
|
||||
/* This is called to record a typed integer constant. The type is
|
||||
popped off the type stack. */
|
||||
boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma));
|
||||
|
||||
/* This is called to record a variable. The type is popped off the
|
||||
type stack. */
|
||||
boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind,
|
||||
bfd_vma));
|
||||
|
||||
/* Start writing out a function. The return type must be popped off
|
||||
the stack. The boolean is true if the function is global. This
|
||||
is followed by calls to function_parameter, followed by block
|
||||
information. */
|
||||
boolean (*start_function) PARAMS ((PTR, const char *, boolean));
|
||||
|
||||
/* Record a function parameter for the current function. The type
|
||||
must be popped off the stack. */
|
||||
boolean (*function_parameter) PARAMS ((PTR, const char *,
|
||||
enum debug_parm_kind, bfd_vma));
|
||||
|
||||
/* Start writing out a block. There is at least one top level block
|
||||
per function. Blocks may be nested. The argument is the
|
||||
starting address of the block. */
|
||||
boolean (*start_block) PARAMS ((PTR, bfd_vma));
|
||||
|
||||
/* Record line number information for the current block. */
|
||||
boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
|
||||
|
||||
/* Finish writing out a block. The argument is the ending address
|
||||
of the block. */
|
||||
boolean (*end_block) PARAMS ((PTR, bfd_vma));
|
||||
|
||||
/* Finish writing out a function. */
|
||||
boolean (*end_function) PARAMS ((PTR));
|
||||
};
|
||||
|
||||
/* Exported functions. */
|
||||
|
||||
/* The first argument to most of these functions is a handle. This
|
||||
handle is returned by the debug_init function. The purpose of the
|
||||
handle is to permit the debugging routines to not use static
|
||||
variables, and hence to be reentrant. This would be useful for a
|
||||
program which wanted to handle two executables simultaneously. */
|
||||
|
||||
/* Return a debugging handle. */
|
||||
|
||||
extern PTR debug_init PARAMS ((void));
|
||||
|
||||
/* Set the source filename. This implicitly starts a new compilation
|
||||
unit. */
|
||||
|
||||
extern boolean debug_set_filename PARAMS ((PTR, const char *));
|
||||
|
||||
/* Append a string to the source filename. */
|
||||
|
||||
extern boolean debug_append_filename PARAMS ((PTR, const char *));
|
||||
|
||||
/* Change source files to the given file name. This is used for
|
||||
include files in a single compilation unit. */
|
||||
|
||||
extern boolean debug_start_source PARAMS ((PTR, const char *));
|
||||
|
||||
/* Record a function definition. This implicitly starts a function
|
||||
block. The debug_type argument is the type of the return value.
|
||||
The boolean indicates whether the function is globally visible.
|
||||
The bfd_vma is the address of the start of the function. Currently
|
||||
the parameter types are specified by calls to
|
||||
debug_record_parameter. */
|
||||
|
||||
extern boolean debug_record_function
|
||||
PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma));
|
||||
|
||||
/* Record a parameter for the current function. */
|
||||
|
||||
extern boolean debug_record_parameter
|
||||
PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma));
|
||||
|
||||
/* End a function definition. The argument is the address where the
|
||||
function ends. */
|
||||
|
||||
extern boolean debug_end_function PARAMS ((PTR, bfd_vma));
|
||||
|
||||
/* Start a block in a function. All local information will be
|
||||
recorded in this block, until the matching call to debug_end_block.
|
||||
debug_start_block and debug_end_block may be nested. The argument
|
||||
is the address at which this block starts. */
|
||||
|
||||
extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
|
||||
|
||||
/* Finish a block in a function. This matches the call to
|
||||
debug_start_block. The argument is the address at which this block
|
||||
ends. */
|
||||
|
||||
extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
|
||||
|
||||
/* Associate a line number in the current source file and function
|
||||
with a given address. */
|
||||
|
||||
extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
|
||||
|
||||
/* Start a named common block. This is a block of variables that may
|
||||
move in memory. */
|
||||
|
||||
extern boolean debug_start_common_block PARAMS ((PTR, const char *));
|
||||
|
||||
/* End a named common block. */
|
||||
|
||||
extern boolean debug_end_common_block PARAMS ((PTR, const char *));
|
||||
|
||||
/* Record a named integer constant. */
|
||||
|
||||
extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma));
|
||||
|
||||
/* Record a named floating point constant. */
|
||||
|
||||
extern boolean debug_record_float_const PARAMS ((PTR, const char *, double));
|
||||
|
||||
/* Record a typed constant with an integral value. */
|
||||
|
||||
extern boolean debug_record_typed_const
|
||||
PARAMS ((PTR, const char *, debug_type, bfd_vma));
|
||||
|
||||
/* Record a label. */
|
||||
|
||||
extern boolean debug_record_label
|
||||
PARAMS ((PTR, const char *, debug_type, bfd_vma));
|
||||
|
||||
/* Record a variable. */
|
||||
|
||||
extern boolean debug_record_variable
|
||||
PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma));
|
||||
|
||||
/* Make an indirect type. The first argument is a pointer to the
|
||||
location where the real type will be placed. The second argument
|
||||
is the type tag, if there is one; this may be NULL; the only
|
||||
purpose of this argument is so that debug_get_type_name can return
|
||||
something useful. This function may be used when a type is
|
||||
referenced before it is defined. */
|
||||
|
||||
extern debug_type debug_make_indirect_type
|
||||
PARAMS ((PTR, debug_type *, const char *));
|
||||
|
||||
/* Make a void type. */
|
||||
|
||||
extern debug_type debug_make_void_type PARAMS ((PTR));
|
||||
|
||||
/* Make an integer type of a given size. The boolean argument is true
|
||||
if the integer is unsigned. */
|
||||
|
||||
extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean));
|
||||
|
||||
/* Make a floating point type of a given size. FIXME: On some
|
||||
platforms, like an Alpha, you probably need to be able to specify
|
||||
the format. */
|
||||
|
||||
extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Make a boolean type of a given size. */
|
||||
|
||||
extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Make a complex type of a given size. */
|
||||
|
||||
extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int));
|
||||
|
||||
/* Make a structure type. The second argument is true for a struct,
|
||||
false for a union. The third argument is the size of the struct.
|
||||
The fourth argument is a NULL terminated array of fields. */
|
||||
|
||||
extern debug_type debug_make_struct_type
|
||||
PARAMS ((PTR, boolean, bfd_vma, debug_field *));
|
||||
|
||||
/* Make an object type. The first three arguments after the handle
|
||||
are the same as for debug_make_struct_type. The next arguments are
|
||||
a NULL terminated array of base classes, a NULL terminated array of
|
||||
methods, the type of the object holding the virtual function table
|
||||
if it is not this object, and a boolean which is true if this
|
||||
object has its own virtual function table. */
|
||||
|
||||
extern debug_type debug_make_object_type
|
||||
PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *,
|
||||
debug_method *, debug_type, boolean));
|
||||
|
||||
/* Make an enumeration type. The arguments are a null terminated
|
||||
array of strings, and an array of corresponding values. */
|
||||
|
||||
extern debug_type debug_make_enum_type
|
||||
PARAMS ((PTR, const char **, bfd_signed_vma *));
|
||||
|
||||
/* Make a pointer to a given type. */
|
||||
|
||||
extern debug_type debug_make_pointer_type
|
||||
PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Make a function returning a given type. FIXME: We should be able
|
||||
to record the parameter types. */
|
||||
|
||||
extern debug_type debug_make_function_type PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Make a reference to a given type. */
|
||||
|
||||
extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Make a range of a given type from a lower to an upper bound. */
|
||||
|
||||
extern debug_type debug_make_range_type
|
||||
PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma));
|
||||
|
||||
/* Make an array type. The second argument is the type of an element
|
||||
of the array. The third argument is the type of a range of the
|
||||
array. The fourth and fifth argument are the lower and upper
|
||||
bounds, respectively (if the bounds are not known, lower should be
|
||||
0 and upper should be -1). The sixth argument is true if this
|
||||
array is actually a string, as in C. */
|
||||
|
||||
extern debug_type debug_make_array_type
|
||||
PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma,
|
||||
boolean));
|
||||
|
||||
/* Make a set of a given type. For example, a Pascal set type. The
|
||||
boolean argument is true if this set is actually a bitstring, as in
|
||||
CHILL. */
|
||||
|
||||
extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean));
|
||||
|
||||
/* Make a type for a pointer which is relative to an object. The
|
||||
second argument is the type of the object to which the pointer is
|
||||
relative. The third argument is the type that the pointer points
|
||||
to. */
|
||||
|
||||
extern debug_type debug_make_offset_type
|
||||
PARAMS ((PTR, debug_type, debug_type));
|
||||
|
||||
/* Make a type for a method function. The second argument is the
|
||||
return type, the third argument is the domain, and the fourth
|
||||
argument is a NULL terminated array of argument types. The domain
|
||||
and the argument array may be NULL, in which case this is a stub
|
||||
method and that information is not available. Stabs debugging uses
|
||||
this, and gets the argument types from the mangled name. */
|
||||
|
||||
extern debug_type debug_make_method_type
|
||||
PARAMS ((PTR, debug_type, debug_type, debug_type *));
|
||||
|
||||
/* Make a const qualified version of a given type. */
|
||||
|
||||
extern debug_type debug_make_const_type PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Make a volatile qualified version of a given type. */
|
||||
|
||||
extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Make an undefined tagged type. For example, a struct which has
|
||||
been mentioned, but not defined. */
|
||||
|
||||
extern debug_type debug_make_undefined_tagged_type
|
||||
PARAMS ((PTR, const char *, enum debug_type_kind));
|
||||
|
||||
/* Make a base class for an object. The second argument is the base
|
||||
class type. The third argument is the bit position of this base
|
||||
class in the object (always 0 unless doing multiple inheritance).
|
||||
The fourth argument is whether this is a virtual class. The fifth
|
||||
argument is the visibility of the base class. */
|
||||
|
||||
extern debug_baseclass debug_make_baseclass
|
||||
PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility));
|
||||
|
||||
/* Make a field for a struct. The second argument is the name. The
|
||||
third argument is the type of the field. The fourth argument is
|
||||
the bit position of the field. The fifth argument is the size of
|
||||
the field (it may be zero). The sixth argument is the visibility
|
||||
of the field. */
|
||||
|
||||
extern debug_field debug_make_field
|
||||
PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma,
|
||||
enum debug_visibility));
|
||||
|
||||
/* Make a static member of an object. The second argument is the
|
||||
name. The third argument is the type of the member. The fourth
|
||||
argument is the physical name of the member (i.e., the name as a
|
||||
global variable). The fifth argument is the visibility of the
|
||||
member. */
|
||||
|
||||
extern debug_field debug_make_static_member
|
||||
PARAMS ((PTR, const char *, debug_type, const char *,
|
||||
enum debug_visibility));
|
||||
|
||||
/* Make a method. The second argument is the name, and the third
|
||||
argument is a NULL terminated array of method variants. Each
|
||||
method variant is a method with this name but with different
|
||||
argument types. */
|
||||
|
||||
extern debug_method debug_make_method
|
||||
PARAMS ((PTR, const char *, debug_method_variant *));
|
||||
|
||||
/* Make a method variant. The second argument is either the physical
|
||||
name of the function, or the encoded argument types, depending upon
|
||||
whether the third argument specifies the argument types or not.
|
||||
The third argument is the type of the function. The fourth
|
||||
argument is the visibility. The fifth argument is whether this is
|
||||
a const function. The sixth argument is whether this is a volatile
|
||||
function. The seventh argument is the offset in the virtual
|
||||
function table, if any. The eighth argument is the virtual
|
||||
function context. FIXME: Are the const and volatile arguments
|
||||
necessary? Could we just use debug_make_const_type? The handling
|
||||
of the second argument is biased toward the way that stabs works. */
|
||||
|
||||
extern debug_method_variant debug_make_method_variant
|
||||
PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
|
||||
boolean, bfd_vma, debug_type));
|
||||
|
||||
/* Make a static method argument. The arguments are the same as for
|
||||
debug_make_method_variant, except that the last two are omitted
|
||||
since a static method can not also be virtual. */
|
||||
|
||||
extern debug_method_variant debug_make_static_method_variant
|
||||
PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
|
||||
boolean));
|
||||
|
||||
/* Name a type. This returns a new type with an attached name. */
|
||||
|
||||
extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type));
|
||||
|
||||
/* Give a tag to a type, such as a struct or union. This returns a
|
||||
new type with an attached tag. */
|
||||
|
||||
extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type));
|
||||
|
||||
/* Record the size of a given type. */
|
||||
|
||||
extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int));
|
||||
|
||||
/* Find a tagged type. */
|
||||
|
||||
extern debug_type debug_find_tagged_type
|
||||
PARAMS ((PTR, const char *, enum debug_type_kind));
|
||||
|
||||
/* Get the name of a type. */
|
||||
|
||||
extern const char *debug_get_type_name PARAMS ((PTR, debug_type));
|
||||
|
||||
/* Write out the recorded debugging information. This takes a set of
|
||||
function pointers which are called to do the actual writing. The
|
||||
first PTR is the debugging handle. The second PTR is a handle
|
||||
which is passed to the functions. */
|
||||
|
||||
extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR));
|
||||
|
||||
#endif /* DEBUG_H */
|
|
@ -21,6 +21,7 @@ objdump \- display information from object files.
|
|||
.RB " | " "\-\-target="\c
|
||||
.I bfdname\c
|
||||
\&\|]
|
||||
.RB "[\|" \-\-debugging "\|]"
|
||||
.RB "[\|" \-d | \-\-disassemble "\|]"
|
||||
.RB "[\|" \-D | \-\-disassemble-all "\|]"
|
||||
.RB "[\|" \-f | \-\-file\-headers "\|]"
|
||||
|
@ -125,6 +126,12 @@ formats available with the `\|\c
|
|||
.B \-i\c
|
||||
\|' option.
|
||||
|
||||
.TP
|
||||
.B \-\-debugging
|
||||
Display debugging information. This attempts to parse debugging
|
||||
information stored in the file and print it out using a C like syntax.
|
||||
Only certain types of debugging information have been implemented.
|
||||
|
||||
.TP
|
||||
.B \-d
|
||||
.TP
|
||||
|
|
|
@ -21,11 +21,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
#include "getopt.h"
|
||||
#include "progress.h"
|
||||
#include "bucomm.h"
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "dis-asm.h"
|
||||
#include "libiberty.h"
|
||||
#include "debug.h"
|
||||
#include "budbg.h"
|
||||
|
||||
/* Internal headers for the ELF .stab-dump code - sorry. */
|
||||
#define BYTES_IN_WORD 32
|
||||
|
@ -60,6 +60,7 @@ char *only; /* -j secname */
|
|||
int wide_output; /* -w */
|
||||
bfd_vma start_address = (bfd_vma) -1; /* --start-address */
|
||||
bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
|
||||
int dump_debugging; /* --debugging */
|
||||
|
||||
/* Extra info to pass to the disassembler address printing function. */
|
||||
struct objdump_disasm_info {
|
||||
|
@ -120,6 +121,9 @@ objdump_print_address PARAMS ((bfd_vma, struct disassemble_info *));
|
|||
|
||||
static void
|
||||
show_line PARAMS ((bfd *, asection *, bfd_vma));
|
||||
|
||||
static const char *
|
||||
endian_string PARAMS ((enum bfd_endian));
|
||||
|
||||
void
|
||||
usage (stream, status)
|
||||
|
@ -128,7 +132,7 @@ usage (stream, status)
|
|||
{
|
||||
fprintf (stream, "\
|
||||
Usage: %s [-ahifdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\
|
||||
[--archive-headers] [--target=bfdname] [--disassemble]\n\
|
||||
[--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n\
|
||||
[--disassemble-all] [--file-headers] [--section-headers] [--headers]\n\
|
||||
[--info] [--section=section-name] [--line-numbers] [--source]\n",
|
||||
program_name);
|
||||
|
@ -153,6 +157,7 @@ static struct option long_options[]=
|
|||
{"private-headers", no_argument, NULL, 'p'},
|
||||
{"architecture", required_argument, NULL, 'm'},
|
||||
{"archive-headers", no_argument, NULL, 'a'},
|
||||
{"debugging", no_argument, &dump_debugging, 1},
|
||||
{"disassemble", no_argument, NULL, 'd'},
|
||||
{"disassemble-all", no_argument, NULL, 'D'},
|
||||
{"dynamic-reloc", no_argument, NULL, 'R'},
|
||||
|
@ -321,7 +326,7 @@ remove_useless_symbols (symbols, count)
|
|||
return out_ptr - symbols;
|
||||
}
|
||||
|
||||
/* Sort symbols into value order. */
|
||||
/* Sort symbols into value order. */
|
||||
|
||||
static int
|
||||
compare_symbols (ap, bp)
|
||||
|
@ -333,6 +338,7 @@ compare_symbols (ap, bp)
|
|||
const char *an, *bn;
|
||||
size_t anl, bnl;
|
||||
boolean af, bf;
|
||||
flagword aflags, bflags;
|
||||
|
||||
if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
|
||||
return 1;
|
||||
|
@ -381,6 +387,27 @@ compare_symbols (ap, bp)
|
|||
if (! af && bf)
|
||||
return -1;
|
||||
|
||||
/* Finally, try to sort global symbols before local symbols before
|
||||
debugging symbols. */
|
||||
|
||||
aflags = a->flags;
|
||||
bflags = b->flags;
|
||||
|
||||
if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING))
|
||||
{
|
||||
if ((aflags & BSF_DEBUGGING) != 0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL))
|
||||
{
|
||||
if ((aflags & BSF_LOCAL) != 0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -432,9 +459,6 @@ objdump_print_address (vma, info)
|
|||
bfd_vma vma;
|
||||
struct disassemble_info *info;
|
||||
{
|
||||
/* @@ For relocateable files, should filter out symbols belonging to
|
||||
the wrong section. Unfortunately, not enough information is supplied
|
||||
to this routine to determine the correct section in all cases. */
|
||||
/* @@ Would it speed things up to cache the last two symbols returned,
|
||||
and maybe their address ranges? For many processors, only one memory
|
||||
operand can be present at a time, so the 2-entry cache wouldn't be
|
||||
|
@ -471,43 +495,14 @@ objdump_print_address (vma, info)
|
|||
}
|
||||
|
||||
/* The symbol we want is now in min, the low end of the range we
|
||||
were searching. */
|
||||
were searching. If there are several symbols with the same
|
||||
value, we want the first one. */
|
||||
thisplace = min;
|
||||
while (thisplace > 0
|
||||
&& (bfd_asymbol_value (sorted_syms[thisplace])
|
||||
== bfd_asymbol_value (sorted_syms[thisplace - 1])))
|
||||
--thisplace;
|
||||
|
||||
{
|
||||
/* If this symbol isn't global, search for one with the same value
|
||||
that is. */
|
||||
bfd_vma val = bfd_asymbol_value (sorted_syms[thisplace]);
|
||||
long i;
|
||||
if (sorted_syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|
||||
for (i = thisplace - 1; i >= 0; i--)
|
||||
{
|
||||
if (bfd_asymbol_value (sorted_syms[i]) == val
|
||||
&& (!(sorted_syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|
||||
|| ((sorted_syms[thisplace]->flags & BSF_DEBUGGING)
|
||||
&& !(sorted_syms[i]->flags & BSF_DEBUGGING))))
|
||||
{
|
||||
thisplace = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sorted_syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|
||||
for (i = thisplace + 1; i < sorted_symcount; i++)
|
||||
{
|
||||
if (bfd_asymbol_value (sorted_syms[i]) == val
|
||||
&& (!(sorted_syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|
||||
|| ((sorted_syms[thisplace]->flags & BSF_DEBUGGING)
|
||||
&& !(sorted_syms[i]->flags & BSF_DEBUGGING))))
|
||||
{
|
||||
thisplace = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
/* If the file is relocateable, and the symbol could be from this
|
||||
section, prefer a symbol from this section over symbols from
|
||||
|
@ -1321,6 +1316,18 @@ display_bfd (abfd)
|
|||
dump_data (abfd);
|
||||
if (disassemble)
|
||||
disassemble_data (abfd);
|
||||
if (dump_debugging)
|
||||
{
|
||||
PTR dhandle;
|
||||
|
||||
dhandle = read_debugging_info (abfd);
|
||||
if (dhandle != NULL)
|
||||
{
|
||||
if (! print_debugging_info (stdout, dhandle))
|
||||
fprintf (stderr, "%s: printing debugging information failed\n",
|
||||
bfd_get_filename (abfd));
|
||||
}
|
||||
}
|
||||
if (syms)
|
||||
{
|
||||
free (syms);
|
||||
|
@ -1678,6 +1685,18 @@ dump_reloc_set (abfd, relpp, relcount)
|
|||
#define L_tmpnam 25
|
||||
#endif
|
||||
|
||||
static const char *
|
||||
endian_string (endian)
|
||||
enum bfd_endian endian;
|
||||
{
|
||||
if (endian == BFD_ENDIAN_BIG)
|
||||
return "big endian";
|
||||
else if (endian == BFD_ENDIAN_LITTLE)
|
||||
return "little endian";
|
||||
else
|
||||
return "endianness unknown";
|
||||
}
|
||||
|
||||
/* List the targets that BFD is configured to support, each followed
|
||||
by its endianness and the architectures it supports. */
|
||||
|
||||
|
@ -1698,8 +1717,8 @@ display_target_list ()
|
|||
int a;
|
||||
|
||||
printf ("%s\n (header %s, data %s)\n", p->name,
|
||||
p->header_byteorder_big_p ? "big endian" : "little endian",
|
||||
p->byteorder_big_p ? "big endian" : "little endian");
|
||||
endian_string (p->header_byteorder),
|
||||
endian_string (p->byteorder));
|
||||
|
||||
if (abfd == NULL)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,195 @@
|
|||
/* rddbg.c -- Read debugging information into a generic form.
|
||||
Copyright (C) 1995 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 reads debugging information into a generic form. This
|
||||
file knows how to dig the debugging information out of an object
|
||||
file. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "bucomm.h"
|
||||
#include "libiberty.h"
|
||||
#include "debug.h"
|
||||
#include "budbg.h"
|
||||
|
||||
static boolean read_section_stabs_debugging_info
|
||||
PARAMS ((bfd *, PTR, boolean *));
|
||||
|
||||
/* Read debugging information from a BFD. Returns a generic debugging
|
||||
pointer. */
|
||||
|
||||
PTR
|
||||
read_debugging_info (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
PTR dhandle;
|
||||
boolean found;
|
||||
|
||||
dhandle = debug_init ();
|
||||
if (dhandle == NULL)
|
||||
return NULL;
|
||||
|
||||
/* All we know about right now is stabs in sections. */
|
||||
|
||||
if (! read_section_stabs_debugging_info (abfd, dhandle, &found))
|
||||
return NULL;
|
||||
|
||||
if (! found)
|
||||
{
|
||||
fprintf (stderr, "%s: no recognized debugging information\n",
|
||||
bfd_get_filename (abfd));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dhandle;
|
||||
}
|
||||
|
||||
/* Read stabs in sections debugging information from a BFD. */
|
||||
|
||||
static boolean
|
||||
read_section_stabs_debugging_info (abfd, dhandle, pfound)
|
||||
bfd *abfd;
|
||||
PTR dhandle;
|
||||
boolean *pfound;
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const char *secname;
|
||||
const char *strsecname;
|
||||
} names[] = { { ".stab", ".stabstr" } };
|
||||
unsigned int i;
|
||||
PTR shandle;
|
||||
|
||||
*pfound = false;
|
||||
shandle = NULL;
|
||||
|
||||
for (i = 0; i < sizeof names / sizeof names[0]; i++)
|
||||
{
|
||||
asection *sec, *strsec;
|
||||
|
||||
sec = bfd_get_section_by_name (abfd, names[i].secname);
|
||||
strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
|
||||
if (sec != NULL && strsec != NULL)
|
||||
{
|
||||
bfd_size_type stabsize, strsize;
|
||||
bfd_byte *stabs, *strings;
|
||||
bfd_byte *stab;
|
||||
bfd_size_type stroff, next_stroff;
|
||||
|
||||
stabsize = bfd_section_size (abfd, sec);
|
||||
stabs = (bfd_byte *) xmalloc (stabsize);
|
||||
if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
|
||||
{
|
||||
fprintf (stderr, "%s: %s: %s\n",
|
||||
bfd_get_filename (abfd), names[i].secname,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
return false;
|
||||
}
|
||||
|
||||
strsize = bfd_section_size (abfd, strsec);
|
||||
strings = (bfd_byte *) xmalloc (strsize);
|
||||
if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
|
||||
{
|
||||
fprintf (stderr, "%s: %s: %s\n",
|
||||
bfd_get_filename (abfd), names[i].strsecname,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shandle == NULL)
|
||||
{
|
||||
shandle = start_stab (dhandle);
|
||||
if (shandle == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
*pfound = true;
|
||||
|
||||
stroff = 0;
|
||||
next_stroff = 0;
|
||||
for (stab = stabs; stab < stabs + stabsize; stab += 12)
|
||||
{
|
||||
bfd_size_type strx;
|
||||
int type;
|
||||
int other;
|
||||
int desc;
|
||||
bfd_vma value;
|
||||
|
||||
/* This code presumes 32 bit values. */
|
||||
|
||||
strx = bfd_get_32 (abfd, stab);
|
||||
type = bfd_get_8 (abfd, stab + 4);
|
||||
other = bfd_get_8 (abfd, stab + 5);
|
||||
desc = bfd_get_16 (abfd, stab + 6);
|
||||
value = bfd_get_32 (abfd, stab + 8);
|
||||
|
||||
if (type == 0)
|
||||
{
|
||||
/* Special type 0 stabs indicate the offset to the
|
||||
next string table. */
|
||||
stroff = next_stroff;
|
||||
next_stroff += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *f, *s;
|
||||
|
||||
f = NULL;
|
||||
s = (char *) strings + stroff + strx;
|
||||
while (s[strlen (s) - 1] == '\\'
|
||||
&& stab + 12 < stabs + stabsize)
|
||||
{
|
||||
stab += 12;
|
||||
s[strlen (s) - 1] = '\0';
|
||||
s = concat (s,
|
||||
((char *) strings
|
||||
+ stroff
|
||||
+ bfd_get_32 (abfd, stab)),
|
||||
(const char *) NULL);
|
||||
if (f != NULL)
|
||||
free (f);
|
||||
f = s;
|
||||
}
|
||||
|
||||
if (! parse_stab (dhandle, shandle, type, desc, value, s))
|
||||
return false;
|
||||
|
||||
/* Don't free f, since I think the stabs code
|
||||
expects strings to hang around. This should be
|
||||
straightened out. FIXME. */
|
||||
}
|
||||
}
|
||||
|
||||
free (stabs);
|
||||
|
||||
/* Don't free strings, since I think the stabs code expects
|
||||
the strings to hang around. This should be straightened
|
||||
out. FIXME. */
|
||||
}
|
||||
}
|
||||
|
||||
if (shandle != NULL)
|
||||
{
|
||||
if (! finish_stab (dhandle, shandle))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue