[Lldb-commits] [lldb] r303907 - Fix bug #28898

Ulrich Weigand via lldb-commits lldb-commits at lists.llvm.org
Mon May 29 11:11:01 PDT 2017


Kamil Rytarowski <n54 at gmx.com> wrote on 29.05.2017 18:10:36:

> Do you offer shell account? I don't have Linux and/or s390x to debug it.

Sorry, this is on an internal IBM machine ... I don't have a publically
accessible machine to reproduce this on at the moment.

I managed to debug a bit myself, and I think the problem is this:

After your change, this routine:
int Editline::GetCharacter(EditLineGetCharType *c) {
now has a "wchar_t *" argument, and stores the output character
as a 4-byte wide character on Linux.

However, the caller of this routine does this (this is the Fedora 24
version of libedit - libedit-3.1-14.20150325cvs.fc24.src.rpm):

        num_read = (*el->el_read.read_char)(el, cp);
        if (num_read < 0)
                el->el_errno = errno;
#ifdef WIDECHAR
        if (el->el_flags & NARROW_READ)
                *cp = *(char *)(void *)cp;
#endif

In my case, the (el->el_flags & NARROW_READ) is true, so it
accesses the wchar_t as a char and extends that to a wchar_t.

On a little-endian machine, this would be a no-op, but on a
big-endian machine, this basically always set the character
to 0.

Now, the question is why is the NARROW_READ flag set.  It
appears this is the case because the EL_GETCFN call that
installs the callback used el_set, not el_wset (that is
what triggers setting vs. clearing NARROW_READ).

The LLDB code does *appear* to use el_wset:
  el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([](
                                     EditLine *editline,
EditLineGetCharType *c) {
            return Editline::InstanceFor(editline)->GetCharacter(c);
          }));

but that's not actually true, because of:

#if LLDB_EDITLINE_USE_WCHAR
[...]
#else
[...]
#define el_wset el_set
[...]
#endif // #if LLDB_EDITLINE_USE_WCHAR

at the top of the file.  Note that on Linux, it appears
LLDB_EDITLINE_USE_WCHAR is unconditionally set to 0:

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) ||
\
    defined(__OpenBSD__)
#define LLDB_EDITLINE_USE_WCHAR 1
#include <codecvt>
#else
#define LLDB_EDITLINE_USE_WCHAR 0
#endif

So in general, it looks like the bug is that LLDB on Linux
always installs the EL_GETFCN callback using el_set, which
causes libedit to assume it actually takes a char *
argument, but LLDB now defines the routine as taking a
wchar_t * argument, which causes the character to be always
read as 0 on all big-endian Linux systems.


Is this enough information for you to fix the problem?
If you'd like me to do more debugging, please let me know.

Bye,
Ulrich

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20170529/92cc3bc4/attachment.html>


More information about the lldb-commits mailing list