1130803Smarcel/* Very simple "bfd" target, for GDB, the GNU debugger.
2130803Smarcel
3130803Smarcel   Copyright 2003 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "target.h"
24130803Smarcel#include "bfd-target.h"
25130803Smarcel#include "gdb_assert.h"
26130803Smarcel#include "gdb_string.h"
27130803Smarcel
28130803Smarcel/* Locate all mappable sections of a BFD file, filling in a target
29130803Smarcel   section for each.  */
30130803Smarcel
31130803Smarcelstruct section_closure
32130803Smarcel{
33130803Smarcel  struct section_table *end;
34130803Smarcel};
35130803Smarcel
36130803Smarcelstatic void
37130803Smarceladd_to_section_table (struct bfd *abfd, struct bfd_section *asect,
38130803Smarcel		      void *closure)
39130803Smarcel{
40130803Smarcel  struct section_closure *pp = closure;
41130803Smarcel  flagword aflag;
42130803Smarcel
43130803Smarcel  /* NOTE: cagney/2003-10-22: Is this pruning useful?  */
44130803Smarcel  aflag = bfd_get_section_flags (abfd, asect);
45130803Smarcel  if (!(aflag & SEC_ALLOC))
46130803Smarcel    return;
47130803Smarcel  if (bfd_section_size (abfd, asect) == 0)
48130803Smarcel    return;
49130803Smarcel  pp->end->bfd = abfd;
50130803Smarcel  pp->end->the_bfd_section = asect;
51130803Smarcel  pp->end->addr = bfd_section_vma (abfd, asect);
52130803Smarcel  pp->end->endaddr = pp->end->addr + bfd_section_size (abfd, asect);
53130803Smarcel  pp->end++;
54130803Smarcel}
55130803Smarcel
56130803Smarcelvoid
57130803Smarcelbuild_target_sections_from_bfd (struct target_ops *targ, struct bfd *abfd)
58130803Smarcel{
59130803Smarcel  unsigned count;
60130803Smarcel  struct section_table *start;
61130803Smarcel  struct section_closure cl;
62130803Smarcel
63130803Smarcel  count = bfd_count_sections (abfd);
64130803Smarcel  target_resize_to_sections (targ, count);
65130803Smarcel  start = targ->to_sections;
66130803Smarcel  cl.end = targ->to_sections;
67130803Smarcel  bfd_map_over_sections (abfd, add_to_section_table, &cl);
68130803Smarcel  gdb_assert (cl.end - start <= count);
69130803Smarcel}
70130803Smarcel
71130803SmarcelLONGEST
72130803Smarceltarget_bfd_xfer_partial (struct target_ops *ops,
73130803Smarcel			 enum target_object object,
74130803Smarcel			 const char *annex, void *readbuf,
75130803Smarcel			 const void *writebuf, ULONGEST offset, LONGEST len)
76130803Smarcel{
77130803Smarcel  switch (object)
78130803Smarcel    {
79130803Smarcel    case TARGET_OBJECT_MEMORY:
80130803Smarcel      {
81130803Smarcel	struct section_table *s = target_section_by_addr (ops, offset);
82130803Smarcel	if (s == NULL)
83130803Smarcel	  return -1;
84130803Smarcel	/* If the length extends beyond the section, truncate it.  Be
85130803Smarcel           careful to not suffer from overflow (wish S contained a
86130803Smarcel           length).  */
87130803Smarcel	if ((offset - s->addr + len) > (s->endaddr - s->addr))
88130803Smarcel	  len = (s->endaddr - s->addr) - (offset - s->addr);
89130803Smarcel	if (readbuf != NULL
90130803Smarcel	    && !bfd_get_section_contents (s->bfd, s->the_bfd_section,
91130803Smarcel					  readbuf, offset - s->addr, len))
92130803Smarcel	  return -1;
93130803Smarcel#if 1
94130803Smarcel	if (writebuf != NULL)
95130803Smarcel	  return -1;
96130803Smarcel#else
97130803Smarcel	/* FIXME: cagney/2003-10-31: The BFD interface doesn't yet
98130803Smarcel           take a const buffer.  */
99130803Smarcel	if (writebuf != NULL
100130803Smarcel	    && !bfd_set_section_contents (s->bfd, s->the_bfd_section,
101130803Smarcel					  writebuf, offset - s->addr, len))
102130803Smarcel	  return -1;
103130803Smarcel#endif
104130803Smarcel	return len;
105130803Smarcel      }
106130803Smarcel    default:
107130803Smarcel      return -1;
108130803Smarcel    }
109130803Smarcel}
110130803Smarcel
111130803Smarcelvoid
112130803Smarceltarget_bfd_xclose (struct target_ops *t, int quitting)
113130803Smarcel{
114130803Smarcel  bfd_close (t->to_data);
115130803Smarcel  xfree (t->to_sections);
116130803Smarcel  xfree (t);
117130803Smarcel}
118130803Smarcel
119130803Smarcelstruct target_ops *
120130803Smarceltarget_bfd_reopen (struct bfd *bfd)
121130803Smarcel{
122130803Smarcel  struct target_ops *t = XZALLOC (struct target_ops);
123130803Smarcel  t->to_shortname = "bfd";
124130803Smarcel  t->to_longname = "BFD backed target";
125130803Smarcel  t->to_doc = "You should never see this";
126130803Smarcel  t->to_xfer_partial = target_bfd_xfer_partial;
127130803Smarcel  t->to_xclose = target_bfd_xclose;
128130803Smarcel  t->to_data = bfd;
129130803Smarcel  build_target_sections_from_bfd (t, bfd);
130130803Smarcel  return t;
131130803Smarcel}
132