[lldb-dev] expr (long)strlen("hello")

Thirumurthi, Ashok ashok.thirumurthi at intel.com
Thu Dec 13 08:52:44 PST 2012


Hi Sean,

I've been reading through source/Expression and really like the way it's constructed - very readable and lots of nifty insights.  What got me onto this tome was a Linux-specific test failure in expression evaluation that uses a call to strlen.

For instance, lang/c/strings fails with a garbage return value on Linux when evaluating the following source:
void
$__lldb_expr(void *$__lldb_arg)
{
    (int)strlen("hello");
}

Interestingly, expr (int)printf("hello") does just fine.  In both cases, FindExternalVisibleDecls uses the Symtab plugin to lookup the address, and the result is analogous.
  static <unknown type> strlen(...)
  static <unknown type> printf(...)

In fact, looking at the log generated by "log enable lldb expr", I found no differences that suggest a different code path.  In fact, the assembly is identical (except for the address in %rcx used as an argument to callq).  I played around with setting a default LanguageType of C++ rather than ObjC++, but other than the metadata, I saw no changes in the resulting assembly (which makes sense since it's fundamentally C code and the same ABI).

At first I wondered if printf succeeded because it accepts varargs, but I find that strcoll("hello", "hell") is also evaluated correctly.  Looking at return types, argument lists, and function attributes (i.e. nounwind and readonly), the difference between the calls that succeed and those that fail on Linux is the return type.  For instance, strcspn("hello", "hell") also fails with a bogus result.  This occurs even if the cast is long as in (long)strlen("hello").  However, adding a function to main.c allows me to evaluate:
size_t do_test(const char *data) {
    return strlen(data);
}
expr (int)do_test("hello")
expr (long)do_test("hello")
expr (size_t)do_test("hello")

In the above case, DWARF is available, so the log is quite different.  Incidentally, size_t isn't a valid cast on OS/X, but it's equivalent to long on 64-bit Linux with ObjC++ or C++.  So, this could be a rough edge.  Note that the problem does not reproduce on Mac OS/X.  I attached the logs on Linux and OS/X, and again there is no difference in the resulting assembly or the dematerialization except for the bogus result.  The logs were prepared against r169556 of lldb.

I'm starting to suspect that there is an error of omission somewhere.  For instance, llvm.org/demo generates a declare statement for strlen that includes attributes that lldb does not generate:

declare i64 @strlen(i8*) nounwind readonly

Any thoughts are certainly welcome,


-        Ashok
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20121213/6dfa99a9/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: strlen-linux.log
Type: application/octet-stream
Size: 14697 bytes
Desc: strlen-linux.log
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20121213/6dfa99a9/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: strlen-mac.log
Type: application/octet-stream
Size: 14470 bytes
Desc: strlen-mac.log
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20121213/6dfa99a9/attachment-0001.obj>


More information about the lldb-dev mailing list