Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
target_gdb_helper_builtin.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "config.h"
20 
21 #include <errno.h>
22 #include <ctype.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 
28 #include "common.h"
29 #include "target_api.h"
30 #include "target.h"
31 
32 #include "target_gdb.h"
33 #include "target_gdb_rsp.h"
34 
35 /*
36  * Oh, this is a pain. A GDB stub by default will probably read virtual
37  * memory; but some stubs (like those that sit outside a VM) will read
38  * whatever memory the VM is exposing at the CPU level -- so if paging
39  * is enabled, then virtual memory; if not, physical memory.
40  *
41  * But, I guess, whether it's KGDB or qemu's GDB, m/M read/write
42  * whatever memory the CPU is addressing. So... the only way we can
43  * translate v2p or r/w physical addrs is by some non-GDB stub route --
44  * like through QEMU's QMP's xp command (or a hack to the VM making
45  * mmap'able memory available). Other debugger stubs might have their
46  * own workarounds.
47  *
48  * So, we only build in support for r/w virtual memory.
49  */
50 
51 /*
52  * Local prototypes.
53  */
54 unsigned char *gdb_helper_builtin_read_tid(struct target *target,
55  tid_t tid,ADDR pgd,ADDR addr,
56  unsigned long length,
57  unsigned char *buf);
58 
60  /* Nothing yet! */
61 };
62 
64  return 0;
65 }
66 
68  return 0;
69 }
70 
72  return 0;
73 }
74 
76  return 0;
77 }
78 
80  return 0;
81 }
82 
84  tid_t tid,ADDR pgd,ADDR addr) {
85  int j;
86  unsigned char *lbuf = NULL;
87  int lbuf_alen = 0,lbuf_len = 0;
88 
89  /*
90  * Best strategy is to read page by page (starting with the remnant
91  * of the page containing @addr), or byte by byte -- depending on
92  * the GDB stub. A page should always be safe, so do that for now.
93  */
94 
95  lbuf_alen = __PAGE_SIZE - (addr & (__PAGE_SIZE - 1));
96  lbuf = realloc(lbuf,lbuf_alen);
97  if (!gdb_helper_builtin_read_tid(target,tid,pgd,addr,lbuf_alen,lbuf)) {
98  verror("failed to read string at 0x%"PRIxADDR" (target %s)!\n",
99  addr,target->name);
100  free(lbuf);
101  return NULL;
102  }
103 
104  do {
105  /*
106  * Scan the mmap as necessary for '\0', malloc as necessary, and
107  * break or keep going.
108  */
109  for (j = lbuf_len; j < lbuf_alen; ++j) {
110  if (lbuf[j] == '\0')
111  break;
112  }
113 
114  if (j < lbuf_alen) {
115  /* Found it! realloc and return. */
116  lbuf = realloc(lbuf,j + 1);
117  return lbuf;
118  }
119  else {
120  lbuf_len = lbuf_alen;
121  lbuf_alen += __PAGE_SIZE;
122  lbuf = realloc(lbuf,lbuf_alen);
123  }
124  } while (1);
125 
126  return (unsigned char *)lbuf;
127 }
128 
129 /*
130  * Reads a block of memory from the target. If @buf is non-NULL, we
131  * assume it is at least @length bytes long; the result is placed into
132  * @buf and @buf is returned. If @buf is NULL, we allocate a buffer
133  * large enough to hold the result (@length if @length >0; if @length is
134  * 0 we attempt to read a string at that address; we stop when we hit a
135  * NULL byte).
136  *
137  * On error, returns NULL, and sets errno.
138  */
140  tid_t tid,ADDR pgd,ADDR addr,
141  unsigned long length,
142  unsigned char *buf) {
143  struct target_thread *tthread;
144  int rc;
145 
146  /*
147  * Check @tid is current thread or global thread or that all threads
148  * share a single address space!
149  *
150  * How to check if all threads share a single address space? Maybe
151  * just by checking the target type for now; if OS, assume threads
152  * need not share an address space; if process or higher-level,
153  * assume they do?
154  */
155  if (target->personality <= TARGET_PERSONALITY_OS && tid != TID_GLOBAL) {
156  tthread = target_load_current_thread(target,0);
157  if (!tthread) {
158  vwarn("could not load current thread; assuming tid %d is current!\n",
159  tid);
160  }
161  else {
162  if (tthread->tid != tid) {
163  verror("tid %d is not current nor global; cannot read!\n",tid);
164  return NULL;
165  }
166  }
167  }
168 
169  if (length == 0)
170  return gdb_helper_builtin_read_v_str(target,tid,pgd,addr);
171 
172  rc = gdb_rsp_read_mem(target,addr,length,buf);
173  if (rc == 0)
174  return buf;
175  else {
176  verror("v 0x%"PRIxADDR" len %lu: %s (%d); continuing\n",
177  addr,length,strerror(errno),rc);
178  return NULL;
179  }
180 }
181 
182 /*
183  * Writes @length bytes from @buf to @addr. Returns the number of bytes
184  * written (and sets errno nonzero if there is an error). Successful if
185  * @return == @length.
186  */
188  tid_t tid,ADDR pgd,ADDR addr,
189  unsigned long length,
190  unsigned char *buf) {
191  struct target_thread *tthread;
192  int rc;
193 
194  /*
195  * Check @tid is current thread or global thread or that all threads
196  * share a single address space!
197  *
198  * How to check if all threads share a single address space? Maybe
199  * just by checking the target type for now; if OS, assume threads
200  * need not share an address space; if process or higher-level,
201  * assume they do?
202  */
203  if (target->personality <= TARGET_PERSONALITY_OS && tid != TID_GLOBAL) {
204  tthread = target_load_current_thread(target,0);
205  if (!tthread) {
206  vwarn("could not load current thread; assuming tid %d is current!\n",
207  tid);
208  }
209  else {
210  if (tthread->tid != tid) {
211  verror("tid %d is not current nor global; cannot read!\n",tid);
212  errno = EINVAL;
213  return 0;
214  }
215  }
216  }
217 
218  rc = gdb_rsp_write_mem(target,addr,length,buf);
219  if (rc == 0) {
220  return length;
221  }
222  else {
223  verror("v 0x%"PRIxADDR" len %lu: %s (%d)\n",
224  addr,length,strerror(errno),rc);
225  return 0;
226  }
227 }
228 
230  return 0;
231 }
232 
235  .attach = gdb_helper_builtin_attach,
236 
237  .handle_exception_any = gdb_helper_builtin_handle_exception_any,
238  .handle_exception_ours = gdb_helper_builtin_handle_exception_ours,
239  .handle_pause = gdb_helper_builtin_handle_pause,
240  /*
241  * No physical address space access; see comments at top!
242  */
243  .addr_v2p = NULL,
244  .read_phys = NULL,
245  .write_phys = NULL,
246 
247  .read_tid = gdb_helper_builtin_read_tid,
248  .write_tid = gdb_helper_builtin_write_tid,
249 
250  .fini = gdb_helper_builtin_fini,
251 };
int gdb_helper_builtin_init(struct target *target)
int gdb_helper_builtin_handle_exception_ours(struct target *target)
int gdb_helper_builtin_handle_exception_any(struct target *target)
int gdb_helper_builtin_attach(struct target *target)
int32_t tid_t
Definition: common.h:36
target_personality_t personality
Definition: target_api.h:2515
int gdb_helper_builtin_handle_pause(struct target *target)
unsigned long gdb_helper_builtin_write_tid(struct target *target, tid_t tid, ADDR pgd, ADDR addr, unsigned long length, unsigned char *buf)
int gdb_rsp_write_mem(struct target *target, ADDR addr, unsigned long length, unsigned char *buf)
#define verror(format,...)
Definition: log.h:30
#define vwarn(format,...)
Definition: log.h:33
void free(void *ptr)
Definition: debugserver.c:207
struct target_thread * target_load_current_thread(struct target *target, int force)
Definition: target_api.c:1305
#define __PAGE_SIZE
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
int gdb_rsp_read_mem(struct target *target, ADDR addr, unsigned long length, unsigned char *buf)
uint32_t ADDR
Definition: common.h:64
char * name
Definition: target_api.h:2521
unsigned char * gdb_helper_builtin_read_tid(struct target *target, tid_t tid, ADDR pgd, ADDR addr, unsigned long length, unsigned char *buf)
#define PRIxADDR
Definition: common.h:67
unsigned char * gdb_helper_builtin_read_v_str(struct target *target, tid_t tid, ADDR pgd, ADDR addr)
struct gdb_helper_ops gdb_helper_ops_builtin
int(* init)(struct target *target)
Definition: target_gdb.h:147
#define TID_GLOBAL
Definition: target_api.h:145
int gdb_helper_builtin_fini(struct target *target)