llvm callgraphscc pass causes core dump - llvm

I wrote an llvm callgraphscc pass, it's very simple as following:
bool MyCallGraphSCCPass::runOnSCC(CallGraphSCC& SCC) {
for (CallGraphSCC::iterator it = SCC.begin(); it != SCC.end(); it++) {
CallGraphNode* node = *it;
Function* func = node->getFunction();
}
return false;
}
This just works fine. However, if I want to print the name of each function as following:
bool MyCallGraphSCCPass::runOnSCC(CallGraphSCC& SCC) {
for (CallGraphSCC::iterator it = SCC.begin(); it != SCC.end(); it++) {
CallGraphNode* node = *it;
Function* func = node->getFunction();
func->getName();
}
return false;
}
Then it can compile (obviously), but when I use opt to run this, there appears an error as following:
0 opt 0x0000000001603412 llvm::sys::PrintStackTrace(_IO_FILE*) + 34
1 opt 0x0000000001602cb4
2 libpthread.so.0 0x00007fd3155f8cb0
3 opt 0x00000000014a86e0 llvm::AttributeSet::getAttributes(unsigned int) const + 0
4 opt 0x00000000014a8748 llvm::AttributeSet::hasAttribute(unsigned int, llvm::Attribute::AttrKind) const + 8
5 call_graph_scc_pass.so 0x00007fd3146062ad test::MyCallGraphSCCPass::runOnSCC(llvm::CallGraphSCC&) + 61
6 opt 0x00000000012aa9aa
7 opt 0x0000000001591188 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 904
8 opt 0x000000000059387b main + 2811
9 libc.so.6 0x00007fd31482976d __libc_start_main + 237
10 opt 0x00000000005b700d
Stack dump:
0. Program arguments: opt -load call_graph_scc_pass.so -scc
1. Running pass 'CallGraph Pass Manager' on module '<stdin>'.
Segmentation fault (core dumped)
Can some one help me with this?

You should check whether the function in the CallGraph is isDeclaration() or not.

This is because node->getFunction() may return a null-pointer and you're not checking for this before dereferencing it.
A CallGraphNode is added to the call graph for all functions in the module without internal linkage. This is because there is a possibility that it could be called from another module. Of course, this is not reachable from the current module, so the caller function is null.
A CallGraphNode is also added if a function address is used for something other than a direct call (such as being stored into memory). It may be called later in a way that the caller can't be tracked statically, so the function field is null here too.

Related

How does LLDB find inlined functions?

