From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6975 invoked by alias); 14 Feb 2002 18:37:55 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 6918 invoked from network); 14 Feb 2002 18:37:50 -0000 Received: from unknown (HELO fw-cam.cambridge.arm.com) (193.131.176.3) by sources.redhat.com with SMTP; 14 Feb 2002 18:37:50 -0000 Received: by fw-cam.cambridge.arm.com; id SAA17922; Thu, 14 Feb 2002 18:37:49 GMT Received: from unknown(172.16.1.2) by fw-cam.cambridge.arm.com via smap (V5.5) id xma017621; Thu, 14 Feb 02 18:37:08 GMT Received: from cam-mail2.cambridge.arm.com (localhost [127.0.0.1]) by cam-admin0.cambridge.arm.com (8.9.3/8.9.3) with ESMTP id SAA03817 for ; Thu, 14 Feb 2002 18:37:07 GMT Received: from sun18.cambridge.arm.com (sun18.cambridge.arm.com [172.16.2.18]) by cam-mail2.cambridge.arm.com (8.9.3/8.9.3) with ESMTP id SAA25550; Thu, 14 Feb 2002 18:37:07 GMT Message-Id: <200202141837.SAA25550@cam-mail2.cambridge.arm.com> X-Mailer: exmh version 2.0.2 2/24/98 To: gdb-patches@sources.redhat.com cc: Richard.Earnshaw@arm.com Reply-To: Richard.Earnshaw@arm.com Organization: ARM Ltd. X-Telephone: +44 1223 400569 (direct+voicemail), +44 1223 400400 (switchbd) X-Fax: +44 1223 400410 X-Address: ARM Ltd., 110 Fulbourn Road, Cherry Hinton, Cambridge CB1 9NJ. X-Url: http://www.arm.com/ Subject: RFC ARM multi-arch and object format detection Mime-Version: 1.0 Content-Type: multipart/mixed ; boundary="==_Exmh_10984999160" Date: Thu, 14 Feb 2002 10:37:00 -0000 From: Richard Earnshaw X-SW-Source: 2002-02/txt/msg00419.txt.bz2 This is a multipart MIME message. --==_Exmh_10984999160 Content-Type: text/plain; charset=us-ascii Content-length: 1167 Most of the remaining multi-arch conversion work for the ARM is target-specific. Below is an initial stab at detecting the various object formats that I know about. It seems that, even for ELF, this isn't an exact science -- There is a fairly-well defined flag in the elf header (EI_OSABI), but no-one seems to set it reliably, certainly gas/gld don't! I'd appreciate comments from anyone who has been through this gloop before. If nobody yells loudly, I'll probably commit this sometime tomorrow. R. * arm-tdep.h (enum arm_abi): New. (struct gdbarch_tdep): New. (LOWEST_PC): Define if not previously defined; use multi-arch tdep variable. * config/arm/tm-arm.h (LOWEST_PC): Delete. * config/arm/tm-nbsd.h (LOWEST_PC): Delete. * armnbsd-nat.c: Include regcache.h. * arm-tdep.c: Include elf/arm.h. (process_note_abi_tag_sections): New function. (get_elfosabi): New function. (arm_gdbarch_init): Try to determine the type of object we've been handed and set the ABI up appropriately. (arm_dump_tdep): Dump target-dependent data. (_initialize_arm_tdep): Register arm_dump_tdep. * Makefile.in (armnbsd-nat.c, arm-tdep.c): Update dependencies. --==_Exmh_10984999160 Content-Type: text/x-patch ; name="gdb-maobjfmt.patch"; charset=us-ascii Content-Description: gdb-maobjfmt.patch Content-Disposition: attachment; filename="gdb-maobjfmt.patch" Content-length: 14291 ? gdbarch.log Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.158 diff -p -r1.158 Makefile.in *** Makefile.in 2002/02/13 20:47:16 1.158 --- Makefile.in 2002/02/14 18:17:15 *************** arm-linux-tdep.o: arm-linux-tdep.c $(def *** 1247,1255 **** arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \ $(gdbcore_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) $(doublest_h) \ $(value_h) $(arch_utils_h) $(solib_svr4_h) arm-tdep.h \ ! $(BFD_SRC)/elf-bfd.h $(INCLUDE_DIR)/coff/internal.h ! armnbsd-nat.o: armnbsd-nat.c $(defs_h) arm-tdep.h bcache.o: bcache.c $(bcache_h) $(defs_h) --- 1247,1256 ---- arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \ $(gdbcore_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) $(doublest_h) \ $(value_h) $(arch_utils_h) $(solib_svr4_h) arm-tdep.h \ ! $(BFD_SRC)/elf-bfd.h $(INCLUDE_DIR)/coff/internal.h \ ! $(INCLUDE_DIR)/elf/arm.h ! armnbsd-nat.o: armnbsd-nat.c $(defs_h) arm-tdep.h $(inferior_h) $(regcache_h) bcache.o: bcache.c $(bcache_h) $(defs_h) Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.40 diff -p -r1.40 arm-tdep.c *** arm-tdep.c 2002/02/13 16:32:33 1.40 --- arm-tdep.c 2002/02/14 18:17:22 *************** *** 39,44 **** --- 39,45 ---- #include "elf-bfd.h" #include "coff/internal.h" + #include "elf/arm.h" /* Each OS has a different mechanism for accessing the various registers stored in the sigcontext structure. *************** arm_coff_make_msymbol_special(int val, s *** 2440,2455 **** MSYMBOL_SET_SPECIAL (msym); } static struct gdbarch * arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; ! if (arches != NULL) ! return arches->gdbarch; ! /* XXX We'll probably need to set the tdep field soon. */ ! gdbarch = gdbarch_alloc (&info, NULL); /* Floating point sizes and format. */ switch (info.byte_order) --- 2441,2670 ---- MSYMBOL_SET_SPECIAL (msym); } + + static void + process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj) + { + enum arm_abi *os_ident_ptr = obj; + const char *name; + unsigned int sectsize; + + name = bfd_get_section_name (abfd, sect); + sectsize = bfd_section_size (abfd, sect); + + if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0) + { + unsigned int name_length, data_length, note_type; + char *note; + + /* If the section is larger than this, it's probably not what we are + looking for. */ + if (sectsize > 128) + sectsize = 128; + + note = alloca (sectsize); + + bfd_get_section_contents (abfd, sect, note, + (file_ptr) 0, (bfd_size_type) sectsize); + + name_length = bfd_h_get_32 (abfd, note); + data_length = bfd_h_get_32 (abfd, note + 4); + note_type = bfd_h_get_32 (abfd, note + 8); + + if (name_length == 4 && data_length == 16 && note_type == 1 + && strcmp (note + 12, "GNU") == 0) + { + int os_number = bfd_h_get_32 (abfd, note + 16); + + /* The case numbers are from abi-tags in glibc */ + switch (os_number) + { + case 0 : + *os_ident_ptr = ARM_ABI_LINUX; + break; + + case 1 : + internal_error + (__FILE__, __LINE__, + "process_note_abi_sections: Hurd objects not supported"); + break; + + case 2 : + internal_error + (__FILE__, __LINE__, + "process_note_abi_sections: Solaris objects not supported"); + break; + + default : + internal_error + (__FILE__, __LINE__, + "process_note_abi_sections: unknown OS number %d", + os_number); + break; + } + } + } + /* NetBSD uses a similar trick. */ + else if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0) + { + unsigned int name_length, desc_length, note_type; + char *note; + + /* If the section is larger than this, it's probably not what we are + looking for. */ + if (sectsize > 128) + sectsize = 128; + + note = alloca (sectsize); + + bfd_get_section_contents (abfd, sect, note, + (file_ptr) 0, (bfd_size_type) sectsize); + + name_length = bfd_h_get_32 (abfd, note); + desc_length = bfd_h_get_32 (abfd, note + 4); + note_type = bfd_h_get_32 (abfd, note + 8); + + if (name_length == 7 && desc_length == 4 && note_type == 1 + && strcmp (note + 12, "NetBSD") == 0) + /* XXX Should we check the version here? + Probably not necessary yet. */ + *os_ident_ptr = ARM_ABI_NETBSD_ELF; + } + } + + /* Return one of the ELFOSABI_ constants for BFDs representing ELF + executables. If it's not an ELF executable or if the OS/ABI couldn't + be determined, simply return -1. */ + + static int + get_elfosabi (bfd *abfd) + { + int elfosabi; + enum arm_abi arm_abi = ARM_ABI_UNKNOWN; + + elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; + + /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate + that we're on a SYSV system. However, GNU/Linux uses a note section + to record OS/ABI info, but leaves e_ident[EI_OSABI] zero. So we + have to check the note sections too. + + GNU/ARM tools set the EI_OSABI field to ELFOSABI_ARM, so handle that + as well.*/ + if (elfosabi == 0 || elfosabi == ELFOSABI_ARM) + { + bfd_map_over_sections (abfd, + process_note_abi_tag_sections, + &arm_abi); + } + + if (arm_abi != ARM_ABI_UNKNOWN) + return arm_abi; + + switch (elfosabi) + { + case ELFOSABI_NONE: + /* Existing ARM Tools don't set this field, so look at the EI_FLAGS + field for more information. */ + + switch (EF_ARM_EABI_VERSION(elf_elfheader(abfd)->e_flags)) + { + case EF_ARM_EABI_VER1: + return ARM_ABI_EABI_V1; + + case EF_ARM_EABI_VER2: + return ARM_ABI_EABI_V2; + + case EF_ARM_EABI_UNKNOWN: + /* Assume GNU tools. */ + return ARM_ABI_APCS; + + default: + internal_error (__FILE__, __LINE__, + "get_elfosabi: Unknown ARM EABI version 0x%lx", + EF_ARM_EABI_VERSION(elf_elfheader(abfd)->e_flags)); + + } + break; + + case ELFOSABI_NETBSD: + return ARM_ABI_NETBSD_ELF; + + case ELFOSABI_FREEBSD: + return ARM_ABI_FREEBSD; + + case ELFOSABI_LINUX: + return ARM_ABI_LINUX; + + case ELFOSABI_ARM: + /* Assume GNU tools with the old APCS abi. */ + return ARM_ABI_APCS; + + default: + } + + return ARM_ABI_UNKNOWN; + } + + /* Initialize the current architecture based on INFO. If possible, re-use an + architecture from ARCHES, which is a list of architectures already created + during this debugging session. + + Called e.g. at program startup, when reading a core file, and when reading + a binary file. */ + static struct gdbarch * arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { + struct gdbarch_tdep *tdep; struct gdbarch *gdbarch; + enum arm_abi arm_abi = ARM_ABI_UNKNOWN; + + /* Try to deterimine the ABI of the object we are loading. */ + + if (info.abfd != NULL) + { + switch (bfd_get_flavour (info.abfd)) + { + case bfd_target_elf_flavour: + arm_abi = get_elfosabi (info.abfd); + break; + + case bfd_target_aout_flavour: + if (strcmp (bfd_get_target(info.abfd), "a.out-arm-netbsd") == 0) + arm_abi = ARM_ABI_NETBSD_AOUT; + else + /* Assume it's an old APCS-style ABI. */ + arm_abi = ARM_ABI_APCS; + break; + + case bfd_target_coff_flavour: + /* Assume it's an old APCS-style ABI. */ + /* XXX WinCE? */ + arm_abi = ARM_ABI_APCS; + break; ! default: ! /* Not sure what to do here, leave the ABI as unknown. */ ! break; ! } ! } ! ! /* Find a candidate among extant architectures. */ ! for (arches = gdbarch_list_lookup_by_info (arches, &info); ! arches != NULL; ! arches = gdbarch_list_lookup_by_info (arches->next, &info)) ! { ! /* Make sure the ABI selection matches. */ ! tdep = gdbarch_tdep (arches->gdbarch); ! if (tdep && tdep->arm_abi == arm_abi) ! return arches->gdbarch; ! } ! ! tdep = xmalloc (sizeof (struct gdbarch_tdep)); ! gdbarch = gdbarch_alloc (&info, tdep); ! tdep->arm_abi = arm_abi; /* Floating point sizes and format. */ switch (info.byte_order) *************** arm_gdbarch_init (struct gdbarch_info in *** 2473,2478 **** --- 2688,2711 ---- "arm_gdbarch_init: bad byte order for float format"); } + switch (arm_abi) + { + case ARM_ABI_UNKNOWN: + case ARM_ABI_EABI_V1: + case ARM_ABI_EABI_V2: + case ARM_ABI_APCS: + case ARM_ABI_WINCE: + tdep->lowest_pc = 0x20; /* Just beyond the vectors. */ + break; + + case ARM_ABI_LINUX: + case ARM_ABI_NETBSD_AOUT: + case ARM_ABI_NETBSD_ELF: + case ARM_ABI_FREEBSD: + tdep->lowest_pc = 0x8000; + break; + } + set_gdbarch_use_generic_dummy_frames (gdbarch, 0); /* Call dummy code. */ *************** arm_gdbarch_init (struct gdbarch_info in *** 2580,2585 **** --- 2813,2875 ---- return gdbarch; } + static void + arm_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) + { + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + if (tdep == NULL) + return; + + switch (tdep->arm_abi) + { + case ARM_ABI_UNKNOWN: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = \n"); + break; + + case ARM_ABI_EABI_V1: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = ARM EABI (version 1)\n"); + break; + + case ARM_ABI_EABI_V2: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = ARM EABI (version 2)\n"); + break; + + case ARM_ABI_LINUX: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = GNU/Linux\n"); + break; + + case ARM_ABI_NETBSD_AOUT: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = NetBSD (a.out)\n"); + break; + + case ARM_ABI_NETBSD_ELF: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = NetBSD (ELF)\n"); + break; + + case ARM_ABI_APCS: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = APCS\n"); + break; + + case ARM_ABI_FREEBSD: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = FreeBSD\n"); + break; + + case ARM_ABI_WINCE: + fprintf_unfiltered (file, "arm_dump_tdep: ABI = Windows CE\n"); + break; + + default: + internal_error (__FILE__, __LINE__, + "arm_dump_tdep: illegal setting of tdep->arm_abi (%d)", + (int) tdep->arm_abi); + break; + } + + fprintf_unfiltered (file, "arm_dump_tdep: Lowest pc = 0x%lx", + (unsigned long) tdep->lowest_pc); + } + void _initialize_arm_tdep (void) { *************** _initialize_arm_tdep (void) *** 2593,2599 **** static char *helptext; if (GDB_MULTI_ARCH) ! register_gdbarch_init (bfd_arch_arm, arm_gdbarch_init); tm_print_insn = gdb_print_insn_arm; --- 2883,2889 ---- static char *helptext; if (GDB_MULTI_ARCH) ! gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep); tm_print_insn = gdb_print_insn_arm; Index: arm-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.h,v retrieving revision 1.2 diff -p -r1.2 arm-tdep.h *** arm-tdep.h 2002/02/13 17:09:07 1.2 --- arm-tdep.h 2002/02/14 18:17:22 *************** *** 99,104 **** --- 99,130 ---- #define FLAG_C 0x20000000 #define FLAG_V 0x10000000 + /* ABI variants that we know about. */ + enum arm_abi + { + ARM_ABI_UNKNOWN, + ARM_ABI_EABI_V1, + ARM_ABI_EABI_V2, + ARM_ABI_LINUX, + ARM_ABI_NETBSD_AOUT, + ARM_ABI_NETBSD_ELF, + ARM_ABI_APCS, + ARM_ABI_FREEBSD, + ARM_ABI_WINCE + }; + + /* Target-dependent structure in gdbarch. */ + struct gdbarch_tdep + { + enum arm_abi arm_abi; /* OS/ABI of inferior. */ + CORE_ADDR lowest_pc; /* Lowest address at which instructions + will appear. */ + }; + + #ifndef LOWEST_PC + #define LOWEST_PC (gdbarch_tdep (current_gdbarch)->lowest_pc) + #endif + /* Prototypes for internal interfaces needed by more than one MD file. */ int arm_pc_is_thumb_dummy (CORE_ADDR); Index: armnbsd-nat.c =================================================================== RCS file: /cvs/src/src/gdb/armnbsd-nat.c,v retrieving revision 1.3 diff -p -r1.3 armnbsd-nat.c *** armnbsd-nat.c 2002/02/11 18:34:08 1.3 --- armnbsd-nat.c 2002/02/14 18:17:22 *************** *** 29,34 **** --- 29,35 ---- #include #include #include "inferior.h" + #include "regcache.h" void fetch_inferior_registers (regno) Index: config/arm/tm-arm.h =================================================================== RCS file: /cvs/src/src/gdb/config/arm/tm-arm.h,v retrieving revision 1.27 diff -p -r1.27 tm-arm.h *** tm-arm.h 2002/02/13 16:32:34 1.27 --- tm-arm.h 2002/02/14 18:17:22 *************** *** 70,76 **** #define CALL_DUMMY_BREAKPOINT_OFFSET arm_call_dummy_breakpoint_offset() extern int arm_call_dummy_breakpoint_offset (void); - /* The first 0x20 bytes are the trap vectors. */ - #define LOWEST_PC 0x20 - #endif /* TM_ARM_H */ --- 70,73 ---- Index: config/arm/tm-nbsd.h =================================================================== RCS file: /cvs/src/src/gdb/config/arm/tm-nbsd.h,v retrieving revision 1.3 diff -p -r1.3 tm-nbsd.h *** tm-nbsd.h 2002/02/11 18:34:12 1.3 --- tm-nbsd.h 2002/02/14 18:17:22 *************** *** 27,36 **** #define JB_ELEMENT_SIZE sizeof(long) /* jmp_buf[_JBLEN] is array of ints */ #define JB_PC 24 /* Setjmp()'s return PC saved here */ - /* The first page is not writeable in NetBSD. */ - #undef LOWEST_PC - #define LOWEST_PC 0x8000 - /* Return non-zero if inside a shared-library entry stub. */ #undef IN_SOLIB_CALL_TRAMPOLINE #define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \ --- 27,32 ---- --==_Exmh_10984999160--