xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/target/target.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1*6881a400Schristos /* String reading
2*6881a400Schristos 
3*6881a400Schristos    Copyright (C) 2022-2023 Free Software Foundation, Inc.
4*6881a400Schristos 
5*6881a400Schristos    This file is part of GDB.
6*6881a400Schristos 
7*6881a400Schristos    This program is free software; you can redistribute it and/or modify
8*6881a400Schristos    it under the terms of the GNU General Public License as published by
9*6881a400Schristos    the Free Software Foundation; either version 3 of the License, or
10*6881a400Schristos    (at your option) any later version.
11*6881a400Schristos 
12*6881a400Schristos    This program is distributed in the hope that it will be useful,
13*6881a400Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*6881a400Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*6881a400Schristos    GNU General Public License for more details.
16*6881a400Schristos 
17*6881a400Schristos    You should have received a copy of the GNU General Public License
18*6881a400Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*6881a400Schristos 
20*6881a400Schristos #include "gdbsupport/common-defs.h"
21*6881a400Schristos #include "target/target.h"
22*6881a400Schristos 
23*6881a400Schristos /* Read LEN bytes of target memory at address MEMADDR, placing the
24*6881a400Schristos    results in GDB's memory at MYADDR.  Returns a count of the bytes
25*6881a400Schristos    actually read, and optionally a target_xfer_status value in the
26*6881a400Schristos    location pointed to by ERRPTR if ERRPTR is non-null.  */
27*6881a400Schristos 
28*6881a400Schristos static int
29*6881a400Schristos partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr,
30*6881a400Schristos 		     int len, int *errptr)
31*6881a400Schristos {
32*6881a400Schristos   int nread;			/* Number of bytes actually read.  */
33*6881a400Schristos   int errcode;			/* Error from last read.  */
34*6881a400Schristos 
35*6881a400Schristos   /* First try a complete read.  */
36*6881a400Schristos   errcode = target_read_memory (memaddr, myaddr, len);
37*6881a400Schristos   if (errcode == 0)
38*6881a400Schristos     {
39*6881a400Schristos       /* Got it all.  */
40*6881a400Schristos       nread = len;
41*6881a400Schristos     }
42*6881a400Schristos   else
43*6881a400Schristos     {
44*6881a400Schristos       /* Loop, reading one byte at a time until we get as much as we can.  */
45*6881a400Schristos       for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
46*6881a400Schristos 	{
47*6881a400Schristos 	  errcode = target_read_memory (memaddr++, myaddr++, 1);
48*6881a400Schristos 	}
49*6881a400Schristos       /* If an error, the last read was unsuccessful, so adjust count.  */
50*6881a400Schristos       if (errcode != 0)
51*6881a400Schristos 	{
52*6881a400Schristos 	  nread--;
53*6881a400Schristos 	}
54*6881a400Schristos     }
55*6881a400Schristos   if (errptr != NULL)
56*6881a400Schristos     {
57*6881a400Schristos       *errptr = errcode;
58*6881a400Schristos     }
59*6881a400Schristos   return (nread);
60*6881a400Schristos }
61*6881a400Schristos 
62*6881a400Schristos /* See target/target.h.  */
63*6881a400Schristos 
64*6881a400Schristos int
65*6881a400Schristos target_read_string (CORE_ADDR addr, int len, int width,
66*6881a400Schristos 		    unsigned int fetchlimit,
67*6881a400Schristos 		    gdb::unique_xmalloc_ptr<gdb_byte> *buffer,
68*6881a400Schristos 		    int *bytes_read)
69*6881a400Schristos {
70*6881a400Schristos   int errcode;			/* Errno returned from bad reads.  */
71*6881a400Schristos   unsigned int nfetch;		/* Chars to fetch / chars fetched.  */
72*6881a400Schristos   gdb_byte *bufptr;		/* Pointer to next available byte in
73*6881a400Schristos 				   buffer.  */
74*6881a400Schristos 
75*6881a400Schristos   /* Loop until we either have all the characters, or we encounter
76*6881a400Schristos      some error, such as bumping into the end of the address space.  */
77*6881a400Schristos 
78*6881a400Schristos   buffer->reset (nullptr);
79*6881a400Schristos 
80*6881a400Schristos   if (len > 0)
81*6881a400Schristos     {
82*6881a400Schristos       /* We want fetchlimit chars, so we might as well read them all in
83*6881a400Schristos 	 one operation.  */
84*6881a400Schristos       unsigned int fetchlen = std::min ((unsigned) len, fetchlimit);
85*6881a400Schristos 
86*6881a400Schristos       buffer->reset ((gdb_byte *) xmalloc (fetchlen * width));
87*6881a400Schristos       bufptr = buffer->get ();
88*6881a400Schristos 
89*6881a400Schristos       nfetch = partial_memory_read (addr, bufptr, fetchlen * width, &errcode)
90*6881a400Schristos 	/ width;
91*6881a400Schristos       addr += nfetch * width;
92*6881a400Schristos       bufptr += nfetch * width;
93*6881a400Schristos     }
94*6881a400Schristos   else if (len == -1)
95*6881a400Schristos     {
96*6881a400Schristos       unsigned long bufsize = 0;
97*6881a400Schristos       unsigned int chunksize;	/* Size of each fetch, in chars.  */
98*6881a400Schristos       int found_nul;		/* Non-zero if we found the nul char.  */
99*6881a400Schristos       gdb_byte *limit;		/* First location past end of fetch buffer.  */
100*6881a400Schristos 
101*6881a400Schristos       found_nul = 0;
102*6881a400Schristos       /* We are looking for a NUL terminator to end the fetching, so we
103*6881a400Schristos 	 might as well read in blocks that are large enough to be efficient,
104*6881a400Schristos 	 but not so large as to be slow if fetchlimit happens to be large.
105*6881a400Schristos 	 So we choose the minimum of 8 and fetchlimit.  We used to use 200
106*6881a400Schristos 	 instead of 8 but 200 is way too big for remote debugging over a
107*6881a400Schristos 	  serial line.  */
108*6881a400Schristos       chunksize = std::min (8u, fetchlimit);
109*6881a400Schristos 
110*6881a400Schristos       do
111*6881a400Schristos 	{
112*6881a400Schristos 	  nfetch = std::min ((unsigned long) chunksize, fetchlimit - bufsize);
113*6881a400Schristos 
114*6881a400Schristos 	  if (*buffer == NULL)
115*6881a400Schristos 	    buffer->reset ((gdb_byte *) xmalloc (nfetch * width));
116*6881a400Schristos 	  else
117*6881a400Schristos 	    buffer->reset ((gdb_byte *) xrealloc (buffer->release (),
118*6881a400Schristos 						  (nfetch + bufsize) * width));
119*6881a400Schristos 
120*6881a400Schristos 	  bufptr = buffer->get () + bufsize * width;
121*6881a400Schristos 	  bufsize += nfetch;
122*6881a400Schristos 
123*6881a400Schristos 	  /* Read as much as we can.  */
124*6881a400Schristos 	  nfetch = partial_memory_read (addr, bufptr, nfetch * width, &errcode)
125*6881a400Schristos 		    / width;
126*6881a400Schristos 
127*6881a400Schristos 	  /* Scan this chunk for the null character that terminates the string
128*6881a400Schristos 	     to print.  If found, we don't need to fetch any more.  Note
129*6881a400Schristos 	     that bufptr is explicitly left pointing at the next character
130*6881a400Schristos 	     after the null character, or at the next character after the end
131*6881a400Schristos 	     of the buffer.  */
132*6881a400Schristos 
133*6881a400Schristos 	  limit = bufptr + nfetch * width;
134*6881a400Schristos 	  while (bufptr < limit)
135*6881a400Schristos 	    {
136*6881a400Schristos 	      bool found_nonzero = false;
137*6881a400Schristos 
138*6881a400Schristos 	      for (int i = 0; !found_nonzero && i < width; ++i)
139*6881a400Schristos 		if (bufptr[i] != 0)
140*6881a400Schristos 		  found_nonzero = true;
141*6881a400Schristos 
142*6881a400Schristos 	      addr += width;
143*6881a400Schristos 	      bufptr += width;
144*6881a400Schristos 	      if (!found_nonzero)
145*6881a400Schristos 		{
146*6881a400Schristos 		  /* We don't care about any error which happened after
147*6881a400Schristos 		     the NUL terminator.  */
148*6881a400Schristos 		  errcode = 0;
149*6881a400Schristos 		  found_nul = 1;
150*6881a400Schristos 		  break;
151*6881a400Schristos 		}
152*6881a400Schristos 	    }
153*6881a400Schristos 	}
154*6881a400Schristos       while (errcode == 0	/* no error */
155*6881a400Schristos 	     && bufptr - buffer->get () < fetchlimit * width	/* no overrun */
156*6881a400Schristos 	     && !found_nul);	/* haven't found NUL yet */
157*6881a400Schristos     }
158*6881a400Schristos   else
159*6881a400Schristos     {				/* Length of string is really 0!  */
160*6881a400Schristos       /* We always allocate *buffer.  */
161*6881a400Schristos       buffer->reset ((gdb_byte *) xmalloc (1));
162*6881a400Schristos       bufptr = buffer->get ();
163*6881a400Schristos       errcode = 0;
164*6881a400Schristos     }
165*6881a400Schristos 
166*6881a400Schristos   /* bufptr and addr now point immediately beyond the last byte which we
167*6881a400Schristos      consider part of the string (including a '\0' which ends the string).  */
168*6881a400Schristos   *bytes_read = bufptr - buffer->get ();
169*6881a400Schristos 
170*6881a400Schristos   return errcode;
171*6881a400Schristos }
172*6881a400Schristos 
173*6881a400Schristos /* See target/target.h.  */
174*6881a400Schristos 
175*6881a400Schristos gdb::unique_xmalloc_ptr<char>
176*6881a400Schristos target_read_string (CORE_ADDR memaddr, int len, int *bytes_read)
177*6881a400Schristos {
178*6881a400Schristos   gdb::unique_xmalloc_ptr<gdb_byte> buffer;
179*6881a400Schristos 
180*6881a400Schristos   int ignore;
181*6881a400Schristos   if (bytes_read == nullptr)
182*6881a400Schristos     bytes_read = &ignore;
183*6881a400Schristos 
184*6881a400Schristos   /* Note that the endian-ness does not matter here.  */
185*6881a400Schristos   int errcode = target_read_string (memaddr, -1, 1, len, &buffer, bytes_read);
186*6881a400Schristos   if (errcode != 0)
187*6881a400Schristos     return {};
188*6881a400Schristos 
189*6881a400Schristos   return gdb::unique_xmalloc_ptr<char> ((char *) buffer.release ());
190*6881a400Schristos }
191