Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Xcode, how to debug with external libraries that you have the source for?

Tags:

c++

c

xcode

qt

lldb

I have a large-ish C/C++/Objective-C project building for OS X in Xcode. The project links to pre-built Qt5 libraries.

That all works very nicely, until something crashes and I get a stack trace with Qt functions in it. If I click on the stack frame for one of the Qt functions, Xcode/lldb displays assembly rather than source - I'm using Qt as an external library, so I don't have any of the Qt source in my project. How can I fix this?

I've tried adding the Qt5 source to the project without adding it to my executable target, but Xcode/lldb still doesn't 'see' the source or figure out that the source files that I added to the project are the same source files referenced in the Qt debug symbols.

How do I tell Xcode/lldb where to find the source for an external library that I'm working with?

EDIT:

Just to add a bit more detail here, when I type 'target modules lookup -t QMenuBar' in the Xcode/lldb console, this is what I see:

Best match found in /Users/ted/Documents/Projects/XXX/_build_osx/Output/Debug/XXX.app/Contents/MacOS/XXX:
id = {0x7100042d49}, name = "QMenuBar", byte-size = 48, decl = qmenubar.h:57, clang_type = "class QMenuBar : public QWidget {
    static const QMetaObject staticMetaObject;
    virtual const QMetaObject *metaObject() const;
    virtual void *qt_metacast(const char *);
    static QString tr(const char *, const char *, int);
    static QString trUtf8(const char *, const char *, int);
    virtual int qt_metacall(QMetaObject::Call, int, void **);
    static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
    explicit QMenuBar(QWidget *);
    virtual void ~QMenuBar();
    QAction *addAction(const QString &);
    QAction *addAction(const QString &, const QObject *, const char *);
    QAction *addMenu(QMenu *);
    QMenu *addMenu(const QString &);
    QMenu *addMenu(const QIcon &, const QString &);
    QAction *addSeparator();
    QAction *insertSeparator(QAction *);
    QAction *insertMenu(QAction *, QMenu *);
    void clear();
    QAction *activeAction() const;
    void setActiveAction(QAction *);
    void setDefaultUp(bool);
    bool isDefaultUp() const;
    virtual QSize sizeHint() const;
    virtual QSize minimumSizeHint() const;
    virtual int heightForWidth(int) const;
    QRect actionGeometry(QAction *) const;
    QAction *actionAt(const QPoint &) const;
    void setCornerWidget(QWidget *, Qt::Corner);
    QWidget *cornerWidget(Qt::Corner) const;
    NSMenu *toNSMenu();
    bool isNativeMenuBar() const;
    void setNativeMenuBar(bool);
    QPlatformMenuBar *platformMenuBar();
    virtual void setVisible(bool);
    void triggered(QAction *);
    void hovered(QAction *);
    virtual void changeEvent(QEvent *);
    virtual void keyPressEvent(QKeyEvent *);
    virtual void mouseReleaseEvent(QMouseEvent *);
    virtual void mousePressEvent(QMouseEvent *);
    virtual void mouseMoveEvent(QMouseEvent *);
    virtual void leaveEvent(QEvent *);
    virtual void paintEvent(QPaintEvent *);
    virtual void resizeEvent(QResizeEvent *);
    virtual void actionEvent(QActionEvent *);
    virtual void focusOutEvent(QFocusEvent *);
    virtual void focusInEvent(QFocusEvent *);
    virtual void timerEvent(QTimerEvent *);
    virtual bool eventFilter(QObject *, QEvent *);
    virtual bool event(QEvent *);
    void initStyleOption(QStyleOptionMenuItem *, const QAction *) const;
    QMenuBarPrivate *d_func();
    const QMenuBarPrivate *d_func() const;
    QMenuBar(const QMenuBar &);
    QMenuBar &operator=(const QMenuBar &);
}"

Clearly my executable has some sort of symbols in it. It's saying that this definition came from qmenubar.h. I have qmenubar.h on my hard drive somewhere - how do I tell Xcode/lldb where to find it?

In Visual Studio in Windows, if I click on a frame in the stack trace that doesn't have source that Visual Studio can easily find, VS pops up a window asking me to browse for the source file - from then on, Visual Studio seems to intuit where the rest of the source is based on the location of the source you browsed for. For example, if I had a stack trace with QMenuBar::focusInEvent() in it, and I clicked on it, Visual Studio would ask me where qmenubar.cpp is. I could browse to C:\Users\ted\Downloads\qt5-everywhere-src-5.3.2\qtcore\src\qmenubar.cpp (or wherever it is) and Visual Studio then assumes that other sources might be located nearby.

