Remove remaining "%ll" uses.
[deliverable/binutils-gdb.git] / gdb / solib-spu.c
1 /* Cell SPU GNU/Linux support -- shared library handling.
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3
4 Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "defs.h"
22 #include "gdbcore.h"
23 #include "gdb_string.h"
24 #include "gdb_assert.h"
25 #include "gdb_stat.h"
26 #include "arch-utils.h"
27 #include "bfd.h"
28 #include "symtab.h"
29 #include "solib.h"
30 #include "solib-svr4.h"
31 #include "solist.h"
32 #include "inferior.h"
33 #include "objfiles.h"
34 #include "observer.h"
35 #include "breakpoint.h"
36 #include "gdbthread.h"
37
38 #include "spu-tdep.h"
39
40 /* Highest SPE id (file handle) the inferior may have. */
41 #define MAX_SPE_FD 1024
42
43 /* Stand-alone SPE executable? */
44 #define spu_standalone_p() \
45 (symfile_objfile && symfile_objfile->obfd \
46 && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu)
47
48
49 /* Relocate main SPE executable. */
50 static void
51 spu_relocate_main_executable (int spufs_fd)
52 {
53 struct section_offsets *new_offsets;
54 int i;
55
56 if (symfile_objfile == NULL)
57 return;
58
59 new_offsets = alloca (symfile_objfile->num_sections
60 * sizeof (struct section_offsets));
61
62 for (i = 0; i < symfile_objfile->num_sections; i++)
63 new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
64
65 objfile_relocate (symfile_objfile, new_offsets);
66 }
67
68 /* When running a stand-alone SPE executable, we may need to skip one more
69 exec event on startup, to get past the binfmt_misc loader. */
70 static void
71 spu_skip_standalone_loader (void)
72 {
73 if (target_has_execution && !current_inferior ()->attach_flag)
74 {
75 struct target_waitstatus ws;
76
77 /* Only some kernels report an extra SIGTRAP with the binfmt_misc
78 loader; others do not. In addition, if we have attached to an
79 already running inferior instead of starting a new one, we will
80 not see the extra SIGTRAP -- and we cannot readily distinguish
81 the two cases, in particular with the extended-remote target.
82
83 Thus we issue a single-step here. If no extra SIGTRAP was pending,
84 this will step past the first instruction of the stand-alone SPE
85 executable loader, but we don't care about that. */
86
87 inferior_thread ()->in_infcall = 1; /* Suppress MI messages. */
88
89 target_resume (inferior_ptid, 1, TARGET_SIGNAL_0);
90 target_wait (minus_one_ptid, &ws, 0);
91 set_executing (minus_one_ptid, 0);
92
93 inferior_thread ()->in_infcall = 0;
94 }
95 }
96
97 /* Build a list of `struct so_list' objects describing the shared
98 objects currently loaded in the inferior. */
99 static struct so_list *
100 spu_current_sos (void)
101 {
102 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
103 struct so_list *head;
104 struct so_list **link_ptr;
105
106 char buf[MAX_SPE_FD * 4];
107 int i, size;
108
109 /* First, retrieve the SVR4 shared library list. */
110 head = svr4_so_ops.current_sos ();
111
112 /* Append our libraries to the end of the list. */
113 for (link_ptr = &head; *link_ptr; link_ptr = &(*link_ptr)->next)
114 ;
115
116 /* Determine list of SPU ids. */
117 size = target_read (&current_target, TARGET_OBJECT_SPU, NULL,
118 buf, 0, sizeof buf);
119
120 /* Do not add stand-alone SPE executable context as shared library,
121 but relocate main SPE executable objfile. */
122 if (spu_standalone_p ())
123 {
124 if (size == 4)
125 {
126 int fd = extract_unsigned_integer (buf, 4, byte_order);
127 spu_relocate_main_executable (fd);
128
129 /* Re-enable breakpoints after main SPU context was established;
130 see also comments in spu_solib_create_inferior_hook. */
131 enable_breakpoints_after_startup ();
132 }
133
134 return head;
135 }
136
137 /* Create an so_list entry for each SPU id. */
138 for (i = 0; i < size; i += 4)
139 {
140 int fd = extract_unsigned_integer (buf + i, 4, byte_order);
141 struct so_list *new;
142
143 unsigned long long addr;
144 char annex[32], id[100];
145 int len;
146
147 /* Read object ID. There's a race window where the inferior may have
148 already created the SPE context, but not installed the object-id
149 yet. Skip such entries; we'll be back for them later. */
150 xsnprintf (annex, sizeof annex, "%d/object-id", fd);
151 len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
152 id, 0, sizeof id);
153 if (len <= 0 || len >= sizeof id)
154 continue;
155 id[len] = 0;
156 if (sscanf (id, "0x%llx", &addr) != 1 || !addr)
157 continue;
158
159 /* Allocate so_list structure. */
160 new = XZALLOC (struct so_list);
161
162 /* Encode FD and object ID in path name. Choose the name so as not
163 to conflict with any (normal) SVR4 library path name. */
164 xsnprintf (new->so_name, sizeof new->so_name, "@%s <%d>",
165 hex_string (addr), fd);
166 strcpy (new->so_original_name, new->so_name);
167
168 *link_ptr = new;
169 link_ptr = &new->next;
170 }
171
172 return head;
173 }
174
175 /* Free so_list information. */
176 static void
177 spu_free_so (struct so_list *so)
178 {
179 if (so->so_original_name[0] != '@')
180 svr4_so_ops.free_so (so);
181 }
182
183 /* Relocate section addresses. */
184 static void
185 spu_relocate_section_addresses (struct so_list *so,
186 struct target_section *sec)
187 {
188 if (so->so_original_name[0] != '@')
189 svr4_so_ops.relocate_section_addresses (so, sec);
190 else
191 {
192 unsigned long long addr;
193 int fd;
194
195 /* Set addr_low/high to just LS offset for display. */
196 if (so->addr_low == 0 && so->addr_high == 0
197 && strcmp (sec->the_bfd_section->name, ".text") == 0)
198 {
199 so->addr_low = sec->addr;
200 so->addr_high = sec->endaddr;
201 }
202
203 /* Decode object ID. */
204 if (sscanf (so->so_original_name, "@0x%llx <%d>", &addr, &fd) != 2)
205 internal_error (__FILE__, __LINE__, "bad object ID");
206
207 sec->addr = SPUADDR (fd, sec->addr);
208 sec->endaddr = SPUADDR (fd, sec->endaddr);
209 }
210 }
211
212
213 /* Inferior memory should contain an SPE executable image at location ADDR.
214 Allocate a BFD representing that executable. Return NULL on error. */
215
216 static void *
217 spu_bfd_iovec_open (bfd *nbfd, void *open_closure)
218 {
219 return open_closure;
220 }
221
222 static int
223 spu_bfd_iovec_close (bfd *nbfd, void *stream)
224 {
225 xfree (stream);
226 return 1;
227 }
228
229 static file_ptr
230 spu_bfd_iovec_pread (bfd *abfd, void *stream, void *buf,
231 file_ptr nbytes, file_ptr offset)
232 {
233 CORE_ADDR addr = *(CORE_ADDR *)stream;
234 int ret;
235
236 ret = target_read_memory (addr + offset, buf, nbytes);
237 if (ret != 0)
238 {
239 bfd_set_error (bfd_error_invalid_operation);
240 return -1;
241 }
242
243 return nbytes;
244 }
245
246 static int
247 spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
248 {
249 /* We don't have an easy way of finding the size of embedded spu
250 images. We could parse the in-memory ELF header and section
251 table to find the extent of the last section but that seems
252 pointless when the size is needed only for checks of other
253 parsed values in dbxread.c. */
254 sb->st_size = INT_MAX;
255 return 0;
256 }
257
258 static bfd *
259 spu_bfd_fopen (char *name, CORE_ADDR addr)
260 {
261 bfd *nbfd;
262
263 CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR));
264 *open_closure = addr;
265
266 nbfd = bfd_openr_iovec (xstrdup (name), "elf32-spu",
267 spu_bfd_iovec_open, open_closure,
268 spu_bfd_iovec_pread, spu_bfd_iovec_close,
269 spu_bfd_iovec_stat);
270 if (!nbfd)
271 return NULL;
272
273 if (!bfd_check_format (nbfd, bfd_object))
274 {
275 bfd_close (nbfd);
276 return NULL;
277 }
278
279 return nbfd;
280 }
281
282 /* Open shared library BFD. */
283 static bfd *
284 spu_bfd_open (char *pathname)
285 {
286 char *original_name = strrchr (pathname, '@');
287 bfd *abfd;
288 asection *spu_name;
289 unsigned long long addr;
290 int fd;
291
292 /* Handle regular SVR4 libraries. */
293 if (!original_name)
294 return svr4_so_ops.bfd_open (pathname);
295
296 /* Decode object ID. */
297 if (sscanf (original_name, "@0x%llx <%d>", &addr, &fd) != 2)
298 internal_error (__FILE__, __LINE__, "bad object ID");
299
300 /* Open BFD representing SPE executable. */
301 abfd = spu_bfd_fopen (original_name, (CORE_ADDR) addr);
302 if (!abfd)
303 error (_("Cannot read SPE executable at %s"), original_name);
304
305 /* Retrieve SPU name note. */
306 spu_name = bfd_get_section_by_name (abfd, ".note.spu_name");
307 if (spu_name)
308 {
309 int sect_size = bfd_section_size (abfd, spu_name);
310 if (sect_size > 20)
311 {
312 char *buf = alloca (sect_size - 20 + strlen (original_name) + 1);
313 bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20);
314 buf[sect_size - 20] = '\0';
315
316 strcat (buf, original_name);
317
318 xfree ((char *)abfd->filename);
319 abfd->filename = xstrdup (buf);
320 }
321 }
322
323 return abfd;
324 }
325
326 /* Lookup global symbol in a SPE executable. */
327 static struct symbol *
328 spu_lookup_lib_symbol (const struct objfile *objfile,
329 const char *name,
330 const domain_enum domain)
331 {
332 if (bfd_get_arch (objfile->obfd) == bfd_arch_spu)
333 return lookup_global_symbol_from_objfile (objfile, name, domain);
334
335 if (svr4_so_ops.lookup_lib_global_symbol != NULL)
336 return svr4_so_ops.lookup_lib_global_symbol (objfile, name, domain);
337 return NULL;
338 }
339
340 /* Enable shared library breakpoint. */
341 static int
342 spu_enable_break (struct objfile *objfile)
343 {
344 struct minimal_symbol *spe_event_sym = NULL;
345
346 /* The libspe library will call __spe_context_update_event whenever any
347 SPE context is allocated or destroyed. */
348 spe_event_sym = lookup_minimal_symbol ("__spe_context_update_event",
349 NULL, objfile);
350
351 /* Place a solib_event breakpoint on the symbol. */
352 if (spe_event_sym)
353 {
354 CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (spe_event_sym);
355 addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, addr,
356 &current_target);
357 create_solib_event_breakpoint (target_gdbarch, addr);
358 return 1;
359 }
360
361 return 0;
362 }
363
364 /* Create inferior hook. */
365 static void
366 spu_solib_create_inferior_hook (int from_tty)
367 {
368 /* Handle SPE stand-alone executables. */
369 if (spu_standalone_p ())
370 {
371 /* After an SPE stand-alone executable was loaded, we'll receive
372 an additional trap due to the binfmt_misc handler. Make sure
373 to skip that trap. */
374 spu_skip_standalone_loader ();
375
376 /* If the user established breakpoints before starting the inferior, GDB
377 would attempt to insert those now. This would fail because the SPU
378 context has not yet been created and the SPU executable has not yet
379 been loaded. To prevent such failures, we disable all user-created
380 breakpoints now; they will be re-enabled in spu_current_sos once the
381 main SPU context has been detected. */
382 disable_breakpoints_before_startup ();
383
384 /* A special case arises when re-starting an executable, because at
385 this point it still resides at the relocated address range that was
386 determined during its last execution. We need to undo the relocation
387 so that that multi-architecture target recognizes the stand-alone
388 initialization special case. */
389 spu_relocate_main_executable (-1);
390 }
391
392 /* Call SVR4 hook -- this will re-insert the SVR4 solib breakpoints. */
393 svr4_so_ops.solib_create_inferior_hook (from_tty);
394
395 /* If the inferior is statically linked against libspe, we need to install
396 our own solib breakpoint right now. Otherwise, it will be installed by
397 the solib_loaded observer below as soon as libspe is loaded. */
398 spu_enable_break (NULL);
399 }
400
401 /* Install SPE "shared library" handling. This is called by -tdep code
402 that wants to support SPU as a secondary architecture. */
403 void
404 set_spu_solib_ops (struct gdbarch *gdbarch)
405 {
406 static struct target_so_ops spu_so_ops;
407
408 /* Initialize this lazily, to avoid an initialization order
409 dependency on solib-svr4.c's _initialize routine. */
410 if (spu_so_ops.current_sos == NULL)
411 {
412 spu_so_ops = svr4_so_ops;
413 spu_so_ops.solib_create_inferior_hook = spu_solib_create_inferior_hook;
414 spu_so_ops.relocate_section_addresses = spu_relocate_section_addresses;
415 spu_so_ops.free_so = spu_free_so;
416 spu_so_ops.current_sos = spu_current_sos;
417 spu_so_ops.bfd_open = spu_bfd_open;
418 spu_so_ops.lookup_lib_global_symbol = spu_lookup_lib_symbol;
419 }
420
421 set_solib_ops (gdbarch, &spu_so_ops);
422 }
423
424 /* Observer for the solib_loaded event. Used to install our breakpoint
425 if libspe is a shared library. */
426 static void
427 spu_solib_loaded (struct so_list *so)
428 {
429 if (strstr (so->so_original_name, "/libspe") != NULL)
430 {
431 solib_read_symbols (so, so->from_tty ? SYMFILE_VERBOSE : 0);
432 spu_enable_break (so->objfile);
433 }
434 }
435
436 void
437 _initialize_spu_solib (void)
438 {
439 observer_attach_solib_loaded (spu_solib_loaded);
440 }
441
This page took 0.038663 seconds and 4 git commands to generate.