X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=c378ce56f74e2ea4906b884d8b7beae0c1b2c54f;hb=13547ab600a0929b12f354dc144f1aef37938f30;hp=bcb47deec381c54a82656b399f5809dbd9497a4e;hpb=edfb1a26487b8c8263b434dd07466733ea17ace9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index bcb47deec3..c378ce56f7 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1341,7 +1341,7 @@ default_xfer_partial (struct target_ops *ops, enum target_object object, (inbuf, outbuf)", instead of separate read/write methods, make life easier. */ -LONGEST +static LONGEST target_read_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *buf, @@ -1350,7 +1350,7 @@ target_read_partial (struct target_ops *ops, return target_xfer_partial (ops, object, annex, buf, NULL, offset, len); } -LONGEST +static LONGEST target_write_partial (struct target_ops *ops, enum target_object object, const char *annex, const gdb_byte *buf, @@ -1373,8 +1373,9 @@ target_read (struct target_ops *ops, (gdb_byte *) buf + xfered, offset + xfered, len - xfered); /* Call an observer, notifying them of the xfer progress? */ - if (xfer <= 0) - /* Call memory_error? */ + if (xfer == 0) + return xfered; + if (xfer < 0) return -1; xfered += xfer; QUIT; @@ -1395,8 +1396,9 @@ target_write (struct target_ops *ops, (gdb_byte *) buf + xfered, offset + xfered, len - xfered); /* Call an observer, notifying them of the xfer progress? */ - if (xfer <= 0) - /* Call memory_error? */ + if (xfer == 0) + return xfered; + if (xfer < 0) return -1; xfered += xfer; QUIT; @@ -1404,6 +1406,72 @@ target_write (struct target_ops *ops, return len; } +/* Wrapper to perform a full read of unknown size. OBJECT/ANNEX will + be read using OPS. The return value will be -1 if the transfer + fails or is not supported; 0 if the object is empty; or the length + of the object otherwise. If a positive value is returned, a + sufficiently large buffer will be allocated using xmalloc and + returned in *BUF_P containing the contents of the object. + + This method should be used for objects sufficiently small to store + in a single xmalloc'd buffer, when no fixed bound on the object's + size is known in advance. Don't try to read TARGET_OBJECT_MEMORY + through this function. */ + +LONGEST +target_read_alloc (struct target_ops *ops, + enum target_object object, + const char *annex, gdb_byte **buf_p) +{ + size_t buf_alloc, buf_pos; + gdb_byte *buf; + LONGEST n; + + /* This function does not have a length parameter; it reads the + entire OBJECT). Also, it doesn't support objects fetched partly + from one target and partly from another (in a different stratum, + e.g. a core file and an executable). Both reasons make it + unsuitable for reading memory. */ + gdb_assert (object != TARGET_OBJECT_MEMORY); + + /* Start by reading up to 4K at a time. The target will throttle + this number down if necessary. */ + buf_alloc = 4096; + buf = xmalloc (buf_alloc); + buf_pos = 0; + while (1) + { + n = target_read_partial (ops, object, annex, &buf[buf_pos], + buf_pos, buf_alloc - buf_pos); + if (n < 0) + { + /* An error occurred. */ + xfree (buf); + return -1; + } + else if (n == 0) + { + /* Read all there was. */ + if (buf_pos == 0) + xfree (buf); + else + *buf_p = buf; + return buf_pos; + } + + buf_pos += n; + + /* If the buffer is filling up, expand it. */ + if (buf_alloc < buf_pos * 2) + { + buf_alloc *= 2; + buf = xrealloc (buf, buf_alloc); + } + + QUIT; + } +} + /* Memory transfer methods. */ void