[SCM] strace branch, master, updated. v4.6-128-g2fb4db3
Denys Vlasenko
dvlasenk at redhat.com
Thu Sep 1 09:42:18 UTC 2011
On Thu, 2011-09-01 at 00:33 +0400, Dmitry V. Levin wrote:
> On Wed, Aug 31, 2011 at 10:32:55AM +0000, Denys Vlasenko wrote:
> > commit 2fb4db3e7aa1d6ac6b4b43f47597197492a846dd
> > Author: Denys Vlasenko <dvlasenk at redhat.com>
> > Date: Wed Aug 31 12:26:03 2011 +0200
> >
> > Optimization: eliminate all remaining usages of strcat()
> >
> > After this change, we don't use strcat() anywhere.
> >
> > * defs.h: Change sprinttv() return type to char *.
> > * time.c (sprinttv): Return pointer past last stored char.
> > * desc.c (decode_select): Change printing logic in order to eliminate
> > usage of strcat() - use stpcpy(), *outptr++ = ch, sprintf() instead.
> > Also reduce usage of strlen().
> > * stream.c (decode_poll): Likewise.
>
> The idea behind this change is quite clear, but some hunks are questionable.
>
> > @@ -544,41 +545,42 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
> > return RVAL_STR;
> > }
> >
> > - fds = (fd_set *) malloc(fdsize);
> > + fds = malloc(fdsize);
> > if (fds == NULL)
> > fprintf(stderr, "out of memory\n");
> >
> > - outstr[0] = '\0';
> > + tcp->auxstr = outstr;
>
> I suggest to initialize tcp->auxstr as late as possible (just in case
> there is a branch of code that might fail to initialize it properly),
> better right before returning RVAL_STR.
Good idea, I just committed a change which does exactly this.
> > + outptr = outstr;
> > + sep = "";
> > for (i = 0; i < 3; i++) {
> > int first = 1;
> >
> > - tcp->auxstr = outstr;
> > arg = args[i+1];
> > if (fds == NULL || !arg ||
> > umoven(tcp, arg, fdsize, (char *) fds) < 0)
> > continue;
> > for (j = 0; j < args[0]; j++) {
> > if (FD_ISSET(j, fds)) {
> > - char str[11 + 3 * sizeof(int)];
> > -
> > - if (first) {
> > - sprintf(str, "%s%s [%u", sep,
> > - i == 0 ? "in" :
> > - i == 1 ? "out" :
> > - "except", j);
> > - first = 0;
> > - sep = ", ";
> > + /* +2 chars needed at the end: ']',NUL */
> > + if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
> > + if (first) {
> > + outptr += sprintf(outptr, "%s%s [%u",
> > + sep,
> > + i == 0 ? "in" : i == 1 ? "out" : "except",
> > + j
> > + );
> > + first = 0;
> > + sep = ", ";
> > + }
> > + else {
> > + outptr += sprintf(outptr, " %u", j);
> > + }
> > }
> > - else
> > - sprintf(str, " %u", j);
>
> I'm not sure about this change. The new code is less readable and
> requires more room in outstr[] than the old code.
>
> > - cumlen += strlen(str);
> > - if (cumlen < sizeof(outstr))
> > - strcat(outstr, str);
Yes, it's possible that in a degenerate case old code would manage to
fit, say, a small integer into str via sprintf(str, " %u", j),
and then
cumlen += strlen(str); if (cumlen < sizeof(outstr)) strcat(outstr, str);
would successfully add it to almost full outstr.
But considering that outstr is "static char outstr[1024]", this can be
"fixed" by enlarging 1024 by about 40.
> > if (args[4]) {
> > - char str[128];
> > -
> > - sprintf(str, "%sleft ", sep);
> > - sprinttv(tcp, args[4], bitness, str + strlen(str));
> > - if ((cumlen += strlen(str)) < sizeof(outstr))
> > - strcat(outstr, str);
> > + if (outptr < end_outstr - 128) {
> > + outptr += sprintf(outptr, "%sleft ", sep);
> > + outptr = sprinttv(tcp, args[4], bitness, outptr);
> > + }
>
> The new code requires more room in outstr[] than the old code.
Enlarging outstr would fix this.
How big do you want "static char outstr[]" to be here? 1060? 1100?
> > -void
> > +char *
> > sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
> > {
> > + int rc;
> > +
> > if (addr == 0)
> > - strcpy(buf, "NULL");
> > - else if (!verbose(tcp))
> > - sprintf(buf, "%#lx", addr);
> > - else {
> > - int rc;
> > + return stpcpy(buf, "NULL");
> >
> > - if (bitness == BITNESS_32
> > + if (!verbose(tcp)) {
> > + buf += sprintf(buf, "%#lx", addr);
> > + return buf;
> > + }
>
> Why not just write it simply
>
> if (!verbose(tcp))
> return buf + sprintf(buf, "%#lx", addr);
>
> > +
> > + if (bitness == BITNESS_32
> > #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
> > - || personality_wordsize[current_personality] == 4
> > + || personality_wordsize[current_personality] == 4
> > #endif
> > - )
> > - {
> > - struct timeval32 tv;
> > -
> > - rc = umove(tcp, addr, &tv);
> > - if (rc >= 0)
> > - sprintf(buf, "{%u, %u}",
> > - tv.tv_sec, tv.tv_usec);
> > - } else {
> > - struct timeval tv;
> > + )
> > + {
> > + struct timeval32 tv;
> > +
> > + rc = umove(tcp, addr, &tv);
> > + if (rc >= 0)
> > + buf += sprintf(buf, "{%u, %u}",
> > + tv.tv_sec, tv.tv_usec);
>
> Why not just return buf + sprintf here,
>
> > + } else {
> > + struct timeval tv;
> >
> > - rc = umove(tcp, addr, &tv);
> > - if (rc >= 0)
> > - sprintf(buf, "{%lu, %lu}",
> > - (unsigned long) tv.tv_sec,
> > - (unsigned long) tv.tv_usec);
> > - }
> > - if (rc < 0)
> > - strcpy(buf, "{...}");
> > + rc = umove(tcp, addr, &tv);
> > + if (rc >= 0)
> > + buf += sprintf(buf, "{%lu, %lu}",
> > + (unsigned long) tv.tv_sec,
> > + (unsigned long) tv.tv_usec);
>
> here and
>
> > }
> > + if (rc < 0)
> > + buf = stpcpy(buf, "{...}");
>
> here?
>
> > +
> > + return buf;
> > }
Good idea, pushed to git this version:
char *
sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
{
int rc;
if (addr == 0)
return stpcpy(buf, "NULL");
if (!verbose(tcp))
return buf + sprintf(buf, "%#lx", addr);
if (bitness == BITNESS_32
#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
|| personality_wordsize[current_personality] == 4
#endif
)
{
struct timeval32 tv;
rc = umove(tcp, addr, &tv);
if (rc >= 0)
return buf + sprintf(buf, "{%u, %u}",
tv.tv_sec, tv.tv_usec);
} else {
struct timeval tv;
rc = umove(tcp, addr, &tv);
if (rc >= 0)
return buf + sprintf(buf, "{%lu, %lu}",
(unsigned long) tv.tv_sec,
(unsigned long) tv.tv_usec);
}
return stpcpy(buf, "{...}");
}
--
vda
More information about the Strace-devel
mailing list