When setting a breakpoint by specifying a Symbol Name, lldb not only resolves that symbol, but also finds where the function has been used inlined. How is that possible?
1: name = 'my_func', locations = 4, resolved = 1, hit count = 1
1.1: where = kernel.development`my_func + 6 at task.c:17, address = 0xxxx, resolved, hit count = 0
1.2: where = kernel.development`func_foo + 119 [inlined] my_func at task.c:22, address = 0xxxx, unresolved, hit count = 0 Options: disabled
1.3: where = kernel.development`func_bar + 95 [inlined] my_func at task.c:65, address = 0xxxx, unresolved, hit count = 1 Options: disabled
Looking at LLDB's source, I could only find where it checked if a certain block is inlined: //source/API/SBBlock.cpp
bool SBBlock::IsInlined() const {
LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsInlined);
if (m_opaque_ptr)
return m_opaque_ptr->GetInlinedFunctionInfo() != nullptr;
return false;
}
An LLDB testcase in split-dwarf-inlining.cpp confirms that DWARF debug information is used to find inline functions.
// RUN: %clangxx -target x86_64-pc-linux -gsplit-dwarf -fsplit-dwarf-inlining \
// RUN: -c %s -o %t
// RUN: %lldb %t -o "breakpoint set -n foo" -b | FileCheck %s
// CHECK: Breakpoint 1: 2 locations
__attribute__((always_inline)) int foo(int x) { return x; }
int bar(int x) { return foo(x); }
If you run dwarfinfo on an executable it'll show "nested" inline methods, so that's how it finds it.
Where it actually finds it:
GetBlock:
Gets the deepest block that contains the frame PC.
https://github.com/llvm-mirror/lldb/blob/d01083a850f577b85501a0902b52fd0930de72c7/include/lldb/API/SBFrame.h#L60
deepest block I believe refers to the inline methods being "nested."
Then it can call getInlinedParent or getParent on that "lowest block" to generate the output. Something like that...

Segmentation fault while testing with google test

I am passing a compound structure pointer to a function after doing all the memory initializations in a test fixture. But as soon as the function gets called the sizeof that struct changes.
Have tried setting watchpoints and everything. don't the what's the issue.
Need help.
This is the code for the test.
sizeof(*ueCb) changes just after calling the function cwRrcSendMibCfgReq.
The function is copying some parameters from ueCb. ueCb has multiple structures inside of it. Accessing ueCb->currContestCellForSel in the function throws a segmentation fault even though I have explicitly allocated memory here. I have checked that the allocation occurs. I check sizeof(*ueCb) in gdb keeping the mentioned fucntion as a breakpoint. The header files are the same. Also ueId remains intact while calling the function. CW_ALLOC is an internal macro which allocates memory. it's working fine I have checked that.
Can't share the whole code because it's part of IP. This code is related to 5G protocol stack.My job is to do unit testing and the entire team isn't able to figure out where the problem is.
TEST(testMib1, test)
{
CwRrcUeCb* ueCb;
CW_ALLOC(CW_REG,CW_POOL,&ueCb, sizeof(CwRrcUeCb));
memset(ueCb, 0, sizeof(CwRrcUeCb));
ueCb->currContestCellForSel = (CwRrcCellCb *)
malloc(sizeof(CwRrcCellCb));
ueCb->currContestCellForSel->phyCellId = 5;
ueCb->ueId = 5;
S16 ret = ROK;
ret = cwRrcSendMibCfgReq(ueCb); // sizeof *ueCb changes after this statement
free(ueCb->currContestCellForSel);
CW_FREE(CW_REG, CW_POOL, ueCb, sizeof (CwRrcUeCb));
// have changed the order just to get to the main point
EXPECT_EQ(ROK, ret);
printf(" Event 9 Done\n\n\n");
}
The backtrace is as follows:
(gdb) backtrace
#0 0x000000000053a673 in cwRrcSendMibCfgReq (rrcUeCb=0x7ffff5d45320) at ../src/5gnrueapp/cw_rrc_fsm.c:2745
#1 0x000000000061dd59 in testMib1_test_Test::TestBody (this=0xa73500) at ../unittest/test_Event9Mib1.cc:79
#2 0x00007ffff71847a3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing:
:Test::*)(), char const*) () from /lib64/libgtest.so.0
#3 0x00007ffff717ab27 in testing::Test::Run() () from /lib64/libgtest.so.0
#4 0x00007ffff717abce in testing::TestInfo::Run() () from /lib64/libgtest.so.0
#5 0x00007ffff717acd5 in testing::TestCase::Run() () from /lib64/libgtest.so.0
#6 0x00007ffff717e018 in testing::internal::UnitTestImpl::RunAllTests() () from /lib64/libgtest.so.0
#7 0x00007ffff717e2a7 in testing::UnitTest::Run() () from /lib64/libgtest.so.0
#8 0x000000000061e156 in main (argc=1, argv=0x7fffffffe1d8) at ../unittest/test_main.cc:38
the function which I'm testing
S16 cwRrcSendMibCfgReq(CwRrcUeCb * rrcUeCb)
{
CtzMibConfigRequest *mibConfig = NULLP;
CW_ALLOC(CW_REG, CW_POOL, &mibConfig, sizeof (CtzMibConfigRequest));
if(NULL == mibConfig)
{
RLOG1(L_FATAL,"Memory Allocation Failed while sending Mib config req ueId:%d",rrcUeCb->ueId);
RETVALUE(RFAILED);
}
mibConfig->pres.pres = 1;
mibConfig->systemFrameNumber = rrcUeCb->cwMibInfo.systemFrameNumber;
mibConfig->subCarrierSpacingCommon = rrcUeCb->cwMibInfo.subCarrierSpacingCommon;
mibConfig->ssb_SubcarrierOffset = rrcUeCb->cwMibInfo.ssb_SubcarrierOffset;
mibConfig->dmrs_TypeAPosition = rrcUeCb->cwMibInfo.dmrs_TypeAPosition;
mibConfig->pdcch_ConfigSIB1.controlResourceSetZero =
rrcUeCb->cwMibInfo.pdcch_ConfigSIB1.controlResourceSetZero;
mibConfig->pdcch_ConfigSIB1.searchSpaceZero = rrcUeCb->cwMibInfo.pdcch_ConfigSIB1.searchSpaceZero;
mibConfig->ueId = rrcUeCb->ueId;
mibConfig->cellId = rrcUeCb->currContestCellForSel->phyCellId;
RLOG0(L_DEBUG,"[CFGREQ] [SRC:RRC ==>> DST:CL(PHY)] : CTZ_CPHY_MIB_CFG_REQ");
printf("\n[SRC:RRC ==>> DST:CL(PHY)] : CTZ_CPHY_MIB_CFG_REQ\n");
CwLiCtzCfgReq(&cwCb.ctzSapCbLst[0]->pst,CTZ_CPHY_MIB_CFG_REQ, mibConfig);
RETVALUE(ROK);
}
Try to swap the order of these lines:
CW_FREE(CW_REG, CW_POOL, ueCb, sizeof (CwRrcUeCb));
free(ueCb->currContestCellForSel);
It seems like you first free ueCb with CW_FREE, and then you access a member pointer of ueCb with ueCb->currContestCellForSel, which might cause the segfault.

Objective-c: NSPasteboard: what's difference with - setData:forType:, - setString:forType: and - setPropertyList:forType:

i want to know what's difference with - setData:forType: - setPropertyList:forType: and - setString:forType: in NSPasteboard api?
https://developer.apple.com/documentation/appkit/nspasteboard?language=objc
when i notice the description of setPropertyList and setString: This method invokes setData:forType: to perform the write.
and when I write String content to pasteboard, I have to use setString and can't use setData. If i use setData, there will be an exception:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Calling -setData:forType: on NSPasteboard or NSPasteboardItem with object of type __NSSetM instead of NSData.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fffcd4a92cb __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fffe22da48d objc_exception_throw + 48
2 CoreFoundation 0x00007fffcd527c3d +[NSException raise:format:] + 205
3 AppKit 0x00007fffcb1af86d -[NSPasteboard _setData:forType:index:usesPboardTypes:] + 287
4 libclipboard.so 0x000000010b36b9ea _ZN5cclib9ccsys_api12ClipboardMac16setClipboardDataEPNS0_13ClipboardDataE + 394
And there is another more serious bug, when i try to set a file to the pasteboard, i use setData method. and will also receive the same exception.
Is there any example to set all pasteboard type to pasteboard?
my code in github: https://github.com/hello-chenchen/cc-clipboard/blob/master/src/clipboard_mac.mm
https://github.com/hello-chenchen/cc-clipboard/blob/master/test/test_mac.mm
the code segment:
int ClipboardMac::setClipboardData(ClipboardData* data){
//FIXED: fix setString failed error
[pasteboard clearContents]
if(EN_CB_FILES == data->type) {
id buffer = (id)data->bufferData;
cout << "setClipboardData: NSFilenamesPboardType" << endl;
//ERROR: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not write property list with invalid format to the pasteboard. The object contains non-property list types: __NSSetM'
return [pasteboard setPropertyList:buffer forType:NSFilenamesPboardType];
} else if(EN_CB_TEXT == data->type) {
NSString* buffer = (NSString*)data->bufferData;
cout << "setClipboardData: NSStringPboardType" << endl;
return [pasteboard setString:buffer forType:NSStringPboardType];
} else {
cout << "setClipboardData: NSRTFDPboardType" << endl;
return CC_INVALID;
}
}
the full error log:
https://github.com/hello-chenchen/cc-clipboard/blob/master/log/error.log
i don't know if i need to malloc the full length of the buffer which i get from the pasteboard by call dataForType method. because when i copy a file type, the buffer is always the same in size(i forget about the read size, maybe 148?).
for the full code:https://github.com/hello-chenchen/cc-clipboard
i am so confused, thanks a lot.

qt/qml list delegate runs on 5.3, crashes on startup in 5.4+

My app with combined C++ and QML lists, has the model implemented in C++, derived from QAbstractListModel, and delegate in QML.
The model has three items stored as QString.
When displaying the list, the delegate has a property numItems initialized from model data as shown:
property int numItems:
{
var tally = 0;
model.item1.length > 0 ? tally++ : "";
model.item2.length > 0 ? tally++ : "";
model.item3.length > 0 ? tally++ : "";
return tally;
}
In Qt5.3, everything runs fine, regardless of whether there is data in the model or not.
In Qt5.4, Qt5.5, and Qt5.6, however, and with zero code changes, I get a segfault/ signal 11:
Error Signal Handler: 11
[bt] Execution path at Wed Apr 6, 2016 2:04:00 PM:
UI/Build/app_x86/debug/(_Z18stiBackTraceToFilei+0x3e)[0x8a29e9]
UI/Build/app_x86/debug/(_Z12stiBackTracev+0x1a)[0x8a29a8]
UI/Build/app_x86/debug/(_Z21stiErrorSignalHandleriP9siginfo_tPv+0x14b[0x8a3e73]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x10d10)[0x7fd23e7d1d10]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0xfafb5)[0x7fd23f54afb5]
/usr/share/qt5/install/lib/libQt5Qml.so.5(_ZN3QV42IR9Optimizer3runEP17QQmlEnginePrivatebb+0x1c2d)[0x7fd23f55070d]
/usr/share/qt5/install/lib/libQt5Qml.so.5(_ZN3QV43JIT20InstructionSelection3runEi+0x91)[0x7fd23f5a0cf1]
/usr/share/qt5/install/lib/libQt5Qml.so.5(_ZN3QV424EvalInstructionSelection7compileEb+0x37)[0x7fd23f52bf37]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x11cfac)[0x7fd23f56cfac]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x2698de)[0x7fd23f6b98de]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26add8)[0x7fd23f6badd8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(_ZN12QQmlDataBlob7tryDoneEv+0x44)[0x7fd23f6b9394]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269ca1)[0x7fd23f6b9ca1]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269f91)[0x7fd23f6b9f91]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26bff8)[0x7fd23f6bbff8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x273da4)[0x7fd23f6c3da4]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26c8ca)[0x7fd23f6bc8ca]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26dfd1)[0x7fd23f6bdfd1]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26e7a8)[0x7fd23f6be7a8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269d59)[0x7fd23f6b9d59]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269f91)[0x7fd23f6b9f91]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26bff8)[0x7fd23f6bbff8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x273da4)[0x7fd23f6c3da4]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26c8ca)[0x7fd23f6bc8ca]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26dfd1)[0x7fd23f6bdfd1]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26e7a8)[0x7fd23f6be7a8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269d59)[0x7fd23f6b9d59]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x269f91)[0x7fd23f6b9f91]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26bff8)[0x7fd23f6bbff8]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x273da4)[0x7fd23f6c3da4]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26c8ca)[0x7fd23f6bc8ca]
/usr/share/qt5/install/lib/libQt5Qml.so.5(+0x26dfd1)[0x7fd23f6bdfd1]
[3]+ Segmentation fault (core dumped)
I have found that if I surround the model.item block of code with a try...catch I can get it to not crash, but the console.error() call in the catch never shows up on the output.
property int numItems:
{
var tally = 0;
try
{
model.item1.length > 0 ? tally++ : "";
model.item2.length > 0 ? tally++ : "";
model.item3.length > 0 ? tally++ : "";
}
catch(err)
{
console.error("Exception in tally calculation: " + err)
}
return tally;
}
This feels like a bandaid rather than a real solution. I need to know if I am missing something more fundamental. Has something changed in the initialization of code starting with Qt5.4?
As you can see from the crash dump, it occurs deep inside of QT/QML libraries. If I set a breakpoint in my code the crash does not happen, making it look more like a race-condition than a fundamental code issue.
What is going on here?

Couldn't determine value's most derived type for dynamic_cast

Recently I am working on the python extension of gdb7, I just want to use it to write a small tool to display the contents of C++ containers (such as list) friendly while debugging.But I got trouble when dealing with list. This is my C++ code for test use:
int main() {
list<int> int_lst;
for (int i = 0; i < 10; ++i)
int_lst.push_back(i);
for(list<int>::const_iterator citer = int_lst.begin();
citer != int_lst.end(); ++citer)
cout << *citer << " ";
cout << endl;
return 0;
}
And I write a small python code following the 'debugging with gdb' tutorial just try to display contents of int_lst
import gdb
class Hello(gdb.Command):
def __init__(self):
super(Hello, self).__init__("plist", gdb.COMMAND_OBSCURE)
def invoke(self, arg, from_tty):
cpp_lst = gdb.parse_and_eval("int_lst")
header = cpp_lst['_M_impl']['_M_node']
next = header['_M_next']
# next is _List_node_base, I have to cast it to its derived type for data
next.dynamic_cast(gdb.lookup_type("std::_List_node<``int>").pointer())
Hello()
In C++ STL, std::_List_node_base is the base class of nodes in list, however only the derived template class std::_List_node has the data member "_M_data" which contains the value, so I have to dynamic_cast it, but gdb complains:
Error occurred in Python command: Couldn't determine value's most derived type for dynamic_cast
I've spent a few hours on it, could anyone experienced offer me some hints about this problem, or any suggestions for me to accomplish this little tool? I really appreciate your help, thanks!
It is difficult to say what went wrong without more information.
GDB is trying to use the RTTI information to find the full object for that field. This is failing for some eason. You can try to reproduce the problem from the CLI by using "set print object on" and then printing the field in question.
Alternatively, is there a particular reason you want to use dynamic_cast? Just use the plain "cast" method instead. I think that will bypass these checks.
Note that for this specific case, you probably should just pick up the existing libstdc++ pretty-printers. These integrate with the existing "print" command in gdb and already handle every complicated data structure in libstdc++. Many distros ship all of this code in a way that automatically enables it when your program uses libstdc++.
I see the same error from dynamic_cast() as well. Using cast() instead of dynamic_cast() there works:
list-pretty-print.cc
#include <iostream>
#include <list>
/* https://github.com/scottt/debugbreak */
#include "debugbreak/debugbreak.h"
using namespace std;
int main()
{
list<int> int_lst;
debug_break();
for (int i = 0; i < 10; ++i)
int_lst.push_back(i);
debug_break();
for(list<int>::const_iterator citer = int_lst.begin();
citer != int_lst.end(); ++citer)
cout << *citer << " ";
cout << endl;
return 0;
}
list-pretty-print.py
import gdb
class PList(gdb.Command):
def __init__(self):
super(PList, self).__init__('plist', gdb.COMMAND_OBSCURE)
def invoke(self, arg, from_tty):
int_list_pointer_type = gdb.lookup_type('std::_List_node<int>').pointer()
lst = gdb.parse_and_eval('int_lst')
node = lst['_M_impl']['_M_node']
nxt = node['_M_next']
if node.address == nxt:
gdb.write('{}\n')
return
else:
gdb.write('{')
while True:
e = nxt.cast(int_list_pointer_type).dereference()
gdb.write('%d, ' % (e['_M_data'],))
nxt = e['_M_next']
if node.address == nxt:
gdb.write('}\n')
return
PList()
test-list-pretty-print.gdb
set confirm off
set pagination off
set python print-stack full
file list-pretty-print
source list-pretty-print.py
run
up 2
plist
continue
up 2
plist
quit
Sample Session
$ gdb -q -x test-list-pretty-print.gdb
Program received signal SIGTRAP, Trace/breakpoint trap.
trap_instruction () at list-pretty-print.cc:15
15 for (int i = 0; i < 10; ++i)
#2 main () at list-pretty-print.cc:13
13 debug_break();
{}
Program received signal SIGTRAP, Trace/breakpoint trap.
trap_instruction () at list-pretty-print.cc:20
20 for(list<int>::const_iterator citer = int_lst.begin();
#2 main () at list-pretty-print.cc:18
18 debug_break();
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }
Looking at the chain of expressions, I'm not sure dynamic_cast() is supposed to work there:
(gdb) whatis int_lst
type = std::list<int, std::allocator<int> >
(gdb) whatis int_lst._M_impl
type = std::_List_base<int, std::allocator<int> >::_List_impl
(gdb) whatis int_lst._M_impl._M_node._M_next
type = std::__detail::_List_node_base *
(gdb) python print gdb.parse_and_eval('int_lst._M_impl._M_node._M_next').dynamic_type
std::__detail::_List_node_base *
(gdb) python print gdb.parse_and_eval('int_lst._M_impl._M_node._M_next').dynamic_cast(gdb.lookup_type('std::_List_node<int>').pointer())
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: Couldn't determine value's most derived type for dynamic_cast
Error while executing Python code.