1/* Very simple "bfd" target, for GDB, the GNU debugger. 2 3 Copyright (C) 2003, 2005, 2007 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 "target.h" 22#include "bfd-target.h" 23#include "gdb_assert.h" 24#include "gdb_string.h" 25 26/* Locate all mappable sections of a BFD file, filling in a target 27 section for each. */ 28 29struct section_closure 30{ 31 struct section_table *end; 32}; 33 34static void 35add_to_section_table (struct bfd *abfd, struct bfd_section *asect, 36 void *closure) 37{ 38 struct section_closure *pp = closure; 39 flagword aflag; 40 41 /* NOTE: cagney/2003-10-22: Is this pruning useful? */ 42 aflag = bfd_get_section_flags (abfd, asect); 43 if (!(aflag & SEC_ALLOC)) 44 return; 45 if (bfd_section_size (abfd, asect) == 0) 46 return; 47 pp->end->bfd = abfd; 48 pp->end->the_bfd_section = asect; 49 pp->end->addr = bfd_section_vma (abfd, asect); 50 pp->end->endaddr = pp->end->addr + bfd_section_size (abfd, asect); 51 pp->end++; 52} 53 54void 55build_target_sections_from_bfd (struct target_ops *targ, struct bfd *abfd) 56{ 57 unsigned count; 58 struct section_table *start; 59 struct section_closure cl; 60 61 count = bfd_count_sections (abfd); 62 target_resize_to_sections (targ, count); 63 start = targ->to_sections; 64 cl.end = targ->to_sections; 65 bfd_map_over_sections (abfd, add_to_section_table, &cl); 66 gdb_assert (cl.end - start <= count); 67} 68 69LONGEST 70target_bfd_xfer_partial (struct target_ops *ops, 71 enum target_object object, 72 const char *annex, gdb_byte *readbuf, 73 const gdb_byte *writebuf, 74 ULONGEST offset, LONGEST len) 75{ 76 switch (object) 77 { 78 case TARGET_OBJECT_MEMORY: 79 { 80 struct section_table *s = target_section_by_addr (ops, offset); 81 if (s == NULL) 82 return -1; 83 /* If the length extends beyond the section, truncate it. Be 84 careful to not suffer from overflow (wish S contained a 85 length). */ 86 if ((offset - s->addr + len) > (s->endaddr - s->addr)) 87 len = (s->endaddr - s->addr) - (offset - s->addr); 88 if (readbuf != NULL 89 && !bfd_get_section_contents (s->bfd, s->the_bfd_section, 90 readbuf, offset - s->addr, len)) 91 return -1; 92#if 1 93 if (writebuf != NULL) 94 return -1; 95#else 96 /* FIXME: cagney/2003-10-31: The BFD interface doesn't yet 97 take a const buffer. */ 98 if (writebuf != NULL 99 && !bfd_set_section_contents (s->bfd, s->the_bfd_section, 100 writebuf, offset - s->addr, len)) 101 return -1; 102#endif 103 return len; 104 } 105 default: 106 return -1; 107 } 108} 109 110void 111target_bfd_xclose (struct target_ops *t, int quitting) 112{ 113 bfd_close (t->to_data); 114 xfree (t->to_sections); 115 xfree (t); 116} 117 118struct target_ops * 119target_bfd_reopen (struct bfd *bfd) 120{ 121 struct target_ops *t = XZALLOC (struct target_ops); 122 t->to_shortname = "bfd"; 123 t->to_longname = _("BFD backed target"); 124 t->to_doc = _("You should never see this"); 125 t->to_xfer_partial = target_bfd_xfer_partial; 126 t->to_xclose = target_bfd_xclose; 127 t->to_data = bfd; 128 build_target_sections_from_bfd (t, bfd); 129 return t; 130} 131