mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-16 14:00:27 +08:00
[multiple changes]
2000-08-28 Daniel Berlin <dberlin@redhat.com> * dwarf2out.c (DIE_LABEL_PREFIX): Remove leading "__". (print_die): If we don't know the offset of the target die, try the symbol. Add a trailing newline. (reverse_all_dies): New fn. (dwarf2out_finish): Call it. (break_out_includes): Reorganize for clarity. (add_sibling_attributes): Don't call reverse_die_lists. (output_comp_unit): Rename from output_comdat_comp_unit. Use for primary CU, too. * flags.h: Add flag_eliminate_dwarf2_dups. * toplev.c (f_options): Support -feliminate-dwarf2-dups. 2000-08-28 Jason Merrill <jason@redhat.com> * dwarf2.h (DW_TAG_GNU_BINCL, DW_TAG_GNU_EINCL): New tags. * dwarf2out.c: #include "md5.h". (DIE_LABEL_PREFIX): New macro. (dw_val_struct): Add 'external' flag to val_die_ref. (add_AT_die_ref, AT_ref): Adjust. (AT_ref_external, set_AT_ref_external): New fns. (build_abbrev_table): Call set_AT_ref_external. (value_format): Call AT_ref_external. (die_struct): Add die_symbol field. (new_die): Clear it. (dwarf_tag_name): Handle BINCL/EINCL. (dwarf2out_start_source_file): Add BINCL DIE. (dwarf2out_end_source_file): Add EINCL DIE. (push_new_compile_unit, pop_compile_unit, clear_die_sizes): New fns. (loc_checksum, attr_checksum, die_checksum): New fns. (is_type_die, is_comdat_die, is_symbol_die): New fns. (compute_section_prefix, assign_symbol_names): New fns. (gen_internal_sym, output_die_symbol, output_symbolic_ref): New fns. (output_die): Call output_die_symbol and AT_ref_external. (output_comdat_comp_unit): New fn, split out from... (dwarf2out_finish): ...here. Also call add_sibling_attributes for secondary CUs. (output_pubnames, output_aranges): Abort if we see entries from secondary CUs. * toplev.h: Declare file_name_nondirectory. * toplev.c (file_name_nondirectory): New fn, moved from C++ frontend. (rest_of_type_compilation): Call dwarf2out_decl if at toplevel. (debug_start_source_file): Call dwarf2out_start_source_file regardless of debug verbosity. (debug_end_source_file): Similarly. * tree.h: Declare clean_symbol_name. * tree.c (clean_symbol_name): Split out from... (get_file_function_name_long): ...here. * dwarf2out.c (new_loc_descr): Use calloc. (splice_child_die): Remove the die from the right parent. (gen_struct_or_union_die): Don't add AT_name to a specification DIE. gcc/cp: 2000-08-28 Jason Merrill <jason@redhat.com> * lex.c (file_name_nondirectory): Move to toplev.c. libiberty: 2000-08-28 Jason Merrill <jason@redhat.com> * Makefile.in (REQUIRED_OFILES): Add md5.o. (CFILES): Add md5.c. * md5.c: New file. include: 2000-08-28 Jason Merrill <jason@redhat.com> * md5.h: New file. gcc/cp: 2000-08-28 Jason Merrill <jason@redhat.com> * cp-tree.h (LOCAL_CLASS_P): New macro. * class.c (finish_struct_1): Use it. From-SVN: r36022
This commit is contained in:
parent
5de0e8d4e0
commit
881c6935bf
@ -1,3 +1,10 @@
|
||||
2000-08-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* lex.c (file_name_nondirectory): Move to toplev.c.
|
||||
|
||||
* cp-tree.h (LOCAL_CLASS_P): New macro.
|
||||
* class.c (finish_struct_1): Use it.
|
||||
|
||||
2000-08-27 Alex Samuel <samuel@codesourcery.com>
|
||||
|
||||
* mangle.c (CLASSTYPE_TEMPLATE_ID_P): Remove unexplained voodoo.
|
||||
|
@ -5200,7 +5200,7 @@ finish_struct_1 (t)
|
||||
maybe_suppress_debug_info (t);
|
||||
|
||||
/* Finish debugging output for this type. */
|
||||
rest_of_type_compilation (t, toplevel_bindings_p ());
|
||||
rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
|
||||
}
|
||||
|
||||
/* When T was built up, the member declarations were added in reverse
|
||||
|
@ -2224,6 +2224,11 @@ struct lang_decl
|
||||
(DECL_CONTEXT (NODE) \
|
||||
&& TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
|
||||
|
||||
/* 1 iff NODE is function-local, but for types. */
|
||||
#define LOCAL_CLASS_P(NODE) \
|
||||
(TYPE_CONTEXT (NODE) \
|
||||
&& TREE_CODE (TYPE_CONTEXT (NODE)) == FUNCTION_DECL)
|
||||
|
||||
/* For a NAMESPACE_DECL: the list of using namespace directives
|
||||
The PURPOSE is the used namespace, the value is the namespace
|
||||
that is the common ancestor. */
|
||||
|
15
gcc/cp/lex.c
15
gcc/cp/lex.c
@ -96,21 +96,6 @@ static int is_extended_char PARAMS ((int));
|
||||
static int is_extended_char_1 PARAMS ((int));
|
||||
static void init_operators PARAMS ((void));
|
||||
|
||||
/* Given a file name X, return the nondirectory portion.
|
||||
Keep in mind that X can be computed more than once. */
|
||||
char *
|
||||
file_name_nondirectory (x)
|
||||
const char *x;
|
||||
{
|
||||
char *tmp = (char *) rindex (x, '/');
|
||||
if (DIR_SEPARATOR != '/' && ! tmp)
|
||||
tmp = (char *) rindex (x, DIR_SEPARATOR);
|
||||
if (tmp)
|
||||
return (char *) (tmp + 1);
|
||||
else
|
||||
return (char *) x;
|
||||
}
|
||||
|
||||
/* This obstack is needed to hold text. It is not safe to use
|
||||
TOKEN_BUFFER because `check_newline' calls `yylex'. */
|
||||
struct obstack inline_text_obstack;
|
||||
|
@ -88,7 +88,9 @@ enum dwarf_tag
|
||||
/* GNU extensions */
|
||||
DW_TAG_format_label = 0x4101, /* for FORTRAN 77 and Fortran 90 */
|
||||
DW_TAG_function_template = 0x4102, /* for C++ */
|
||||
DW_TAG_class_template = 0x4103 /* for C++ */
|
||||
DW_TAG_class_template = 0x4103, /* for C++ */
|
||||
DW_TAG_GNU_BINCL = 0x4104,
|
||||
DW_TAG_GNU_EINCL = 0x4105
|
||||
};
|
||||
|
||||
#define DW_TAG_lo_user 0x4080
|
||||
|
613
gcc/dwarf2out.c
613
gcc/dwarf2out.c
@ -23,9 +23,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* TODO: Implement .debug_str handling, and share entries somehow.
|
||||
Eliminate duplicates by putting common info in a separate section
|
||||
to be collected by the linker and referring to it with
|
||||
DW_FORM_ref_addr.
|
||||
Emit .debug_line header even when there are no functions, since
|
||||
the file numbers are used by .debug_info. Alternately, leave
|
||||
out locations for types and decls.
|
||||
@ -56,6 +53,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "toplev.h"
|
||||
#include "varray.h"
|
||||
#include "ggc.h"
|
||||
#include "md5.h"
|
||||
#include "tm_p.h"
|
||||
|
||||
/* Decide whether we want to emit frame unwind information for the current
|
||||
@ -303,6 +301,7 @@ static void def_cfa_1 PARAMS ((const char *, dw_cfa_location *));
|
||||
#define FDE_AFTER_SIZE_LABEL "LSFDE"
|
||||
#define FDE_END_LABEL "LEFDE"
|
||||
#define FDE_LENGTH_LABEL "LLFDE"
|
||||
#define DIE_LABEL_PREFIX "DW"
|
||||
|
||||
/* Definitions of defaults for various types of primitive assembly language
|
||||
output operations. These may be overridden from within the tm.h file,
|
||||
@ -2124,7 +2123,10 @@ typedef struct dw_val_struct
|
||||
long unsigned val_unsigned;
|
||||
dw_long_long_const val_long_long;
|
||||
dw_float_const val_float;
|
||||
dw_die_ref val_die_ref;
|
||||
struct {
|
||||
dw_die_ref die;
|
||||
int external;
|
||||
} val_die_ref;
|
||||
unsigned val_fde_index;
|
||||
char *val_str;
|
||||
char *val_lbl_id;
|
||||
@ -2995,6 +2997,7 @@ dw_attr_node;
|
||||
typedef struct die_struct
|
||||
{
|
||||
enum dwarf_tag die_tag;
|
||||
char *die_symbol;
|
||||
dw_attr_ref die_attr;
|
||||
dw_die_ref die_parent;
|
||||
dw_die_ref die_child;
|
||||
@ -3338,20 +3341,38 @@ static void equate_decl_number_to_die PARAMS ((tree, dw_die_ref));
|
||||
static void print_spaces PARAMS ((FILE *));
|
||||
static void print_die PARAMS ((dw_die_ref, FILE *));
|
||||
static void print_dwarf_line_table PARAMS ((FILE *));
|
||||
static void reverse_die_lists PARAMS ((dw_die_ref));
|
||||
static void reverse_all_dies PARAMS ((dw_die_ref));
|
||||
static dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref));
|
||||
static dw_die_ref pop_compile_unit PARAMS ((dw_die_ref));
|
||||
static void loc_checksum PARAMS ((dw_loc_descr_ref, struct md5_ctx *));
|
||||
static void attr_checksum PARAMS ((dw_attr_ref, struct md5_ctx *));
|
||||
static void die_checksum PARAMS ((dw_die_ref, struct md5_ctx *));
|
||||
static void compute_section_prefix PARAMS ((dw_die_ref));
|
||||
static int is_type_die PARAMS ((dw_die_ref));
|
||||
static int is_comdat_die PARAMS ((dw_die_ref));
|
||||
static int is_symbol_die PARAMS ((dw_die_ref));
|
||||
static char *gen_internal_sym PARAMS ((void));
|
||||
static void assign_symbol_names PARAMS ((dw_die_ref));
|
||||
static void break_out_includes PARAMS ((dw_die_ref));
|
||||
static void add_sibling_attributes PARAMS ((dw_die_ref));
|
||||
static void build_abbrev_table PARAMS ((dw_die_ref));
|
||||
static unsigned long size_of_string PARAMS ((const char *));
|
||||
static int constant_size PARAMS ((long unsigned));
|
||||
static unsigned long size_of_die PARAMS ((dw_die_ref));
|
||||
static void calc_die_sizes PARAMS ((dw_die_ref));
|
||||
static void clear_die_sizes PARAMS ((dw_die_ref));
|
||||
static unsigned long size_of_line_prolog PARAMS ((void));
|
||||
static unsigned long size_of_pubnames PARAMS ((void));
|
||||
static unsigned long size_of_aranges PARAMS ((void));
|
||||
static enum dwarf_form value_format PARAMS ((dw_attr_ref));
|
||||
static void output_value_format PARAMS ((dw_attr_ref));
|
||||
static void output_abbrev_section PARAMS ((void));
|
||||
static void output_die_symbol PARAMS ((dw_die_ref));
|
||||
static void output_symbolic_ref PARAMS ((dw_die_ref));
|
||||
static void output_die PARAMS ((dw_die_ref));
|
||||
static void output_compilation_unit_header PARAMS ((void));
|
||||
static void output_comp_unit PARAMS ((dw_die_ref));
|
||||
static const char *dwarf2_name PARAMS ((tree, int));
|
||||
static void add_pubname PARAMS ((tree, dw_die_ref));
|
||||
static void output_pubnames PARAMS ((void));
|
||||
@ -3441,7 +3462,6 @@ static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
|
||||
static void gen_abstract_function PARAMS ((tree));
|
||||
static rtx save_rtx PARAMS ((rtx));
|
||||
static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
|
||||
static void reverse_die_lists PARAMS ((dw_die_ref));
|
||||
|
||||
/* Section names used to hold DWARF debugging information. */
|
||||
#ifndef DEBUG_INFO_SECTION
|
||||
@ -3728,6 +3748,10 @@ dwarf_tag_name (tag)
|
||||
return "DW_TAG_function_template";
|
||||
case DW_TAG_class_template:
|
||||
return "DW_TAG_class_template";
|
||||
case DW_TAG_GNU_BINCL:
|
||||
return "DW_TAG_GNU_BINCL";
|
||||
case DW_TAG_GNU_EINCL:
|
||||
return "DW_TAG_GNU_EINCL";
|
||||
default:
|
||||
return "DW_TAG_<unknown>";
|
||||
}
|
||||
@ -4079,7 +4103,7 @@ decl_class_context (decl)
|
||||
}
|
||||
|
||||
/* Add an attribute/value pair to a DIE. We build the lists up in reverse
|
||||
addition order, and correct that in add_sibling_attributes. */
|
||||
addition order, and correct that in reverse_all_dies. */
|
||||
|
||||
static inline void
|
||||
add_dwarf_attr (die, attr)
|
||||
@ -4264,7 +4288,8 @@ add_AT_die_ref (die, attr_kind, targ_die)
|
||||
attr->dw_attr_next = NULL;
|
||||
attr->dw_attr = attr_kind;
|
||||
attr->dw_attr_val.val_class = dw_val_class_die_ref;
|
||||
attr->dw_attr_val.v.val_die_ref = targ_die;
|
||||
attr->dw_attr_val.v.val_die_ref.die = targ_die;
|
||||
attr->dw_attr_val.v.val_die_ref.external = 0;
|
||||
add_dwarf_attr (die, attr);
|
||||
}
|
||||
|
||||
@ -4274,11 +4299,34 @@ AT_ref (a)
|
||||
register dw_attr_ref a;
|
||||
{
|
||||
if (a && AT_class (a) == dw_val_class_die_ref)
|
||||
return a->dw_attr_val.v.val_die_ref;
|
||||
return a->dw_attr_val.v.val_die_ref.die;
|
||||
|
||||
abort ();
|
||||
}
|
||||
|
||||
static inline int AT_ref_external PARAMS ((dw_attr_ref));
|
||||
static inline int
|
||||
AT_ref_external (a)
|
||||
register dw_attr_ref a;
|
||||
{
|
||||
if (a && AT_class (a) == dw_val_class_die_ref)
|
||||
return a->dw_attr_val.v.val_die_ref.external;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void set_AT_ref_external PARAMS ((dw_attr_ref, int));
|
||||
static inline void
|
||||
set_AT_ref_external (a, i)
|
||||
register dw_attr_ref a;
|
||||
int i;
|
||||
{
|
||||
if (a && AT_class (a) == dw_val_class_die_ref)
|
||||
a->dw_attr_val.v.val_die_ref.external = i;
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Add an FDE reference attribute value to a DIE. */
|
||||
|
||||
static inline void
|
||||
@ -4611,7 +4659,7 @@ remove_children (die)
|
||||
}
|
||||
|
||||
/* Add a child DIE below its parent. We build the lists up in reverse
|
||||
addition order, and correct that in add_sibling_attributes. */
|
||||
addition order, and correct that in reverse_all_dies. */
|
||||
|
||||
static inline void
|
||||
add_child_die (die, child_die)
|
||||
@ -4677,6 +4725,7 @@ new_die (tag_value, parent_die)
|
||||
die->die_parent = NULL;
|
||||
die->die_sib = NULL;
|
||||
die->die_attr = NULL;
|
||||
die->die_symbol = NULL;
|
||||
|
||||
if (parent_die != NULL)
|
||||
add_child_die (parent_die, die);
|
||||
@ -4822,7 +4871,12 @@ print_die (die, outfile)
|
||||
break;
|
||||
case dw_val_class_die_ref:
|
||||
if (AT_ref (a) != NULL)
|
||||
fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset);
|
||||
{
|
||||
if (AT_ref (a)->die_offset == 0)
|
||||
fprintf (outfile, "die -> label: %s", AT_ref (a)->die_symbol);
|
||||
else
|
||||
fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset);
|
||||
}
|
||||
else
|
||||
fprintf (outfile, "die -> <null>");
|
||||
break;
|
||||
@ -4851,6 +4905,8 @@ print_die (die, outfile)
|
||||
|
||||
print_indent -= 4;
|
||||
}
|
||||
if (print_indent == 0)
|
||||
fprintf (outfile, "\n");
|
||||
}
|
||||
|
||||
/* Print the contents of the source code line number correspondence table.
|
||||
@ -4925,10 +4981,370 @@ reverse_die_lists (die)
|
||||
die->die_child = cp;
|
||||
}
|
||||
|
||||
/* Traverse the DIE, reverse its lists of attributes and children, and
|
||||
add a sibling attribute if it may have the effect of speeding up
|
||||
access to siblings. To save some space, avoid generating sibling
|
||||
attributes for DIE's without children. */
|
||||
/* reverse_die_lists only reverses the single die you pass it. Since
|
||||
we used to reverse all dies in add_sibling_attributes, which runs
|
||||
through all the dies, it would reverse all the dies. Now, however,
|
||||
since we don't call reverse_die_lists in add_sibling_attributes, we
|
||||
need a routine to recursively reverse all the dies. This is that
|
||||
routine. */
|
||||
|
||||
static void
|
||||
reverse_all_dies (die)
|
||||
register dw_die_ref die;
|
||||
{
|
||||
register dw_die_ref c;
|
||||
|
||||
reverse_die_lists (die);
|
||||
|
||||
for (c = die->die_child; c; c = c->die_sib)
|
||||
reverse_all_dies (c);
|
||||
}
|
||||
|
||||
/* Start a new compilation unit DIE for an include file. OLD_UNIT is
|
||||
the CU for the enclosing include file, if any. BINCL_DIE is the
|
||||
DW_TAG_GNU_BINCL DIE that marks the start of the DIEs for this
|
||||
include file. */
|
||||
|
||||
static dw_die_ref
|
||||
push_new_compile_unit (old_unit, bincl_die)
|
||||
dw_die_ref old_unit, bincl_die;
|
||||
{
|
||||
const char *filename = get_AT_string (bincl_die, DW_AT_name);
|
||||
dw_die_ref new_unit = gen_compile_unit_die (filename);
|
||||
new_unit->die_sib = old_unit;
|
||||
return new_unit;
|
||||
}
|
||||
|
||||
/* Close an include-file CU and reopen the enclosing one. */
|
||||
|
||||
static dw_die_ref
|
||||
pop_compile_unit (old_unit)
|
||||
dw_die_ref old_unit;
|
||||
{
|
||||
dw_die_ref new_unit = old_unit->die_sib;
|
||||
old_unit->die_sib = NULL;
|
||||
return new_unit;
|
||||
}
|
||||
|
||||
#define PROCESS(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx)
|
||||
#define PROCESS_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO), ctx)
|
||||
|
||||
/* Calculate the checksum of a location expression. */
|
||||
|
||||
static inline void
|
||||
loc_checksum (loc, ctx)
|
||||
dw_loc_descr_ref loc;
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
PROCESS (loc->dw_loc_opc);
|
||||
PROCESS (loc->dw_loc_oprnd1);
|
||||
PROCESS (loc->dw_loc_oprnd2);
|
||||
}
|
||||
|
||||
/* Calculate the checksum of an attribute. */
|
||||
|
||||
static void
|
||||
attr_checksum (at, ctx)
|
||||
dw_attr_ref at;
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
dw_loc_descr_ref loc;
|
||||
rtx r;
|
||||
|
||||
PROCESS (at->dw_attr);
|
||||
|
||||
/* We don't care about differences in file numbering. */
|
||||
if (at->dw_attr == DW_AT_decl_file)
|
||||
return;
|
||||
|
||||
switch (AT_class (at))
|
||||
{
|
||||
case dw_val_class_const:
|
||||
PROCESS (at->dw_attr_val.v.val_int);
|
||||
break;
|
||||
case dw_val_class_unsigned_const:
|
||||
PROCESS (at->dw_attr_val.v.val_unsigned);
|
||||
break;
|
||||
case dw_val_class_long_long:
|
||||
PROCESS (at->dw_attr_val.v.val_long_long);
|
||||
break;
|
||||
case dw_val_class_float:
|
||||
PROCESS (at->dw_attr_val.v.val_float);
|
||||
break;
|
||||
case dw_val_class_flag:
|
||||
PROCESS (at->dw_attr_val.v.val_flag);
|
||||
break;
|
||||
|
||||
case dw_val_class_str:
|
||||
PROCESS_STRING (AT_string (at));
|
||||
break;
|
||||
case dw_val_class_addr:
|
||||
r = AT_addr (at);
|
||||
switch (GET_CODE (r))
|
||||
{
|
||||
case SYMBOL_REF:
|
||||
PROCESS_STRING (XSTR (r, 0));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
|
||||
case dw_val_class_loc:
|
||||
for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
|
||||
loc_checksum (loc, ctx);
|
||||
break;
|
||||
|
||||
case dw_val_class_die_ref:
|
||||
if (AT_ref (at)->die_offset)
|
||||
PROCESS (AT_ref (at)->die_offset);
|
||||
/* FIXME else use target die name or something. */
|
||||
|
||||
case dw_val_class_fde_ref:
|
||||
case dw_val_class_lbl_id:
|
||||
case dw_val_class_lbl_offset:
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the checksum of a DIE. */
|
||||
|
||||
static void
|
||||
die_checksum (die, ctx)
|
||||
dw_die_ref die;
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
dw_die_ref c;
|
||||
dw_attr_ref a;
|
||||
|
||||
PROCESS (die->die_tag);
|
||||
|
||||
for (a = die->die_attr; a; a = a->dw_attr_next)
|
||||
attr_checksum (a, ctx);
|
||||
|
||||
for (c = die->die_child; c; c = c->die_sib)
|
||||
die_checksum (c, ctx);
|
||||
}
|
||||
|
||||
#undef PROCESS
|
||||
#undef PROCESS_STRING
|
||||
|
||||
/* The prefix to attach to symbols on DIEs in the current comdat debug
|
||||
info section. */
|
||||
static char *comdat_symbol_id;
|
||||
|
||||
/* The index of the current symbol within the current comdat CU. */
|
||||
static unsigned int comdat_symbol_number;
|
||||
|
||||
/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
|
||||
children, and set comdat_symbol_id accordingly. */
|
||||
|
||||
static void
|
||||
compute_section_prefix (unit_die)
|
||||
dw_die_ref unit_die;
|
||||
{
|
||||
char *p, *name;
|
||||
int i;
|
||||
unsigned char checksum[16];
|
||||
struct md5_ctx ctx;
|
||||
|
||||
md5_init_ctx (&ctx);
|
||||
die_checksum (unit_die, &ctx);
|
||||
md5_finish_ctx (&ctx, checksum);
|
||||
|
||||
p = file_name_nondirectory (get_AT_string (unit_die, DW_AT_name));
|
||||
name = (char *) alloca (strlen (p) + 64);
|
||||
sprintf (name, "%s.", p);
|
||||
|
||||
clean_symbol_name (name);
|
||||
|
||||
p = name + strlen (name);
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
sprintf (p, "%.2x", checksum[i]);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
comdat_symbol_id = unit_die->die_symbol = xstrdup (name);
|
||||
comdat_symbol_number = 0;
|
||||
}
|
||||
|
||||
/* Returns nonzero iff DIE represents a type, in the sense of TYPE_P. */
|
||||
|
||||
static int
|
||||
is_type_die (die)
|
||||
dw_die_ref die;
|
||||
{
|
||||
switch (die->die_tag)
|
||||
{
|
||||
case DW_TAG_array_type:
|
||||
case DW_TAG_class_type:
|
||||
case DW_TAG_enumeration_type:
|
||||
case DW_TAG_pointer_type:
|
||||
case DW_TAG_reference_type:
|
||||
case DW_TAG_string_type:
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_union_type:
|
||||
case DW_TAG_ptr_to_member_type:
|
||||
case DW_TAG_set_type:
|
||||
case DW_TAG_subrange_type:
|
||||
case DW_TAG_base_type:
|
||||
case DW_TAG_const_type:
|
||||
case DW_TAG_file_type:
|
||||
case DW_TAG_packed_type:
|
||||
case DW_TAG_volatile_type:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU.
|
||||
Basically, we want to choose the bits that are likely to be shared between
|
||||
compilations (types) and leave out the bits that are specific to individual
|
||||
compilations (functions). */
|
||||
|
||||
static int
|
||||
is_comdat_die (c)
|
||||
dw_die_ref c;
|
||||
{
|
||||
#if 1
|
||||
/* I think we want to leave base types and __vtbl_ptr_type in the
|
||||
main CU, as we do for stabs. The advantage is a greater
|
||||
likelihood of sharing between objects that don't include headers
|
||||
in the same order (and therefore would put the base types in a
|
||||
different comdat). jason 8/28/00 */
|
||||
if (c->die_tag == DW_TAG_base_type)
|
||||
return 0;
|
||||
|
||||
if (c->die_tag == DW_TAG_pointer_type
|
||||
|| c->die_tag == DW_TAG_reference_type
|
||||
|| c->die_tag == DW_TAG_const_type
|
||||
|| c->die_tag == DW_TAG_volatile_type)
|
||||
{
|
||||
dw_die_ref t = get_AT_ref (c, DW_AT_type);
|
||||
return t ? is_comdat_die (t) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return is_type_die (c);
|
||||
}
|
||||
|
||||
/* Returns 1 iff C is the sort of DIE that might be referred to from another
|
||||
compilation unit. */
|
||||
|
||||
static int
|
||||
is_symbol_die (c)
|
||||
dw_die_ref c;
|
||||
{
|
||||
if (is_type_die (c))
|
||||
return 1;
|
||||
if (get_AT (c, DW_AT_declaration)
|
||||
&& ! get_AT (c, DW_AT_specification))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
gen_internal_sym ()
|
||||
{
|
||||
char buf[256];
|
||||
static int label_num;
|
||||
ASM_GENERATE_INTERNAL_LABEL (buf, "LDIE", label_num++);
|
||||
return xstrdup (buf);
|
||||
}
|
||||
|
||||
/* Assign symbols to all worthy DIEs under DIE. */
|
||||
|
||||
static void
|
||||
assign_symbol_names (die)
|
||||
register dw_die_ref die;
|
||||
{
|
||||
register dw_die_ref c;
|
||||
|
||||
if (is_symbol_die (die))
|
||||
{
|
||||
if (comdat_symbol_id)
|
||||
{
|
||||
char *p = alloca (strlen (comdat_symbol_id) + 64);
|
||||
sprintf (p, "%s.%s.%x", DIE_LABEL_PREFIX,
|
||||
comdat_symbol_id, comdat_symbol_number++);
|
||||
die->die_symbol = xstrdup (p);
|
||||
}
|
||||
else
|
||||
die->die_symbol = gen_internal_sym ();
|
||||
}
|
||||
|
||||
for (c = die->die_child; c != NULL; c = c->die_sib)
|
||||
assign_symbol_names (c);
|
||||
}
|
||||
|
||||
/* Traverse the DIE (which is always comp_unit_die), and set up
|
||||
additional compilation units for each of the include files we see
|
||||
bracketed by BINCL/EINCL. */
|
||||
|
||||
static void
|
||||
break_out_includes (die)
|
||||
register dw_die_ref die;
|
||||
{
|
||||
dw_die_ref *ptr;
|
||||
register dw_die_ref unit = NULL;
|
||||
limbo_die_node *node;
|
||||
|
||||
for (ptr = &(die->die_child); *ptr; )
|
||||
{
|
||||
register dw_die_ref c = *ptr;
|
||||
|
||||
if (c->die_tag == DW_TAG_GNU_BINCL
|
||||
|| c->die_tag == DW_TAG_GNU_EINCL
|
||||
|| (unit && is_comdat_die (c)))
|
||||
{
|
||||
/* This DIE is for a secondary CU; remove it from the main one. */
|
||||
*ptr = c->die_sib;
|
||||
|
||||
if (c->die_tag == DW_TAG_GNU_BINCL)
|
||||
{
|
||||
unit = push_new_compile_unit (unit, c);
|
||||
free_die (c);
|
||||
}
|
||||
else if (c->die_tag == DW_TAG_GNU_EINCL)
|
||||
{
|
||||
unit = pop_compile_unit (unit);
|
||||
free_die (c);
|
||||
}
|
||||
else
|
||||
add_child_die (unit, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Leave this DIE in the main CU. */
|
||||
ptr = &(c->die_sib);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* We can only use this in debugging, since the frontend doesn't check
|
||||
to make sure that we leave every include file we enter. */
|
||||
if (unit != NULL)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
assign_symbol_names (die);
|
||||
for (node = limbo_die_list; node; node = node->next)
|
||||
{
|
||||
compute_section_prefix (node->die);
|
||||
assign_symbol_names (node->die);
|
||||
}
|
||||
}
|
||||
|
||||
/* Traverse the DIE and add a sibling attribute if it may have the
|
||||
effect of speeding up access to siblings. To save some space,
|
||||
avoid generating sibling attributes for DIE's without children. */
|
||||
|
||||
static void
|
||||
add_sibling_attributes (die)
|
||||
@ -4936,9 +5352,8 @@ add_sibling_attributes (die)
|
||||
{
|
||||
register dw_die_ref c;
|
||||
|
||||
reverse_die_lists (die);
|
||||
|
||||
if (die != comp_unit_die && die->die_sib && die->die_child != NULL)
|
||||
if (die->die_tag != DW_TAG_compile_unit
|
||||
&& die->die_sib && die->die_child != NULL)
|
||||
/* Add the sibling link to the front of the attribute list. */
|
||||
add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
|
||||
|
||||
@ -4960,6 +5375,20 @@ build_abbrev_table (die)
|
||||
register unsigned long n_alloc;
|
||||
register dw_die_ref c;
|
||||
register dw_attr_ref d_attr, a_attr;
|
||||
|
||||
/* Scan the DIE references, and mark as external any that refer to
|
||||
DIEs from other CUs (i.e. those with cleared die_offset). */
|
||||
for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next)
|
||||
{
|
||||
if (AT_class (d_attr) == dw_val_class_die_ref
|
||||
&& AT_ref (d_attr)->die_offset == 0)
|
||||
{
|
||||
if (AT_ref (d_attr)->die_symbol == 0)
|
||||
abort ();
|
||||
set_AT_ref_external (d_attr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
|
||||
{
|
||||
register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
|
||||
@ -5130,6 +5559,20 @@ calc_die_sizes (die)
|
||||
next_die_offset += 1;
|
||||
}
|
||||
|
||||
/* Clear the offsets and sizes for a die and its children. We do this so
|
||||
that we know whether or not a reference needs to use FORM_ref_addr; only
|
||||
DIEs in the same CU will have non-zero offsets available. */
|
||||
|
||||
static void
|
||||
clear_die_sizes (die)
|
||||
dw_die_ref die;
|
||||
{
|
||||
register dw_die_ref c;
|
||||
die->die_offset = 0;
|
||||
for (c = die->die_child; c; c = c->die_sib)
|
||||
clear_die_sizes (c);
|
||||
}
|
||||
|
||||
/* Return the size of the line information prolog generated for the
|
||||
compilation unit. */
|
||||
|
||||
@ -5250,7 +5693,10 @@ value_format (a)
|
||||
case dw_val_class_flag:
|
||||
return DW_FORM_flag;
|
||||
case dw_val_class_die_ref:
|
||||
return DW_FORM_ref;
|
||||
if (AT_ref_external (a))
|
||||
return DW_FORM_ref_addr;
|
||||
else
|
||||
return DW_FORM_ref;
|
||||
case dw_val_class_fde_ref:
|
||||
return DW_FORM_data;
|
||||
case dw_val_class_lbl_id:
|
||||
@ -5333,6 +5779,39 @@ output_abbrev_section ()
|
||||
fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
|
||||
}
|
||||
|
||||
/* Output a symbol we can use to refer to this DIE from another CU. */
|
||||
|
||||
static inline void
|
||||
output_die_symbol (die)
|
||||
register dw_die_ref die;
|
||||
{
|
||||
char *sym = die->die_symbol;
|
||||
|
||||
if (sym == 0)
|
||||
return;
|
||||
|
||||
if (strncmp (sym, DIE_LABEL_PREFIX, sizeof (DIE_LABEL_PREFIX) - 1) == 0)
|
||||
/* We make these global, not weak; if the target doesn't support
|
||||
.linkonce, it doesn't support combining the sections, so debugging
|
||||
will break. */
|
||||
ASM_GLOBALIZE_LABEL (asm_out_file, sym);
|
||||
ASM_OUTPUT_LABEL (asm_out_file, sym);
|
||||
}
|
||||
|
||||
/* Output a symbolic (i.e. FORM_ref_addr) reference to TARGET_DIE. */
|
||||
|
||||
static inline void
|
||||
output_symbolic_ref (target_die)
|
||||
dw_die_ref target_die;
|
||||
{
|
||||
char *sym = target_die->die_symbol;
|
||||
|
||||
if (sym == 0)
|
||||
abort ();
|
||||
|
||||
ASM_OUTPUT_DWARF_OFFSET (asm_out_file, sym);
|
||||
}
|
||||
|
||||
/* Output the DIE and its attributes. Called recursively to generate
|
||||
the definitions of each child DIE. */
|
||||
|
||||
@ -5344,6 +5823,11 @@ output_die (die)
|
||||
register dw_die_ref c;
|
||||
register unsigned long size;
|
||||
|
||||
/* If someone in another CU might refer to us, set up a symbol for
|
||||
them to point to. */
|
||||
if (die->die_symbol)
|
||||
output_die_symbol (die);
|
||||
|
||||
output_uleb128 (die->die_abbrev);
|
||||
if (flag_debug_asm)
|
||||
fprintf (asm_out_file, " (DIE (0x%lx) %s)",
|
||||
@ -5457,7 +5941,10 @@ output_die (die)
|
||||
break;
|
||||
|
||||
case dw_val_class_die_ref:
|
||||
ASM_OUTPUT_DWARF_DATA (asm_out_file, AT_ref (a)->die_offset);
|
||||
if (AT_ref_external (a))
|
||||
output_symbolic_ref (AT_ref (a));
|
||||
else
|
||||
ASM_OUTPUT_DWARF_DATA (asm_out_file, AT_ref (a)->die_offset);
|
||||
break;
|
||||
|
||||
case dw_val_class_fde_ref:
|
||||
@ -5547,6 +6034,44 @@ output_compilation_unit_header ()
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
|
||||
/* Output the compilation unit DIE and its children. */
|
||||
|
||||
static void
|
||||
output_comp_unit (die)
|
||||
dw_die_ref die;
|
||||
{
|
||||
char *secname;
|
||||
|
||||
if (die->die_child == 0)
|
||||
return;
|
||||
|
||||
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
|
||||
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
|
||||
calc_die_sizes (die);
|
||||
|
||||
build_abbrev_table (die);
|
||||
|
||||
if (die->die_symbol)
|
||||
{
|
||||
secname = (char *) alloca (strlen (die->die_symbol) + 24);
|
||||
sprintf (secname, ".gnu.linkonce.wi.%s", die->die_symbol);
|
||||
die->die_symbol = NULL;
|
||||
}
|
||||
else
|
||||
secname = (char *) DEBUG_INFO_SECTION;
|
||||
|
||||
/* Output debugging information. */
|
||||
fputc ('\n', asm_out_file);
|
||||
ASM_OUTPUT_SECTION (asm_out_file, secname);
|
||||
output_compilation_unit_header ();
|
||||
output_die (die);
|
||||
|
||||
/* Leave the sizes on the main CU, since we do it last and we use the
|
||||
sizes in output_pubnames. */
|
||||
if (die->die_symbol)
|
||||
clear_die_sizes (die);
|
||||
}
|
||||
|
||||
/* The DWARF2 pubname for a nested thingy looks like "A::f". The output
|
||||
of decl_printable_name for C++ looks like "A::f(int)". Let's drop the
|
||||
argument list, and maybe the scope. */
|
||||
@ -5622,6 +6147,10 @@ output_pubnames ()
|
||||
{
|
||||
register pubname_ref pub = &pubname_table[i];
|
||||
|
||||
/* We shouldn't see pubnames for DIEs outside of the main CU. */
|
||||
if (pub->die->die_offset == 0)
|
||||
abort ();
|
||||
|
||||
ASM_OUTPUT_DWARF_DATA (asm_out_file, pub->die->die_offset);
|
||||
if (flag_debug_asm)
|
||||
fprintf (asm_out_file, "\t%s DIE offset", ASM_COMMENT_START);
|
||||
@ -5735,6 +6264,10 @@ output_aranges ()
|
||||
{
|
||||
dw_die_ref die = arange_table[i];
|
||||
|
||||
/* We shouldn't see aranges for DIEs outside of the main CU. */
|
||||
if (die->die_offset == 0)
|
||||
abort ();
|
||||
|
||||
if (die->die_tag == DW_TAG_subprogram)
|
||||
ASM_OUTPUT_DWARF_ADDR (asm_out_file, get_AT_low_pc (die));
|
||||
else
|
||||
@ -10134,6 +10667,12 @@ void
|
||||
dwarf2out_start_source_file (filename)
|
||||
register const char *filename ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (flag_eliminate_dwarf2_dups)
|
||||
{
|
||||
/* Record the beginning of the file for break_out_includes. */
|
||||
dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die);
|
||||
add_AT_string (bincl_die, DW_AT_name, filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* Record the end of a source file, for later output
|
||||
@ -10142,6 +10681,11 @@ dwarf2out_start_source_file (filename)
|
||||
void
|
||||
dwarf2out_end_source_file ()
|
||||
{
|
||||
if (flag_eliminate_dwarf2_dups)
|
||||
{
|
||||
/* Record the end of the file for break_out_includes. */
|
||||
new_die (DW_TAG_GNU_EINCL, comp_unit_die);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from check_newline in c-parse.y. The `buffer' parameter contains
|
||||
@ -10291,9 +10835,19 @@ dwarf2out_finish ()
|
||||
emit full debugging info for them. */
|
||||
retry_incomplete_types ();
|
||||
|
||||
/* Traverse the DIE's, reverse their lists of attributes and children,
|
||||
and add add sibling attributes to those DIE's that have children. */
|
||||
/* We need to reverse all the dies before break_out_includes, or
|
||||
we'll see the end of an include file before the beginning. */
|
||||
reverse_all_dies (comp_unit_die);
|
||||
|
||||
/* Generate separate CUs for each of the include files we've seen.
|
||||
They will go into limbo_die_list. */
|
||||
break_out_includes (comp_unit_die);
|
||||
|
||||
/* Traverse the DIE's and add add sibling attributes to those DIE's
|
||||
that have children. */
|
||||
add_sibling_attributes (comp_unit_die);
|
||||
for (node = limbo_die_list; node; node = node->next)
|
||||
add_sibling_attributes (node->die);
|
||||
|
||||
/* Output a terminator label for the .text section. */
|
||||
fputc ('\n', asm_out_file);
|
||||
@ -10339,22 +10893,17 @@ dwarf2out_finish ()
|
||||
add_AT_unsigned (die, DW_AT_macro_info, 0);
|
||||
#endif
|
||||
|
||||
/* Output all of the compilation units. We put the main one last so that
|
||||
the offsets are available to output_pubnames. */
|
||||
for (node = limbo_die_list; node; node = node->next)
|
||||
output_comp_unit (node->die);
|
||||
output_comp_unit (comp_unit_die);
|
||||
|
||||
/* Output the abbreviation table. */
|
||||
fputc ('\n', asm_out_file);
|
||||
ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
|
||||
build_abbrev_table (comp_unit_die);
|
||||
output_abbrev_section ();
|
||||
|
||||
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
|
||||
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
|
||||
calc_die_sizes (comp_unit_die);
|
||||
|
||||
/* Output debugging information. */
|
||||
fputc ('\n', asm_out_file);
|
||||
ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
|
||||
output_compilation_unit_header ();
|
||||
output_die (comp_unit_die);
|
||||
|
||||
if (pubname_table_in_use)
|
||||
{
|
||||
/* Output public names table. */
|
||||
|
@ -577,3 +577,7 @@ extern enum graph_dump_types graph_dump_format;
|
||||
string identifying the compiler. */
|
||||
|
||||
extern int flag_no_ident;
|
||||
|
||||
/* Nonzero means we should do dwarf2 duplicate elimination. */
|
||||
|
||||
extern int flag_eliminate_dwarf2_dups;
|
||||
|
31
gcc/toplev.c
31
gcc/toplev.c
@ -422,6 +422,10 @@ tree (*lang_expand_constant) PARAMS ((tree)) = 0;
|
||||
|
||||
void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
|
||||
|
||||
/* Nonzero if doing dwarf2 duplicate elimination. */
|
||||
|
||||
int flag_eliminate_dwarf2_dups = 0;
|
||||
|
||||
/* Nonzero if generating code to do profiling. */
|
||||
|
||||
int profile_flag = 0;
|
||||
@ -944,6 +948,8 @@ const char *user_label_prefix;
|
||||
|
||||
lang_independent_options f_options[] =
|
||||
{
|
||||
{"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
|
||||
"Perform DWARF2 duplicate elimination"},
|
||||
{"float-store", &flag_float_store, 1,
|
||||
"Do not store floats in registers" },
|
||||
{"volatile", &flag_volatile, 1,
|
||||
@ -1656,6 +1662,21 @@ strip_off_ending (name, len)
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a file name X, return the nondirectory portion. */
|
||||
|
||||
char *
|
||||
file_name_nondirectory (x)
|
||||
const char *x;
|
||||
{
|
||||
char *tmp = (char *) rindex (x, '/');
|
||||
if (DIR_SEPARATOR != '/' && ! tmp)
|
||||
tmp = (char *) rindex (x, DIR_SEPARATOR);
|
||||
if (tmp)
|
||||
return (char *) (tmp + 1);
|
||||
else
|
||||
return (char *) x;
|
||||
}
|
||||
|
||||
/* Output a quoted string. */
|
||||
|
||||
void
|
||||
@ -2560,6 +2581,10 @@ rest_of_type_compilation (type, toplev)
|
||||
#ifdef SDB_DEBUGGING_INFO
|
||||
if (write_symbols == SDB_DEBUG)
|
||||
sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
|
||||
#endif
|
||||
#ifdef DWARF2_DEBUGGING_INFO
|
||||
if (write_symbols == DWARF2_DEBUG && toplev)
|
||||
dwarf2out_decl (TYPE_STUB_DECL (type));
|
||||
#endif
|
||||
timevar_pop (TV_SYMOUT);
|
||||
}
|
||||
@ -4973,8 +4998,7 @@ debug_start_source_file (filename)
|
||||
dwarfout_start_new_source_file (filename);
|
||||
#endif /* DWARF_DEBUGGING_INFO */
|
||||
#ifdef DWARF2_DEBUGGING_INFO
|
||||
if (debug_info_level == DINFO_LEVEL_VERBOSE
|
||||
&& write_symbols == DWARF2_DEBUG)
|
||||
if (write_symbols == DWARF2_DEBUG)
|
||||
dwarf2out_start_source_file (filename);
|
||||
#endif /* DWARF2_DEBUGGING_INFO */
|
||||
#ifdef SDB_DEBUGGING_INFO
|
||||
@ -5000,8 +5024,7 @@ debug_end_source_file (lineno)
|
||||
dwarfout_resume_previous_source_file (lineno);
|
||||
#endif /* DWARF_DEBUGGING_INFO */
|
||||
#ifdef DWARF2_DEBUGGING_INFO
|
||||
if (debug_info_level == DINFO_LEVEL_VERBOSE
|
||||
&& write_symbols == DWARF2_DEBUG)
|
||||
if (write_symbols == DWARF2_DEBUG)
|
||||
dwarf2out_end_source_file ();
|
||||
#endif /* DWARF2_DEBUGGING_INFO */
|
||||
#ifdef SDB_DEBUGGING_INFO
|
||||
|
@ -35,6 +35,7 @@ extern int read_integral_parameter PARAMS ((const char *, const char *,
|
||||
const int));
|
||||
extern int count_error PARAMS ((int));
|
||||
extern void strip_off_ending PARAMS ((char *, int));
|
||||
extern char *file_name_nondirectory PARAMS ((const char *));
|
||||
extern void print_time PARAMS ((const char *, long));
|
||||
extern void debug_start_source_file PARAMS ((const char *));
|
||||
extern void debug_end_source_file PARAMS ((unsigned));
|
||||
|
34
gcc/tree.c
34
gcc/tree.c
@ -5386,6 +5386,26 @@ append_random_chars (template)
|
||||
template[6] = '\0';
|
||||
}
|
||||
|
||||
/* P is a string that will be used in a symbol. Mask out any characters
|
||||
that are not valid in that context. */
|
||||
|
||||
void
|
||||
clean_symbol_name (p)
|
||||
char *p;
|
||||
{
|
||||
for (; *p; p++)
|
||||
if (! ( ISDIGIT(*p)
|
||||
#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
|
||||
|| *p == '$'
|
||||
#endif
|
||||
#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
|
||||
|| *p == '.'
|
||||
#endif
|
||||
|| ISUPPER(*p)
|
||||
|| ISLOWER(*p)))
|
||||
*p = '_';
|
||||
}
|
||||
|
||||
/* Generate a name for a function unique to this translation unit.
|
||||
TYPE is some string to identify the purpose of this function to the
|
||||
linker or collect2. */
|
||||
@ -5431,19 +5451,7 @@ get_file_function_name_long (type)
|
||||
|
||||
/* Don't need to pull weird characters out of global names. */
|
||||
if (p != first_global_object_name)
|
||||
{
|
||||
for (q = buf+11; *q; q++)
|
||||
if (! ( ISDIGIT(*q)
|
||||
#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
|
||||
|| *q == '$'
|
||||
#endif
|
||||
#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
|
||||
|| *q == '.'
|
||||
#endif
|
||||
|| ISUPPER(*q)
|
||||
|| ISLOWER(*q)))
|
||||
*q = '_';
|
||||
}
|
||||
clean_symbol_name (buf + 11);
|
||||
|
||||
return get_identifier (buf);
|
||||
}
|
||||
|
@ -2435,6 +2435,7 @@ extern tree builtin_function PARAMS ((const char *, tree, int,
|
||||
|
||||
/* In tree.c */
|
||||
extern char *perm_calloc PARAMS ((int, long));
|
||||
extern void clean_symbol_name PARAMS ((char *));
|
||||
extern tree get_file_function_name PARAMS ((int));
|
||||
extern tree get_file_function_name_long PARAMS ((const char *));
|
||||
extern tree get_set_constructor_bits PARAMS ((tree, char *, int));
|
||||
|
@ -1,3 +1,7 @@
|
||||
2000-08-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* md5.h: New file.
|
||||
|
||||
2000-08-24 Greg McGary <greg@mcgary.org>
|
||||
|
||||
* libiberty.h (ARRAY_SIZE): New macro.
|
||||
|
146
include/md5.h
Normal file
146
include/md5.h
Normal file
@ -0,0 +1,146 @@
|
||||
/* md5.h - Declaration of functions and data types used for MD5 sum
|
||||
computing library functions.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
NOTE: The canonical source of this file is maintained with the GNU C
|
||||
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
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, 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 _MD5_H
|
||||
#define _MD5_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined HAVE_LIMITS_H || _LIBC
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
/* The following contortions are an attempt to use the C preprocessor
|
||||
to determine an unsigned integral type that is 32 bits wide. An
|
||||
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
|
||||
doing that would require that the configure script compile and *run*
|
||||
the resulting executable. Locally running cross-compiled executables
|
||||
is usually not possible. */
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <sys/types.h>
|
||||
typedef u_int32_t md5_uint32;
|
||||
#else
|
||||
# if defined __STDC__ && __STDC__
|
||||
# define UINT_MAX_32_BITS 4294967295U
|
||||
# else
|
||||
# define UINT_MAX_32_BITS 0xFFFFFFFF
|
||||
# endif
|
||||
|
||||
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
|
||||
This should be valid for all systems GNU cares about because
|
||||
that doesn't include 16-bit systems, and only modern systems
|
||||
(that certainly have <limits.h>) have 64+-bit integral types. */
|
||||
|
||||
# ifndef UINT_MAX
|
||||
# define UINT_MAX UINT_MAX_32_BITS
|
||||
# endif
|
||||
|
||||
# if UINT_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned int md5_uint32;
|
||||
# else
|
||||
# if USHRT_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned short md5_uint32;
|
||||
# else
|
||||
# if ULONG_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned long md5_uint32;
|
||||
# else
|
||||
/* The following line is intended to evoke an error.
|
||||
Using #error is not portable enough. */
|
||||
"Cannot determine unsigned 32-bit data type."
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#undef __P
|
||||
#if defined (__STDC__) && __STDC__
|
||||
#define __P(x) x
|
||||
#else
|
||||
#define __P(x) ()
|
||||
#endif
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct md5_ctx
|
||||
{
|
||||
md5_uint32 A;
|
||||
md5_uint32 B;
|
||||
md5_uint32 C;
|
||||
md5_uint32 D;
|
||||
|
||||
md5_uint32 total[2];
|
||||
md5_uint32 buflen;
|
||||
char buffer[128];
|
||||
};
|
||||
|
||||
/*
|
||||
* The following three functions are build up the low level used in
|
||||
* the functions `md5_stream' and `md5_buffer'.
|
||||
*/
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(RFC 1321, 3.3: Step 3) */
|
||||
extern void md5_init_ctx __P ((struct md5_ctx *ctx));
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is necessary that LEN is a multiple of 64!!! */
|
||||
extern void md5_process_block __P ((const void *buffer, size_t len,
|
||||
struct md5_ctx *ctx));
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is NOT required that LEN is a multiple of 64. */
|
||||
extern void md5_process_bytes __P ((const void *buffer, size_t len,
|
||||
struct md5_ctx *ctx));
|
||||
|
||||
/* Process the remaining bytes in the buffer and put result from CTX
|
||||
in first 16 bytes following RESBUF. The result is always in little
|
||||
endian byte order, so that a byte-wise output yields to the wanted
|
||||
ASCII representation of the message digest.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
|
||||
|
||||
|
||||
/* Put result from CTX in first 16 bytes following RESBUF. The result is
|
||||
always in little endian byte order, so that a byte-wise output yields
|
||||
to the wanted ASCII representation of the message digest.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
|
||||
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
resulting message digest number will be written into the 16 bytes
|
||||
beginning at RESBLOCK. */
|
||||
extern int md5_stream __P ((FILE *stream, void *resblock));
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
result is always in little endian byte order, so that a byte-wise
|
||||
output yields to the wanted ASCII representation of the message
|
||||
digest. */
|
||||
extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
|
||||
|
||||
#endif
|
@ -1,3 +1,9 @@
|
||||
2000-08-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* Makefile.in (REQUIRED_OFILES): Add md5.o.
|
||||
(CFILES): Add md5.c.
|
||||
* md5.c: New file.
|
||||
|
||||
2000-08-27 Alex Samuel <samuel@codesourcery.com>
|
||||
|
||||
* cp-demangle.c (demangle_name): Initialize template_p in local
|
||||
|
@ -128,7 +128,7 @@ CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \
|
||||
bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c \
|
||||
cp-demangle.c dyn-string.c fdmatch.c fnmatch.c getcwd.c \
|
||||
getpwd.c getopt.c getopt1.c getpagesize.c getruntime.c \
|
||||
floatformat.c hashtab.c hex.c index.c insque.c memchr.c memcmp.c \
|
||||
floatformat.c hashtab.c hex.c index.c insque.c md5.c memchr.c memcmp.c\
|
||||
memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \
|
||||
partition.c pexecute.c putenv.c random.c rename.c rindex.c setenv.c \
|
||||
sigsetmask.c sort.c spaces.c splay-tree.c strcasecmp.c strncasecmp.c \
|
||||
@ -140,7 +140,7 @@ CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \
|
||||
# These are always included in the library.
|
||||
REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o cp-demangle.o \
|
||||
dyn-string.o fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o \
|
||||
getruntime.o hashtab.o hex.o floatformat.o objalloc.o obstack.o \
|
||||
getruntime.o hashtab.o hex.o floatformat.o md5.o objalloc.o obstack.o \
|
||||
partition.o pexecute.o sort.o spaces.o splay-tree.o strerror.o \
|
||||
strsignal.o xatexit.o xexit.o xmalloc.o xmemdup.o xstrdup.o \
|
||||
xstrerror.o
|
||||
|
419
libiberty/md5.c
Normal file
419
libiberty/md5.c
Normal file
@ -0,0 +1,419 @@
|
||||
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
|
||||
according to the definition of MD5 in RFC 1321 from April 1992.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
NOTE: The canonical source of this file is maintained with the GNU C
|
||||
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
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, 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. */
|
||||
|
||||
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if STDC_HEADERS || defined _LIBC
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <endian.h>
|
||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define SWAP(n) \
|
||||
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||
#else
|
||||
# define SWAP(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
64-byte boundary. (RFC 1321, 3.1: Step 1) */
|
||||
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(RFC 1321, 3.3: Step 3) */
|
||||
void
|
||||
md5_init_ctx (ctx)
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
ctx->B = 0xefcdab89;
|
||||
ctx->C = 0x98badcfe;
|
||||
ctx->D = 0x10325476;
|
||||
|
||||
ctx->total[0] = ctx->total[1] = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
/* Put result from CTX in first 16 bytes following RESBUF. The result
|
||||
must be in little endian byte order.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_read_ctx (ctx, resbuf)
|
||||
const struct md5_ctx *ctx;
|
||||
void *resbuf;
|
||||
{
|
||||
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
|
||||
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
|
||||
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
|
||||
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
|
||||
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
prolog according to the standard and write the result to RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_finish_ctx (ctx, resbuf)
|
||||
struct md5_ctx *ctx;
|
||||
void *resbuf;
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
md5_uint32 bytes = ctx->buflen;
|
||||
size_t pad;
|
||||
|
||||
/* Now count remaining bytes. */
|
||||
ctx->total[0] += bytes;
|
||||
if (ctx->total[0] < bytes)
|
||||
++ctx->total[1];
|
||||
|
||||
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||
*(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
|
||||
*(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
|
||||
(ctx->total[0] >> 29));
|
||||
|
||||
/* Process last bytes. */
|
||||
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
return md5_read_ctx (ctx, resbuf);
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
resulting message digest number will be written into the 16 bytes
|
||||
beginning at RESBLOCK. */
|
||||
int
|
||||
md5_stream (stream, resblock)
|
||||
FILE *stream;
|
||||
void *resblock;
|
||||
{
|
||||
/* Important: BLOCKSIZE must be a multiple of 64. */
|
||||
#define BLOCKSIZE 4096
|
||||
struct md5_ctx ctx;
|
||||
char buffer[BLOCKSIZE + 72];
|
||||
size_t sum;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
|
||||
/* Iterate over full file contents. */
|
||||
while (1)
|
||||
{
|
||||
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||
computation function processes the whole buffer so that with the
|
||||
next round of the loop another block can be read. */
|
||||
size_t n;
|
||||
sum = 0;
|
||||
|
||||
/* Read block. Take care for partial reads. */
|
||||
do
|
||||
{
|
||||
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
|
||||
|
||||
sum += n;
|
||||
}
|
||||
while (sum < BLOCKSIZE && n != 0);
|
||||
if (n == 0 && ferror (stream))
|
||||
return 1;
|
||||
|
||||
/* If end of file is reached, end the loop. */
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||
BLOCKSIZE % 64 == 0
|
||||
*/
|
||||
md5_process_block (buffer, BLOCKSIZE, &ctx);
|
||||
}
|
||||
|
||||
/* Add the last bytes if necessary. */
|
||||
if (sum > 0)
|
||||
md5_process_bytes (buffer, sum, &ctx);
|
||||
|
||||
/* Construct result in desired memory. */
|
||||
md5_finish_ctx (&ctx, resblock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
result is always in little endian byte order, so that a byte-wise
|
||||
output yields to the wanted ASCII representation of the message
|
||||
digest. */
|
||||
void *
|
||||
md5_buffer (buffer, len, resblock)
|
||||
const char *buffer;
|
||||
size_t len;
|
||||
void *resblock;
|
||||
{
|
||||
struct md5_ctx ctx;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
|
||||
/* Process whole buffer but last len % 64 bytes. */
|
||||
md5_process_bytes (buffer, len, &ctx);
|
||||
|
||||
/* Put result in desired memory area. */
|
||||
return md5_finish_ctx (&ctx, resblock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md5_process_bytes (buffer, len, ctx)
|
||||
const void *buffer;
|
||||
size_t len;
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (left_over + add > 64)
|
||||
{
|
||||
md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||
(left_over + add) & 63);
|
||||
ctx->buflen = (left_over + add) & 63;
|
||||
}
|
||||
|
||||
buffer = (const char *) buffer + add;
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len > 64)
|
||||
{
|
||||
md5_process_block (buffer, len & ~63, ctx);
|
||||
buffer = (const char *) buffer + (len & ~63);
|
||||
len &= 63;
|
||||
}
|
||||
|
||||
/* Move remaining bytes in internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy (ctx->buffer, buffer, len);
|
||||
ctx->buflen = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* These are the four functions used in the four steps of the MD5 algorithm
|
||||
and defined in the RFC 1321. The first function is a little bit optimized
|
||||
(as found in Colin Plumbs public domain implementation). */
|
||||
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
|
||||
#define FF(b, c, d) (d ^ (b & (c ^ d)))
|
||||
#define FG(b, c, d) FF (d, b, c)
|
||||
#define FH(b, c, d) (b ^ c ^ d)
|
||||
#define FI(b, c, d) (c ^ (b | ~d))
|
||||
|
||||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
It is assumed that LEN % 64 == 0. */
|
||||
|
||||
void
|
||||
md5_process_block (buffer, len, ctx)
|
||||
const void *buffer;
|
||||
size_t len;
|
||||
struct md5_ctx *ctx;
|
||||
{
|
||||
md5_uint32 correct_words[16];
|
||||
const md5_uint32 *words = buffer;
|
||||
size_t nwords = len / sizeof (md5_uint32);
|
||||
const md5_uint32 *endp = words + nwords;
|
||||
md5_uint32 A = ctx->A;
|
||||
md5_uint32 B = ctx->B;
|
||||
md5_uint32 C = ctx->C;
|
||||
md5_uint32 D = ctx->D;
|
||||
|
||||
/* First increment the byte count. RFC 1321 specifies the possible
|
||||
length of the file up to 2^64 bits. Here we only compute the
|
||||
number of bytes. Do a double word increment. */
|
||||
ctx->total[0] += len;
|
||||
if (ctx->total[0] < len)
|
||||
++ctx->total[1];
|
||||
|
||||
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||
the loop. */
|
||||
while (words < endp)
|
||||
{
|
||||
md5_uint32 *cwp = correct_words;
|
||||
md5_uint32 A_save = A;
|
||||
md5_uint32 B_save = B;
|
||||
md5_uint32 C_save = C;
|
||||
md5_uint32 D_save = D;
|
||||
|
||||
/* First round: using the given function, the context and a constant
|
||||
the next context is computed. Because the algorithms processing
|
||||
unit is a 32-bit word and it is determined to work on words in
|
||||
little endian byte order we perhaps have to change the byte order
|
||||
before the computation. To reduce the work for the next steps
|
||||
we store the swapped words in the array CORRECT_WORDS. */
|
||||
|
||||
#define OP(a, b, c, d, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
|
||||
++words; \
|
||||
CYCLIC (a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
|
||||
|
||||
/* Before we start, one word to the strange constants.
|
||||
They are defined in RFC 1321 as
|
||||
|
||||
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||
*/
|
||||
|
||||
/* Round 1. */
|
||||
OP (A, B, C, D, 7, 0xd76aa478);
|
||||
OP (D, A, B, C, 12, 0xe8c7b756);
|
||||
OP (C, D, A, B, 17, 0x242070db);
|
||||
OP (B, C, D, A, 22, 0xc1bdceee);
|
||||
OP (A, B, C, D, 7, 0xf57c0faf);
|
||||
OP (D, A, B, C, 12, 0x4787c62a);
|
||||
OP (C, D, A, B, 17, 0xa8304613);
|
||||
OP (B, C, D, A, 22, 0xfd469501);
|
||||
OP (A, B, C, D, 7, 0x698098d8);
|
||||
OP (D, A, B, C, 12, 0x8b44f7af);
|
||||
OP (C, D, A, B, 17, 0xffff5bb1);
|
||||
OP (B, C, D, A, 22, 0x895cd7be);
|
||||
OP (A, B, C, D, 7, 0x6b901122);
|
||||
OP (D, A, B, C, 12, 0xfd987193);
|
||||
OP (C, D, A, B, 17, 0xa679438e);
|
||||
OP (B, C, D, A, 22, 0x49b40821);
|
||||
|
||||
/* For the second to fourth round we have the possibly swapped words
|
||||
in CORRECT_WORDS. Redefine the macro to take an additional first
|
||||
argument specifying the function to use. */
|
||||
#undef OP
|
||||
#define OP(f, a, b, c, d, k, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += f (b, c, d) + correct_words[k] + T; \
|
||||
CYCLIC (a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Round 2. */
|
||||
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
|
||||
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
|
||||
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
|
||||
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
|
||||
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
|
||||
OP (FG, D, A, B, C, 10, 9, 0x02441453);
|
||||
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
|
||||
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
|
||||
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
|
||||
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
|
||||
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
|
||||
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
|
||||
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
|
||||
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
|
||||
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
|
||||
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
|
||||
|
||||
/* Round 3. */
|
||||
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
|
||||
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
|
||||
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
|
||||
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
|
||||
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
|
||||
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
|
||||
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
|
||||
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
|
||||
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
|
||||
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
|
||||
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
|
||||
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
|
||||
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
|
||||
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
|
||||
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
|
||||
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
|
||||
|
||||
/* Round 4. */
|
||||
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
|
||||
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
|
||||
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
|
||||
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
|
||||
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
|
||||
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
|
||||
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
|
||||
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
|
||||
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
|
||||
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
|
||||
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
|
||||
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
|
||||
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
|
||||
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
|
||||
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
|
||||
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
|
||||
|
||||
/* Add the starting values of the context. */
|
||||
A += A_save;
|
||||
B += B_save;
|
||||
C += C_save;
|
||||
D += D_save;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->A = A;
|
||||
ctx->B = B;
|
||||
ctx->C = C;
|
||||
ctx->D = D;
|
||||
}
|
Loading…
Reference in New Issue
Block a user