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_generic.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013, 2015 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 "target.h"
20 
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 /*
25  * A generic file read function. If the user doesn't supply a buffer,
26  * we malloc one, and they must free it later. If they specify a zero
27  * length, we attempt to read as many bytes as possible until we see a
28  * \0 byte -- i.e., we hit the end of a string. On error we return
29  * NULL.
30  */
31 unsigned char *target_generic_fd_read(int fd,
32  ADDR addr,
33  unsigned long length,
34  unsigned char *buf) {
35  unsigned char *lbuf = buf;
36  unsigned char *tbuf;
37  int bufinc = 128;
38  int bufsiz = length;
39  int read_until_null = !length;
40  int rc = 0;
41  int retval;
42  int len;
43 
44  vdebug(5,LA_TARGET,LF_TOTHER,"reading fd %d at 0x%"PRIxADDR" into %p (%d)\n",
45  fd,addr,buf,length);
46 
47  /* We must malloc their buffer if they want us to read a NUL-term
48  * string!
49  */
50  if (buf && !length) {
51  errno = EINVAL;
52  return NULL;
53  }
54 
55  if (!lbuf) {
56  if (read_until_null)
57  bufsiz = bufinc;
58  lbuf = malloc(bufsiz);
59  }
60 
61  if (lseek64(fd,addr,SEEK_SET) == (off64_t) -1) {
62  verror("lseek64(%d,0x%"PRIxADDR",0): %s\n",fd,addr,strerror(errno));
63  return NULL;
64  }
65 
66  while (1) {
67  retval = read(fd,lbuf+rc,bufsiz - rc);
68  if (retval > 0) {
69  rc += retval;
70  if (rc < bufsiz && !read_until_null) {
71  /* read some more bytes */
72  }
73  else if (read_until_null
74  && (len = strnlen((const char *)lbuf,rc)) < rc) {
75  /* we've found a NUL-term string */
76  if (!(lbuf = (void *)realloc(lbuf,len + 1))) {
77  free(lbuf);
78  verror("realloc: %s\n",strerror(errno));
79  return NULL;
80  }
81  return lbuf;
82  }
83  else if (read_until_null && rc == bufsiz) {
84  /* expand our buffer via realloc, or malloc. */
85  if (!(lbuf = (void *)realloc(lbuf,bufsiz + bufinc))) {
86  tbuf = malloc(bufsiz + bufinc);
87  if (!tbuf) {
88  /* we can't recover from this! */
89  free(lbuf);
90  verror("malloc: %s\n",strerror(errno));
91  return NULL;
92  }
93  memcpy(tbuf,lbuf,bufsiz);
94  free(lbuf);
95  lbuf = tbuf;
96  }
97  bufsiz += bufinc;
98  }
99  else if (!read_until_null && rc == bufsiz) {
100  /* we're done! */
101  return lbuf;
102  }
103  }
104  else if (retval == 0 && rc != bufsiz) {
105  if (lbuf != buf)
106  free(lbuf);
107  verror("EOF before reading %d bytes!\n",bufsiz);
108  errno = EOF;
109  return NULL;
110  }
111  else if (retval < 0
112  && retval != EAGAIN && retval != EINTR) {
113  if (lbuf != buf)
114  free(lbuf);
115  verror("read: %s\n",strerror(errno));
116  return NULL;
117  }
118  else
119  break;
120  }
121 
122  return lbuf;
123 }
124 
125 unsigned long target_generic_fd_write(int fd,
126  ADDR addr,
127  unsigned long length,
128  unsigned char *buf) {
129  size_t rc;
130  long total = 0;
131 
132  if (lseek64(fd,addr,0) == (off_t)-1) {
133  verror("lseek64: %s",strerror(errno));
134  return -1;
135  }
136 
137  while (1) {
138  rc = write(fd,buf+total,length-total);
139  if (rc > 0 && (total + rc) == length) {
140  total += rc;
141  break;
142  }
143  else if ((rc > 0 && rc < length)
144  || (rc <= 0 && (rc == EAGAIN || rc == EINTR)))
145  total += rc;
146  else {
147  verror("write error: %s (after %ld bytes of %lu total) (buf 0x%p)\n",
148  strerror(errno),total,length,(void *)buf);
149  break;
150  }
151  }
152 
153  return total;
154 }
unsigned char * target_generic_fd_read(int fd, ADDR addr, unsigned long length, unsigned char *buf)
#define verror(format,...)
Definition: log.h:30
void free(void *ptr)
Definition: debugserver.c:207
Definition: log.h:167
int len
Definition: dumptarget.c:52
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
Definition: log.h:70
uint32_t ADDR
Definition: common.h:64
#define PRIxADDR
Definition: common.h:67
unsigned long target_generic_fd_write(int fd, ADDR addr, unsigned long length, unsigned char *buf)
void * malloc(size_t size)
Definition: debugserver.c:214