Automatic date update in version.in
[external/binutils.git] / gdb / arm-symbian-tdep.c
1 /* ARM Symbian OS target support.
2
3    Copyright (C) 2008-2017 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "frame.h"
22 #include "objfiles.h"
23 #include "osabi.h"
24 #include "solib.h"
25 #include "solib-target.h"
26 #include "target.h"
27 #include "elf-bfd.h"
28
29 /* If PC is in a DLL import stub, return the address of the `real'
30    function belonging to the stub.  */
31
32 static CORE_ADDR
33 arm_symbian_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
34 {
35   struct gdbarch *gdbarch;
36   enum bfd_endian byte_order;
37   ULONGEST insn;
38   CORE_ADDR dest;
39   gdb_byte buf[4];
40
41   if (!in_plt_section (pc))
42     return 0;
43
44   if (target_read_memory (pc, buf, 4) != 0)
45     return 0;
46
47   gdbarch = get_frame_arch (frame);
48   byte_order = gdbarch_byte_order (gdbarch);
49
50   /* ldr pc, [pc, #-4].  */
51   insn = extract_unsigned_integer (buf, 4, byte_order);
52   if (insn != 0xe51ff004)
53     return 0;
54
55   if (target_read_memory (pc + 4, buf, 4) != 0)
56     return 0;
57
58   dest = extract_unsigned_integer (buf, 4, byte_order);
59   return gdbarch_addr_bits_remove (gdbarch, dest);
60 }
61
62 static void
63 arm_symbian_init_abi (struct gdbarch_info info,
64                       struct gdbarch *gdbarch)
65 {
66   /* Shared library handling.  */
67   set_gdbarch_skip_trampoline_code (gdbarch, arm_symbian_skip_trampoline_code);
68
69   /* On this target, the toolchain outputs ELF files, with `sym' for
70      filename extension (e.g., `FOO.sym'); these are post-linker
71      processed into PE-ish DLLs (e.g., `FOO.dll'), and it's these that
72      are actually copied to and run on the target.  Naturally, when
73      listing shared libraries, Symbian stubs report the DLL filenames.
74      Setting this makes it so that GDB automatically looks for the
75      corresponding ELF files on the host's filesystem.  */
76   set_gdbarch_solib_symbols_extension (gdbarch, "sym");
77
78   /* Canonical paths on this target look like `c:\sys\bin\bar.dll',
79      for example.  */
80   set_gdbarch_has_dos_based_file_system (gdbarch, 1);
81
82   set_solib_ops (gdbarch, &solib_target_so_ops);
83 }
84
85 /* Recognize Symbian object files.  */
86
87 static enum gdb_osabi
88 arm_symbian_osabi_sniffer (bfd *abfd)
89 {
90   Elf_Internal_Phdr *phdrs;
91   long phdrs_size;
92   int num_phdrs, i;
93
94   /* Symbian executables are always shared objects (ET_DYN).  */
95   if (elf_elfheader (abfd)->e_type == ET_EXEC)
96     return GDB_OSABI_UNKNOWN;
97
98   if (elf_elfheader (abfd)->e_ident[EI_OSABI] != ELFOSABI_NONE)
99     return GDB_OSABI_UNKNOWN;
100
101   /* Check for the ELF headers not being part of any PT_LOAD segment.
102      Symbian is the only GDB supported (or GNU binutils supported) ARM
103      target which uses a postlinker to flatten ELF files, dropping the
104      ELF dynamic info in the process.  */
105   phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
106   if (phdrs_size == -1)
107     return GDB_OSABI_UNKNOWN;
108
109   phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size);
110   num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
111   if (num_phdrs == -1)
112     return GDB_OSABI_UNKNOWN;
113
114   for (i = 0; i < num_phdrs; i++)
115     if (phdrs[i].p_type == PT_LOAD && phdrs[i].p_offset == 0)
116       return GDB_OSABI_UNKNOWN;
117
118   /* Looks like a Symbian binary.  */
119   return GDB_OSABI_SYMBIAN;
120 }
121
122 void
123 _initialize_arm_symbian_tdep (void)
124 {
125   gdbarch_register_osabi_sniffer (bfd_arch_arm,
126                                   bfd_target_elf_flavour,
127                                   arm_symbian_osabi_sniffer);
128
129   gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_SYMBIAN,
130                           arm_symbian_init_abi);
131 }