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