From 8ced9d34ff56ac4435c9176617e738a9a715cbd5 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 31 Aug 1999 01:08:26 +0000 Subject: [PATCH] Initial revision --- gdb/gdb-events.c | 227 +++++ gdb/gdb-events.h | 97 ++ gdb/gdb-events.sh | 568 ++++++++++++ gdb/gdbarch.sh | 1858 ++++++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.base/async.c | 48 + gdb/testsuite/gdb.base/async.exp | 153 ++++ 6 files changed, 2951 insertions(+) create mode 100644 gdb/gdb-events.c create mode 100644 gdb/gdb-events.h create mode 100755 gdb/gdb-events.sh create mode 100755 gdb/gdbarch.sh create mode 100644 gdb/testsuite/gdb.base/async.c create mode 100644 gdb/testsuite/gdb.base/async.exp diff --git a/gdb/gdb-events.c b/gdb/gdb-events.c new file mode 100644 index 0000000000..a8c41925de --- /dev/null +++ b/gdb/gdb-events.c @@ -0,0 +1,227 @@ +/* User Interface Events. + Copyright 1999 Free Software Foundation, Inc. + + Contributed by Cygnus Solutions. + +This file is part of GDB. + +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. */ + +/* Work in progress */ + +/* This file was created with the aid of ``gdb-events.sh''. + + The bourn shell script ``gdb-events.sh'' creates the files + ``new-gdb-events.c'' and ``new-gdb-events.h and then compares + them against the existing ``gdb-events.[hc]''. Any differences + found being reported. + + If editing this file, please also run gdb-events.sh and merge any + changes into that script. Conversely, when making sweeping changes + to this file, modifying gdb-events.sh and using its output may + prove easier. */ + + +#include "defs.h" +#include "gdb-events.h" +#include "gdbcmd.h" + +#undef XMALLOC +#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) + +#if WITH_GDB_EVENTS +static struct gdb_events null_event_hooks; +static struct gdb_events queue_event_hooks; +static struct gdb_events *current_event_hooks = &null_event_hooks; +#endif + +int gdb_events_debug; + +#if WITH_GDB_EVENTS + +void +breakpoint_create_event (int b) +{ + if (gdb_events_debug) + fprintf_unfiltered (gdb_stdlog, "breakpoint_create_event\n"); + if (!current_event_hooks->breakpoint_create) + return; + current_event_hooks->breakpoint_create (b); +} + +void +breakpoint_delete_event (int b) +{ + if (gdb_events_debug) + fprintf_unfiltered (gdb_stdlog, "breakpoint_delete_event\n"); + if (!current_event_hooks->breakpoint_delete) + return; + current_event_hooks->breakpoint_delete (b); +} + +void +breakpoint_modify_event (int b) +{ + if (gdb_events_debug) + fprintf_unfiltered (gdb_stdlog, "breakpoint_modify_event\n"); + if (!current_event_hooks->breakpoint_modify) + return; + current_event_hooks->breakpoint_modify (b); +} + +#endif + +#if WITH_GDB_EVENTS +void +set_gdb_event_hooks (struct gdb_events *vector) +{ + if (vector == NULL) + current_event_hooks = &queue_event_hooks; + else + current_event_hooks = vector; +} +#endif + +enum gdb_event + { + breakpoint_create, + breakpoint_delete, + breakpoint_modify, + nr_gdb_events + }; + +struct breakpoint_create + { + int b; + }; + +struct breakpoint_delete + { + int b; + }; + +struct breakpoint_modify + { + int b; + }; + +struct event + { + enum gdb_event type; + struct event *next; + union + { + struct breakpoint_create breakpoint_create; + struct breakpoint_delete breakpoint_delete; + struct breakpoint_modify breakpoint_modify; + } + data; + }; +struct event *pending_events; +struct event *delivering_events; + +static void +append (struct event *new_event) +{ + struct event **event = &pending_events; + while ((*event) != NULL) + event = &((*event)->next); + (*event) = new_event; + (*event)->next = NULL; +} + +static void +queue_breakpoint_create (int b) +{ + struct event *event = XMALLOC (struct event); + event->type = breakpoint_create; + event->data.breakpoint_create.b = b; + append (event); +} + +static void +queue_breakpoint_delete (int b) +{ + struct event *event = XMALLOC (struct event); + event->type = breakpoint_delete; + event->data.breakpoint_delete.b = b; + append (event); +} + +static void +queue_breakpoint_modify (int b) +{ + struct event *event = XMALLOC (struct event); + event->type = breakpoint_modify; + event->data.breakpoint_modify.b = b; + append (event); +} + +void +gdb_events_deliver (struct gdb_events *vector) +{ + /* Just zap any events left around from last time. */ + while (delivering_events != NULL) + { + struct event *event = delivering_events; + delivering_events = event->next; + free (event); + } + /* Process any pending events. Because one of the deliveries could + bail out we move everything off of the pending queue onto an + in-progress queue where it can, later, be cleaned up if + necessary. */ + delivering_events = pending_events; + pending_events = NULL; + while (delivering_events != NULL) + { + struct event *event = delivering_events; + switch (event->type) + { + case breakpoint_create: + vector->breakpoint_create + (event->data.breakpoint_create.b); + break; + case breakpoint_delete: + vector->breakpoint_delete + (event->data.breakpoint_delete.b); + break; + case breakpoint_modify: + vector->breakpoint_modify + (event->data.breakpoint_modify.b); + break; + } + delivering_events = event->next; + free (event); + } +} + +void _initialize_gdb_events (void); +void +_initialize_gdb_events (void) +{ +#if WITH_GDB_EVENTS + queue_event_hooks.breakpoint_create = queue_breakpoint_create; + queue_event_hooks.breakpoint_delete = queue_breakpoint_delete; + queue_event_hooks.breakpoint_modify = queue_breakpoint_modify; +#endif + add_show_from_set (add_set_cmd ("eventdebug", + class_maintenance, + var_zinteger, + (char *)&gdb_events_debug, + "Set event debugging.\n\ +When non-zero, event/notify debugging is enabled.", &setlist), + &showlist); +} diff --git a/gdb/gdb-events.h b/gdb/gdb-events.h new file mode 100644 index 0000000000..ab6051717f --- /dev/null +++ b/gdb/gdb-events.h @@ -0,0 +1,97 @@ +/* User Interface Events. + Copyright 1999 Free Software Foundation, Inc. + + Contributed by Cygnus Solutions. + +This file is part of GDB. + +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. */ + +/* Work in progress */ + +/* This file was created with the aid of ``gdb-events.sh''. + + The bourn shell script ``gdb-events.sh'' creates the files + ``new-gdb-events.c'' and ``new-gdb-events.h and then compares + them against the existing ``gdb-events.[hc]''. Any differences + found being reported. + + If editing this file, please also run gdb-events.sh and merge any + changes into that script. Conversely, when making sweeping changes + to this file, modifying gdb-events.sh and using its output may + prove easier. */ + + +#ifndef GDB_EVENTS_H +#define GDB_EVENTS_H + +#ifndef WITH_GDB_EVENTS +#define WITH_GDB_EVENTS 1 +#endif + + +/* COMPAT: pointer variables for old, unconverted events. + A call to set_gdb_events() will automatically update these. */ + + + +/* Type definition of all hook functions. + Recommended pratice is to first declare each hook function using + the below ftype and then define it. */ + +typedef void (gdb_events_breakpoint_create_ftype) (int b); +typedef void (gdb_events_breakpoint_delete_ftype) (int b); +typedef void (gdb_events_breakpoint_modify_ftype) (int b); + + +/* gdb-events: object. */ + +struct gdb_events + { + gdb_events_breakpoint_create_ftype *breakpoint_create; + gdb_events_breakpoint_delete_ftype *breakpoint_delete; + gdb_events_breakpoint_modify_ftype *breakpoint_modify; + }; + + +/* Interface into events functions. + Where a *_p() predicate is present, it must called before calling + the hook proper. */ +extern void breakpoint_create_event (int b); +extern void breakpoint_delete_event (int b); +extern void breakpoint_modify_event (int b); + + +/* When GDB_EVENTS are not being used, completly disable them. */ + +#if !WITH_GDB_EVENTS +#define breakpoint_create_event(b) 0 +#define breakpoint_delete_event(b) 0 +#define breakpoint_modify_event(b) 0 +#endif + +/* Install custom gdb-events hooks. */ +extern void set_gdb_event_hooks (struct gdb_events *vector); + +/* Deliver any pending events. */ +extern void gdb_events_deliver (struct gdb_events *vector); + +#if !WITH_GDB_EVENTS +#define set_gdb_events(x) 0 +#define set_gdb_event_hooks(x) 0 +#define gdb_events_deliver(x) 0 +#endif + +#endif diff --git a/gdb/gdb-events.sh b/gdb/gdb-events.sh new file mode 100755 index 0000000000..ab70bb19d0 --- /dev/null +++ b/gdb/gdb-events.sh @@ -0,0 +1,568 @@ +#!/bin/sh + +# User Interface Events. +# Copyright 1999 Free Software Foundation, Inc. +# +# Contributed by Cygnus Solutions. +# +# This file is part of GDB. +# +# 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. + +# +# What happens next: +# + +# The gdb-events.h/gdb-events.c files this script generates are commited +# and published. + +# Any UI module that is installing events is changed so that the +# events are installed using the ``set_gdb_events()'' and +# ``gdb_event_hooks()'' interfaces. There could prove to be an issue +# here with respect to annotate. We might need to accomodate a hook +# stack that allows several ui blocks to install their own events. + +# Each of the variable events (as currently generated) is converteded +# to either a straight function call or a function call with a +# predicate. + + +IFS=: + +read="class returntype function formal actual attrib" + +function_list () +{ + # category: + # # -> disable + # * -> compatibility - pointer variable that is initialized + # by set_gdb_events(). + # ? -> Predicate and function proper. + # f -> always call (must have a void returntype) + # return-type + # name + # formal argument list + # actual argument list + # attributes + # description + cat < new-gdb-events.h +copyright +cat <&2 +#../move-if-change new-gdb-events.h gdb-events.h +if ! test -r gdb-events.h +then + echo "File missing? mv new-gdb-events.h gdb-events.h" 1>&2 +elif ! diff -c gdb-events.h new-gdb-events.h +then + echo "gdb-events.h changed? cp new-gdb-events.h gdb-events.h" 1>&2 +fi + + + +# +# C file +# + +exec > new-gdb-events.c +copyright +cat <${function};" + echo "}" + echo "" + echo "${returntype}" + echo "${function}_event (${formal})" + echo "{" + echo " return current_events->${function} (${actual});" + echo "}" + ;; + "f" ) + echo "" + echo "void" + echo "${function}_event (${formal})" + echo "{" + echo " if (gdb_events_debug)" + echo " fprintf_unfiltered (gdb_stdlog, \"${function}_event\\n\");" + echo " if (!current_event_hooks->${function})" + echo " return;" + echo " current_event_hooks->${function} (${actual});" + echo "}" + ;; + esac +done +echo "" +echo "#endif" + +# Set hooks function +echo "" +cat <${function};" + ;; + esac +done +cat <next); + (*event) = new_event; + (*event)->next = NULL; +} +EOF + +# schedule a given event +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo "" + echo "static void" + echo "queue_${function} (${formal})" + echo "{" + echo " struct event *event = XMALLOC (struct event);" + echo " event->type = ${function};" + for arg in `echo ${actual} | tr '[,]' '[ ]'`; do + echo " event->data.${function}.${arg} = ${arg};" + done + echo " append (event);" + echo "}" + ;; + esac +done + +# deliver +echo "" +cat <next; + free (event); + } + /* Process any pending events. Because one of the deliveries could + bail out we move everything off of the pending queue onto an + in-progress queue where it can, later, be cleaned up if + necessary. */ + delivering_events = pending_events; + pending_events = NULL; + while (delivering_events != NULL) + { + struct event *event = delivering_events; + switch (event->type) + { +EOF +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo " case ${function}:" + echo " vector->${function}" + sep=" (" + ass="" + for arg in `echo ${actual} | tr '[,]' '[ ]'`; do + ass="${ass}${sep}event->data.${function}.${arg}" + sep=", + " + done + echo "${ass});" + echo " break;" + ;; + esac +done +cat <next; + free (event); + } +} +EOF + +# Finally the initialization +echo "" +cat <&2 +#../move-if-change new-gdb-events.c gdb-events.c +if ! test -r gdb-events.c +then + echo "File missing? mv new-gdb-events.c gdb-events.c" 1>&2 +elif ! diff -c gdb-events.c new-gdb-events.c +then + echo "gdb-events.c changed? cp new-gdb-events.c gdb-events.c" 1>&2 +fi diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh new file mode 100755 index 0000000000..5ad6b65fa6 --- /dev/null +++ b/gdb/gdbarch.sh @@ -0,0 +1,1858 @@ +#!/usr/local/bin/bash + +# Architecture commands for GDB, the GNU debugger. +# Copyright 1998-1999 Free Software Foundation, Inc. +# +# This file is part of GDB. +# +# 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. + +IFS=: + +read="class level macro returntype function formal actual attrib default init init_p fmt print print_p description" + +function_list () +{ + # category: + # # -> disable + # f -> function + # v -> variable + # i -> set from info + # macro-name + # return-type + # name + # formal argument list + # actual argument list + # attrib + # default exp + # init exp + # init_p exp + # print + # description + cat <printable_name:TARGET_ARCHITECTURE != NULL +# +i:2:TARGET_BYTE_ORDER:int:byte_order::::BIG_ENDIAN +# +v:1:TARGET_PTR_BIT:int:ptr_bit::::8 * sizeof (void*):0 +#v:1:TARGET_CHAR_BIT:int:char_bit::::8 * sizeof (char):0 +v:1:TARGET_SHORT_BIT:int:short_bit::::8 * sizeof (short):0 +v:1:TARGET_INT_BIT:int:int_bit::::8 * sizeof (int):0 +v:1:TARGET_LONG_BIT:int:long_bit::::8 * sizeof (long):0 +v:1:TARGET_LONG_LONG_BIT:int:long_long_bit::::8 * sizeof (LONGEST):0 +v:1:TARGET_FLOAT_BIT:int:float_bit::::8 * sizeof (float):0 +v:1:TARGET_DOUBLE_BIT:int:double_bit::::8 * sizeof (double):0 +v:1:TARGET_LONG_DOUBLE_BIT:int:long_double_bit::::8 * sizeof (long double):0 +# +f:1:TARGET_READ_PC:CORE_ADDR:read_pc:int pid:pid::0:0 +f:1:TARGET_WRITE_PC:void:write_pc:CORE_ADDR val, int pid:val, pid::0:0 +f:1:TARGET_READ_FP:CORE_ADDR:read_fp:void:::0:0 +f:1:TARGET_WRITE_FP:void:write_fp:CORE_ADDR val:val::0:0 +f:1:TARGET_READ_SP:CORE_ADDR:read_sp:void:::0:0 +f:1:TARGET_WRITE_SP:void:write_sp:CORE_ADDR val:val::0:0 +# +v:2:NUM_REGS:int:num_regs::::0:-1 +v:2:SP_REGNUM:int:sp_regnum::::0:-1 +v:2:FP_REGNUM:int:fp_regnum::::0:-1 +v:2:PC_REGNUM:int:pc_regnum::::0:-1 +f:2:REGISTER_NAME:char *:register_name:int regnr:regnr::0:0 +v:2:REGISTER_SIZE:int:register_size::::0:-1 +v:2:REGISTER_BYTES:int:register_bytes::::0:-1 +f:2:REGISTER_BYTE:int:register_byte:int reg_nr:reg_nr::0:0 +f:2:REGISTER_RAW_SIZE:int:register_raw_size:int reg_nr:reg_nr::0:0 +v:2:MAX_REGISTER_RAW_SIZE:int:max_register_raw_size::::0:-1 +f:2:REGISTER_VIRTUAL_SIZE:int:register_virtual_size:int reg_nr:reg_nr::0:0 +v:2:MAX_REGISTER_VIRTUAL_SIZE:int:max_register_virtual_size::::0:-1 +f:2:REGISTER_VIRTUAL_TYPE:struct type *:register_virtual_type:int reg_nr:reg_nr::0:0 +# +v:1:USE_GENERIC_DUMMY_FRAMES:int:use_generic_dummy_frames::::0:-1 +v:2:CALL_DUMMY_LOCATION:int:call_dummy_location::::0:0 +f:2:CALL_DUMMY_ADDRESS:CORE_ADDR:call_dummy_address:void:::0:0:gdbarch->call_dummy_location == AT_ENTRY_POINT && gdbarch->call_dummy_address == 0: +v:2:CALL_DUMMY_START_OFFSET:CORE_ADDR:call_dummy_start_offset::::0:-1::0x%08lx +v:2:CALL_DUMMY_BREAKPOINT_OFFSET:CORE_ADDR:call_dummy_breakpoint_offset::::0:-1::0x%08lx +v:1:CALL_DUMMY_BREAKPOINT_OFFSET_P:int:call_dummy_breakpoint_offset_p::::0:-1 +v:2:CALL_DUMMY_LENGTH:int:call_dummy_length::::0:-1::::CALL_DUMMY_LOCATION == BEFORE_TEXT_END || CALL_DUMMY_LOCATION == AFTER_TEXT_END +f:2:PC_IN_CALL_DUMMY:int:pc_in_call_dummy:CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address:pc, sp, frame_address::0:0 +v:1:CALL_DUMMY_P:int:call_dummy_p::::0:-1 +v:2:CALL_DUMMY_WORDS:LONGEST *:call_dummy_words::::0:::0x%08lx +v:2:SIZEOF_CALL_DUMMY_WORDS:int:sizeof_call_dummy_words::::0:::0x%08lx +v:1:CALL_DUMMY_STACK_ADJUST_P:int:call_dummy_stack_adjust_p::::0:-1::0x%08lx +v:2:CALL_DUMMY_STACK_ADJUST:int:call_dummy_stack_adjust::::0::gdbarch->call_dummy_stack_adjust_p && gdbarch->call_dummy_stack_adjust == 0:0x%08lx::CALL_DUMMY_STACK_ADJUST_P +f:2:FIX_CALL_DUMMY:void:fix_call_dummy:char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, struct value **args, struct type *type, int gcc_p:dummy, pc, fun, nargs, args, type, gcc_p::0:0 +# +v:2:BELIEVE_PCC_PROMOTION:int:believe_pcc_promotion::::0:::::# +v:2:BELIEVE_PCC_PROMOTION_TYPE:int:believe_pcc_promotion_type::::0:::::# +f:1:GET_SAVED_REGISTER:void:get_saved_register:char *raw_buffer, int *optimized, CORE_ADDR *addrp, struct frame_info *frame, int regnum, enum lval_type *lval:raw_buffer, optimized, addrp, frame, regnum, lval::generic_get_saved_register:0 +# +f:1:REGISTER_CONVERTIBLE:int:register_convertible:int nr:nr::0:0 +f:2:REGISTER_CONVERT_TO_VIRTUAL:void:register_convert_to_virtual:int regnum, struct type *type, char *from, char *to:regnum, type, from, to::0:0 +f:2:REGISTER_CONVERT_TO_RAW:void:register_convert_to_raw:struct type *type, int regnum, char *from, char *to:type, regnum, from, to::0:0 +# +f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf::0:0 +f:1:PUSH_ARGUMENTS:CORE_ADDR:push_arguments:int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr:nargs, args, sp, struct_return, struct_addr::0:0 +f:2:PUSH_DUMMY_FRAME:void:push_dummy_frame:void:-::0:0 +f:1:PUSH_RETURN_ADDRESS:CORE_ADDR:push_return_address:CORE_ADDR pc, CORE_ADDR sp:pc, sp::0:0 +f:2:POP_FRAME:void:pop_frame:void:-::0:0 +# +# I wish that these would just go away.... +f:2:D10V_MAKE_DADDR:CORE_ADDR:d10v_make_daddr:CORE_ADDR x:x::0:0 +f:2:D10V_MAKE_IADDR:CORE_ADDR:d10v_make_iaddr:CORE_ADDR x:x::0:0 +f:2:D10V_DADDR_P:int:d10v_daddr_p:CORE_ADDR x:x::0:0 +f:2:D10V_IADDR_P:int:d10v_iaddr_p:CORE_ADDR x:x::0:0 +f:2:D10V_CONVERT_DADDR_TO_RAW:CORE_ADDR:d10v_convert_daddr_to_raw:CORE_ADDR x:x::0:0 +f:2:D10V_CONVERT_IADDR_TO_RAW:CORE_ADDR:d10v_convert_iaddr_to_raw:CORE_ADDR x:x::0:0 +# +f:2:STORE_STRUCT_RETURN:void:store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp::0:0 +f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, char *valbuf:type, valbuf::0:0 +f:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:char *regbuf:regbuf::0:0 +f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type::0:0 +# +f:2:FRAME_INIT_SAVED_REGS:void:frame_init_saved_regs:struct frame_info *frame:frame::0:0 +f:2:INIT_EXTRA_FRAME_INFO:void:init_extra_frame_info:int fromleaf, struct frame_info *frame:fromleaf, frame::0:0 +# +f:2:SKIP_PROLOGUE:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip::0:0 +f:2:INNER_THAN:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs::0:0 +f:2:BREAKPOINT_FROM_PC:unsigned char *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0:0 +v:2:DECR_PC_AFTER_BREAK:CORE_ADDR:decr_pc_after_break::::0:-1 +v:2:FUNCTION_START_OFFSET:CORE_ADDR:function_start_offset::::0:-1 +# +f:2:REMOTE_TRANSLATE_XFER_ADDRESS:void:remote_translate_xfer_address:CORE_ADDR gdb_addr, int gdb_len, CORE_ADDR *rem_addr, int *rem_len:gdb_addr, gdb_len, rem_addr, rem_len::0:0 +# +v:2:FRAME_ARGS_SKIP:CORE_ADDR:frame_args_skip::::0:-1 +f:2:FRAMELESS_FUNCTION_INVOCATION:int:frameless_function_invocation:struct frame_info *fi:fi::0:0 +f:2:FRAME_CHAIN:CORE_ADDR:frame_chain:struct frame_info *frame:frame::0:0 +f:1:FRAME_CHAIN_VALID:int:frame_chain_valid:CORE_ADDR chain, struct frame_info *thisframe:chain, thisframe::0:0 +f:2:FRAME_SAVED_PC:CORE_ADDR:frame_saved_pc:struct frame_info *fi:fi::0:0 +f:2:FRAME_ARGS_ADDRESS:CORE_ADDR:frame_args_address:struct frame_info *fi:fi::0:0 +f:2:FRAME_LOCALS_ADDRESS:CORE_ADDR:frame_locals_address:struct frame_info *fi:fi::0:0 +f:2:SAVED_PC_AFTER_CALL:CORE_ADDR:saved_pc_after_call:struct frame_info *frame:frame::0:0 +f:2:FRAME_NUM_ARGS:int:frame_num_args:struct frame_info *frame:frame::0:0 +# +EOF + grep -v '^#' +} + + +# dump it out +if true +then + exec > new-gdbarch + function_list | while eval read $read + do + cat <&2 +fi + +copyright () +{ +cat < new-gdbarch.h +copyright +cat < 1) || !defined (${macro})" + echo "#define ${macro} (gdbarch_${function} (current_gdbarch))" + echo "#endif" + echo "#endif" + ;; + esac +done + +# function typedef's +echo "" +echo "" +echo "/* The following are initialized by the target dependant code. */" +function_list | while eval read $read +do + case "${class}" in + "v" ) + echo "" + echo "extern ${returntype} gdbarch_${function} (struct gdbarch *gdbarch);" + echo "extern void set_gdbarch_${function} (struct gdbarch *gdbarch, ${returntype} ${function});" + echo "#if GDB_MULTI_ARCH" + echo "#if (GDB_MULTI_ARCH > 1) || !defined (${macro})" + echo "#define ${macro} (gdbarch_${function} (current_gdbarch))" + echo "#endif" + echo "#endif" + ;; + "f" ) + echo "" + echo "typedef ${returntype} (gdbarch_${function}_ftype) (${formal});" + if [ "${formal}" = "void" ] + then + echo "extern ${returntype} gdbarch_${function} (struct gdbarch *gdbarch);" + else + echo "extern ${returntype} gdbarch_${function} (struct gdbarch *gdbarch, ${formal});" + fi + echo "extern void set_gdbarch_${function} (struct gdbarch *gdbarch, gdbarch_${function}_ftype *${function});" + echo "#if GDB_MULTI_ARCH" + echo "#if (GDB_MULTI_ARCH > 1) || !defined (${macro})" + if [ "${actual}" = "" ] + then + echo "#define ${macro}() (gdbarch_${function} (current_gdbarch))" + elif [ "${actual}" = "-" ] + then + echo "#define ${macro} (gdbarch_${function} (current_gdbarch))" + else + echo "#define ${macro}(${actual}) (gdbarch_${function} (current_gdbarch, ${actual}))" + fi + echo "#endif" + echo "#endif" + ;; + esac +done + +# close it off +cat <arch == bfd_arch_d10v) +#ifndef D10V_MAKE_DADDR +#define D10V_MAKE_DADDR(X) (internal_error ("gdbarch: D10V_MAKE_DADDR"), 0) +#endif +#ifndef D10V_MAKE_IADDR +#define D10V_MAKE_IADDR(X) (internal_error ("gdbarch: D10V_MAKE_IADDR"), 0) +#endif + + +/* Fallback definition of FRAMELESS_FUNCTION_INVOCATION */ +#ifndef FRAMELESS_FUNCTION_INVOCATION +#define FRAMELESS_FUNCTION_INVOCATION(FI) (0) +#endif + + +/* Fallback definition of REGISTER_CONVERTIBLE etc */ +extern int generic_register_convertible_not (int reg_nr); +#ifndef REGISTER_CONVERTIBLE +#define REGISTER_CONVERTIBLE(x) (0) +#endif +#ifndef REGISTER_CONVERT_TO_VIRTUAL +#define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a) +#endif +#ifndef REGISTER_CONVERT_TO_RAW +#define REGISTER_CONVERT_TO_RAW(x, y, z, a) +#endif + + +/* Fallback definition for EXTRACT_STRUCT_VALUE_ADDRESS */ +#ifndef EXTRACT_STRUCT_VALUE_ADDRESS +#define EXTRACT_STRUCT_VALUE_ADDRESS_P (0) +#define EXTRACT_STRUCT_VALUE_ADDRESS(X) (internal_error ("gdbarch: EXTRACT_STRUCT_VALUE_ADDRESS"), 0) +#else +#ifndef EXTRACT_STRUCT_VALUE_ADDRESS_P +#define EXTRACT_STRUCT_VALUE_ADDRESS_P (1) +#endif +#endif + + +/* Fallback definition for REGISTER_NAME for systems still defining + REGISTER_NAMES. */ +#ifndef REGISTER_NAME +extern char *gdb_register_names[]; +#define REGISTER_NAME(i) gdb_register_names[i] +#endif + + +/* Set the dynamic target-system-dependant parameters (architecture, + byte-order, ...) using information found in the BFD */ + +extern void set_gdbarch_from_file (bfd *); + + +/* Explicitly set the dynamic target-system-dependant parameters based + on bfd_architecture and machine. */ + +extern void set_architecture_from_arch_mach (enum bfd_architecture, unsigned long); + + +/* Helper function for targets that don't know how my arguments are + being passed */ + +extern int frame_num_args_unknown (struct frame_info *fi); + + +/* gdbarch trace variable */ +extern int gdbarch_debug; + +extern void gdbarch_dump (void); + +#endif +EOF +exec 1>&2 +#../move-if-change new-gdbarch.h gdbarch.h +if ! test -r gdbarch.h +then + echo "gdbarch.h missing? cp new-gdbarch.h gdbarch.h" 1>&2 +elif diff -c gdbarch.h new-gdbarch.h +then + echo "gdbarch.h unchanged" 1>&2 +else + echo "gdbarch.h has changed? cp new-gdbarch.h gdbarch.h" 1>&2 +fi + + +# +# C file +# + +exec > new-gdbarch.c +copyright +cat < +#include "symtab.h" +#include "frame.h" +#include "inferior.h" +#include "breakpoint.h" +#include "wait.h" +#include "gdbcore.h" +#include "gdbcmd.h" +#include "target.h" +#include "gdbthread.h" +#include "annotate.h" +#include "symfile.h" /* for overlay functions */ +#endif +#include "symcat.h" + + +/* Static function declarations */ + +static void verify_gdbarch (struct gdbarch *gdbarch); +static void init_gdbarch_data (struct gdbarch *); +static void init_gdbarch_swap (struct gdbarch *); +static void swapout_gdbarch_swap (struct gdbarch *); +static void swapin_gdbarch_swap (struct gdbarch *); + +/* Convenience macro for allocting typesafe memory. */ + +#ifndef XMALLOC +#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) +#endif + + +/* Non-zero if we want to trace architecture code. */ + +#ifndef GDBARCH_DEBUG +#define GDBARCH_DEBUG 0 +#endif +int gdbarch_debug = GDBARCH_DEBUG; + +EOF + +# gdbarch open the gdbarch object +echo "" +echo "/* Maintain the struct gdbarch object */" +echo "" +echo "struct gdbarch" +echo "{" +echo " /* basic architectural information */" +function_list | while eval read $read +do + case "${class}" in + "i" ) echo " ${returntype} ${function};" ;; + esac +done +echo "" +echo " /* target specific vector. */" +echo " struct gdbarch_tdep *tdep;" +echo "" +echo " /* per-architecture data-pointers */" +echo " int nr_data;" +echo " void **data;" +echo "" +echo " /* per-architecture swap-regions */" +echo " struct gdbarch_swap *swap;" +echo "" +cat <tdep = tdep; +EOF +echo "" +function_list | while eval read $read +do + case "${class}" in + "i" ) echo " gdbarch->${function} = info->${function};" + esac +done +echo "" +echo " /* Force the explicit initialization of these. */" +function_list | while eval read $read +do + case "${class}" in + "f" | "v" ) + if [ "${init}" != "" -a "${init}" != "0" ] + then + echo " gdbarch->${function} = ${init};" + fi + ;; + esac +done +cat <byte_order == 0) + internal_error ("verify_gdbarch: byte-order unset"); + if (gdbarch->bfd_arch_info == NULL) + internal_error ("verify_gdbarch: bfd_arch_info unset"); + /* Check those that need to be defined for the given multi-arch level. */ +EOF +function_list | while eval read $read +do + case "${class}" in + "f" | "v" ) + if [ "${init_p}" ] + then + echo " if ((GDB_MULTI_ARCH >= ${level})" + echo " && (${init_p}))" + echo " internal_error (\"gdbarch: verify_gdbarch: ${function} invalid\");" + elif [ "${init}" ] + then + echo " if ((GDB_MULTI_ARCH >= ${level})" + echo " && (gdbarch->${function} == ${init}))" + echo " internal_error (\"gdbarch: verify_gdbarch: ${function} invalid\");" + fi + ;; + esac +done +cat <${function}" + echo " /*${macro} ()*/);" + ;; + * ) + test "${fmt}" || fmt="%ld" + test "${print}" || print="(long) ${macro}" + if [ "${print_p}" = "#" ] + then + echo "#ifdef ${macro}" + echo " fprintf_unfiltered (gdb_stdlog," + echo " \"gdbarch_update: ${macro} = ${fmt}\\n\"," + echo " ${print});" + echo "#endif" + elif [ "${print_p}" ] + then + echo " if (${print_p})" + echo " fprintf_unfiltered (gdb_stdlog," + echo " \"gdbarch_update: ${macro} = ${fmt}\\n\"," + echo " ${print});" + else + echo " fprintf_unfiltered (gdb_stdlog," + echo " \"gdbarch_update: ${macro} = ${fmt}\\n\"," + echo " ${print});" + fi + ;; + esac +done +echo "}" + + +# GET/SET +echo "" +cat <= 2) + /* FIXME: gdb_std??? */ + fprintf_unfiltered (gdb_stdlog, "gdbarch_tdep called\n"); + return gdbarch->tdep; +} +EOF +echo "" +function_list | while eval read $read +do + case "${class}" in + "f" ) + echo "" + echo "${returntype}" + if [ "${formal}" = "void" ] + then + echo "gdbarch_${function} (struct gdbarch *gdbarch)" + else + echo "gdbarch_${function} (struct gdbarch *gdbarch, ${formal})" + fi + echo "{" + echo " if (gdbarch->${function} == 0)" + echo " internal_error (\"gdbarch: gdbarch_${function} invalid\");" + echo " if (gdbarch_debug >= 2)" + echo " /* FIXME: gdb_std??? */" + echo " fprintf_unfiltered (gdb_stdlog, \"gdbarch_${function} called\n\");" + test "${actual}" = "-" && actual="" + if [ "${returntype}" = "void" ] + then + echo " gdbarch->${function} (${actual});" + else + echo " return gdbarch->${function} (${actual});" + fi + echo "}" + echo "" + echo "void" + echo "set_gdbarch_${function} (struct gdbarch *gdbarch," + echo " `echo ${function} | tr '[0-9a-z_]' ' '` gdbarch_${function}_ftype ${function})" + echo "{" + echo " gdbarch->${function} = ${function};" + echo "}" + ;; + "v" ) + echo "" + echo "${returntype}" + echo "gdbarch_${function} (struct gdbarch *gdbarch)" + echo "{" + if [ "${init_p}" ] + then + echo " if (${init_p})" + echo " internal_error (\"gdbarch: gdbarch_${function} invalid\");" + elif [ "${init}" ] + then + echo " if (gdbarch->${function} == ${init})" + echo " internal_error (\"gdbarch: gdbarch_${function} invalid\");" + fi + echo " if (gdbarch_debug >= 2)" + echo " /* FIXME: gdb_std??? */" + echo " fprintf_unfiltered (gdb_stdlog, \"gdbarch_${function} called\n\");" + echo " return gdbarch->${function};" + echo "}" + echo "" + echo "void" + echo "set_gdbarch_${function} (struct gdbarch *gdbarch," + echo " `echo ${function} | tr '[0-9a-z_]' ' '` ${returntype} ${function})" + echo "{" + echo " gdbarch->${function} = ${function};" + echo "}" + ;; + "i" ) + echo "" + echo "${returntype}" + echo "gdbarch_${function} (struct gdbarch *gdbarch)" + echo "{" + echo " if (gdbarch_debug >= 2)" + echo " /* FIXME: gdb_std??? */" + echo " fprintf_unfiltered (gdb_stdlog, \"gdbarch_${function} called\n\");" + echo " return gdbarch->${function};" + echo "}" + ;; + esac +done + +# All the trailing guff +cat <next); + (*curr) = XMALLOC (struct gdbarch_data_registration); + (*curr)->next = NULL; + (*curr)->init = init; + (*curr)->data = XMALLOC (struct gdbarch_data); + (*curr)->data->index = gdbarch_data_registrary.nr++; + return (*curr)->data; +} + + +/* Walk through all the registered users initializing each in turn. */ + +static void +init_gdbarch_data (struct gdbarch *gdbarch) +{ + struct gdbarch_data_registration *rego; + gdbarch->nr_data = gdbarch_data_registrary.nr + 1; + gdbarch->data = xmalloc (sizeof (void*) * gdbarch->nr_data); + for (rego = gdbarch_data_registrary.registrations; + rego != NULL; + rego = rego->next) + { + if (rego->data->index < gdbarch->nr_data) + gdbarch->data[rego->data->index] = rego->init (); + } +} + + +/* Return the current value of the specified per-architecture + data-pointer. */ + +void * +gdbarch_data (data) + struct gdbarch_data *data; +{ + if (data->index >= current_gdbarch->nr_data) + internal_error ("gdbarch_data: request for non-existant data."); + return current_gdbarch->data[data->index]; +} + + + +/* Keep a registrary of swaped data required by GDB modules. */ + +struct gdbarch_swap +{ + void *swap; + struct gdbarch_swap_registration *source; + struct gdbarch_swap *next; +}; + +struct gdbarch_swap_registration +{ + void *data; + unsigned long sizeof_data; + gdbarch_swap_ftype *init; + struct gdbarch_swap_registration *next; +}; + +struct gdbarch_swap_registrary +{ + int nr; + struct gdbarch_swap_registration *registrations; +}; + +struct gdbarch_swap_registrary gdbarch_swap_registrary = +{ + 0, NULL, +}; + +void +register_gdbarch_swap (void *data, + unsigned long sizeof_data, + gdbarch_swap_ftype *init) +{ + struct gdbarch_swap_registration **rego; + for (rego = &gdbarch_swap_registrary.registrations; + (*rego) != NULL; + rego = &(*rego)->next); + (*rego) = XMALLOC (struct gdbarch_swap_registration); + (*rego)->next = NULL; + (*rego)->init = init; + (*rego)->data = data; + (*rego)->sizeof_data = sizeof_data; +} + + +static void +init_gdbarch_swap (struct gdbarch *gdbarch) +{ + struct gdbarch_swap_registration *rego; + struct gdbarch_swap **curr = &gdbarch->swap; + for (rego = gdbarch_swap_registrary.registrations; + rego != NULL; + rego = rego->next) + { + if (rego->data != NULL) + { + (*curr) = XMALLOC (struct gdbarch_swap); + (*curr)->source = rego; + (*curr)->swap = xmalloc (rego->sizeof_data); + (*curr)->next = NULL; + memset (rego->data, 0, rego->sizeof_data); + curr = &(*curr)->next; + } + if (rego->init != NULL) + rego->init (); + } +} + +static void +swapout_gdbarch_swap (struct gdbarch *gdbarch) +{ + struct gdbarch_swap *curr; + for (curr = gdbarch->swap; + curr != NULL; + curr = curr->next) + memcpy (curr->swap, curr->source->data, curr->source->sizeof_data); +} + +static void +swapin_gdbarch_swap (struct gdbarch *gdbarch) +{ + struct gdbarch_swap *curr; + for (curr = gdbarch->swap; + curr != NULL; + curr = curr->next) + memcpy (curr->source->data, curr->swap, curr->source->sizeof_data); +} + + +/* Keep a registrary of the architectures known by GDB. */ + +struct gdbarch_init_registration +{ + enum bfd_architecture bfd_architecture; + gdbarch_init_ftype *init; + struct gdbarch_list *arches; + struct gdbarch_init_registration *next; +}; + +static struct gdbarch_init_registration *gdbarch_init_registrary = NULL; + +void +register_gdbarch_init (enum bfd_architecture bfd_architecture, + gdbarch_init_ftype *init) +{ + struct gdbarch_init_registration **curr; + const struct bfd_arch_info *bfd_arch_info; + /* Check that BFD reconizes this architecture */ + bfd_arch_info = bfd_lookup_arch (bfd_architecture, 0); + if (bfd_arch_info == NULL) + { + internal_error ("gdbarch: Attempt to register unknown architecture (%d)", bfd_architecture); + } + /* Check that we haven't seen this architecture before */ + for (curr = &gdbarch_init_registrary; + (*curr) != NULL; + curr = &(*curr)->next) + { + if (bfd_architecture == (*curr)->bfd_architecture) + internal_error ("gdbarch: Duplicate registraration of architecture (%s)", + bfd_arch_info->printable_name); + } + /* log it */ + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "register_gdbarch_init (%s, 0x%08lx)\n", + bfd_arch_info->printable_name, + (long) init); + /* Append it */ + (*curr) = XMALLOC (struct gdbarch_init_registration); + (*curr)->bfd_architecture = bfd_architecture; + (*curr)->init = init; + (*curr)->arches = NULL; + (*curr)->next = NULL; +} + + + +/* Look for an architecture using gdbarch_info. Base search on only + BFD_ARCH_INFO and BYTE_ORDER. */ + +struct gdbarch_list * +gdbarch_list_lookup_by_info (struct gdbarch_list *arches, + const struct gdbarch_info *info) +{ + for (; arches != NULL; arches = arches->next) + { + if (info->bfd_arch_info != arches->gdbarch->bfd_arch_info) + continue; + if (info->byte_order != arches->gdbarch->byte_order) + continue; + return arches; + } + return NULL; +} + + +/* Update the current architecture. Return ZERO if the update request + failed. */ + +int +gdbarch_update (struct gdbarch_info info) +{ + struct gdbarch *new_gdbarch; + struct gdbarch_list **list; + struct gdbarch_init_registration *rego; + + /* Fill in any missing bits. Most important is the bfd_architecture + which is used to select the target architecture. */ + if (info.bfd_architecture == bfd_arch_unknown) + { + if (info.bfd_arch_info != NULL) + info.bfd_architecture = info.bfd_arch_info->arch; + else if (info.abfd != NULL) + info.bfd_architecture = bfd_get_arch (info.abfd); + /* FIXME - should query BFD for its default architecture. */ + else + info.bfd_architecture = current_gdbarch->bfd_arch_info->arch; + } + if (info.bfd_arch_info == NULL) + { + if (target_architecture_auto && info.abfd != NULL) + info.bfd_arch_info = bfd_get_arch_info (info.abfd); + else + info.bfd_arch_info = current_gdbarch->bfd_arch_info; + } + if (info.byte_order == 0) + { + if (target_byte_order_auto && info.abfd != NULL) + info.byte_order = (bfd_big_endian (info.abfd) ? BIG_ENDIAN + : bfd_little_endian (info.abfd) ? LITTLE_ENDIAN + : 0); + else + info.byte_order = current_gdbarch->byte_order; + /* FIXME - should query BFD for its default byte-order. */ + } + /* A default for abfd? */ + + /* Find the target that knows about this architecture. */ + for (rego = gdbarch_init_registrary; + rego != NULL && rego->bfd_architecture != info.bfd_architecture; + rego = rego->next); + if (rego == NULL) + { + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "gdbarch_update: No matching architecture\n"); + return 0; + } + + if (gdbarch_debug) + { + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: info.bfd_architecture %d (%s)\n", + info.bfd_architecture, + bfd_lookup_arch (info.bfd_architecture, 0)->printable_name); + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: info.bfd_arch_info %s\n", + (info.bfd_arch_info != NULL + ? info.bfd_arch_info->printable_name + : "(null)")); + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: info.byte_order %d (%s)\n", + info.byte_order, + (info.byte_order == BIG_ENDIAN ? "big" + : info.byte_order == LITTLE_ENDIAN ? "little" + : "default")); + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: info.abfd 0x%lx\n", + (long) info.abfd); + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: info.tdep_info 0x%lx\n", + (long) info.tdep_info); + } + + /* Ask the target for a replacement architecture. */ + new_gdbarch = rego->init (info, rego->arches); + + /* Did the target like it? No. Reject the change. */ + if (new_gdbarch == NULL) + { + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "gdbarch_update: Target rejected architecture\n"); + return 0; + } + + /* Did the architecture change? No. Do nothing. */ + if (current_gdbarch == new_gdbarch) + { + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "gdbarch_update: Architecture 0x%08lx (%s) unchanged\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + return 1; + } + + /* Swap all data belonging to the old target out */ + swapout_gdbarch_swap (current_gdbarch); + + /* Is this a pre-existing architecture? Yes. Swap it in. */ + for (list = ®o->arches; + (*list) != NULL; + list = &(*list)->next) + { + if ((*list)->gdbarch == new_gdbarch) + { + if (gdbarch_debug) + fprintf_unfiltered (gdb_stdlog, "gdbarch_update: Previous architecture 0x%08lx (%s) selected\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + current_gdbarch = new_gdbarch; + swapin_gdbarch_swap (new_gdbarch); + return 1; + } + } + + /* Append this new architecture to this targets list. */ + (*list) = XMALLOC (struct gdbarch_list); + (*list)->next = NULL; + (*list)->gdbarch = new_gdbarch; + + /* Switch to this new architecture. Dump it out. */ + current_gdbarch = new_gdbarch; + if (gdbarch_debug) + { + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: New architecture 0x%08lx (%s) selected\n", + (long) new_gdbarch, + new_gdbarch->bfd_arch_info->printable_name); + gdbarch_dump (); + } + + /* Check that the newly installed architecture is valid. */ + verify_gdbarch (new_gdbarch); + + /* Initialize the per-architecture memory (swap) areas. + CURRENT_GDBARCH must be update before these modules are + called. */ + init_gdbarch_swap (new_gdbarch); + + /* Initialize the per-architecture data-pointer of all parties that + registered an interest in this architecture. CURRENT_GDBARCH + must be updated before these modules are called. */ + init_gdbarch_data (new_gdbarch); + + return 1; +} + + + +/* Functions to manipulate the endianness of the target. */ + +#ifdef TARGET_BYTE_ORDER_SELECTABLE +/* compat - Catch old targets that expect a selectable byte-order to + default to BIG_ENDIAN */ +#ifndef TARGET_BYTE_ORDER_DEFAULT +#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN +#endif +#endif +#if !TARGET_BYTE_ORDER_SELECTABLE_P +#ifndef TARGET_BYTE_ORDER_DEFAULT +/* compat - Catch old non byte-order selectable targets that do not + define TARGET_BYTE_ORDER_DEFAULT and instead expect + TARGET_BYTE_ORDER to be used as the default. For targets that + defined neither TARGET_BYTE_ORDER nor TARGET_BYTE_ORDER_DEFAULT the + below will get a strange compiler warning. */ +#define TARGET_BYTE_ORDER_DEFAULT TARGET_BYTE_ORDER +#endif +#endif +#ifndef TARGET_BYTE_ORDER_DEFAULT +#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN /* arbitrary */ +#endif +int target_byte_order = TARGET_BYTE_ORDER_DEFAULT; +int target_byte_order_auto = 1; + +/* Chain containing the \"set endian\" commands. */ +static struct cmd_list_element *endianlist = NULL; + +/* Called by \`\`show endian''. */ +static void +show_endian (char *args, int from_tty) +{ + char *msg = + (TARGET_BYTE_ORDER_AUTO + ? "The target endianness is set automatically (currently %s endian)\n" + : "The target is assumed to be %s endian\n"); + printf_unfiltered (msg, (TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little")); +} + +/* Called if the user enters \`\`set endian'' without an argument. */ +static void +set_endian (char *args, int from_tty) +{ + printf_unfiltered ("\"set endian\" must be followed by \"auto\", \"big\" or \"little\".\n"); + show_endian (args, from_tty); +} + +/* Called by \`\`set endian big''. */ +static void +set_endian_big (char *args, int from_tty) +{ + if (TARGET_BYTE_ORDER_SELECTABLE_P) + { + target_byte_order = BIG_ENDIAN; + target_byte_order_auto = 0; + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.byte_order = BIG_ENDIAN; + gdbarch_update (info); + } + } + else + { + printf_unfiltered ("Byte order is not selectable."); + show_endian (args, from_tty); + } +} + +/* Called by \`\`set endian little''. */ +static void +set_endian_little (char *args, int from_tty) +{ + if (TARGET_BYTE_ORDER_SELECTABLE_P) + { + target_byte_order = LITTLE_ENDIAN; + target_byte_order_auto = 0; + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.byte_order = LITTLE_ENDIAN; + gdbarch_update (info); + } + } + else + { + printf_unfiltered ("Byte order is not selectable."); + show_endian (args, from_tty); + } +} + +/* Called by \`\`set endian auto''. */ +static void +set_endian_auto (char *args, int from_tty) +{ + if (TARGET_BYTE_ORDER_SELECTABLE_P) + { + target_byte_order_auto = 1; + } + else + { + printf_unfiltered ("Byte order is not selectable."); + show_endian (args, from_tty); + } +} + +/* Set the endianness from a BFD. */ +static void +set_endian_from_file (bfd *abfd) +{ + if (TARGET_BYTE_ORDER_SELECTABLE_P) + { + int want; + + if (bfd_big_endian (abfd)) + want = BIG_ENDIAN; + else + want = LITTLE_ENDIAN; + if (TARGET_BYTE_ORDER_AUTO) + target_byte_order = want; + else if (TARGET_BYTE_ORDER != want) + warning ("%s endian file does not match %s endian target.", + want == BIG_ENDIAN ? "big" : "little", + TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); + } + else + { + if (bfd_big_endian (abfd) + ? TARGET_BYTE_ORDER != BIG_ENDIAN + : TARGET_BYTE_ORDER == BIG_ENDIAN) + warning ("%s endian file does not match %s endian target.", + bfd_big_endian (abfd) ? "big" : "little", + TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); + } +} + + + +/* Functions to manipulate the architecture of the target */ + +enum set_arch { set_arch_auto, set_arch_manual }; + +int target_architecture_auto = 1; +extern const struct bfd_arch_info bfd_default_arch_struct; +const struct bfd_arch_info *target_architecture = &bfd_default_arch_struct; +int (*target_architecture_hook) (const struct bfd_arch_info *ap); + +static void show_endian (char *, int); +static void set_endian (char *, int); +static void set_endian_big (char *, int); +static void set_endian_little (char *, int); +static void set_endian_auto (char *, int); +static void set_endian_from_file (bfd *); +static int arch_ok (const struct bfd_arch_info *arch); +static void set_arch (const struct bfd_arch_info *arch, enum set_arch type); +static void show_architecture (char *, int); +static void set_architecture (char *, int); +static void info_architecture (char *, int); +static void set_architecture_from_file (bfd *); + +/* Do the real work of changing the current architecture */ + +static int +arch_ok (const struct bfd_arch_info *arch) +{ + /* Should be performing the more basic check that the binary is + compatible with GDB. */ + /* Check with the target that the architecture is valid. */ + return (target_architecture_hook == NULL + || target_architecture_hook (arch)); +} + +static void +set_arch (const struct bfd_arch_info *arch, + enum set_arch type) +{ + switch (type) + { + case set_arch_auto: + if (!arch_ok (arch)) + warning ("Target may not support %s architecture", + arch->printable_name); + target_architecture = arch; + break; + case set_arch_manual: + if (!arch_ok (arch)) + { + printf_unfiltered ("Target does not support \`%s' architecture.\n", + arch->printable_name); + } + else + { + target_architecture_auto = 0; + target_architecture = arch; + } + break; + } + if (gdbarch_debug) + gdbarch_dump (); +} + +/* Called if the user enters \`\`show architecture'' without an argument. */ +static void +show_architecture (char *args, int from_tty) +{ + const char *arch; + arch = TARGET_ARCHITECTURE->printable_name; + if (target_architecture_auto) + printf_filtered ("The target architecture is set automatically (currently %s)\n", arch); + else + printf_filtered ("The target architecture is assumed to be %s\n", arch); +} + +/* Called if the user enters \`\`set architecture'' with or without an + argument. */ +static void +set_architecture (char *args, int from_tty) +{ + if (args == NULL) + { + printf_unfiltered ("\"set architecture\" must be followed by \"auto\" or an architecture name.\n"); + } + else if (strcmp (args, "auto") == 0) + { + target_architecture_auto = 1; + } + else if (GDB_MULTI_ARCH) + { + const struct bfd_arch_info *arch = bfd_scan_arch (args); + if (arch == NULL) + printf_unfiltered ("Architecture \`%s' not reconized.\n", args); + else + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.bfd_arch_info = arch; + if (gdbarch_update (info)) + target_architecture_auto = 0; + else + printf_unfiltered ("Architecture \`%s' not reconized.\n", args); + } + } + else + { + const struct bfd_arch_info *arch = bfd_scan_arch (args); + if (arch != NULL) + set_arch (arch, set_arch_manual); + else + printf_unfiltered ("Architecture \`%s' not reconized.\n", args); + } +} + +/* Called if the user enters \`\`info architecture'' without an argument. */ +static void +info_architecture (char *args, int from_tty) +{ + enum bfd_architecture a; + if (GDB_MULTI_ARCH) + { + if (gdbarch_init_registrary != NULL) + { + struct gdbarch_init_registration *rego; + printf_filtered ("Available architectures are:\n"); + for (rego = gdbarch_init_registrary; + rego != NULL; + rego = rego->next) + { + const struct bfd_arch_info *ap; + ap = bfd_lookup_arch (rego->bfd_architecture, 0); + if (ap != NULL) + { + do + { + printf_filtered (" %s", ap->printable_name); + ap = ap->next; + } + while (ap != NULL); + printf_filtered ("\n"); + } + } + } + else + { + printf_filtered ("There are no available architectures.\n"); + } + return; + } + printf_filtered ("Available architectures are:\n"); + for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++) + { + const struct bfd_arch_info *ap = bfd_lookup_arch (a, 0); + if (ap != NULL) + { + do + { + printf_filtered (" %s", ap->printable_name); + ap = ap->next; + } + while (ap != NULL); + printf_filtered ("\n"); + } + } +} + +/* Set the architecture from arch/machine */ +void +set_architecture_from_arch_mach (arch, mach) + enum bfd_architecture arch; + unsigned long mach; +{ + const struct bfd_arch_info *wanted = bfd_lookup_arch (arch, mach); + if (wanted != NULL) + set_arch (wanted, set_arch_manual); + else + internal_error ("gdbarch: hardwired architecture/machine not reconized"); +} + +/* Set the architecture from a BFD */ +static void +set_architecture_from_file (bfd *abfd) +{ + const struct bfd_arch_info *wanted = bfd_get_arch_info (abfd); + if (target_architecture_auto) + { + set_arch (wanted, set_arch_auto); + } + else if (wanted != target_architecture) + { + warning ("%s architecture file may be incompatible with %s target.", + wanted->printable_name, + target_architecture->printable_name); + } +} + + +/* Misc helper functions for targets. */ + +int +frame_num_args_unknown (fi) + struct frame_info *fi; +{ + return -1; +} + + +int +generic_register_convertible_not (num) + int num; +{ + return 0; +} + +/* Disassembler */ + +/* Pointer to the target-dependent disassembly function. */ +int (*tm_print_insn) (bfd_vma, disassemble_info *); +disassemble_info tm_print_insn_info; + + + +/* Set the dynamic target-system-dependant parameters (architecture, + byte-order) using information found in the BFD */ + +void +set_gdbarch_from_file (abfd) + bfd *abfd; +{ + if (GDB_MULTI_ARCH) + { + struct gdbarch_info info; + memset (&info, 0, sizeof info); + info.abfd = abfd; + gdbarch_update (info); + return; + } + set_architecture_from_file (abfd); + set_endian_from_file (abfd); +} + + +#if defined (CALL_DUMMY) +/* FIXME - this should go away */ +LONGEST call_dummy_words[] = CALL_DUMMY; +int sizeof_call_dummy_words = sizeof (call_dummy_words); +#endif + + +extern void _initialize_gdbarch (void); +void +_initialize_gdbarch () +{ + add_prefix_cmd ("endian", class_support, set_endian, + "Set endianness of target.", + &endianlist, "set endian ", 0, &setlist); + add_cmd ("big", class_support, set_endian_big, + "Set target as being big endian.", &endianlist); + add_cmd ("little", class_support, set_endian_little, + "Set target as being little endian.", &endianlist); + add_cmd ("auto", class_support, set_endian_auto, + "Select target endianness automatically.", &endianlist); + add_cmd ("endian", class_support, show_endian, + "Show endianness of target.", &showlist); + + add_cmd ("architecture", class_support, set_architecture, + "Set architecture of target.", &setlist); + add_alias_cmd ("processor", "architecture", class_support, 1, &setlist); + add_cmd ("architecture", class_support, show_architecture, + "Show architecture of target.", &showlist); + add_cmd ("architecture", class_support, info_architecture, + "List supported target architectures", &infolist); + + INIT_DISASSEMBLE_INFO_NO_ARCH (tm_print_insn_info, gdb_stdout, (fprintf_ftype)fprintf_filtered); + tm_print_insn_info.flavour = bfd_target_unknown_flavour; + tm_print_insn_info.read_memory_func = dis_asm_read_memory; + tm_print_insn_info.memory_error_func = dis_asm_memory_error; + tm_print_insn_info.print_address_func = dis_asm_print_address; + + add_show_from_set (add_set_cmd ("archdebug", + class_maintenance, + var_zinteger, + (char *)&gdbarch_debug, + "Set architecture debugging.\n\\ +When non-zero, architecture debugging is enabled.", &setlist), + &showlist); +} +EOF + +# close things off +exec 1>&2 +#../move-if-change new-gdbarch.c gdbarch.c +if ! test -r gdbarch.c +then + echo "gdbarch.c missing? cp new-gdbarch.c gdbarch.c" 1>&2 +elif diff -c gdbarch.c new-gdbarch.c +then + echo "gdbarch.c unchanged" 1>&2 +else + echo "gdbarch.c has changed? cp new-gdbarch.c gdbarch.c" 1>&2 +fi diff --git a/gdb/testsuite/gdb.base/async.c b/gdb/testsuite/gdb.base/async.c new file mode 100644 index 0000000000..0d9c8752b7 --- /dev/null +++ b/gdb/testsuite/gdb.base/async.c @@ -0,0 +1,48 @@ + + +#ifdef PROTOTYPES +int +foo (void) +#else +int +foo () +#endif +{ + int x, y; + + x = 5; + y = 3; + + return x + y; +} + +#ifdef PROTOTYPES +int +main (void) +#else +int +main () +#endif +{ + int y, z; + + y = 2; + z = 9; + y = foo (); + z = y; + y = y + 2; + y = baz (); + return 0; +} + + +#ifdef PROTOTYPES +int +baz (void) +#else +int +baz () +#endif +{ + return 5; +} diff --git a/gdb/testsuite/gdb.base/async.exp b/gdb/testsuite/gdb.base/async.exp new file mode 100644 index 0000000000..4a97f9cc7a --- /dev/null +++ b/gdb/testsuite/gdb.base/async.exp @@ -0,0 +1,153 @@ +# Copyright (C) 1999 +# Free Software Foundation, Inc. + +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + +if $tracelevel then { + strace $tracelevel +} + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "async" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +######################################## +## +## Don't do any of these tests until we reach consensus on this file. +## +return 0 +######################################## + +set board [target_info name] +set current_target [target_info gdb_protocol] +if { $current_target == "remote" } { + unset_board_info "gdb_protocol" + set_board_info "gdb_protocol" "async" + } else { + return 0 + } + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +if [target_info exists gdb_stub] { + gdb_step_for_stub; +} + +# +# set it up at a breakpoint so we can play with it +# +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +gdb_test "break baz" "" "" + +# +# Make sure we get a 'completed' message when the target is done. +# +gdb_test "set display-exec-done on" "" "" + + +send_gdb "next&\n" +gdb_expect { + -re "^next&\r\n$gdb_prompt.*z = 9.*completed\.\r\n" { pass "next &" } + -re "$gdb_prompt.*completed\.$" { fail "next &" } + timeout { fail "(timeout) next &" } +} + +send_gdb "step&\n" +gdb_expect { + -re "^step&\r\n$gdb_prompt.*y = foo \\(\\).*completed\.\r\n" { pass "step &" } + -re "$gdb_prompt.*completed\.$" { fail "step &" } + timeout { fail "(timeout) step &" } +} + +send_gdb "step&\n" +gdb_expect { + -re "^step&\r\n$gdb_prompt foo \\(\\) at .*async.c.*x = 5.*completed\.\r\n" \ + { pass "step &" } + -re "$gdb_prompt.*completed\.$" { fail "step &" } + timeout { fail "(timeout) step &" } +} + +send_gdb "stepi&\n" +gdb_expect { + -re "^stepi&\r\n$gdb_prompt.*$hex.*x = 5.*completed\.\r\n" { pass "stepi &" } + -re "$gdb_prompt.*completed\.$" { fail "stepi &" } + timeout { fail "(timeout) stepi &" } +} + +send_gdb "nexti&\n" +gdb_expect { + -re "^nexti&\r\n$gdb_prompt.*y = 3.*completed\.\r\n" { pass "nexti &" } + -re "$gdb_prompt.*completed\.$" { fail "nexti &" } + timeout { fail "(timeout) nexti &" } +} + +send_gdb "finish&\n" +gdb_expect { + -re "^finish&\r\nRun till exit from #0 foo \\(\\) at.*async.c.*\r\n$gdb_prompt.*$hex in main \\(\\) at.*async.c.*y = foo \\(\\).*Value returned is.*= 8.*completed\.\r\n" \ + { pass "finish &" } + -re "$gdb_prompt.*completed\.$" { fail "finish &" } + timeout { fail "(timeout) finish &" } +} + +send_gdb "jump 33&\n" +gdb_expect { + -re "^jump 33&.*Continuing at $hex.*$gdb_prompt.*Breakpoint 2, baz \\(\\) at.*async.c.*return 5.*completed\.\r\n" \ + { pass "jump &" } + -re ".*$gdb_prompt.*completed\.$" { fail "jump &" } + timeout { fail "(timeout) jump &" } +} + +send_gdb "until 35&\n" +gdb_expect { + -re "^until 35&.*$gdb_prompt.*$hex in main \\(\\) at.*async.c.*y = baz \\(\\).*completed\.\r\n" \ + { pass "until &" } + -re "$gdb_prompt.*completed\.$" { fail "until &" } + timeout { fail "(timeout) until &" } +} + +gdb_test "set display-exec-done off" "" "" + +unset_board_info "gdb_protocol" +set_board_info "gdb_protocol" "remote" + + + + + + -- 2.11.0