How does this work with Xcode?

like image 651
Ted Middleton Avatar asked Nov 01 '22 07:11

Ted Middleton


1 Answers

I think I've found the answer to my question, but it actually just leads to more questions. See Xcode equivalent of Visual Studio's "Find Source".

I'm thinking that perhaps my program or my build of Qt doesn't have symbols, or fewer symbols than is necessary. In particular, here's the output of target modules lookup --address <address> --verbose (image is a lldb synonym for target modules) in that linked SO question:

  (lldb) image lookup -va main
    Address: hello[0x0000000100000f40] (hello.__TEXT.__text + 0)
    Summary: hello`main at hello.c:5
     Module: file = "/private/tmp/hello", arch = "x86_64"
CompileUnit: id = {0x00000000}, file = "/tmp/hello.c", language = "ISO C:1999"
   Function: id = {0x00000026}, name = "main", range = [0x0000000100000f40-0x0000000100000f6d)
   FuncType: id = {0x00000026}, decl = hello.c:4, clang_type = "int (void)"
     Blocks: id = {0x00000026}, range = [0x100000f40-0x100000f6d)
  LineEntry: [0x0000000100000f40-0x0000000100000f56): /tmp/hello.c:5
     Symbol: id = {0x00000004}, range = [0x0000000100000f40-0x0000000100000f6d), name="main"

here's an example from the LLVM webpage on "The LLDB Debugger" (http://lldb.llvm.org/symbolication.html):

>(lldb) image lookup --address 0x100123aa3 --verbose
      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 110)
      Summary: a.out`main + 50 at main.c:13
       Module: file = "/tmp/a.out", arch = "x86_64"
  CompileUnit: id = {0x00000000}, file = "/tmp/main.c", language = "ISO C:1999"
     Function: id = {0x0000004f}, name = "main", range = [0x0000000100000bc0-0x0000000100000dc9)
     FuncType: id = {0x0000004f}, decl = main.c:9, clang_type = "int (int, const char **, const char **, const char **)"
       Blocks: id = {0x0000004f}, range = [0x100000bc0-0x100000dc9)
               id = {0x000000ae}, range = [0x100000bf2-0x100000dc4)
    LineEntry: [0x0000000100000bf2-0x0000000100000bfa): /tmp/main.c:13:23
       Symbol: id = {0x00000004}, range = [0x0000000100000bc0-0x0000000100000dc9), name="main"
     Variable: id = {0x000000bf}, name = "path", type= "char [1024]", location = DW_OP_fbreg(-1072), decl = main.c:28
     Variable: id = {0x00000072}, name = "argc", type= "int", location = r13, decl = main.c:8
     Variable: id = {0x00000081}, name = "argv", type= "const char **", location = r12, decl = main.c:8
     Variable: id = {0x00000090}, name = "envp", type= "const char **", location = r15, decl = main.c:8
     Variable: id = {0x0000009f}, name = "aapl", type= "const char **", location = rbx, decl = main.c:8

and here's the output of my Qt5Widgets QMenuBar address:

(lldb) image lookup --address 0x103058d57 --verbose
      Address: libQt5Widgets_debug.5.dylib[0x000000000026dd57] (libQt5Widgets_debug.5.dylib.__TEXT.__text + 2525127)
      Summary: libQt5Widgets_debug.5.dylib`QMenuBar::actionEvent(QActionEvent*) + 711
       Module: file = "/Users/ted/Documents/Projects/work/third_party/qt/5.3.2/osx/x86_64/lib/libQt5Widgets_debug.5.dylib", arch = "x86_64"
       Symbol: id = {0x0000c190}, range = [0x0000000103058a90-0x0000000103059260), name="QMenuBar::actionEvent(QActionEvent*)", mangled="_ZN8QMenuBar11actionEventEP12QActionEvent"

Ack! Where's the source file (CompileUnit) reference? Thanks to @vsoftco for the suggestion and anyone else who saw this question. I'm going to have to dig a bit into the Qt5 build system and figure out where those symbols went.

like image 165
Ted Middleton Avatar answered Nov 04 '22 10:11

Ted Middleton