diff options
-rw-r--r-- | backends/ChangeLog | 14 | ||||
-rw-r--r-- | backends/Makefile.am | 2 | ||||
-rw-r--r-- | backends/i386_regs.c | 12 | ||||
-rw-r--r-- | backends/ia64_init.c | 4 | ||||
-rw-r--r-- | backends/ia64_regs.c | 219 | ||||
-rw-r--r-- | backends/ia64_retval.c | 223 | ||||
-rw-r--r-- | backends/ppc_regs.c | 8 | ||||
-rw-r--r-- | backends/s390_regs.c | 4 | ||||
-rw-r--r-- | tests/ChangeLog | 5 | ||||
-rw-r--r-- | tests/allregs.c | 5 |
10 files changed, 480 insertions, 16 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog index e7416332..949f8375 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,17 @@ +2006-07-21 Roland McGrath <roland@redhat.com> + + * i386_regs.c (i386_register_name): Fix return value when using stpcpy. + * ppc_regs.c (ppc_register_name): Likewise. + * s390_regs.c (s390_register_name): Likewise. + + * ia64_retval.c: New file. + * Makefile.am (ia64_SRCS): Add it. + * ia64_init.c (ia64_init): Install return_value_location hook. + + * ia64_regs.c: New file. + * Makefile.am (ia64_SRCS): Add it. + * ia64_init.c (ia64_init): Install register_name hook. + 2006-07-05 Ulrich Drepper <drepper@redhat.com> * alpha_init.c: Initialize sysvhash_entrysize. diff --git a/backends/Makefile.am b/backends/Makefile.am index 13a809de..95143bcb 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -84,7 +84,7 @@ x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c \ libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS) am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os) -ia64_SRCS = ia64_init.c ia64_symbol.c +ia64_SRCS = ia64_init.c ia64_symbol.c ia64_regs.c ia64_retval.c libebl_ia64_pic_a_SOURCES = $(ia64_SRCS) am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os) diff --git a/backends/i386_regs.c b/backends/i386_regs.c index c2c21423..248700b6 100644 --- a/backends/i386_regs.c +++ b/backends/i386_regs.c @@ -1,5 +1,5 @@ /* Register names and numbers for i386 DWARF. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -72,9 +72,9 @@ i386_register_name (Ebl *ebl __attribute__ ((unused)), break; case 9: - return stpcpy (name, "eflags") - name; + return stpcpy (name, "eflags") + 1 - name; case 10: - return stpcpy (name, "trapno") - name; + return stpcpy (name, "trapno") + 1 - name; case 11 ... 18: name[0] = 's'; @@ -99,11 +99,11 @@ i386_register_name (Ebl *ebl __attribute__ ((unused)), break; case 37: - return stpcpy (name, "fctrl") - name; + return stpcpy (name, "fctrl") + 1 - name; case 38: - return stpcpy (name, "fstat") - name; + return stpcpy (name, "fstat") + 1 - name; case 39: - return stpcpy (name, "mxcsr") - name; + return stpcpy (name, "mxcsr") + 1 - name; case 40 ... 45: name[0] = "ecsdfg"[regno - 40]; diff --git a/backends/ia64_init.c b/backends/ia64_init.c index 42f0634b..490c774a 100644 --- a/backends/ia64_init.c +++ b/backends/ia64_init.c @@ -1,5 +1,5 @@ /* Initialization of IA-64 specific backend library. - Copyright (C) 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2002, 2003, 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -55,6 +55,8 @@ ia64_init (elf, machine, eh, ehlen) HOOK (eh, dynamic_tag_name); HOOK (eh, dynamic_tag_check); HOOK (eh, machine_flag_check); + HOOK (eh, register_name); + HOOK (eh, return_value_location); return MODVERSION; } diff --git a/backends/ia64_regs.c b/backends/ia64_regs.c new file mode 100644 index 00000000..bcb456e9 --- /dev/null +++ b/backends/ia64_regs.c @@ -0,0 +1,219 @@ +/* Register names and numbers for IA64 DWARF. + Copyright (C) 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils 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; version 2 of the License. + + Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#define BACKEND i386_ +#include "libebl_CPU.h" + +ssize_t +ia64_register_name (Ebl *ebl __attribute__ ((unused)), + int regno, char *name, size_t namelen, + const char **prefix, const char **setname) +{ + if (name == NULL) + return 687 + 64; + + if (regno < 0 || regno > 687 + 63 || namelen < 12) + return -1; + + *prefix = ""; + + *setname = "application"; + switch (regno) + { + case 0 ... 9: + name[0] = 'r'; + name[1] = (regno - 0) + '0'; + namelen = 2; + *setname = "integer"; + break; + + case 10 ... 99: + name[0] = 'r'; + name[1] = (regno - 0) / 10 + '0'; + name[2] = (regno - 0) % 10 + '0'; + namelen = 3; + *setname = "integer"; + break; + + case 100 ... 127: + name[0] = 'r'; + name[1] = '1'; + name[2] = (regno - 100) / 10 + '0'; + name[3] = (regno - 0) % 10 + '0'; + namelen = 4; + *setname = "integer"; + break; + + case 128 + 0 ... 128 + 9: + name[0] = 'f'; + name[1] = (regno - 128) + '0'; + namelen = 2; + *setname = "FPU"; + break; + + case 128 + 10 ... 128 + 99: + name[0] = 'f'; + name[1] = (regno - 128) / 10 + '0'; + name[2] = (regno - 128) % 10 + '0'; + namelen = 3; + *setname = "FPU"; + break; + + case 128 + 100 ... 128 + 127: + name[0] = 'f'; + name[1] = '1'; + name[2] = (regno - 128 - 100) / 10 + '0'; + name[3] = (regno - 128) % 10 + '0'; + namelen = 4; + *setname = "FPU"; + break; + + case 320 + 0 ... 320 + 7: + name[0] = 'b'; + name[1] = (regno - 320) + '0'; + namelen = 2; + *setname = "branch"; + break; + + case 328: + return stpcpy (name, "vfp") + 1 - name; + case 329: + return stpcpy (name, "vrap") + 1 - name; + case 330: + return stpcpy (name, "pr") + 1 - name; + case 331: + return stpcpy (name, "ip") + 1 - name; + case 332: + return stpcpy (name, "psr") + 1 - name; + case 333: + return stpcpy (name, "cfm") + 1 - name; + + case 334 + 0 ... 334 + 7: + name[0] = 'k'; + name[1] = 'r'; + name[2] = (regno - 334) + '0'; + namelen = 3; + break; + + case 350: + return stpcpy (name, "rsc") + 1 - name; + case 351: + return stpcpy (name, "bsp") + 1 - name; + case 352: + return stpcpy (name, "bspstore") + 1 - name; + case 353: + return stpcpy (name, "rnat") + 1 - name; + case 355: + return stpcpy (name, "fcr") + 1 - name; + case 358: + return stpcpy (name, "eflag") + 1 - name; + case 359: + return stpcpy (name, "csd") + 1 - name; + case 360: + return stpcpy (name, "ssd") + 1 - name; + case 361: + return stpcpy (name, "cflg") + 1 - name; + case 362: + return stpcpy (name, "fsr") + 1 - name; + case 363: + return stpcpy (name, "fir") + 1 - name; + case 364: + return stpcpy (name, "fdr") + 1 - name; + case 366: + return stpcpy (name, "ccv") + 1 - name; + case 370: + return stpcpy (name, "unat") + 1 - name; + case 374: + return stpcpy (name, "fpsr") + 1 - name; + case 378: + return stpcpy (name, "itc") + 1 - name; + case 398: + return stpcpy (name, "pfs") + 1 - name; + case 399: + return stpcpy (name, "lc") + 1 - name; + case 400: + return stpcpy (name, "ec") + 1 - name; + + case 462 + 0 ... 462 + 9: + name[0] = 'n'; + name[1] = 'a'; + name[2] = 't'; + name[3] = (regno - 462) + '0'; + namelen = 4; + *setname = "NAT"; + break; + + case 462 + 10 ... 462 + 99: + name[0] = 'n'; + name[1] = 'a'; + name[2] = 't'; + name[3] = (regno - 462) / 10 + '0'; + name[4] = (regno - 462) % 10 + '0'; + namelen = 5; + *setname = "NAT"; + break; + + case 462 + 100 ... 462 + 127: + name[0] = 'n'; + name[1] = 'a'; + name[2] = 't'; + name[3] = (regno - 462 - 100) / 10 + '0'; + name[4] = (regno - 462) % 10 + '0'; + namelen = 5; + *setname = "NAT"; + break; + + case 590: + return stpcpy (name, "bof") + 1 - name; + + case 687 + 0 ... 687 + 9: + name[0] = 'p'; + name[1] = (regno - 687) + '0'; + namelen = 2; + *setname = "predicate"; + break; + + case 687 + 10 ... 687 + 63: + name[0] = 'p'; + name[1] = (regno - 687) / 10 + '0'; + name[2] = (regno - 687) % 10 + '0'; + namelen = 3; + *setname = "predicate"; + break; + + default: + *setname = NULL; + return 0; + } + + name[namelen++] = '\0'; + return namelen; +} diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c new file mode 100644 index 00000000..b66fe5c2 --- /dev/null +++ b/backends/ia64_retval.c @@ -0,0 +1,223 @@ +/* Function return value location for IA64 ABI. + Copyright (C) 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils 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; version 2 of the License. + + Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> + +#define BACKEND ia64_ +#include "libebl_CPU.h" + + +/* r8, or pair r8, r9, or aggregate up to r8-r11. */ +static const Dwarf_Op loc_intreg[] = + { + { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_reg10 }, { .atom = DW_OP_piece, .number = 8 }, + { .atom = DW_OP_reg11 }, { .atom = DW_OP_piece, .number = 8 }, + }; +#define nloc_intreg 1 +#define nloc_intregs(n) (2 * (n)) + +/* f8, or aggregate up to f8-f15. */ +#define DEFINE_FPREG(size) \ + static const Dwarf_Op loc_fpreg_##size[] = \ + { \ + { .atom = DW_OP_regx, .number = 128 + 8 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 9 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 10 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 11 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 12 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 13 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 14 }, \ + { .atom = DW_OP_piece, .number = size }, \ + { .atom = DW_OP_regx, .number = 128 + 15 }, \ + { .atom = DW_OP_piece, .number = size }, \ + } +#define nloc_fpreg 1 +#define nloc_fpregs(n) (2 * (n)) + +DEFINE_FPREG (4); +DEFINE_FPREG (8); +DEFINE_FPREG (10); + +#undef DEFINE_FPREG + + +/* The return value is a structure and is actually stored in stack space + passed in a hidden argument by the caller. But, the compiler + helpfully returns the address of that space in r8. */ +static const Dwarf_Op loc_aggregate[] = + { + { .atom = DW_OP_breg8, .number = 0 } + }; +#define nloc_aggregate 1 + + +int +ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) +{ + /* Start with the function's type, and get the DW_AT_type attribute, + which is the type of the return value. */ + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr (functypedie, DW_AT_type, &attr_mem); + if (attr == NULL) + /* The function has no return value, like a `void' function in C. */ + return 0; + + Dwarf_Die die_mem; + Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); + int tag = dwarf_tag (typedie); + + /* Follow typedefs and qualifiers to get to the actual type. */ + while (tag == DW_TAG_typedef + || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type + || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type) + { + attr = dwarf_attr (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + + Dwarf_Word size; + switch (tag) + { + case -1: + return -1; + + case DW_TAG_subrange_type: + if (! dwarf_hasattr (typedie, DW_AT_byte_size)) + { + attr = dwarf_attr (typedie, DW_AT_type, &attr_mem); + typedie = dwarf_formref_die (attr, &die_mem); + tag = dwarf_tag (typedie); + } + /* Fall through. */ + + case DW_TAG_base_type: + case DW_TAG_enumeration_type: + case DW_TAG_pointer_type: + case DW_TAG_ptr_to_member_type: + if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size, + &attr_mem), &size) != 0) + { + if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) + size = 8; + else + return -1; + } + if (tag == DW_TAG_base_type) + { + Dwarf_Word encoding; + if (dwarf_formudata (dwarf_attr (typedie, DW_AT_encoding, + &attr_mem), &encoding) != 0) + return -1; + + switch (encoding) + { + case DW_ATE_float: + switch (size) + { + case 4: /* float */ + *locp = loc_fpreg_4; + return nloc_fpreg; + case 8: /* double */ + *locp = loc_fpreg_8; + return nloc_fpreg; + case 10: /* x86-style long double, not really used */ + *locp = loc_fpreg_10; + return nloc_fpreg; + case 16: /* long double, IEEE quad format */ + *locp = loc_intreg; + return nloc_intregs (2); + } + return -2; + + case DW_ATE_complex_float: + switch (size) + { + case 4 * 2: /* complex float */ + *locp = loc_fpreg_4; + return nloc_fpregs (2); + case 8 * 2: /* complex double */ + *locp = loc_fpreg_8; + return nloc_fpregs (2); + case 10 * 2: /* complex long double (x86-style) */ + *locp = loc_fpreg_10; + return nloc_fpregs (2); + case 16 * 2: /* complex long double (IEEE quad) */ + *locp = loc_intreg; + return nloc_intregs (4); + } + return -2; + } + } + + intreg: + *locp = loc_intreg; + if (size <= 8) + return nloc_intreg; + if (size <= 32) + return nloc_intregs ((size + 7) / 8); + + large: + *locp = loc_aggregate; + return nloc_aggregate; + + case DW_TAG_structure_type: + case DW_TAG_class_type: + case DW_TAG_union_type: + case DW_TAG_array_type: + if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size, + &attr_mem), &size) != 0) + return -1; + if (size > 32) + goto large; + + /* XXX + Must examine the fields in picayune ways to determine the + actual answer. If it qualifies as an HFA (all floats) + then it should be returned in fp regs. + */ + + goto intreg; + } + + /* XXX We don't have a good way to return specific errors from ebl calls. + This value means we do not understand the type, but it is well-formed + DWARF and might be valid. */ + return -2; +} diff --git a/backends/ppc_regs.c b/backends/ppc_regs.c index 3d3d904d..bea8d357 100644 --- a/backends/ppc_regs.c +++ b/backends/ppc_regs.c @@ -1,5 +1,5 @@ /* Register names and numbers for PowerPC DWARF. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -83,11 +83,11 @@ ppc_register_name (Ebl *ebl __attribute__ ((unused)), break; case 64: - return stpcpy (name, "cr") - name; + return stpcpy (name, "cr") + 1 - name; case 65: - return stpcpy (name, "fpscr") - name; + return stpcpy (name, "fpscr") + 1 - name; case 66: - return stpcpy (name, "msr") - name; + return stpcpy (name, "msr") + 1 - name; case 70 + 0 ... 70 + 9: name[0] = 's'; diff --git a/backends/s390_regs.c b/backends/s390_regs.c index 61c60744..28b79898 100644 --- a/backends/s390_regs.c +++ b/backends/s390_regs.c @@ -114,9 +114,9 @@ s390_register_name (Ebl *ebl __attribute__ ((unused)), break; case 64: - return stpcpy (name, "pswm") - name; + return stpcpy (name, "pswm") + 1 - name; case 65: - return stpcpy (name, "pswa") - name; + return stpcpy (name, "pswa") + 1 - name; default: *setname = NULL; diff --git a/tests/ChangeLog b/tests/ChangeLog index cbb4ac7e..070b2f52 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2006-07-21 Roland McGrath <roland@redhat.com> + + * allregs.c (struct reginfo): Increase size of name. + (one_register): Assert that it's big enough. + 2006-04-04 Roland McGrath <roland@redhat.com> * run-bug1-test.sh: Test a second case, to cover both byte orders. diff --git a/tests/allregs.c b/tests/allregs.c index bad4c85e..baec94ed 100644 --- a/tests/allregs.c +++ b/tests/allregs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Red Hat, Inc. +/* Copyright (C) 2005, 2006 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -62,7 +62,7 @@ struct reginfo { const char *set, *pfx; int regno; - char name[8]; + char name[32]; }; static int @@ -103,6 +103,7 @@ one_register (void *arg, state->info[regno].regno = regno; state->info[regno].set = setname; state->info[regno].pfx = prefix; + assert (strlen (regname) < sizeof state->info[regno].name); strcpy (state->info[regno].name, regname); return DWARF_CB_OK; |